Tue, 13 Mar 2012 13:50:48 -0400
7109878: The instanceKlass EnclosingMethhod attribute fields can be folded into the _inner_class field.
Summary: Fold instanceKlass::_enclosing_method_class_index and instanceKlass::_enclosing_method_method_index into the instanceKlass::_inner_classes array.
Reviewed-by: never, coleenp
Contributed-by: Jiangli Zhou <jiangli.zhou@oracle.com>
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Mar 09 13:34:45 2012 -0800 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Tue Mar 13 13:50:48 2012 -0400 1.3 @@ -359,6 +359,12 @@ 1.4 public static final int innerClassNextOffset = 4; 1.5 }; 1.6 1.7 + public static interface EnclosingMethodAttributeOffset { 1.8 + public static final int enclosing_method_class_index_offset = 0; 1.9 + public static final int enclosing_method_method_index_offset = 1; 1.10 + public static final int enclosing_method_attribute_size = 2; 1.11 + }; 1.12 + 1.13 // refer to compute_modifier_flags in VM code. 1.14 public long computeModifierFlags() { 1.15 long access = getAccessFlags(); 1.16 @@ -367,9 +373,14 @@ 1.17 int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength(); 1.18 if (length > 0) { 1.19 if (Assert.ASSERTS_ENABLED) { 1.20 - Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking"); 1.21 + Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 1.22 + length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size, 1.23 + "just checking"); 1.24 } 1.25 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 1.26 + if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { 1.27 + break; 1.28 + } 1.29 int ioff = innerClassList.getShortAt(i + 1.30 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 1.31 // 'ioff' can be zero. 1.32 @@ -419,9 +430,14 @@ 1.33 int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength(); 1.34 if (length > 0) { 1.35 if (Assert.ASSERTS_ENABLED) { 1.36 - Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking"); 1.37 + Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 1.38 + length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size, 1.39 + "just checking"); 1.40 } 1.41 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 1.42 + if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { 1.43 + break; 1.44 + } 1.45 int ioff = innerClassList.getShortAt(i + 1.46 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 1.47 // 'ioff' can be zero.
2.1 --- a/src/share/vm/classfile/classFileParser.cpp Fri Mar 09 13:34:45 2012 -0800 2.2 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Mar 13 13:50:48 2012 -0400 2.3 @@ -2315,13 +2315,32 @@ 2.4 #define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC) 2.5 2.6 // Return number of classes in the inner classes attribute table 2.7 -u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { 2.8 +u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start, 2.9 + bool parsed_enclosingmethod_attribute, 2.10 + u2 enclosing_method_class_index, 2.11 + u2 enclosing_method_method_index, 2.12 + constantPoolHandle cp, 2.13 + instanceKlassHandle k, TRAPS) { 2.14 ClassFileStream* cfs = stream(); 2.15 - cfs->guarantee_more(2, CHECK_0); // length 2.16 - u2 length = cfs->get_u2_fast(); 2.17 - 2.18 - // 4-tuples of shorts [inner_class_info_index, outer_class_info_index, inner_name_index, inner_class_access_flags] 2.19 - typeArrayOop ic = oopFactory::new_permanent_shortArray(length*4, CHECK_0); 2.20 + u1* current_mark = cfs->current(); 2.21 + u2 length = 0; 2.22 + if (inner_classes_attribute_start != NULL) { 2.23 + cfs->set_current(inner_classes_attribute_start); 2.24 + cfs->guarantee_more(2, CHECK_0); // length 2.25 + length = cfs->get_u2_fast(); 2.26 + } 2.27 + 2.28 + // 4-tuples of shorts of inner classes data and 2 shorts of enclosing 2.29 + // method data: 2.30 + // [inner_class_info_index, 2.31 + // outer_class_info_index, 2.32 + // inner_name_index, 2.33 + // inner_class_access_flags, 2.34 + // ... 2.35 + // enclosing_method_class_index, 2.36 + // enclosing_method_method_index] 2.37 + int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0); 2.38 + typeArrayOop ic = oopFactory::new_permanent_shortArray(size, CHECK_0); 2.39 typeArrayHandle inner_classes(THREAD, ic); 2.40 int index = 0; 2.41 int cp_size = cp->length(); 2.42 @@ -2372,8 +2391,8 @@ 2.43 2.44 // 4347400: make sure there's no duplicate entry in the classes array 2.45 if (_need_verify && _major_version >= JAVA_1_5_VERSION) { 2.46 - for(int i = 0; i < inner_classes->length(); i += 4) { 2.47 - for(int j = i + 4; j < inner_classes->length(); j += 4) { 2.48 + for(int i = 0; i < length * 4; i += 4) { 2.49 + for(int j = i + 4; j < length * 4; j += 4) { 2.50 guarantee_property((inner_classes->ushort_at(i) != inner_classes->ushort_at(j) || 2.51 inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) || 2.52 inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) || 2.53 @@ -2384,8 +2403,19 @@ 2.54 } 2.55 } 2.56 2.57 + // Set EnclosingMethod class and method indexes. 2.58 + if (parsed_enclosingmethod_attribute) { 2.59 + inner_classes->short_at_put(index++, enclosing_method_class_index); 2.60 + inner_classes->short_at_put(index++, enclosing_method_method_index); 2.61 + } 2.62 + assert(index == size, "wrong size"); 2.63 + 2.64 // Update instanceKlass with inner class info. 2.65 k->set_inner_classes(inner_classes()); 2.66 + 2.67 + // Restore buffer's current position. 2.68 + cfs->set_current(current_mark); 2.69 + 2.70 return length; 2.71 } 2.72 2.73 @@ -2490,6 +2520,10 @@ 2.74 int runtime_visible_annotations_length = 0; 2.75 u1* runtime_invisible_annotations = NULL; 2.76 int runtime_invisible_annotations_length = 0; 2.77 + u1* inner_classes_attribute_start = NULL; 2.78 + u4 inner_classes_attribute_length = 0; 2.79 + u2 enclosing_method_class_index = 0; 2.80 + u2 enclosing_method_method_index = 0; 2.81 // Iterate over attributes 2.82 while (attributes_count--) { 2.83 cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length 2.84 @@ -2522,11 +2556,9 @@ 2.85 } else { 2.86 parsed_innerclasses_attribute = true; 2.87 } 2.88 - u2 num_of_classes = parse_classfile_inner_classes_attribute(cp, k, CHECK); 2.89 - if (_need_verify && _major_version >= JAVA_1_5_VERSION) { 2.90 - guarantee_property(attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, 2.91 - "Wrong InnerClasses attribute length in class file %s", CHECK); 2.92 - } 2.93 + inner_classes_attribute_start = cfs->get_u1_buffer(); 2.94 + inner_classes_attribute_length = attribute_length; 2.95 + cfs->skip_u1(inner_classes_attribute_length, CHECK); 2.96 } else if (tag == vmSymbols::tag_synthetic()) { 2.97 // Check for Synthetic tag 2.98 // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec 2.99 @@ -2568,22 +2600,21 @@ 2.100 parsed_enclosingmethod_attribute = true; 2.101 } 2.102 cfs->guarantee_more(4, CHECK); // class_index, method_index 2.103 - u2 class_index = cfs->get_u2_fast(); 2.104 - u2 method_index = cfs->get_u2_fast(); 2.105 - if (class_index == 0) { 2.106 + enclosing_method_class_index = cfs->get_u2_fast(); 2.107 + enclosing_method_method_index = cfs->get_u2_fast(); 2.108 + if (enclosing_method_class_index == 0) { 2.109 classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK); 2.110 } 2.111 // Validate the constant pool indices and types 2.112 - if (!cp->is_within_bounds(class_index) || 2.113 - !is_klass_reference(cp, class_index)) { 2.114 + if (!cp->is_within_bounds(enclosing_method_class_index) || 2.115 + !is_klass_reference(cp, enclosing_method_class_index)) { 2.116 classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK); 2.117 } 2.118 - if (method_index != 0 && 2.119 - (!cp->is_within_bounds(method_index) || 2.120 - !cp->tag_at(method_index).is_name_and_type())) { 2.121 + if (enclosing_method_method_index != 0 && 2.122 + (!cp->is_within_bounds(enclosing_method_method_index) || 2.123 + !cp->tag_at(enclosing_method_method_index).is_name_and_type())) { 2.124 classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK); 2.125 } 2.126 - k->set_enclosing_method_indices(class_index, method_index); 2.127 } else if (tag == vmSymbols::tag_bootstrap_methods() && 2.128 _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { 2.129 if (parsed_bootstrap_methods_attribute) 2.130 @@ -2606,6 +2637,20 @@ 2.131 CHECK); 2.132 k->set_class_annotations(annotations()); 2.133 2.134 + if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { 2.135 + u2 num_of_classes = parse_classfile_inner_classes_attribute( 2.136 + inner_classes_attribute_start, 2.137 + parsed_innerclasses_attribute, 2.138 + enclosing_method_class_index, 2.139 + enclosing_method_method_index, 2.140 + cp, k, CHECK); 2.141 + if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) { 2.142 + guarantee_property( 2.143 + inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, 2.144 + "Wrong InnerClasses attribute length in class file %s", CHECK); 2.145 + } 2.146 + } 2.147 + 2.148 if (_max_bootstrap_specifier_index >= 0) { 2.149 guarantee_property(parsed_bootstrap_methods_attribute, 2.150 "Missing BootstrapMethods attribute in class file %s", CHECK);
3.1 --- a/src/share/vm/classfile/classFileParser.hpp Fri Mar 09 13:34:45 2012 -0800 3.2 +++ b/src/share/vm/classfile/classFileParser.hpp Tue Mar 13 13:50:48 2012 -0400 3.3 @@ -130,7 +130,11 @@ 3.4 void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS); 3.5 void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, 3.6 instanceKlassHandle k, int length, TRAPS); 3.7 - u2 parse_classfile_inner_classes_attribute(constantPoolHandle cp, 3.8 + u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start, 3.9 + bool parsed_enclosingmethod_attribute, 3.10 + u2 enclosing_method_class_index, 3.11 + u2 enclosing_method_method_index, 3.12 + constantPoolHandle cp, 3.13 instanceKlassHandle k, TRAPS); 3.14 void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS); 3.15 void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
4.1 --- a/src/share/vm/memory/dump.cpp Fri Mar 09 13:34:45 2012 -0800 4.2 +++ b/src/share/vm/memory/dump.cpp Tue Mar 13 13:50:48 2012 -0400 4.3 @@ -297,16 +297,14 @@ 4.4 4.5 if (obj->blueprint()->oop_is_instanceKlass()) { 4.6 instanceKlass* ik = instanceKlass::cast((klassOop)obj); 4.7 - typeArrayOop inner_classes = ik->inner_classes(); 4.8 - if (inner_classes != NULL) { 4.9 - constantPoolOop constants = ik->constants(); 4.10 - int n = inner_classes->length(); 4.11 - for (int i = 0; i < n; i += instanceKlass::inner_class_next_offset) { 4.12 - int ioff = i + instanceKlass::inner_class_inner_name_offset; 4.13 - int index = inner_classes->ushort_at(ioff); 4.14 - if (index != 0) { 4.15 - _closure->do_symbol(constants->symbol_at_addr(index)); 4.16 - } 4.17 + instanceKlassHandle ik_h((klassOop)obj); 4.18 + InnerClassesIterator iter(ik_h); 4.19 + constantPoolOop constants = ik->constants(); 4.20 + for (; !iter.done(); iter.next()) { 4.21 + int index = iter.inner_name_index(); 4.22 + 4.23 + if (index != 0) { 4.24 + _closure->do_symbol(constants->symbol_at_addr(index)); 4.25 } 4.26 } 4.27 }
5.1 --- a/src/share/vm/oops/instanceKlass.cpp Fri Mar 09 13:34:45 2012 -0800 5.2 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Mar 13 13:50:48 2012 -0400 5.3 @@ -1132,6 +1132,36 @@ 5.4 return probe; 5.5 } 5.6 5.7 +u2 instanceKlass::enclosing_method_data(int offset) { 5.8 + typeArrayOop inner_class_list = inner_classes(); 5.9 + if (inner_class_list == NULL) { 5.10 + return 0; 5.11 + } 5.12 + int length = inner_class_list->length(); 5.13 + if (length % inner_class_next_offset == 0) { 5.14 + return 0; 5.15 + } else { 5.16 + int index = length - enclosing_method_attribute_size; 5.17 + typeArrayHandle inner_class_list_h(inner_class_list); 5.18 + assert(offset < enclosing_method_attribute_size, "invalid offset"); 5.19 + return inner_class_list_h->ushort_at(index + offset); 5.20 + } 5.21 +} 5.22 + 5.23 +void instanceKlass::set_enclosing_method_indices(u2 class_index, 5.24 + u2 method_index) { 5.25 + typeArrayOop inner_class_list = inner_classes(); 5.26 + assert (inner_class_list != NULL, "_inner_classes list is not set up"); 5.27 + int length = inner_class_list->length(); 5.28 + if (length % inner_class_next_offset == enclosing_method_attribute_size) { 5.29 + int index = length - enclosing_method_attribute_size; 5.30 + typeArrayHandle inner_class_list_h(inner_class_list); 5.31 + inner_class_list_h->ushort_at_put( 5.32 + index + enclosing_method_class_index_offset, class_index); 5.33 + inner_class_list_h->ushort_at_put( 5.34 + index + enclosing_method_method_index_offset, method_index); 5.35 + } 5.36 +} 5.37 5.38 // Lookup or create a jmethodID. 5.39 // This code is called by the VMThread and JavaThreads so the 5.40 @@ -2106,28 +2136,21 @@ 5.41 jint access = access_flags().as_int(); 5.42 5.43 // But check if it happens to be member class. 5.44 - typeArrayOop inner_class_list = inner_classes(); 5.45 - int length = (inner_class_list == NULL) ? 0 : inner_class_list->length(); 5.46 - assert (length % instanceKlass::inner_class_next_offset == 0, "just checking"); 5.47 - if (length > 0) { 5.48 - typeArrayHandle inner_class_list_h(THREAD, inner_class_list); 5.49 - instanceKlassHandle ik(THREAD, k); 5.50 - for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) { 5.51 - int ioff = inner_class_list_h->ushort_at( 5.52 - i + instanceKlass::inner_class_inner_class_info_offset); 5.53 - 5.54 - // Inner class attribute can be zero, skip it. 5.55 - // Strange but true: JVM spec. allows null inner class refs. 5.56 - if (ioff == 0) continue; 5.57 - 5.58 - // only look at classes that are already loaded 5.59 - // since we are looking for the flags for our self. 5.60 - Symbol* inner_name = ik->constants()->klass_name_at(ioff); 5.61 - if ((ik->name() == inner_name)) { 5.62 - // This is really a member class. 5.63 - access = inner_class_list_h->ushort_at(i + instanceKlass::inner_class_access_flags_offset); 5.64 - break; 5.65 - } 5.66 + instanceKlassHandle ik(THREAD, k); 5.67 + InnerClassesIterator iter(ik); 5.68 + for (; !iter.done(); iter.next()) { 5.69 + int ioff = iter.inner_class_info_index(); 5.70 + // Inner class attribute can be zero, skip it. 5.71 + // Strange but true: JVM spec. allows null inner class refs. 5.72 + if (ioff == 0) continue; 5.73 + 5.74 + // only look at classes that are already loaded 5.75 + // since we are looking for the flags for our self. 5.76 + Symbol* inner_name = ik->constants()->klass_name_at(ioff); 5.77 + if ((ik->name() == inner_name)) { 5.78 + // This is really a member class. 5.79 + access = iter.inner_access_flags(); 5.80 + break; 5.81 } 5.82 } 5.83 // Remember to strip ACC_SUPER bit
6.1 --- a/src/share/vm/oops/instanceKlass.hpp Fri Mar 09 13:34:45 2012 -0800 6.2 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Mar 13 13:50:48 2012 -0400 6.3 @@ -188,7 +188,17 @@ 6.4 klassOop _host_klass; 6.5 // Class signers. 6.6 objArrayOop _signers; 6.7 - // inner_classes attribute. 6.8 + // The InnerClasses attribute and EnclosingMethod attribute. The 6.9 + // _inner_classes is an array of shorts. If the class has InnerClasses 6.10 + // attribute, then the _inner_classes array begins with 4-tuples of shorts 6.11 + // [inner_class_info_index, outer_class_info_index, 6.12 + // inner_name_index, inner_class_access_flags] for the InnerClasses 6.13 + // attribute. If the EnclosingMethod attribute exists, it occupies the 6.14 + // last two shorts [class_index, method_index] of the array. If only 6.15 + // the InnerClasses attribute exists, the _inner_classes array length is 6.16 + // number_of_inner_classes * 4. If the class has both InnerClasses 6.17 + // and EnclosingMethod attributes the _inner_classes array length is 6.18 + // number_of_inner_classes * 4 + enclosing_method_attribute_size. 6.19 typeArrayOop _inner_classes; 6.20 // Implementors of this interface (not valid if it overflows) 6.21 klassOop _implementors[implementors_limit]; 6.22 @@ -251,8 +261,6 @@ 6.23 // Array of interesting part(s) of the previous version(s) of this 6.24 // instanceKlass. See PreviousVersionWalker below. 6.25 GrowableArray<PreviousVersionNode *>* _previous_versions; 6.26 - u2 _enclosing_method_class_index; // Constant pool index for class of enclosing method, or 0 if none 6.27 - u2 _enclosing_method_method_index; // Constant pool index for name and type of enclosing method, or 0 if none 6.28 // JVMTI fields can be moved to their own structure - see 6315920 6.29 unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH 6.30 jint _cached_class_file_len; // JVMTI: length of above 6.31 @@ -351,6 +359,12 @@ 6.32 inner_class_next_offset = 4 6.33 }; 6.34 6.35 + enum EnclosingMethodAttributeOffset { 6.36 + enclosing_method_class_index_offset = 0, 6.37 + enclosing_method_method_index_offset = 1, 6.38 + enclosing_method_attribute_size = 2 6.39 + }; 6.40 + 6.41 // method override check 6.42 bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS); 6.43 6.44 @@ -533,11 +547,15 @@ 6.45 Symbol* generic_signature() const { return _generic_signature; } 6.46 void set_generic_signature(Symbol* sig) { _generic_signature = sig; } 6.47 6.48 - u2 enclosing_method_class_index() const { return _enclosing_method_class_index; } 6.49 - u2 enclosing_method_method_index() const { return _enclosing_method_method_index; } 6.50 + u2 enclosing_method_data(int offset); 6.51 + u2 enclosing_method_class_index() { 6.52 + return enclosing_method_data(enclosing_method_class_index_offset); 6.53 + } 6.54 + u2 enclosing_method_method_index() { 6.55 + return enclosing_method_data(enclosing_method_method_index_offset); 6.56 + } 6.57 void set_enclosing_method_indices(u2 class_index, 6.58 - u2 method_index) { _enclosing_method_class_index = class_index; 6.59 - _enclosing_method_method_index = method_index; } 6.60 + u2 method_index); 6.61 6.62 // jmethodID support 6.63 static jmethodID get_jmethod_id(instanceKlassHandle ik_h, 6.64 @@ -1053,4 +1071,83 @@ 6.65 nmethod* get_nmethod() { return _nmethod; } 6.66 }; 6.67 6.68 +// An iterator that's used to access the inner classes indices in the 6.69 +// instanceKlass::_inner_classes array. 6.70 +class InnerClassesIterator : public StackObj { 6.71 + private: 6.72 + typeArrayHandle _inner_classes; 6.73 + int _length; 6.74 + int _idx; 6.75 + public: 6.76 + 6.77 + InnerClassesIterator(instanceKlassHandle k) { 6.78 + _inner_classes = k->inner_classes(); 6.79 + if (k->inner_classes() != NULL) { 6.80 + _length = _inner_classes->length(); 6.81 + // The inner class array's length should be the multiple of 6.82 + // inner_class_next_offset if it only contains the InnerClasses 6.83 + // attribute data, or it should be 6.84 + // n*inner_class_next_offset+enclosing_method_attribute_size 6.85 + // if it also contains the EnclosingMethod data. 6.86 + assert((_length % instanceKlass::inner_class_next_offset == 0 || 6.87 + _length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size), 6.88 + "just checking"); 6.89 + // Remove the enclosing_method portion if exists. 6.90 + if (_length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size) { 6.91 + _length -= instanceKlass::enclosing_method_attribute_size; 6.92 + } 6.93 + } else { 6.94 + _length = 0; 6.95 + } 6.96 + _idx = 0; 6.97 + } 6.98 + 6.99 + int length() const { 6.100 + return _length; 6.101 + } 6.102 + 6.103 + void next() { 6.104 + _idx += instanceKlass::inner_class_next_offset; 6.105 + } 6.106 + 6.107 + bool done() const { 6.108 + return (_idx >= _length); 6.109 + } 6.110 + 6.111 + u2 inner_class_info_index() const { 6.112 + return _inner_classes->ushort_at( 6.113 + _idx + instanceKlass::inner_class_inner_class_info_offset); 6.114 + } 6.115 + 6.116 + void set_inner_class_info_index(u2 index) { 6.117 + _inner_classes->ushort_at_put( 6.118 + _idx + instanceKlass::inner_class_inner_class_info_offset, index); 6.119 + } 6.120 + 6.121 + u2 outer_class_info_index() const { 6.122 + return _inner_classes->ushort_at( 6.123 + _idx + instanceKlass::inner_class_outer_class_info_offset); 6.124 + } 6.125 + 6.126 + void set_outer_class_info_index(u2 index) { 6.127 + _inner_classes->ushort_at_put( 6.128 + _idx + instanceKlass::inner_class_outer_class_info_offset, index); 6.129 + } 6.130 + 6.131 + u2 inner_name_index() const { 6.132 + return _inner_classes->ushort_at( 6.133 + _idx + instanceKlass::inner_class_inner_name_offset); 6.134 + } 6.135 + 6.136 + void set_inner_name_index(u2 index) { 6.137 + _inner_classes->ushort_at_put( 6.138 + _idx + instanceKlass::inner_class_inner_name_offset, index); 6.139 + } 6.140 + 6.141 + u2 inner_access_flags() const { 6.142 + return _inner_classes->ushort_at( 6.143 + _idx + instanceKlass::inner_class_access_flags_offset); 6.144 + } 6.145 +}; 6.146 + 6.147 #endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP
7.1 --- a/src/share/vm/oops/instanceKlassKlass.cpp Fri Mar 09 13:34:45 2012 -0800 7.2 +++ b/src/share/vm/oops/instanceKlassKlass.cpp Tue Mar 13 13:50:48 2012 -0400 7.3 @@ -416,7 +416,6 @@ 7.4 ik->set_methods_annotations(NULL); 7.5 ik->set_methods_parameter_annotations(NULL); 7.6 ik->set_methods_default_annotations(NULL); 7.7 - ik->set_enclosing_method_indices(0, 0); 7.8 ik->set_jvmti_cached_class_field_map(NULL); 7.9 ik->set_initial_method_idnum(0); 7.10 assert(k()->is_parsable(), "should be parsable here.");
8.1 --- a/src/share/vm/prims/jvm.cpp Fri Mar 09 13:34:45 2012 -0800 8.2 +++ b/src/share/vm/prims/jvm.cpp Tue Mar 13 13:50:48 2012 -0400 8.3 @@ -1301,9 +1301,6 @@ 8.4 // Inner class reflection /////////////////////////////////////////////////////////////////////////////// 8.5 8.6 JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) 8.7 - const int inner_class_info_index = 0; 8.8 - const int outer_class_info_index = 1; 8.9 - 8.10 JvmtiVMObjectAllocEventCollector oam; 8.11 // ofClass is a reference to a java_lang_Class object. The mirror object 8.12 // of an instanceKlass 8.13 @@ -1315,26 +1312,26 @@ 8.14 } 8.15 8.16 instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass))); 8.17 - 8.18 - if (k->inner_classes()->length() == 0) { 8.19 + InnerClassesIterator iter(k); 8.20 + 8.21 + if (iter.length() == 0) { 8.22 // Neither an inner nor outer class 8.23 oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); 8.24 return (jobjectArray)JNIHandles::make_local(env, result); 8.25 } 8.26 8.27 // find inner class info 8.28 - typeArrayHandle icls(thread, k->inner_classes()); 8.29 constantPoolHandle cp(thread, k->constants()); 8.30 - int length = icls->length(); 8.31 + int length = iter.length(); 8.32 8.33 // Allocate temp. result array 8.34 objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL); 8.35 objArrayHandle result (THREAD, r); 8.36 int members = 0; 8.37 8.38 - for(int i = 0; i < length; i += 4) { 8.39 - int ioff = icls->ushort_at(i + inner_class_info_index); 8.40 - int ooff = icls->ushort_at(i + outer_class_info_index); 8.41 + for (; !iter.done(); iter.next()) { 8.42 + int ioff = iter.inner_class_info_index(); 8.43 + int ooff = iter.outer_class_info_index(); 8.44 8.45 if (ioff != 0 && ooff != 0) { 8.46 // Check to see if the name matches the class we're looking for 8.47 @@ -1392,17 +1389,13 @@ 8.48 bool* inner_is_member, 8.49 TRAPS) { 8.50 Thread* thread = THREAD; 8.51 - const int inner_class_info_index = inner_class_inner_class_info_offset; 8.52 - const int outer_class_info_index = inner_class_outer_class_info_offset; 8.53 - 8.54 - if (k->inner_classes()->length() == 0) { 8.55 + InnerClassesIterator iter(k); 8.56 + if (iter.length() == 0) { 8.57 // No inner class info => no declaring class 8.58 return NULL; 8.59 } 8.60 8.61 - typeArrayHandle i_icls(thread, k->inner_classes()); 8.62 constantPoolHandle i_cp(thread, k->constants()); 8.63 - int i_length = i_icls->length(); 8.64 8.65 bool found = false; 8.66 klassOop ok; 8.67 @@ -1410,10 +1403,10 @@ 8.68 *inner_is_member = false; 8.69 8.70 // Find inner_klass attribute 8.71 - for (int i = 0; i < i_length && !found; i += inner_class_next_offset) { 8.72 - int ioff = i_icls->ushort_at(i + inner_class_info_index); 8.73 - int ooff = i_icls->ushort_at(i + outer_class_info_index); 8.74 - int noff = i_icls->ushort_at(i + inner_class_inner_name_offset); 8.75 + for (; !iter.done() && !found; iter.next()) { 8.76 + int ioff = iter.inner_class_info_index(); 8.77 + int ooff = iter.outer_class_info_index(); 8.78 + int noff = iter.inner_name_index(); 8.79 if (ioff != 0) { 8.80 // Check to see if the name matches the class we're looking for 8.81 // before attempting to find the class.
9.1 --- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Fri Mar 09 13:34:45 2012 -0800 9.2 +++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Tue Mar 13 13:50:48 2012 -0400 9.3 @@ -292,8 +292,8 @@ 9.4 9.5 // Compute the number of entries in the InnerClasses attribute 9.6 u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() { 9.7 - typeArrayOop inner_class_list = ikh()->inner_classes(); 9.8 - return (inner_class_list == NULL) ? 0 : inner_class_list->length(); 9.9 + InnerClassesIterator iter(ikh()); 9.10 + return iter.length(); 9.11 } 9.12 9.13 // Write an annotation attribute. The VM stores them in raw form, so all we need 9.14 @@ -324,26 +324,20 @@ 9.15 // JVMSpec| } classes[number_of_classes]; 9.16 // JVMSpec| } 9.17 void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) { 9.18 - typeArrayOop inner_class_list = ikh()->inner_classes(); 9.19 - guarantee(inner_class_list != NULL && inner_class_list->length() == length, 9.20 + InnerClassesIterator iter(ikh()); 9.21 + guarantee(iter.length() != 0 && iter.length() == length, 9.22 "caller must check"); 9.23 - typeArrayHandle inner_class_list_h(thread(), inner_class_list); 9.24 - assert (length % instanceKlass::inner_class_next_offset == 0, "just checking"); 9.25 u2 entry_count = length / instanceKlass::inner_class_next_offset; 9.26 u4 size = 2 + entry_count * (2+2+2+2); 9.27 9.28 write_attribute_name_index("InnerClasses"); 9.29 write_u4(size); 9.30 write_u2(entry_count); 9.31 - for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) { 9.32 - write_u2(inner_class_list_h->ushort_at( 9.33 - i + instanceKlass::inner_class_inner_class_info_offset)); 9.34 - write_u2(inner_class_list_h->ushort_at( 9.35 - i + instanceKlass::inner_class_outer_class_info_offset)); 9.36 - write_u2(inner_class_list_h->ushort_at( 9.37 - i + instanceKlass::inner_class_inner_name_offset)); 9.38 - write_u2(inner_class_list_h->ushort_at( 9.39 - i + instanceKlass::inner_class_access_flags_offset)); 9.40 + for (; !iter.done(); iter.next()) { 9.41 + write_u2(iter.inner_class_info_index()); 9.42 + write_u2(iter.outer_class_info_index()); 9.43 + write_u2(iter.inner_name_index()); 9.44 + write_u2(iter.inner_access_flags()); 9.45 } 9.46 } 9.47
10.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Mar 09 13:34:45 2012 -0800 10.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 13 13:50:48 2012 -0400 10.3 @@ -2400,44 +2400,33 @@ 10.4 // new constant indices as needed. The inner classes info is a 10.5 // quadruple: 10.6 // (inner_class_info, outer_class_info, inner_name, inner_access_flags) 10.7 - typeArrayOop inner_class_list = scratch_class->inner_classes(); 10.8 - int icl_length = (inner_class_list == NULL) ? 0 : inner_class_list->length(); 10.9 - if (icl_length > 0) { 10.10 - typeArrayHandle inner_class_list_h(THREAD, inner_class_list); 10.11 - for (int i = 0; i < icl_length; 10.12 - i += instanceKlass::inner_class_next_offset) { 10.13 - int cur_index = inner_class_list_h->ushort_at(i 10.14 - + instanceKlass::inner_class_inner_class_info_offset); 10.15 - if (cur_index == 0) { 10.16 - continue; // JVM spec. allows null inner class refs so skip it 10.17 - } 10.18 - int new_index = find_new_index(cur_index); 10.19 - if (new_index != 0) { 10.20 - RC_TRACE_WITH_THREAD(0x00080000, THREAD, 10.21 - ("inner_class_info change: %d to %d", cur_index, new_index)); 10.22 - inner_class_list_h->ushort_at_put(i 10.23 - + instanceKlass::inner_class_inner_class_info_offset, new_index); 10.24 - } 10.25 - cur_index = inner_class_list_h->ushort_at(i 10.26 - + instanceKlass::inner_class_outer_class_info_offset); 10.27 - new_index = find_new_index(cur_index); 10.28 - if (new_index != 0) { 10.29 - RC_TRACE_WITH_THREAD(0x00080000, THREAD, 10.30 - ("outer_class_info change: %d to %d", cur_index, new_index)); 10.31 - inner_class_list_h->ushort_at_put(i 10.32 - + instanceKlass::inner_class_outer_class_info_offset, new_index); 10.33 - } 10.34 - cur_index = inner_class_list_h->ushort_at(i 10.35 - + instanceKlass::inner_class_inner_name_offset); 10.36 - new_index = find_new_index(cur_index); 10.37 - if (new_index != 0) { 10.38 - RC_TRACE_WITH_THREAD(0x00080000, THREAD, 10.39 - ("inner_name change: %d to %d", cur_index, new_index)); 10.40 - inner_class_list_h->ushort_at_put(i 10.41 - + instanceKlass::inner_class_inner_name_offset, new_index); 10.42 - } 10.43 - } // end for each inner class 10.44 - } // end if we have inner classes 10.45 + InnerClassesIterator iter(scratch_class); 10.46 + for (; !iter.done(); iter.next()) { 10.47 + int cur_index = iter.inner_class_info_index(); 10.48 + if (cur_index == 0) { 10.49 + continue; // JVM spec. allows null inner class refs so skip it 10.50 + } 10.51 + int new_index = find_new_index(cur_index); 10.52 + if (new_index != 0) { 10.53 + RC_TRACE_WITH_THREAD(0x00080000, THREAD, 10.54 + ("inner_class_info change: %d to %d", cur_index, new_index)); 10.55 + iter.set_inner_class_info_index(new_index); 10.56 + } 10.57 + cur_index = iter.outer_class_info_index(); 10.58 + new_index = find_new_index(cur_index); 10.59 + if (new_index != 0) { 10.60 + RC_TRACE_WITH_THREAD(0x00080000, THREAD, 10.61 + ("outer_class_info change: %d to %d", cur_index, new_index)); 10.62 + iter.set_outer_class_info_index(new_index); 10.63 + } 10.64 + cur_index = iter.inner_name_index(); 10.65 + new_index = find_new_index(cur_index); 10.66 + if (new_index != 0) { 10.67 + RC_TRACE_WITH_THREAD(0x00080000, THREAD, 10.68 + ("inner_name change: %d to %d", cur_index, new_index)); 10.69 + iter.set_inner_name_index(new_index); 10.70 + } 10.71 + } // end for each inner class 10.72 10.73 // Attach each method in klass to the new constant pool and update 10.74 // to use new constant pool indices as needed:
11.1 --- a/src/share/vm/runtime/reflection.cpp Fri Mar 09 13:34:45 2012 -0800 11.2 +++ b/src/share/vm/runtime/reflection.cpp Tue Mar 13 13:50:48 2012 -0400 11.3 @@ -591,14 +591,11 @@ 11.4 // Caller is responsible for figuring out in advance which case must be true. 11.5 void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner, 11.6 bool inner_is_member, TRAPS) { 11.7 - const int inner_class_info_index = 0; 11.8 - const int outer_class_info_index = 1; 11.9 - 11.10 - typeArrayHandle icls (THREAD, outer->inner_classes()); 11.11 + InnerClassesIterator iter(outer); 11.12 constantPoolHandle cp (THREAD, outer->constants()); 11.13 - for(int i = 0; i < icls->length(); i += 4) { 11.14 - int ioff = icls->ushort_at(i + inner_class_info_index); 11.15 - int ooff = icls->ushort_at(i + outer_class_info_index); 11.16 + for (; !iter.done(); iter.next()) { 11.17 + int ioff = iter.inner_class_info_index(); 11.18 + int ooff = iter.outer_class_info_index(); 11.19 11.20 if (inner_is_member && ioff != 0 && ooff != 0) { 11.21 klassOop o = cp->klass_at(ooff, CHECK);