6964458: Reimplement class meta-data storage to use native memory

Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes

Co-authored-by: Stefan Karlsson <stefan.karlsson@oracle.com>
Co-authored-by: Mikael Gerdin <mikael.gerdin@oracle.com>
Co-authored-by: Tom Rodriguez <tom.rodriguez@oracle.com>
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
This commit is contained in:
Jon Masamitsu 2012-09-01 13:25:18 -04:00 committed by Coleen Phillimore
parent 36eee7c8c8
commit 5c58d27aac
853 changed files with 26124 additions and 82956 deletions

View file

@ -45,7 +45,7 @@
#endif
// FIXME: add Deprecated, LVTT attributes
// FIXME: fix Synthetic attribute
// FIXME: per Serguei, add error return handling for constantPoolOopDesc::copy_cpool_bytes()
// FIXME: per Serguei, add error return handling for ConstantPool::copy_cpool_bytes()
// Write the field information portion of ClassFile structure
@ -53,7 +53,7 @@
// JVMSpec| field_info fields[fields_count];
void JvmtiClassFileReconstituter::write_field_infos() {
HandleMark hm(thread());
objArrayHandle fields_anno(thread(), ikh()->fields_annotations());
Array<AnnotationArray*>* fields_anno = ikh()->fields_annotations();
// Compute the real number of Java fields
int java_fields = ikh()->java_fields_count();
@ -67,9 +67,7 @@ void JvmtiClassFileReconstituter::write_field_infos() {
guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field");
// int offset = ikh()->field_offset( index );
int generic_signature_index = fs.generic_signature_index();
typeArrayHandle anno(thread(), fields_anno.not_null() ?
(typeArrayOop)(fields_anno->obj_at(fs.index())) :
(typeArrayOop)NULL);
AnnotationArray* anno = fields_anno == NULL ? NULL : fields_anno->at(fs.index());
// JVMSpec| field_info {
// JVMSpec| u2 access_flags;
@ -92,7 +90,7 @@ void JvmtiClassFileReconstituter::write_field_infos() {
if (generic_signature_index != 0) {
++attr_count;
}
if (anno.not_null()) {
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
@ -109,7 +107,7 @@ void JvmtiClassFileReconstituter::write_field_infos() {
if (generic_signature_index != 0) {
write_signature_attribute(generic_signature_index);
}
if (anno.not_null()) {
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
}
@ -133,7 +131,7 @@ void JvmtiClassFileReconstituter::write_field_infos() {
// JVMSpec| attribute_info attributes[attributes_count];
// JVMSpec| }
void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
constMethodHandle const_method(thread(), method->constMethod());
ConstMethod* const_method = method->constMethod();
u2 line_num_cnt = 0;
int stackmap_len = 0;
int local_variable_table_length = 0;
@ -234,7 +232,7 @@ void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
// JVMSpec| u2 number_of_exceptions;
// JVMSpec| u2 exception_index_table[number_of_exceptions];
// JVMSpec| }
void JvmtiClassFileReconstituter::write_exceptions_attribute(constMethodHandle const_method) {
void JvmtiClassFileReconstituter::write_exceptions_attribute(ConstMethod* const_method) {
CheckedExceptionElement* checked_exceptions = const_method->checked_exceptions_start();
int checked_exceptions_length = const_method->checked_exceptions_length();
int size =
@ -307,11 +305,11 @@ u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {
// JSR202| ...
// JSR202| }
void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_name,
typeArrayHandle annos) {
AnnotationArray* annos) {
u4 length = annos->length();
write_attribute_name_index(attr_name);
write_u4(length);
memcpy(writeable_address(length), annos->byte_at_addr(0), length);
memcpy(writeable_address(length), annos->adr_at(0), length);
}
@ -330,7 +328,7 @@ void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {
InnerClassesIterator iter(ikh());
guarantee(iter.length() != 0 && iter.length() == length,
"caller must check");
u2 entry_count = length / instanceKlass::inner_class_next_offset;
u2 entry_count = length / InstanceKlass::inner_class_next_offset;
u4 size = 2 + entry_count * (2+2+2+2);
write_attribute_name_index("InnerClasses");
@ -433,7 +431,7 @@ void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle me
write_u4(stackmap_len);
memcpy(
writeable_address(stackmap_len),
(void*)(method->stackmap_data()->byte_at_addr(0)),
(void*)(method->stackmap_data()->adr_at(0)),
stackmap_len);
}
@ -447,11 +445,11 @@ void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle me
// JVMSpec| }
void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
AccessFlags access_flags = method->access_flags();
constMethodHandle const_method(thread(), method->constMethod());
ConstMethod* const_method = method->constMethod();
u2 generic_signature_index = const_method->generic_signature_index();
typeArrayHandle anno(thread(), method->annotations());
typeArrayHandle param_anno(thread(), method->parameter_annotations());
typeArrayHandle default_anno(thread(), method->annotation_default());
AnnotationArray* anno = method->annotations();
AnnotationArray* param_anno = method->parameter_annotations();
AnnotationArray* default_anno = method->annotation_default();
write_u2(access_flags.get_flags() & JVM_RECOGNIZED_METHOD_MODIFIERS);
write_u2(const_method->name_index());
@ -466,7 +464,7 @@ void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
if (const_method->has_checked_exceptions()) {
++attr_count; // has Exceptions attribute
}
if (default_anno.not_null()) {
if (default_anno != NULL) {
++attr_count; // has AnnotationDefault attribute
}
// Deprecated attribute would go here
@ -476,10 +474,10 @@ void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
if (generic_signature_index != 0) {
++attr_count;
}
if (anno.not_null()) {
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
if (param_anno.not_null()) {
if (param_anno != NULL) {
++attr_count; // has RuntimeVisibleParameterAnnotations attribute
}
@ -490,7 +488,7 @@ void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
if (const_method->has_checked_exceptions()) {
write_exceptions_attribute(const_method);
}
if (default_anno.not_null()) {
if (default_anno != NULL) {
write_annotations_attribute("AnnotationDefault", default_anno);
}
// Deprecated attribute would go here
@ -500,10 +498,10 @@ void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
if (generic_signature_index != 0) {
write_signature_attribute(generic_signature_index);
}
if (anno.not_null()) {
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
if (param_anno.not_null()) {
if (param_anno != NULL) {
write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno);
}
}
@ -514,7 +512,7 @@ void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
void JvmtiClassFileReconstituter::write_class_attributes() {
u2 inner_classes_length = inner_classes_attribute_length();
Symbol* generic_signature = ikh()->generic_signature();
typeArrayHandle anno(thread(), ikh()->class_annotations());
AnnotationArray* anno = ikh()->class_annotations();
int attr_count = 0;
if (generic_signature != NULL) {
@ -529,7 +527,7 @@ void JvmtiClassFileReconstituter::write_class_attributes() {
if (inner_classes_length > 0) {
++attr_count;
}
if (anno.not_null()) {
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
@ -547,7 +545,7 @@ void JvmtiClassFileReconstituter::write_class_attributes() {
if (inner_classes_length > 0) {
write_inner_classes_attribute(inner_classes_length);
}
if (anno.not_null()) {
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
}
@ -557,33 +555,33 @@ void JvmtiClassFileReconstituter::write_class_attributes() {
// JVMSpec| method_info methods[methods_count];
void JvmtiClassFileReconstituter::write_method_infos() {
HandleMark hm(thread());
objArrayHandle methods(thread(), ikh()->methods());
Array<Method*>* methods = ikh()->methods();
int num_methods = methods->length();
write_u2(num_methods);
if (JvmtiExport::can_maintain_original_method_order()) {
int index;
int original_index;
int* method_order = NEW_RESOURCE_ARRAY(int, num_methods);
intArray method_order(num_methods, 0);
// invert the method order mapping
for (index = 0; index < num_methods; index++) {
original_index = ikh()->method_ordering()->int_at(index);
original_index = ikh()->method_ordering()->at(index);
assert(original_index >= 0 && original_index < num_methods,
"invalid original method index");
method_order[original_index] = index;
method_order.at_put(original_index, index);
}
// write in original order
for (original_index = 0; original_index < num_methods; original_index++) {
index = method_order[original_index];
methodHandle method(thread(), (methodOop)(ikh()->methods()->obj_at(index)));
index = method_order.at(original_index);
methodHandle method(thread(), methods->at(index));
write_method_info(method);
}
} else {
// method order not preserved just dump the method infos
for (int index = 0; index < num_methods; index++) {
methodHandle method(thread(), (methodOop)(ikh()->methods()->obj_at(index)));
methodHandle method(thread(), methods->at(index));
write_method_info(method);
}
}
@ -613,18 +611,18 @@ void JvmtiClassFileReconstituter::write_class_file_format() {
// JVMSpec| u2 this_class;
// JVMSpec| u2 super_class;
write_u2(class_symbol_to_cpool_index(ikh()->name()));
klassOop super_class = ikh()->super();
Klass* super_class = ikh()->super();
write_u2(super_class == NULL? 0 : // zero for java.lang.Object
class_symbol_to_cpool_index(super_class->klass_part()->name()));
class_symbol_to_cpool_index(super_class->name()));
// JVMSpec| u2 interfaces_count;
// JVMSpec| u2 interfaces[interfaces_count];
objArrayHandle interfaces(thread(), ikh()->local_interfaces());
Array<Klass*>* interfaces = ikh()->local_interfaces();
int num_interfaces = interfaces->length();
write_u2(num_interfaces);
for (int index = 0; index < num_interfaces; index++) {
HandleMark hm(thread());
instanceKlassHandle iikh(thread(), klassOop(interfaces->obj_at(index)));
instanceKlassHandle iikh(thread(), interfaces->at(index));
write_u2(class_symbol_to_cpool_index(iikh->name()));
}
@ -693,7 +691,7 @@ void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
unsigned char* p = bytecodes;
Bytecodes::Code code;
bool is_rewritten = instanceKlass::cast(mh->method_holder())->is_rewritten();
bool is_rewritten = InstanceKlass::cast(mh->method_holder())->is_rewritten();
while ((code = bs.next()) >= 0) {
assert(Bytecodes::is_java_code(code), "sanity check");
@ -713,7 +711,8 @@ void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
// During linking the get/put and invoke instructions are rewritten
// with an index into the constant pool cache. The original constant
// pool index must be returned to caller. Rewrite the index.
if (is_rewritten && len >= 3) {
if (is_rewritten && len > 1) {
bool is_wide = false;
switch (code) {
case Bytecodes::_getstatic : // fall through
case Bytecodes::_putstatic : // fall through
@ -723,7 +722,7 @@ void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokedynamic : // fall through
case Bytecodes::_invokeinterface :
case Bytecodes::_invokeinterface : {
assert(len == 3 ||
(code == Bytecodes::_invokeinterface && len == 5) ||
(code == Bytecodes::_invokedynamic && len == 5),
@ -731,17 +730,36 @@ void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
int cpci = Bytes::get_native_u2(bcp+1);
bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic);
if (is_invokedynamic)
ConstantPoolCacheEntry* entry;
if (is_invokedynamic) {
cpci = Bytes::get_native_u4(bcp+1);
entry = mh->constants()->invokedynamic_cp_cache_entry_at(cpci);
} else {
// cache cannot be pre-fetched since some classes won't have it yet
ConstantPoolCacheEntry* entry =
mh->constants()->cache()->main_entry_at(cpci);
entry = mh->constants()->cache()->entry_at(cpci);
}
int i = entry->constant_pool_index();
assert(i < mh->constants()->length(), "sanity check");
Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering
if (is_invokedynamic) *(p+3) = *(p+4) = 0;
break;
}
case Bytecodes::_ldc_w:
is_wide = true; // fall through
case Bytecodes::_ldc: {
if (bs.raw_code() == Bytecodes::_fast_aldc || bs.raw_code() == Bytecodes::_fast_aldc_w) {
int cpci = is_wide ? Bytes::get_native_u2(bcp+1) : (u1)(*(bcp+1));
int i = mh->constants()->object_to_cp_index(cpci);
assert(i < mh->constants()->length(), "sanity check");
if (is_wide) {
Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering
} else {
*(p+1) = (u1)i;
}
}
break;
}
}
}
p += len;