diff src/share/vm/classfile/classFileParser.cpp @ 3938:e6b1331a51d2

7086585: make Java field injection more flexible Reviewed-by: jrose, twisti, kvn, coleenp
author never
date Sat, 10 Sep 2011 17:29:02 -0700
parents 498c6cf70f7e
children 4ceaf61479fc cd5d8cafcc84
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp	Sat Sep 10 00:11:04 2011 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Sat Sep 10 17:29:02 2011 -0700
@@ -36,6 +36,7 @@
 #include "memory/oopFactory.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/constantPoolOop.hpp"
+#include "oops/fieldStreams.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceMirrorKlass.hpp"
 #include "oops/klass.inline.hpp"
@@ -991,42 +992,98 @@
   STATIC_BYTE,          // Boolean, Byte, char
   STATIC_SHORT,         // shorts
   STATIC_WORD,          // ints
-  STATIC_DOUBLE,        // long or double
-  STATIC_ALIGNED_DOUBLE,// aligned long or double
+  STATIC_DOUBLE,        // aligned long or double
   NONSTATIC_OOP,
   NONSTATIC_BYTE,
   NONSTATIC_SHORT,
   NONSTATIC_WORD,
   NONSTATIC_DOUBLE,
-  NONSTATIC_ALIGNED_DOUBLE
+  MAX_FIELD_ALLOCATION_TYPE,
+  BAD_ALLOCATION_TYPE = -1
 };
 
-
-struct FieldAllocationCount {
-  unsigned int static_oop_count;
-  unsigned int static_byte_count;
-  unsigned int static_short_count;
-  unsigned int static_word_count;
-  unsigned int static_double_count;
-  unsigned int nonstatic_oop_count;
-  unsigned int nonstatic_byte_count;
-  unsigned int nonstatic_short_count;
-  unsigned int nonstatic_word_count;
-  unsigned int nonstatic_double_count;
+static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {
+  BAD_ALLOCATION_TYPE, // 0
+  BAD_ALLOCATION_TYPE, // 1
+  BAD_ALLOCATION_TYPE, // 2
+  BAD_ALLOCATION_TYPE, // 3
+  NONSTATIC_BYTE ,     // T_BOOLEAN  =  4,
+  NONSTATIC_SHORT,     // T_CHAR     =  5,
+  NONSTATIC_WORD,      // T_FLOAT    =  6,
+  NONSTATIC_DOUBLE,    // T_DOUBLE   =  7,
+  NONSTATIC_BYTE,      // T_BYTE     =  8,
+  NONSTATIC_SHORT,     // T_SHORT    =  9,
+  NONSTATIC_WORD,      // T_INT      = 10,
+  NONSTATIC_DOUBLE,    // T_LONG     = 11,
+  NONSTATIC_OOP,       // T_OBJECT   = 12,
+  NONSTATIC_OOP,       // T_ARRAY    = 13,
+  BAD_ALLOCATION_TYPE, // T_VOID     = 14,
+  BAD_ALLOCATION_TYPE, // T_ADDRESS  = 15,
+  BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16,
+  BAD_ALLOCATION_TYPE, // T_CONFLICT = 17,
+  BAD_ALLOCATION_TYPE, // 0
+  BAD_ALLOCATION_TYPE, // 1
+  BAD_ALLOCATION_TYPE, // 2
+  BAD_ALLOCATION_TYPE, // 3
+  STATIC_BYTE ,        // T_BOOLEAN  =  4,
+  STATIC_SHORT,        // T_CHAR     =  5,
+  STATIC_WORD,          // T_FLOAT    =  6,
+  STATIC_DOUBLE,       // T_DOUBLE   =  7,
+  STATIC_BYTE,         // T_BYTE     =  8,
+  STATIC_SHORT,        // T_SHORT    =  9,
+  STATIC_WORD,         // T_INT      = 10,
+  STATIC_DOUBLE,       // T_LONG     = 11,
+  STATIC_OOP,          // T_OBJECT   = 12,
+  STATIC_OOP,          // T_ARRAY    = 13,
+  BAD_ALLOCATION_TYPE, // T_VOID     = 14,
+  BAD_ALLOCATION_TYPE, // T_ADDRESS  = 15,
+  BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16,
+  BAD_ALLOCATION_TYPE, // T_CONFLICT = 17,
 };
 
-typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface,
-                                              struct FieldAllocationCount *fac,
-                                              objArrayHandle* fields_annotations, TRAPS) {
+static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) {
+  assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values");
+  FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)];
+  assert(result != BAD_ALLOCATION_TYPE, "bad type");
+  return result;
+}
+
+class FieldAllocationCount: public ResourceObj {
+ public:
+  unsigned int count[MAX_FIELD_ALLOCATION_TYPE];
+
+  FieldAllocationCount() {
+    for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) {
+      count[i] = 0;
+    }
+  }
+
+  FieldAllocationType update(bool is_static, BasicType type) {
+    FieldAllocationType atype = basic_type_to_atype(is_static, type);
+    count[atype]++;
+    return atype;
+  }
+};
+
+
+typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
+                                              constantPoolHandle cp, bool is_interface,
+                                              FieldAllocationCount *fac,
+                                              objArrayHandle* fields_annotations,
+                                              int* java_fields_count_ptr, TRAPS) {
   ClassFileStream* cfs = stream();
   typeArrayHandle nullHandle;
   cfs->guarantee_more(2, CHECK_(nullHandle));  // length
   u2 length = cfs->get_u2_fast();
+  *java_fields_count_ptr = length;
+
+  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*instanceKlass::next_offset, CHECK_(nullHandle));
+  typeArrayOop new_fields = oopFactory::new_permanent_shortArray((length + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle));
   typeArrayHandle fields(THREAD, new_fields);
 
