8004823: Add VM support for type annotation reflection

Reviewed-by: dholmes, coleenp
This commit is contained in:
Joel Borggren-Franck 2012-12-20 10:22:19 +01:00 committed by Stefan Karlsson
parent 9c761152db
commit 6ed6cb5375
22 changed files with 302 additions and 11 deletions

View file

@ -906,6 +906,7 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
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 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
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 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
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 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
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 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
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 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
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 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
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 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
}
(*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 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
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 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
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 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
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 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
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<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
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 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
&method_annotations,
&method_parameter_annotations,
&method_default_annotations,
&method_type_annotations,
CHECK_NULL);
if (method->is_final()) {
@ -2411,7 +2467,13 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
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<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
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 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
// 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 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
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 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
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 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
&methods_annotations,
&methods_parameter_annotations,
&methods_default_annotations,
&methods_type_annotations,
&has_default_methods,
CHECK_(nullHandle));
@ -3270,6 +3360,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
}
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