7109878: The instanceKlass EnclosingMethhod attribute fields can be folded into the _inner_class field.

Tue, 13 Mar 2012 13:50:48 -0400

author
jiangli
date
Tue, 13 Mar 2012 13:50:48 -0400
changeset 3670
f7c4174b33ba
parent 3636
fde683df4c27
child 3671
21b94feb697c

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>

agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java file | annotate | diff | comparison | revisions
src/share/vm/classfile/classFileParser.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/classFileParser.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/dump.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlassKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvm.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiClassFileReconstituter.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiRedefineClasses.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/reflection.cpp file | annotate | diff | comparison | revisions
     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);

mercurial