hotspot/src/share/vm/classfile/classFileParser.cpp
changeset 12772 d317e5e08194
parent 12587 8f819769ca1b
child 13282 9872915dd78d
child 13195 be27e1b6a4b9
child 13291 9de3b1387cb8
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Fri May 18 14:57:28 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Mon May 21 14:10:35 2012 -0400
@@ -1082,12 +1082,36 @@
 
   int num_injected = 0;
   InjectedField* injected = JavaClasses::get_injected(class_name, &num_injected);
-
-  // Tuples of shorts [access, name index, sig index, initial value index, byte offset, generic signature index]
-  typeArrayOop new_fields = oopFactory::new_permanent_shortArray((length + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle));
-  typeArrayHandle fields(THREAD, new_fields);
+  int total_fields = length + num_injected;
+
+  // The field array starts with tuples of shorts
+  // [access, name index, sig index, initial value index, byte offset].
+  // A generic signature slot only exists for field with generic
+  // signature attribute. And the access flag is set with
+  // JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic
+  // signature slots are at the end of the field array and after all
+  // other fields data.
+  //
+  //   f1: [access, name index, sig index, initial value index, low_offset, high_offset]
+  //   f2: [access, name index, sig index, initial value index, low_offset, high_offset]
+  //       ...
+  //   fn: [access, name index, sig index, initial value index, low_offset, high_offset]
+  //       [generic signature index]
+  //       [generic signature index]
+  //       ...
+  //
+  // Allocate a temporary resource array for field data. For each field,
+  // a slot is reserved in the temporary array for the generic signature
+  // index. After parsing all fields, the data are copied to a permanent
+  // array and any unused slots will be discarded.
+  ResourceMark rm(THREAD);
+  u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD(
+             THREAD, u2, total_fields * (FieldInfo::field_slots + 1));
 
   typeArrayHandle field_annotations;
+  // The generic signature slots start after all other fields' data.
+  int generic_signature_slot = total_fields * FieldInfo::field_slots;
+  int num_generic_signature = 0;
   for (int n = 0; n < length; n++) {
     cfs->guarantee_more(8, CHECK_(nullHandle));  // access_flags, name_index, descriptor_index, attributes_count
 
@@ -1135,14 +1159,19 @@
       if (is_synthetic) {
         access_flags.set_is_synthetic();
       }
+      if (generic_signature_index != 0) {
+        access_flags.set_field_has_generic_signature();
+        fa[generic_signature_slot] = generic_signature_index;
+        generic_signature_slot ++;
+        num_generic_signature ++;
+      }
     }
 
-    FieldInfo* field = FieldInfo::from_field_array(fields(), n);
+    FieldInfo* field = FieldInfo::from_field_array(fa, n);
     field->initialize(access_flags.as_short(),
                       name_index,
                       signature_index,
                       constantvalue_index,
-                      generic_signature_index,
                       0);
 
     BasicType type = cp->basic_type_for_signature_at(signature_index);
@@ -1155,8 +1184,8 @@
     field->set_offset(atype);
   }
 
+  int index = length;
   if (num_injected != 0) {
-    int index = length;
     for (int n = 0; n < num_injected; n++) {
       // Check for duplicates
       if (injected[n].may_be_java) {
@@ -1164,7 +1193,7 @@
         Symbol* signature = injected[n].signature();
         bool duplicate = false;
         for (int i = 0; i < length; i++) {
-          FieldInfo* f = FieldInfo::from_field_array(fields(), i);
+          FieldInfo* f = FieldInfo::from_field_array(fa, i);
           if (name      == cp->symbol_at(f->name_index()) &&
               signature == cp->symbol_at(f->signature_index())) {
             // Symbol is desclared in Java so skip this one
@@ -1179,12 +1208,11 @@
       }
 
       // Injected field
-      FieldInfo* field = FieldInfo::from_field_array(fields(), index);
+      FieldInfo* field = FieldInfo::from_field_array(fa, index);
       field->initialize(JVM_ACC_FIELD_INTERNAL,
                         injected[n].name_index,
                         injected[n].signature_index,
                         0,
-                        0,
                         0);
 
       BasicType type = FieldType::basic_type(injected[n].signature());
@@ -1197,17 +1225,27 @@
       field->set_offset(atype);
       index++;
     }
-
-    if (index < length + num_injected) {
-      // sometimes injected fields already exist in the Java source so
-      // the fields array could be too long.  In that case trim the
-      // fields array.
-      new_fields = oopFactory::new_permanent_shortArray(index * FieldInfo::field_slots, CHECK_(nullHandle));
-      for (int i = 0; i < index * FieldInfo::field_slots; i++) {
-        new_fields->short_at_put(i, fields->short_at(i));
-      }
-      fields = new_fields;
+  }
+
+  // Now copy the fields' data from the temporary resource array.
+  // Sometimes injected fields already exist in the Java source so
+  // the fields array could be too long.  In that case the
+  // fields array is trimed. Also unused slots that were reserved
+  // for generic signature indexes are discarded.
+  typeArrayOop new_fields = oopFactory::new_permanent_shortArray(
+    index * FieldInfo::field_slots + num_generic_signature,
+    CHECK_(nullHandle));
+  typeArrayHandle fields(THREAD, new_fields);
+  {
+    int i = 0;
+    for (; i < index * FieldInfo::field_slots; i++) {
+      new_fields->short_at_put(i, fa[i]);
     }
+    for (int j = total_fields * FieldInfo::field_slots;
+         j < generic_signature_slot; j++) {
+      new_fields->short_at_put(i++, fa[j]);
+    }
+    assert(i == new_fields->length(), "");
   }
 
   if (_need_verify && length > 1) {