-  int index = 0;
   typeArrayHandle field_annotations;
   for (int n = 0; n < length; n++) {
     cfs->guarantee_more(8, CHECK_(nullHandle));  // access_flags, name_index, descriptor_index, attributes_count
@@ -1077,93 +1134,77 @@
       }
     }
 
-    fields->short_at_put(index++, access_flags.as_short());
-    fields->short_at_put(index++, name_index);
-    fields->short_at_put(index++, signature_index);
-    fields->short_at_put(index++, constantvalue_index);
+    FieldInfo* field = FieldInfo::from_field_array(fields(), 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);
 
     // Remember how many oops we encountered and compute allocation type
-    BasicType type = cp->basic_type_for_signature_at(signature_index);
-    FieldAllocationType atype;
-    if ( is_static ) {
-      switch ( type ) {
-        case  T_BOOLEAN:
-        case  T_BYTE:
-          fac->static_byte_count++;
-          atype = STATIC_BYTE;
-          break;
-        case  T_LONG:
-        case  T_DOUBLE:
-          if (Universe::field_type_should_be_aligned(type)) {
-            atype = STATIC_ALIGNED_DOUBLE;
-          } else {
-            atype = STATIC_DOUBLE;
-          }
-          fac->static_double_count++;
-          break;
-        case  T_CHAR:
-        case  T_SHORT:
-          fac->static_short_count++;
-          atype = STATIC_SHORT;
-          break;
-        case  T_FLOAT:
-        case  T_INT:
-          fac->static_word_count++;
-          atype = STATIC_WORD;
-          break;
-        case  T_ARRAY:
-        case  T_OBJECT:
-          fac->static_oop_count++;
-          atype = STATIC_OOP;
-          break;
-        case  T_ADDRESS:
-        case  T_VOID:
-        default:
-          assert(0, "bad field type");
-      }
-    } else {
-      switch ( type ) {
-        case  T_BOOLEAN:
-        case  T_BYTE:
-          fac->nonstatic_byte_count++;
-          atype = NONSTATIC_BYTE;
-          break;
-        case  T_LONG:
-        case  T_DOUBLE:
-          if (Universe::field_type_should_be_aligned(type)) {
-            atype = NONSTATIC_ALIGNED_DOUBLE;
-          } else {
-            atype = NONSTATIC_DOUBLE;
-          }
-          fac->nonstatic_double_count++;
-          break;
-        case  T_CHAR:
-        case  T_SHORT:
-          fac->nonstatic_short_count++;
-          atype = NONSTATIC_SHORT;
-          break;
-        case  T_FLOAT:
-        case  T_INT:
-          fac->nonstatic_word_count++;
-          atype = NONSTATIC_WORD;
-          break;
-        case  T_ARRAY:
-        case  T_OBJECT:
-          fac->nonstatic_oop_count++;
-          atype = NONSTATIC_OOP;
-          break;
-        case  T_ADDRESS:
-        case  T_VOID:
-        default:
-          assert(0, "bad field type");
-      }
-    }
+    FieldAllocationType atype = fac->update(is_static, type);
 
     // The correct offset is computed later (all oop fields will be located together)
     // We temporarily store the allocation type in the offset field
-    fields->short_at_put(index++, atype);
-    fields->short_at_put(index++, 0);  // Clear out high word of byte offset
-    fields->short_at_put(index++, generic_signature_index);
+    field->set_offset(atype);
+  }
+
+  if (num_injected != 0) {
+    int index = length;
+    for (int n = 0; n < num_injected; n++) {
+      // Check for duplicates
+      if (injected[n].may_be_java) {
+        Symbol* name      = injected[n].name();
+        Symbol* signature = injected[n].signature();
+        bool duplicate = false;
+        for (int i = 0; i < length; i++) {
+          FieldInfo* f = FieldInfo::from_field_array(fields(), 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
+            duplicate = true;
+            break;
+          }
+        }
+        if (duplicate) {
+          // These will be removed from the field array at the end
+          continue;
+        }
+      }
+
+      // Injected field
+      FieldInfo* field = FieldInfo::from_field_array(fields(), 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());
+
+      // Remember how many oops we encountered and compute allocation type
+      FieldAllocationType atype = fac->update(false, type);
+
+      // The correct offset is computed later (all oop fields will be located together)
+      // We temporarily store the allocation type in the offset field
+      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;
+    }
   }
 
   if (_need_verify && length > 1) {
@@ -1175,11 +1216,9 @@
     bool dup = false;
     {
       debug_only(No_Safepoint_Verifier nsv;)
-      for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) {
-        int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
-        Symbol* name = cp->symbol_at(name_index);
-        int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset);
-        Symbol* sig = cp->symbol_at(sig_index);
+      for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
+        Symbol* name = fs.name();
+        Symbol* sig = fs.signature();
         // If no duplicates, add name/signature in hashtable names_and_sigs.
         if (!put_after_lookup(name, sig, names_and_sigs)) {
           dup = true;
@@ -2592,227 +2631,6 @@
 }
 
 
-void ClassFileParser::java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr,
-  constantPoolHandle cp, FieldAllocationCount *fac_ptr, TRAPS) {
-  // This code is for compatibility with earlier jdk's that do not
-  // have the "discovered" field in java.lang.ref.Reference.  For 1.5
-  // the check for the "discovered" field should issue a warning if
-  // the field is not found.  For 1.6 this code should be issue a
-  // fatal error if the "discovered" field is not found.
-  //
-  // Increment fac.nonstatic_oop_count so that the start of the
-  // next type of non-static oops leaves room for the fake oop.
-  // Do not increment next_nonstatic_oop_offset so that the
-  // fake oop is place after the java.lang.ref.Reference oop
-  // fields.
-  //
-  // Check the fields in java.lang.ref.Reference for the "discovered"
-  // field.  If it is not present, artifically create a field for it.
-  // This allows this VM to run on early JDK where the field is not
-  // present.
-  int reference_sig_index = 0;
-  int reference_name_index = 0;
-  int reference_index = 0;
-  int extra = java_lang_ref_Reference::number_of_fake_oop_fields;
-  const int n = (*fields_ptr)()->length();
-  for (int i = 0; i < n; i += instanceKlass::next_offset ) {
-    int name_index =
-    (*fields_ptr)()->ushort_at(i + instanceKlass::name_index_offset);
-    int sig_index  =
-      (*fields_ptr)()->ushort_at(i + instanceKlass::signature_index_offset);
-    Symbol* f_name = cp->symbol_at(name_index);
-    Symbol* f_sig  = cp->symbol_at(sig_index);
-    if (f_sig == vmSymbols::reference_signature() && reference_index == 0) {
-      // Save the index for reference signature for later use.
-      // The fake discovered field does not entries in the
-      // constant pool so the index for its signature cannot
-      // be extracted from the constant pool.  It will need
-      // later, however.  It's signature is vmSymbols::reference_signature()
-      // so same an index for that signature.
-      reference_sig_index = sig_index;
-      reference_name_index = name_index;
-      reference_index = i;
-    }
-    if (f_name == vmSymbols::reference_discovered_name() &&
-      f_sig == vmSymbols::reference_signature()) {
-      // The values below are fake but will force extra
-      // non-static oop fields and a corresponding non-static
-      // oop map block to be allocated.
-      extra = 0;
-      break;
-    }
-  }
-  if (extra != 0) {
-    fac_ptr->nonstatic_oop_count += extra;
-    // Add the additional entry to "fields" so that the klass
-    // contains the "discoverd" field and the field will be initialized
-    // in instances of the object.
-    int fields_with_fix_length = (*fields_ptr)()->length() +
-      instanceKlass::next_offset;
-    typeArrayOop ff = oopFactory::new_permanent_shortArray(
-                                                fields_with_fix_length, CHECK);
-    typeArrayHandle fields_with_fix(THREAD, ff);
-
-    // Take everything from the original but the length.
-    for (int idx = 0; idx < (*fields_ptr)->length(); idx++) {
-      fields_with_fix->ushort_at_put(idx, (*fields_ptr)->ushort_at(idx));
-    }
-
-    // Add the fake field at the end.
-    int i = (*fields_ptr)->length();
-    // There is no name index for the fake "discovered" field nor
-    // signature but a signature is needed so that the field will
-    // be properly initialized.  Use one found for
-    // one of the other reference fields. Be sure the index for the
-    // name is 0.  In fieldDescriptor::initialize() the index of the
-    // name is checked.  That check is by passed for the last nonstatic
-    // oop field in a java.lang.ref.Reference which is assumed to be
-    // this artificial "discovered" field.  An assertion checks that
-    // the name index is 0.
-    assert(reference_index != 0, "Missing signature for reference");
-
-    int j;
-    for (j = 0; j < instanceKlass::next_offset; j++) {
-      fields_with_fix->ushort_at_put(i + j,
-        (*fields_ptr)->ushort_at(reference_index +j));
-    }
-    // Clear the public access flag and set the private access flag.
-    short flags;
-    flags =
-      fields_with_fix->ushort_at(i + instanceKlass::access_flags_offset);
-    assert(!(flags & JVM_RECOGNIZED_FIELD_MODIFIERS), "Unexpected access flags set");
-    flags = flags & (~JVM_ACC_PUBLIC);
-    flags = flags | JVM_ACC_PRIVATE;
-    AccessFlags access_flags;
-    access_flags.set_flags(flags);
-    assert(!access_flags.is_public(), "Failed to clear public flag");
-    assert(access_flags.is_private(), "Failed to set private flag");
-    fields_with_fix->ushort_at_put(i + instanceKlass::access_flags_offset,
-      flags);
-
-    assert(fields_with_fix->ushort_at(i + instanceKlass::name_index_offset)
-      == reference_name_index, "The fake reference name is incorrect");
-    assert(fields_with_fix->ushort_at(i + instanceKlass::signature_index_offset)
-      == reference_sig_index, "The fake reference signature is incorrect");
-    // The type of the field is stored in the low_offset entry during
-    // parsing.
-    assert(fields_with_fix->ushort_at(i + instanceKlass::low_offset) ==
-      NONSTATIC_OOP, "The fake reference type is incorrect");
-
-    // "fields" is allocated in the permanent generation.  Disgard
-    // it and let it be collected.
-    (*fields_ptr) = fields_with_fix;
-  }
-  return;
-}
-
-
-void ClassFileParser::java_lang_Class_fix_pre(int* nonstatic_field_size,
-                                              FieldAllocationCount *fac_ptr) {
-  // Add fake fields for java.lang.Class instances
-  //
-  // This is not particularly nice. We should consider adding a
-  // private transient object field at the Java level to
-  // java.lang.Class. Alternatively we could add a subclass of
-  // instanceKlass which provides an accessor and size computer for
-  // this field, but that appears to be more code than this hack.
-  //
-  // NOTE that we wedge these in at the beginning rather than the
-  // end of the object because the Class layout changed between JDK
-  // 1.3 and JDK 1.4 with the new reflection implementation; some
-  // nonstatic oop fields were added at the Java level. The offsets
-  // of these fake fields can't change between these two JDK
-  // versions because when the offsets are computed at bootstrap
-  // time we don't know yet which version of the JDK we're running in.
-
-  // The values below are fake but will force three non-static oop fields and
-  // a corresponding non-static oop map block to be allocated.
-  const int extra = java_lang_Class::number_of_fake_oop_fields;
-  fac_ptr->nonstatic_oop_count += extra;
-
-  // Reserve some leading space for fake ints
-  *nonstatic_field_size += align_size_up(java_lang_Class::hc_number_of_fake_int_fields * BytesPerInt, heapOopSize) / heapOopSize;
-}
-
-
-void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_ptr) {
-  // Cause the extra fake fields in java.lang.Class to show up before
-  // the Java fields for layout compatibility between 1.3 and 1.4
-  // Incrementing next_nonstatic_oop_offset here advances the
-  // location where the real java fields are placed.
-  const int extra = java_lang_Class::number_of_fake_oop_fields;
-  (*next_nonstatic_oop_offset_ptr) += (extra * heapOopSize);
-}
-
-
-// Force MethodHandle.vmentry to be an unmanaged pointer.
-// There is no way for a classfile to express this, so we must help it.
-void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp,
-                                                    typeArrayHandle fields,
-                                                    FieldAllocationCount *fac_ptr,
-                                                    TRAPS) {
-  // Add fake fields for java.lang.invoke.MethodHandle instances
-  //
-  // This is not particularly nice, but since there is no way to express
-  // a native wordSize field in Java, we must do it at this level.
-
-  if (!EnableInvokeDynamic)  return;
-
-  int word_sig_index = 0;
-  const int cp_size = cp->length();
-  for (int index = 1; index < cp_size; index++) {
-    if (cp->tag_at(index).is_utf8() &&
-        cp->symbol_at(index) == vmSymbols::machine_word_signature()) {
-      word_sig_index = index;
-      break;
-    }
-  }
-
-  if (word_sig_index == 0)
-    THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
-              "missing I or J signature (for vmentry) in java.lang.invoke.MethodHandle");
-
-  // Find vmentry field and change the signature.
-  bool found_vmentry = false;
-  for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) {
-    int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
-    int sig_index  = fields->ushort_at(i + instanceKlass::signature_index_offset);
-    int acc_flags  = fields->ushort_at(i + instanceKlass::access_flags_offset);
-    Symbol* f_name = cp->symbol_at(name_index);
-    Symbol* f_sig  = cp->symbol_at(sig_index);
-    if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) {
-      if (f_sig == vmSymbols::machine_word_signature()) {
-        // If the signature of vmentry is already changed, we're done.
-        found_vmentry = true;
-        break;
-      }
-      else if (f_sig == vmSymbols::byte_signature()) {
-        // Adjust the field type from byte to an unmanaged pointer.
-        assert(fac_ptr->nonstatic_byte_count > 0, "");
-        fac_ptr->nonstatic_byte_count -= 1;
-
-        fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index);
-        assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64");
-        if (wordSize == longSize)  fac_ptr->nonstatic_double_count += 1;
-        else                       fac_ptr->nonstatic_word_count   += 1;
-
-        FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
-        assert(atype == NONSTATIC_BYTE, "");
-        FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD;
-        fields->ushort_at_put(i + instanceKlass::low_offset, new_atype);
-
-        found_vmentry = true;
-        break;
-      }
-    }
-  }
-
-  if (!found_vmentry)
-    THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
-              "missing vmentry byte field in java.lang.invoke.MethodHandle");
-}
-
-
 instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
                                                     Handle class_loader,
                                                     Handle protection_domain,
@@ -3025,10 +2843,13 @@
       local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle));
     }
 
+    int java_fields_count = 0;
     // Fields (offsets are filled in later)
-    struct FieldAllocationCount fac = {0,0,0,0,0,0,0,0,0,0};
+    FieldAllocationCount fac;
     objArrayHandle fields_annotations;
-    typeArrayHandle fields = parse_fields(cp, access_flags.is_interface(), &fac, &fields_annotations, CHECK_(nullHandle));
+    typeArrayHandle fields = parse_fields(class_name, cp, access_flags.is_interface(), &fac, &fields_annotations,
+                                          &java_fields_count,
+                                          CHECK_(nullHandle));
     // Methods
     bool has_final_method = false;
     AccessFlags promoted_flags;
@@ -3146,51 +2967,33 @@
     // Calculate the starting byte offsets
     next_static_oop_offset      = instanceMirrorKlass::offset_of_static_fields();
     next_static_double_offset   = next_static_oop_offset +
-                                  (fac.static_oop_count * heapOopSize);
-    if ( fac.static_double_count &&
+                                  (fac.count[STATIC_OOP] * heapOopSize);
+    if ( fac.count[STATIC_DOUBLE] &&
          (Universe::field_type_should_be_aligned(T_DOUBLE) ||
           Universe::field_type_should_be_aligned(T_LONG)) ) {
       next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
     }
 
     next_static_word_offset     = next_static_double_offset +
-                                  (fac.static_double_count * BytesPerLong);
+                                  (fac.count[STATIC_DOUBLE] * BytesPerLong);
     next_static_short_offset    = next_static_word_offset +
-                                  (fac.static_word_count * BytesPerInt);
+                                  (fac.count[STATIC_WORD] * BytesPerInt);
     next_static_byte_offset     = next_static_short_offset +
-                                  (fac.static_short_count * BytesPerShort);
+                                  (fac.count[STATIC_SHORT] * BytesPerShort);
     next_static_type_offset     = align_size_up((next_static_byte_offset +
-                                  fac.static_byte_count ), wordSize );
+                                  fac.count[STATIC_BYTE] ), wordSize );
     static_field_size           = (next_static_type_offset -
                                   next_static_oop_offset) / wordSize;
 
-    // Add fake fields for java.lang.Class instances (also see below)
-    if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) {
-      java_lang_Class_fix_pre(&nonstatic_field_size, &fac);
-    }
-
     first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
                                    nonstatic_field_size * heapOopSize;
     next_nonstatic_field_offset = first_nonstatic_field_offset;
 
-    // adjust the vmentry field declaration in java.lang.invoke.MethodHandle
-    if (EnableInvokeDynamic && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) {
-      java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
-    }
-
-    // Add a fake "discovered" field if it is not present
-    // for compatibility with earlier jdk's.
-    if (class_name == vmSymbols::java_lang_ref_Reference()
-      && class_loader.is_null()) {
-      java_lang_ref_Reference_fix_pre(&fields, cp, &fac, CHECK_(nullHandle));
-    }
-    // end of "discovered" field compactibility fix
-
-    unsigned int nonstatic_double_count = fac.nonstatic_double_count;
-    unsigned int nonstatic_word_count   = fac.nonstatic_word_count;
-    unsigned int nonstatic_short_count  = fac.nonstatic_short_count;
-    unsigned int nonstatic_byte_count   = fac.nonstatic_byte_count;
-    unsigned int nonstatic_oop_count    = fac.nonstatic_oop_count;
+    unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE];
+    unsigned int nonstatic_word_count   = fac.count[NONSTATIC_WORD];
+    unsigned int nonstatic_short_count  = fac.count[NONSTATIC_SHORT];
+    unsigned int nonstatic_byte_count   = fac.count[NONSTATIC_BYTE];
+    unsigned int nonstatic_oop_count    = fac.count[NONSTATIC_OOP];
 
     bool super_has_nonstatic_fields =
             (super_klass() != NULL && super_klass->has_nonstatic_fields());
@@ -3210,20 +3013,7 @@
     nonstatic_oop_counts  = NEW_RESOURCE_ARRAY_IN_THREAD(
               THREAD, unsigned int, nonstatic_oop_count + 1);
 
-    // Add fake fields for java.lang.Class instances (also see above).
-    // FieldsAllocationStyle and CompactFields values will be reset to default.
-    if(class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) {
-      java_lang_Class_fix_post(&next_nonstatic_field_offset);
-      nonstatic_oop_offsets[0] = first_nonstatic_field_offset;
-      const uint fake_oop_count = (next_nonstatic_field_offset -
-                                   first_nonstatic_field_offset) / heapOopSize;
-      nonstatic_oop_counts[0] = fake_oop_count;
-      nonstatic_oop_map_count = 1;
-      nonstatic_oop_count -= fake_oop_count;
-      first_nonstatic_oop_offset = first_nonstatic_field_offset;
-    } else {
-      first_nonstatic_oop_offset = 0; // will be set for first oop field
-    }
+    first_nonstatic_oop_offset = 0; // will be set for first oop field
 
 #ifndef PRODUCT
     if( PrintCompactFieldsSavings ) {
@@ -3378,10 +3168,9 @@
     // Iterate over fields again and compute correct offsets.
     // The field allocation type was temporarily stored in the offset slot.
     // oop fields are located before non-oop fields (static and non-static).
-    int len = fields->length();
-    for (int i = 0; i < len; i += instanceKlass::next_offset) {
+    for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) {
       int real_offset;
-      FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
+      FieldAllocationType atype = (FieldAllocationType) fs.offset();
       switch (atype) {
         case STATIC_OOP:
           real_offset = next_static_oop_offset;
@@ -3399,7 +3188,6 @@
           real_offset = next_static_word_offset;
           next_static_word_offset += BytesPerInt;
           break;
-        case STATIC_ALIGNED_DOUBLE:
         case STATIC_DOUBLE:
           real_offset = next_static_double_offset;
           next_static_double_offset += BytesPerLong;
@@ -3461,7 +3249,6 @@
             next_nonstatic_word_offset += BytesPerInt;
           }
           break;
-        case NONSTATIC_ALIGNED_DOUBLE:
         case NONSTATIC_DOUBLE:
           real_offset = next_nonstatic_double_offset;
           next_nonstatic_double_offset += BytesPerLong;
@@ -3469,8 +3256,7 @@
         default:
           ShouldNotReachHere();
       }
-      fields->short_at_put(i + instanceKlass::low_offset,  extract_low_short_from_int(real_offset));
-      fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset));
+      fs.set_offset(real_offset);
     }
 
     // Size of instances
@@ -3517,12 +3303,12 @@
     this_klass->set_class_loader(class_loader());
     this_klass->set_nonstatic_field_size(nonstatic_field_size);
     this_klass->set_has_nonstatic_fields(has_nonstatic_fields);
-    this_klass->set_static_oop_field_count(fac.static_oop_count);
+    this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]);
     cp->set_pool_holder(this_klass());
     error_handler.set_in_error(false);   // turn off error handler for cp
     this_klass->set_constants(cp());
     this_klass->set_local_interfaces(local_interfaces());
-    this_klass->set_fields(fields());
+    this_klass->set_fields(fields(), java_fields_count);
     this_klass->set_methods(methods());
     if (has_final_method) {
       this_klass->set_has_final_method();