mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
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:
parent
36eee7c8c8
commit
5c58d27aac
853 changed files with 26124 additions and 82956 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue