Mercurial > hg > graal-jvmci-8
diff src/share/vm/classfile/classFileParser.cpp @ 7457:35431a769282
8004823: Add VM support for type annotation reflection
Reviewed-by: dholmes, coleenp
Contributed-by: joel.franck@oracle.com
author | stefank |
---|---|
date | Thu, 20 Dec 2012 10:22:19 +0100 |
parents | 5fafdef522c6 |
children | ade95d680b42 |
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp Wed Dec 19 10:35:08 2012 -0800 +++ b/src/share/vm/classfile/classFileParser.cpp Thu Dec 20 10:22:19 2012 +0100 @@ -906,6 +906,7 @@ bool* is_synthetic_addr, u2* generic_signature_index_addr, AnnotationArray** field_annotations, + AnnotationArray** field_type_annotations, ClassFileParser::FieldAnnotationCollector* parsed_annotations, TRAPS) { ClassFileStream* cfs = stream(); @@ -917,6 +918,10 @@ int runtime_visible_annotations_length = 0; u1* runtime_invisible_annotations = NULL; int runtime_invisible_annotations_length = 0; + u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; while (attributes_count--) { cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length u2 attribute_name_index = cfs->get_u2_fast(); @@ -971,6 +976,16 @@ runtime_invisible_annotations = cfs->get_u1_buffer(); assert(runtime_invisible_annotations != NULL, "null invisible annotations"); cfs->skip_u1(runtime_invisible_annotations_length, CHECK); + } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + runtime_visible_type_annotations_length = attribute_length; + runtime_visible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); + cfs->skip_u1(runtime_visible_type_annotations_length, CHECK); + } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK); } else { cfs->skip_u1(attribute_length, CHECK); // Skip unknown attributes } @@ -988,6 +1003,12 @@ runtime_invisible_annotations, runtime_invisible_annotations_length, CHECK); + *field_type_annotations = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK); return; } @@ -1084,6 +1105,7 @@ bool is_interface, FieldAllocationCount *fac, Array<AnnotationArray*>** fields_annotations, + Array<AnnotationArray*>** fields_type_annotations, u2* java_fields_count_ptr, TRAPS) { ClassFileStream* cfs = stream(); cfs->guarantee_more(2, CHECK_NULL); // length @@ -1119,6 +1141,7 @@ THREAD, u2, total_fields * (FieldInfo::field_slots + 1)); AnnotationArray* field_annotations = NULL; + AnnotationArray* field_type_annotations = NULL; // The generic signature slots start after all other fields' data. int generic_signature_slot = total_fields * FieldInfo::field_slots; int num_generic_signature = 0; @@ -1160,7 +1183,7 @@ cp, attributes_count, is_static, signature_index, &constantvalue_index, &is_synthetic, &generic_signature_index, &field_annotations, - &parsed_annotations, + &field_type_annotations, &parsed_annotations, CHECK_NULL); if (field_annotations != NULL) { if (*fields_annotations == NULL) { @@ -1170,6 +1193,14 @@ } (*fields_annotations)->at_put(n, field_annotations); } + if (field_type_annotations != NULL) { + if (*fields_type_annotations == NULL) { + *fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>( + loader_data, length, NULL, + CHECK_NULL); + } + (*fields_type_annotations)->at_put(n, field_type_annotations); + } if (is_synthetic) { access_flags.set_is_synthetic(); } @@ -1831,6 +1862,7 @@ AnnotationArray** method_annotations, AnnotationArray** method_parameter_annotations, AnnotationArray** method_default_annotations, + AnnotationArray** method_type_annotations, TRAPS) { ClassFileStream* cfs = stream(); methodHandle nullHandle; @@ -1918,6 +1950,10 @@ int runtime_visible_parameter_annotations_length = 0; u1* runtime_invisible_parameter_annotations = NULL; int runtime_invisible_parameter_annotations_length = 0; + u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; u1* annotation_default = NULL; int annotation_default_length = 0; @@ -2159,6 +2195,17 @@ annotation_default = cfs->get_u1_buffer(); assert(annotation_default != NULL, "null annotation default"); cfs->skip_u1(annotation_default_length, CHECK_(nullHandle)); + } else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + runtime_visible_type_annotations_length = method_attribute_length; + runtime_visible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); + // No need for the VM to parse Type annotations + cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_(nullHandle)); + } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + runtime_invisible_type_annotations_length = method_attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK_(nullHandle)); } else { // Skip unknown attributes cfs->skip_u1(method_attribute_length, CHECK_(nullHandle)); @@ -2333,6 +2380,12 @@ NULL, 0, CHECK_(nullHandle)); + *method_type_annotations = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK_(nullHandle)); if (name == vmSymbols::finalize_method_name() && signature == vmSymbols::void_method_signature()) { @@ -2364,12 +2417,14 @@ Array<AnnotationArray*>** methods_annotations, Array<AnnotationArray*>** methods_parameter_annotations, Array<AnnotationArray*>** methods_default_annotations, + Array<AnnotationArray*>** methods_type_annotations, bool* has_default_methods, TRAPS) { ClassFileStream* cfs = stream(); AnnotationArray* method_annotations = NULL; AnnotationArray* method_parameter_annotations = NULL; AnnotationArray* method_default_annotations = NULL; + AnnotationArray* method_type_annotations = NULL; cfs->guarantee_more(2, CHECK_NULL); // length u2 length = cfs->get_u2_fast(); if (length == 0) { @@ -2386,6 +2441,7 @@ &method_annotations, &method_parameter_annotations, &method_default_annotations, + &method_type_annotations, CHECK_NULL); if (method->is_final()) { @@ -2411,7 +2467,13 @@ MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL); } (*methods_default_annotations)->at_put(index, method_default_annotations); + if (*methods_type_annotations == NULL) { + *methods_type_annotations = + MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL); + } + (*methods_type_annotations)->at_put(index, method_type_annotations); } + if (_need_verify && length > 1) { // Check duplicated methods ResourceMark rm(THREAD); @@ -2445,6 +2507,7 @@ Array<AnnotationArray*>* methods_annotations, Array<AnnotationArray*>* methods_parameter_annotations, Array<AnnotationArray*>* methods_default_annotations, + Array<AnnotationArray*>* methods_type_annotations, TRAPS) { int length = methods->length(); // If JVMTI original method ordering or sharing is enabled we have to @@ -2463,7 +2526,8 @@ // Note that the ordering is not alphabetical, see Symbol::fast_compare Method::sort_methods(methods, methods_annotations, methods_parameter_annotations, - methods_default_annotations); + methods_default_annotations, + methods_type_annotations); // If JVMTI original method ordering or sharing is enabled construct int // array remembering the original ordering @@ -2728,6 +2792,10 @@ int runtime_visible_annotations_length = 0; u1* runtime_invisible_annotations = NULL; int runtime_invisible_annotations_length = 0; + u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; u1* inner_classes_attribute_start = NULL; u4 inner_classes_attribute_length = 0; u2 enclosing_method_class_index = 0; @@ -2834,6 +2902,17 @@ classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); parsed_bootstrap_methods_attribute = true; parse_classfile_bootstrap_methods_attribute(loader_data, cp, attribute_length, CHECK); + } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) { + runtime_visible_type_annotations_length = attribute_length; + runtime_visible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); + // No need for the VM to parse Type annotations + cfs->skip_u1(runtime_visible_type_annotations_length, CHECK); + } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_type_annotations()) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK); } else { // Unknown attribute cfs->skip_u1(attribute_length, CHECK); @@ -2850,6 +2929,13 @@ runtime_invisible_annotations_length, CHECK); set_class_annotations(annotations); + AnnotationArray* type_annotations = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK); + set_class_type_annotations(type_annotations); if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { u2 num_of_classes = parse_classfile_inner_classes_attribute( @@ -3190,7 +3276,9 @@ // Fields (offsets are filled in later) FieldAllocationCount fac; Array<AnnotationArray*>* fields_annotations = NULL; + Array<AnnotationArray*>* fields_type_annotations = NULL; Array<u2>* fields = parse_fields(loader_data, class_name, cp, access_flags.is_interface(), &fac, &fields_annotations, + &fields_type_annotations, &java_fields_count, CHECK_(nullHandle)); // Methods @@ -3202,6 +3290,7 @@ Array<AnnotationArray*>* methods_annotations = NULL; Array<AnnotationArray*>* methods_parameter_annotations = NULL; Array<AnnotationArray*>* methods_default_annotations = NULL; + Array<AnnotationArray*>* methods_type_annotations = NULL; Array<Method*>* methods = parse_methods(loader_data, cp, access_flags.is_interface(), &promoted_flags, @@ -3209,6 +3298,7 @@ &methods_annotations, &methods_parameter_annotations, &methods_default_annotations, + &methods_type_annotations, &has_default_methods, CHECK_(nullHandle)); @@ -3270,6 +3360,7 @@ methods_annotations, methods_parameter_annotations, methods_default_annotations, + methods_type_annotations, CHECK_(nullHandle)); // promote flags from parse_methods() to the klass' flags @@ -3687,11 +3778,13 @@ if (is_anonymous()) // I am well known to myself cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve + // Allocate an annotation type if needed. if (fields_annotations != NULL || methods_annotations != NULL || methods_parameter_annotations != NULL || - methods_default_annotations != NULL) { - // Allocate an annotation type if needed. + methods_default_annotations != NULL || + fields_type_annotations != NULL || + methods_type_annotations != NULL) { Annotations* anno = Annotations::allocate(loader_data, fields_annotations, methods_annotations, methods_parameter_annotations, @@ -3701,6 +3794,16 @@ this_klass->set_annotations(NULL); } + if (fields_type_annotations != NULL || + methods_type_annotations != NULL) { + assert(this_klass->annotations() != NULL, "annotations should have been allocated"); + Annotations* anno = Annotations::allocate(loader_data, + fields_type_annotations, + methods_type_annotations, + NULL, + NULL, CHECK_(nullHandle)); + this_klass->annotations()->set_type_annotations(anno); + } this_klass->set_minor_version(minor_version); this_klass->set_major_version(major_version); @@ -3725,6 +3828,7 @@ // Fill in field values obtained by parse_classfile_attributes if (parsed_annotations.has_any_annotations()) parsed_annotations.apply_to(this_klass); + // Create annotations if (_annotations != NULL && this_klass->annotations() == NULL) { Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); @@ -3732,6 +3836,19 @@ } apply_parsed_class_attributes(this_klass); + // Create type annotations + if (_type_annotations != NULL) { + if (this_klass->annotations() == NULL) { + Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); + this_klass->set_annotations(anno); + } + if (this_klass->annotations()->type_annotations() == NULL) { + Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); + this_klass->annotations()->set_type_annotations(anno); + } + this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations); + } + // Miranda methods if ((num_miranda_methods > 0) || // if this class introduced new miranda methods or