< prev index next >

src/hotspot/share/classfile/classFileParser.cpp

Print this page

        

@@ -19,19 +19,21 @@
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  *
  */
+
 #include "precompiled.hpp"
 #include "jvm.h"
 #include "aot/aotLoader.hpp"
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/defaultMethods.hpp"
 #include "classfile/dictionary.hpp"
+#include <classfile/fieldLayoutBuilder.hpp>
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/packageEntry.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"

@@ -54,13 +56,15 @@
 #include "oops/klassVtable.hpp"
 #include "oops/metadata.hpp"
 #include "oops/method.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
+#include "oops/valueKlass.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/os.hpp"
 #include "runtime/perfData.hpp"
 #include "runtime/reflection.hpp"

@@ -125,10 +129,12 @@
 
 #define JAVA_13_VERSION                   57
 
 #define JAVA_14_VERSION                   58
 
+#define CONSTANT_CLASS_DESCRIPTORS        58
+
 void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
   assert((bad_constant == JVM_CONSTANT_Module ||
           bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION,
          "Unexpected bad constant pool entry");
   if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant;

@@ -164,11 +170,11 @@
     // Each of the following case guarantees one more byte in the stream
     // for the following tag or the access_flags following constant pool,
     // so we don't need bounds-check for reading tag.
     const u1 tag = cfs->get_u1_fast();
     switch (tag) {
-      case JVM_CONSTANT_Class : {
+      case JVM_CONSTANT_Class: {
         cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags
         const u2 name_index = cfs->get_u2_fast();
         cp->klass_index_at_put(index, name_index);
         break;
       }

@@ -494,11 +500,18 @@
       case JVM_CONSTANT_ClassIndex: {
         const int class_index = cp->klass_index_at(index);
         check_property(valid_symbol_at(class_index),
           "Invalid constant pool index %u in class file %s",
           class_index, CHECK);
-        cp->unresolved_klass_at_put(index, class_index, num_klasses++);
+
+        Symbol* const name = cp->symbol_at(class_index);
+        const unsigned int name_len = name->utf8_length();
+        if (name->is_Q_signature()) {
+          cp->unresolved_qdescriptor_at_put(index, class_index, num_klasses++);
+        } else {
+          cp->unresolved_klass_at_put(index, class_index, num_klasses++);
+        }
         break;
       }
       case JVM_CONSTANT_StringIndex: {
         const int string_index = cp->string_index_at(index);
         check_property(valid_symbol_at(string_index),

@@ -751,18 +764,29 @@
             const int name_and_type_ref_index =
               cp->name_and_type_ref_index_at(ref_index);
             const int name_ref_index =
               cp->name_ref_index_at(name_and_type_ref_index);
             const Symbol* const name = cp->symbol_at(name_ref_index);
-            if (ref_kind == JVM_REF_newInvokeSpecial) {
-              if (name != vmSymbols::object_initializer_name()) {
+            if (name != vmSymbols::object_initializer_name()) {
+              if (ref_kind == JVM_REF_newInvokeSpecial) {
                 classfile_parse_error(
                   "Bad constructor name at constant pool index %u in class file %s",
                     name_ref_index, CHECK);
               }
             } else {
-              if (name == vmSymbols::object_initializer_name()) {
+              // The allowed invocation mode of <init> depends on its signature.
+              // This test corresponds to verify_invoke_instructions in the verifier.
+              const int signature_ref_index =
+                cp->signature_ref_index_at(name_and_type_ref_index);
+              const Symbol* const signature = cp->symbol_at(signature_ref_index);
+              if (signature->is_void_method_signature()
+                  && ref_kind == JVM_REF_newInvokeSpecial) {
+                // OK, could be a constructor call
+              } else if (!signature->is_void_method_signature()
+                         && ref_kind == JVM_REF_invokeStatic) {
+                // also OK, could be a static factory call
+              } else {
                 classfile_parse_error(
                   "Bad method name at constant pool index %u in class file %s",
                   name_ref_index, CHECK);
               }
             }

@@ -1061,62 +1085,10 @@
                              CHECK);
     }
   }
 }
 
-class AnnotationCollector : public ResourceObj{
-public:
-  enum Location { _in_field, _in_method, _in_class };
-  enum ID {
-    _unknown = 0,
-    _method_CallerSensitive,
-    _method_ForceInline,
-    _method_DontInline,
-    _method_InjectedProfile,
-    _method_LambdaForm_Compiled,
-    _method_Hidden,
-    _method_HotSpotIntrinsicCandidate,
-    _jdk_internal_vm_annotation_Contended,
-    _field_Stable,
-    _jdk_internal_vm_annotation_ReservedStackAccess,
-    _annotation_LIMIT
-  };
-  const Location _location;
-  int _annotations_present;
-  u2 _contended_group;
-
-  AnnotationCollector(Location location)
-    : _location(location), _annotations_present(0)
-  {
-    assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "");
-  }
-  // If this annotation name has an ID, report it (or _none).
-  ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name);
-  // Set the annotation name:
-  void set_annotation(ID id) {
-    assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
-    _annotations_present |= nth_bit((int)id);
-  }
-
-  void remove_annotation(ID id) {
-    assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
-    _annotations_present &= ~nth_bit((int)id);
-  }
-
-  // Report if the annotation is present.
-  bool has_any_annotations() const { return _annotations_present != 0; }
-  bool has_annotation(ID id) const { return (nth_bit((int)id) & _annotations_present) != 0; }
-
-  void set_contended_group(u2 group) { _contended_group = group; }
-  u2 contended_group() const { return _contended_group; }
-
-  bool is_contended() const { return has_annotation(_jdk_internal_vm_annotation_Contended); }
-
-  void set_stable(bool stable) { set_annotation(_field_Stable); }
-  bool is_stable() const { return has_annotation(_field_Stable); }
-};
-
 // This class also doubles as a holder for metadata cleanup.
 class ClassFileParser::FieldAnnotationCollector : public AnnotationCollector {
 private:
   ClassLoaderData* _loader_data;
   AnnotationArray* _field_annotations;

@@ -1140,16 +1112,10 @@
 public:
   MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
   void apply_to(const methodHandle& m);
 };
 
-class ClassFileParser::ClassAnnotationCollector : public AnnotationCollector{
-public:
-  ClassAnnotationCollector() : AnnotationCollector(_in_class) { }
-  void apply_to(InstanceKlass* ik);
-};
-
 
 static int skip_annotation_value(const u1*, int, int); // fwd decl
 
 // Safely increment index by val if does not pass limit
 #define SAFE_ADD(index, limit, val) \

@@ -1463,15 +1429,17 @@
   STATIC_OOP,           // Oops
   STATIC_BYTE,          // Boolean, Byte, char
   STATIC_SHORT,         // shorts
   STATIC_WORD,          // ints
   STATIC_DOUBLE,        // aligned long or double
+  STATIC_FLATTENABLE,   // flattenable field
   NONSTATIC_OOP,
   NONSTATIC_BYTE,
   NONSTATIC_SHORT,
   NONSTATIC_WORD,
   NONSTATIC_DOUBLE,
+  NONSTATIC_FLATTENABLE,
   MAX_FIELD_ALLOCATION_TYPE,
   BAD_ALLOCATION_TYPE = -1
 };
 
 static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {

@@ -1487,16 +1455,17 @@
   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_METADATA    = 17,
-  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
-  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 19,
+  NONSTATIC_OOP,       // T_VALUETYPE   = 14,
+  BAD_ALLOCATION_TYPE, // T_VOID        = 15,
+  BAD_ALLOCATION_TYPE, // T_ADDRESS     = 16,
+  BAD_ALLOCATION_TYPE, // T_NARROWOOP   = 17,
+  BAD_ALLOCATION_TYPE, // T_METADATA    = 18,
+  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 19,
+  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 20,
   BAD_ALLOCATION_TYPE, // 0
   BAD_ALLOCATION_TYPE, // 1
   BAD_ALLOCATION_TYPE, // 2
   BAD_ALLOCATION_TYPE, // 3
   STATIC_BYTE ,        // T_BOOLEAN     =  4,

@@ -1507,22 +1476,26 @@
   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_METADATA    = 17,
-  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
-  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 19,
+  STATIC_OOP,          // T_VALUETYPE   = 14,
+  BAD_ALLOCATION_TYPE, // T_VOID        = 15,
+  BAD_ALLOCATION_TYPE, // T_ADDRESS     = 16,
+  BAD_ALLOCATION_TYPE, // T_NARROWOOP   = 17,
+  BAD_ALLOCATION_TYPE, // T_METADATA    = 18,
+  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 19,
+  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 20
 };
 
-static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) {
+static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type, bool is_flattenable) {
   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");
+  if (is_flattenable) {
+    result = is_static ? STATIC_FLATTENABLE : NONSTATIC_FLATTENABLE;
+  }
   return result;
 }
 
 class ClassFileParser::FieldAllocationCount : public ResourceObj {
  public:

@@ -1532,12 +1505,12 @@
     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);
+  FieldAllocationType update(bool is_static, BasicType type, bool is_flattenable) {
+    FieldAllocationType atype = basic_type_to_atype(is_static, type, is_flattenable);
     if (atype != BAD_ALLOCATION_TYPE) {
       // Make sure there is no overflow with injected fields.
       assert(count[atype] < 0xFFFF, "More than 65535 fields");
       count[atype]++;
     }

@@ -1547,10 +1520,11 @@
 
 // Side-effects: populates the _fields, _fields_annotations,
 // _fields_type_annotations fields
 void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
                                    bool is_interface,
+                                   bool is_value_type,
                                    FieldAllocationCount* const fac,
                                    ConstantPool* cp,
                                    const int cp_size,
                                    u2* const java_fields_count_ptr,
                                    TRAPS) {

@@ -1569,11 +1543,15 @@
   *java_fields_count_ptr = length;
 
   int num_injected = 0;
   const InjectedField* const injected = JavaClasses::get_injected(_class_name,
                                                                   &num_injected);
-  const int total_fields = length + num_injected;
+
+  // two more slots are required for inline classes:
+  // one for the static field with a reference to the pre-allocated default value
+  // one for the field the JVM injects when detecting an empty inline class
+  const int total_fields = length + num_injected + (is_value_type ? 2 : 0);
 
   // 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

@@ -1599,17 +1577,20 @@
                                               total_fields * (FieldInfo::field_slots + 1));
 
   // The generic signature slots start after all other fields' data.
   int generic_signature_slot = total_fields * FieldInfo::field_slots;
   int num_generic_signature = 0;
+  int instance_fields_count = 0;
   for (int n = 0; n < length; n++) {
     // access_flags, name_index, descriptor_index, attributes_count
     cfs->guarantee_more(8, CHECK);
 
+    jint recognized_modifiers = JVM_RECOGNIZED_FIELD_MODIFIERS;
+
+    const jint flags = cfs->get_u2_fast() & recognized_modifiers;
+    verify_legal_field_modifiers(flags, is_interface, is_value_type, CHECK);
     AccessFlags access_flags;
-    const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
-    verify_legal_field_modifiers(flags, is_interface, CHECK);
     access_flags.set_flags(flags);
 
     const u2 name_index = cfs->get_u2_fast();
     check_property(valid_symbol_at(name_index),
       "Invalid constant pool index %u for field name in class file %s",

@@ -1621,10 +1602,27 @@
     check_property(valid_symbol_at(signature_index),
       "Invalid constant pool index %u for field signature in class file %s",
       signature_index, CHECK);
     const Symbol* const sig = cp->symbol_at(signature_index);
     verify_legal_field_signature(name, sig, CHECK);
+    assert(!access_flags.is_flattenable(), "ACC_FLATTENABLE should have been filtered out");
+    if (sig->is_Q_signature()) {
+      // assert(_major_version >= CONSTANT_CLASS_DESCRIPTORS, "Q-descriptors are only supported in recent classfiles");
+      access_flags.set_is_flattenable();
+    }
+    if (access_flags.is_flattenable()) {
+      // Array flattenability cannot be specified.  Arrays of value classes are
+      // are always flattenable.  Arrays of other classes are not flattenable.
+      if (sig->utf8_length() > 1 && sig->char_at(0) == '[') {
+        classfile_parse_error(
+            "Field \"%s\" with signature \"%s\" in class file %s is invalid."
+            " ACC_FLATTENABLE cannot be specified for an array",
+            name->as_C_string(), sig->as_klass_external_name(), CHECK);
+      }
+      _has_flattenable_fields = true;
+    }
+    if (!access_flags.is_static()) instance_fields_count++;
 
     u2 constantvalue_index = 0;
     bool is_synthetic = false;
     u2 generic_signature_index = 0;
     const bool is_static = access_flags.is_static();

@@ -1680,11 +1678,11 @@
                       signature_index,
                       constantvalue_index);
     const BasicType type = cp->basic_type_for_signature_at(signature_index);
 
     // Remember how many oops we encountered and compute allocation type
-    const FieldAllocationType atype = fac->update(is_static, type);
+    const FieldAllocationType atype = fac->update(is_static, type, access_flags.is_flattenable());
     field->set_allocation_type(atype);
 
     // After field is initialized with type, we can augment it with aux info
     if (parsed_annotations.has_any_annotations())
       parsed_annotations.apply_to(field);

@@ -1721,16 +1719,41 @@
                         0);
 
       const BasicType type = FieldType::basic_type(injected[n].signature());
 
       // Remember how many oops we encountered and compute allocation type
-      const FieldAllocationType atype = fac->update(false, type);
+      const FieldAllocationType atype = fac->update(false, type, false);
       field->set_allocation_type(atype);
       index++;
     }
   }
 
+  if (is_value_type) {
+    FieldInfo* const field = FieldInfo::from_field_array(fa, index);
+    field->initialize(JVM_ACC_FIELD_INTERNAL | JVM_ACC_STATIC,
+                      vmSymbols::default_value_name_enum,
+                      vmSymbols::java_lang_Object_enum,
+                      0);
+    const BasicType type = FieldType::basic_type(vmSymbols::object_signature());
+    const FieldAllocationType atype = fac->update(true, type, false);
+    field->set_allocation_type(atype);
+    index++;
+  }
+
+  if (is_value_type && instance_fields_count == 0) {
+    _is_empty_value = true;
+    FieldInfo* const field = FieldInfo::from_field_array(fa, index);
+    field->initialize(JVM_ACC_FIELD_INTERNAL,
+        vmSymbols::empty_marker_name_enum,
+        vmSymbols::byte_signature_enum,
+        0);
+    const BasicType type = FieldType::basic_type(vmSymbols::byte_signature());
+    const FieldAllocationType atype = fac->update(false, type, false);
+    field->set_allocation_type(atype);
+    index++;
+  }
+
   assert(NULL == _fields, "invariant");
 
   _fields =
     MetadataFactory::new_array<u2>(_loader_data,
                                    index * FieldInfo::field_slots + num_generic_signature,

@@ -2042,15 +2065,20 @@
                                             const Symbol* sig,
                                             TRAPS) const {
   assert(name != NULL, "invariant");
   assert(sig != NULL, "invariant");
 
+  const char* class_note = "";
+  if (is_value_type() && name == vmSymbols::object_initializer_name()) {
+    class_note = " (an inline class)";
+  }
+
   ResourceMark rm(THREAD);
   Exceptions::fthrow(THREAD_AND_LOCATION,
       vmSymbols::java_lang_ClassFormatError(),
-      "%s \"%s\" in class %s has illegal signature \"%s\"", type,
-      name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
+      "%s \"%s\" in class %s%s has illegal signature \"%s\"", type,
+      name->as_C_string(), _class_name->as_C_string(), class_note, sig->as_C_string());
 }
 
 AnnotationCollector::ID
 AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
                                       const Symbol* name) {

@@ -2310,10 +2338,11 @@
 // from the method back up to the containing klass. These flag values
 // are added to klass's access_flags.
 
 Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
                                       bool is_interface,
+                                      bool is_value_type,
                                       const ConstantPool* cp,
                                       AccessFlags* const promoted_flags,
                                       TRAPS) {
   assert(cfs != NULL, "invariant");
   assert(cp != NULL, "invariant");

@@ -2350,15 +2379,57 @@
       flags &= JVM_ACC_STATIC | JVM_ACC_STRICT;
     } else {
       classfile_parse_error("Method <clinit> is not static in class file %s", CHECK_NULL);
     }
   } else {
-    verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL);
+    verify_legal_method_modifiers(flags, is_interface, is_value_type, name, CHECK_NULL);
   }
 
-  if (name == vmSymbols::object_initializer_name() && is_interface) {
-    classfile_parse_error("Interface cannot have a method named <init>, class file %s", CHECK_NULL);
+  if (name == vmSymbols::object_initializer_name()) {
+    if (is_interface) {
+      classfile_parse_error("Interface cannot have a method named <init>, class file %s", CHECK_NULL);
+    } else if (!is_value_type && signature->is_void_method_signature()) {
+      // OK, a constructor
+    } else if (is_value_type && !signature->is_void_method_signature()) {
+      // also OK, a static factory, as long as the return value is good
+      bool ok = false;
+      SignatureStream ss((Symbol*) signature, true);
+      while (!ss.at_return_type())  ss.next();
+      if (ss.is_object()) {
+        TempNewSymbol ret = ss.as_symbol_or_null();
+        const Symbol* required = class_name();
+        if (is_unsafe_anonymous()) {
+          // The original class name in the UAC byte stream gets changed.  So
+          // using the original name in the return type is no longer valid.
+          required = vmSymbols::java_lang_Object();
+        }
+        ok = (ret == required);
+      }
+      if (!ok) {
+        throwIllegalSignature("Method", name, signature, CHECK_0);
+      }
+    } else {
+      // not OK, so throw the same error as in verify_legal_method_signature.
+      throwIllegalSignature("Method", name, signature, CHECK_0);
+    }
+    // A declared <init> method must always be either a non-static
+    // object constructor, with a void return, or else it must be a
+    // static factory method, with a non-void return.  No other
+    // definition of <init> is possible.
+    //
+    // The verifier (in verify_invoke_instructions) will inspect the
+    // signature of any attempt to invoke <init>, and ensures that it
+    // returns non-void if and only if it is being invoked by
+    // invokestatic, and void if and only if it is being invoked by
+    // invokespecial.
+    //
+    // When a symbolic reference to <init> is resolved for a
+    // particular invocation mode (special or static), the mode is
+    // matched to the JVM_ACC_STATIC modifier of the <init> method.
+    // Thus, it is impossible to statically invoke a constructor, and
+    // impossible to "new + invokespecial" a static factory, either
+    // through bytecode or through reflection.
   }
 
   int args_size = -1;  // only used when _need_verify is true
   if (_need_verify) {
     args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +

@@ -2925,10 +2996,11 @@
 // from the methods back up to the containing klass. These flag values
 // are added to klass's access_flags.
 // Side-effects: populates the _methods field in the parser
 void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
                                     bool is_interface,
+                                    bool is_value_type,
                                     AccessFlags* promoted_flags,
                                     bool* has_final_method,
                                     bool* declares_nonstatic_concrete_methods,
                                     TRAPS) {
   assert(cfs != NULL, "invariant");

@@ -2949,10 +3021,11 @@
                                                    CHECK);
 
     for (int index = 0; index < length; index++) {
       Method* method = parse_method(cfs,
                                     is_interface,
+                                    is_value_type,
                                     _cp,
                                     promoted_flags,
                                     CHECK);
 
       if (method->is_final()) {

@@ -3141,18 +3214,24 @@
       inner_name_index, CHECK_0);
     if (_need_verify) {
       guarantee_property(inner_class_info_index != outer_class_info_index,
                          "Class is both outer and inner class in class file %s", CHECK_0);
     }
-    // Access flags
-    jint flags;
+
+    jint recognized_modifiers = RECOGNIZED_INNER_CLASS_MODIFIERS;
     // JVM_ACC_MODULE is defined in JDK-9 and later.
     if (_major_version >= JAVA_9_VERSION) {
-      flags = cfs->get_u2_fast() & (RECOGNIZED_INNER_CLASS_MODIFIERS | JVM_ACC_MODULE);
-    } else {
-      flags = cfs->get_u2_fast() & RECOGNIZED_INNER_CLASS_MODIFIERS;
+      recognized_modifiers |= JVM_ACC_MODULE;
     }
+    // JVM_ACC_VALUE is defined for class file version 55 and later
+    if (supports_value_types()) {
+      recognized_modifiers |= JVM_ACC_VALUE;
+    }
+
+    // Access flags
+    jint flags = cfs->get_u2_fast() & recognized_modifiers;
+
     if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
       // Set abstract bit for old class files for backward compatibility
       flags |= JVM_ACC_ABSTRACT;
     }
     verify_legal_class_modifiers(flags, CHECK_0);

@@ -3351,10 +3430,12 @@
   bool runtime_invisible_type_annotations_exists = false;
   bool runtime_invisible_annotations_exists = false;
   bool parsed_source_debug_ext_annotations_exist = false;
   const u1* inner_classes_attribute_start = NULL;
   u4  inner_classes_attribute_length = 0;
+  const u1* value_types_attribute_start = NULL;
+  u4 value_types_attribute_length = 0;
   u2  enclosing_method_class_index = 0;
   u2  enclosing_method_method_index = 0;
   const u1* nest_members_attribute_start = NULL;
   u4  nest_members_attribute_length = 0;
 

@@ -3700,11 +3781,12 @@
                                                         TRAPS) {
   assert(cp != NULL, "invariant");
   const InstanceKlass* super_klass = NULL;
 
   if (super_class_index == 0) {
-    check_property(_class_name == vmSymbols::java_lang_Object(),
+    check_property(_class_name == vmSymbols::java_lang_Object()
+                   || (_access_flags.get_flags() & JVM_ACC_VALUE),
                    "Invalid superclass index %u in class file %s",
                    super_class_index,
                    CHECK_NULL);
   } else {
     check_property(valid_klass_reference_at(super_class_index),

@@ -3727,43 +3809,10 @@
     }
   }
   return super_klass;
 }
 
-static unsigned int compute_oop_map_count(const InstanceKlass* super,
-                                          unsigned int nonstatic_oop_map_count,
-                                          int first_nonstatic_oop_offset) {
-
-  unsigned int map_count =
-    NULL == super ? 0 : super->nonstatic_oop_map_count();
-  if (nonstatic_oop_map_count > 0) {
-    // We have oops to add to map
-    if (map_count == 0) {
-      map_count = nonstatic_oop_map_count;
-    }
-    else {
-      // Check whether we should add a new map block or whether the last one can
-      // be extended
-      const OopMapBlock* const first_map = super->start_of_nonstatic_oop_maps();
-      const OopMapBlock* const last_map = first_map + map_count - 1;
-
-      const int next_offset = last_map->offset() + last_map->count() * heapOopSize;
-      if (next_offset == first_nonstatic_oop_offset) {
-        // There is no gap bettwen superklass's last oop field and first
-        // local oop field, merge maps.
-        nonstatic_oop_map_count -= 1;
-      }
-      else {
-        // Superklass didn't end with a oop field, add extra maps
-        assert(next_offset < first_nonstatic_oop_offset, "just checking");
-      }
-      map_count += nonstatic_oop_map_count;
-    }
-  }
-  return map_count;
-}
-
 #ifndef PRODUCT
 static void print_field_layout(const Symbol* name,
                                Array<u2>* fields,
                                const constantPoolHandle& cp,
                                int instance_size,

@@ -3797,22 +3846,144 @@
   tty->print("  @%3d %s\n", static_fields_end, "--- static fields end ---");
   tty->print("\n");
 }
 #endif
 
-// Values needed for oopmap and InstanceKlass creation
-class ClassFileParser::FieldLayoutInfo : public ResourceObj {
- public:
-  int*          nonstatic_oop_offsets;
-  unsigned int* nonstatic_oop_counts;
-  unsigned int  nonstatic_oop_map_count;
-  unsigned int  total_oop_map_count;
-  int           instance_size;
-  int           nonstatic_field_size;
-  int           static_field_size;
-  bool          has_nonstatic_fields;
-};
+OopMapBlocksBuilder::OopMapBlocksBuilder(unsigned int  max_blocks, TRAPS) {
+  max_nonstatic_oop_maps = max_blocks;
+  nonstatic_oop_map_count = 0;
+  if (max_blocks == 0) {
+    nonstatic_oop_maps = NULL;
+  } else {
+    nonstatic_oop_maps = NEW_RESOURCE_ARRAY_IN_THREAD(
+        THREAD, OopMapBlock, max_nonstatic_oop_maps);
+    memset(nonstatic_oop_maps, 0, sizeof(OopMapBlock) * max_blocks);
+  }
+}
+
+OopMapBlock* OopMapBlocksBuilder::last_oop_map() const {
+  assert(nonstatic_oop_map_count > 0, "Has no oop maps");
+  return nonstatic_oop_maps + (nonstatic_oop_map_count - 1);
+}
+
+// addition of super oop maps
+void OopMapBlocksBuilder::initialize_inherited_blocks(OopMapBlock* blocks, unsigned int nof_blocks) {
+  assert(nof_blocks && nonstatic_oop_map_count == 0 &&
+      nof_blocks <= max_nonstatic_oop_maps, "invariant");
+
+  memcpy(nonstatic_oop_maps, blocks, sizeof(OopMapBlock) * nof_blocks);
+  nonstatic_oop_map_count += nof_blocks;
+}
+
+// collection of oops
+void OopMapBlocksBuilder::add(int offset, int count) {
+  if (nonstatic_oop_map_count == 0) {
+    nonstatic_oop_map_count++;
+  }
+  OopMapBlock*  nonstatic_oop_map = last_oop_map();
+  if (nonstatic_oop_map->count() == 0) {  // Unused map, set it up
+    nonstatic_oop_map->set_offset(offset);
+    nonstatic_oop_map->set_count(count);
+  } else if (nonstatic_oop_map->is_contiguous(offset)) { // contiguous, add
+    nonstatic_oop_map->increment_count(count);
+  } else { // Need a new one...
+    nonstatic_oop_map_count++;
+    assert(nonstatic_oop_map_count <= max_nonstatic_oop_maps, "range check");
+    nonstatic_oop_map = last_oop_map();
+    nonstatic_oop_map->set_offset(offset);
+    nonstatic_oop_map->set_count(count);
+  }
+}
+
+// general purpose copy, e.g. into allocated instanceKlass
+void OopMapBlocksBuilder::copy(OopMapBlock* dst) {
+  if (nonstatic_oop_map_count != 0) {
+    memcpy(dst, nonstatic_oop_maps, sizeof(OopMapBlock) * nonstatic_oop_map_count);
+  }
+}
+
+// Sort and compact adjacent blocks
+void OopMapBlocksBuilder::compact(TRAPS) {
+  if (nonstatic_oop_map_count <= 1) {
+    return;
+  }
+  /*
+   * Since field layout sneeks in oops before values, we will be able to condense
+   * blocks. There is potential to compact between super, own refs and values
+   * containing refs.
+   *
+   * Currently compaction is slightly limited due to values being 8 byte aligned.
+   * This may well change: FixMe if doesn't, the code below is fairly general purpose
+   * and maybe it doesn't need to be.
+   */
+  qsort(nonstatic_oop_maps, nonstatic_oop_map_count, sizeof(OopMapBlock),
+      (_sort_Fn)OopMapBlock::compare_offset);
+  if (nonstatic_oop_map_count < 2) {
+    return;
+  }
+
+  //Make a temp copy, and iterate through and copy back into the orig
+  ResourceMark rm(THREAD);
+  OopMapBlock* oop_maps_copy = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, OopMapBlock,
+      nonstatic_oop_map_count);
+  OopMapBlock* oop_maps_copy_end = oop_maps_copy + nonstatic_oop_map_count;
+  copy(oop_maps_copy);
+  OopMapBlock*  nonstatic_oop_map = nonstatic_oop_maps;
+  unsigned int new_count = 1;
+  oop_maps_copy++;
+  while(oop_maps_copy < oop_maps_copy_end) {
+    assert(nonstatic_oop_map->offset() < oop_maps_copy->offset(), "invariant");
+    if (nonstatic_oop_map->is_contiguous(oop_maps_copy->offset())) {
+      nonstatic_oop_map->increment_count(oop_maps_copy->count());
+    } else {
+      nonstatic_oop_map++;
+      new_count++;
+      nonstatic_oop_map->set_offset(oop_maps_copy->offset());
+      nonstatic_oop_map->set_count(oop_maps_copy->count());
+    }
+    oop_maps_copy++;
+  }
+  assert(new_count <= nonstatic_oop_map_count, "end up with more maps after compact() ?");
+  nonstatic_oop_map_count = new_count;
+}
+
+void OopMapBlocksBuilder::print_on(outputStream* st) const {
+  st->print_cr("  OopMapBlocks: %3d  /%3d", nonstatic_oop_map_count, max_nonstatic_oop_maps);
+  if (nonstatic_oop_map_count > 0) {
+    OopMapBlock* map = nonstatic_oop_maps;
+    OopMapBlock* last_map = last_oop_map();
+    assert(map <= last_map, "Last less than first");
+    while (map <= last_map) {
+      st->print_cr("    Offset: %3d  -%3d Count: %3d", map->offset(),
+          map->offset() + map->offset_span() - heapOopSize, map->count());
+      map++;
+    }
+  }
+}
+
+void OopMapBlocksBuilder::print_value_on(outputStream* st) const {
+  print_on(st);
+}
+
+void ClassFileParser::throwValueTypeLimitation(THREAD_AND_LOCATION_DECL,
+                                               const char* msg,
+                                               const Symbol* name,
+                                               const Symbol* sig) const {
+
+  ResourceMark rm(THREAD);
+  if (name == NULL || sig == NULL) {
+    Exceptions::fthrow(THREAD_AND_LOCATION_ARGS,
+        vmSymbols::java_lang_ClassFormatError(),
+        "class: %s - %s", _class_name->as_C_string(), msg);
+  }
+  else {
+    Exceptions::fthrow(THREAD_AND_LOCATION_ARGS,
+        vmSymbols::java_lang_ClassFormatError(),
+        "\"%s\" sig: \"%s\" class: %s - %s", name->as_C_string(), sig->as_C_string(),
+        _class_name->as_C_string(), msg);
+  }
+}
 
 // Layout fields and fill in FieldLayoutInfo.  Could use more refactoring!
 void ClassFileParser::layout_fields(ConstantPool* cp,
                                     const FieldAllocationCount* fac,
                                     const ClassAnnotationCollector* parsed_annotations,

@@ -3822,10 +3993,16 @@
   assert(cp != NULL, "invariant");
 
   // Field size and offset computation
   int nonstatic_field_size = _super_klass == NULL ? 0 :
                                _super_klass->nonstatic_field_size();
+  int next_nonstatic_valuetype_offset = 0;
+  int first_nonstatic_valuetype_offset = 0;
+
+  // Fields that are value types are handled differently depending if they are static or not:
+  // - static fields are oops
+  // - non-static fields are embedded
 
   // Count the contended fields by type.
   //
   // We ignore static fields, because @Contended is not supported for them.
   // The layout code below will also ignore the static fields.

@@ -3842,12 +4019,13 @@
   }
 
 
   // Calculate the starting byte offsets
   int next_static_oop_offset    = InstanceMirrorKlass::offset_of_static_fields();
+  // Value types in static fields are not embedded, they are handled with oops
   int next_static_double_offset = next_static_oop_offset +
-                                      ((fac->count[STATIC_OOP]) * heapOopSize);
+                                  ((fac->count[STATIC_OOP] + fac->count[STATIC_FLATTENABLE]) * heapOopSize);
   if (fac->count[STATIC_DOUBLE]) {
     next_static_double_offset = align_up(next_static_double_offset, BytesPerLong);
   }
 
   int next_static_word_offset   = next_static_double_offset +

@@ -3858,57 +4036,144 @@
                                   ((fac->count[STATIC_SHORT]) * BytesPerShort);
 
   int nonstatic_fields_start  = instanceOopDesc::base_offset_in_bytes() +
                                 nonstatic_field_size * heapOopSize;
 
+  // First field of value types is aligned on a long boundary in order to ease
+  // in-lining of value types (with header removal) in packed arrays and
+  // flatten value types
+  int initial_value_type_padding = 0;
+  if (is_value_type()) {
+    int old = nonstatic_fields_start;
+    nonstatic_fields_start = align_up(nonstatic_fields_start, BytesPerLong);
+    initial_value_type_padding = nonstatic_fields_start - old;
+  }
+
   int next_nonstatic_field_offset = nonstatic_fields_start;
 
   const bool is_contended_class     = parsed_annotations->is_contended();
 
   // Class is contended, pad before all the fields
   if (is_contended_class) {
     next_nonstatic_field_offset += ContendedPaddingWidth;
   }
 
+  // Temporary value types restrictions
+  if (is_value_type()) {
+    if (is_contended_class) {
+      throwValueTypeLimitation(THREAD_AND_LOCATION, "Value Types do not support @Contended annotation yet");
+      return;
+    }
+  }
+
   // Compute the non-contended fields count.
   // The packing code below relies on these counts to determine if some field
   // can be squeezed into the alignment gap. Contended fields are obviously
   // exempt from that.
   unsigned int nonstatic_double_count = fac->count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
   unsigned int nonstatic_word_count   = fac->count[NONSTATIC_WORD]   - fac_contended.count[NONSTATIC_WORD];
   unsigned int nonstatic_short_count  = fac->count[NONSTATIC_SHORT]  - fac_contended.count[NONSTATIC_SHORT];
   unsigned int nonstatic_byte_count   = fac->count[NONSTATIC_BYTE]   - fac_contended.count[NONSTATIC_BYTE];
   unsigned int nonstatic_oop_count    = fac->count[NONSTATIC_OOP]    - fac_contended.count[NONSTATIC_OOP];
 
+  int static_value_type_count = 0;
+  int nonstatic_value_type_count = 0;
+  int* nonstatic_value_type_indexes = NULL;
+  Klass** nonstatic_value_type_klasses = NULL;
+  unsigned int value_type_oop_map_count = 0;
+  int not_flattened_value_types = 0;
+
+  int max_nonstatic_value_type = fac->count[NONSTATIC_FLATTENABLE] + 1;
+
+  nonstatic_value_type_indexes = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, int,
+                                                              max_nonstatic_value_type);
+  for (int i = 0; i < max_nonstatic_value_type; i++) {
+    nonstatic_value_type_indexes[i] = -1;
+  }
+  nonstatic_value_type_klasses = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, Klass*,
+                                                              max_nonstatic_value_type);
+
+  for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
+    if (fs.allocation_type() == STATIC_FLATTENABLE) {
+      ResourceMark rm;
+      if (!fs.signature()->is_Q_signature()) {
+        THROW(vmSymbols::java_lang_ClassFormatError());
+      }
+      static_value_type_count++;
+    } else if (fs.allocation_type() == NONSTATIC_FLATTENABLE) {
+      // Pre-resolve the flattenable field and check for value type circularity issues.
+      ResourceMark rm;
+      if (!fs.signature()->is_Q_signature()) {
+        THROW(vmSymbols::java_lang_ClassFormatError());
+      }
+      Klass* klass =
+        SystemDictionary::resolve_flattenable_field_or_fail(&fs,
+                                                            Handle(THREAD, _loader_data->class_loader()),
+                                                            _protection_domain, true, CHECK);
+      assert(klass != NULL, "Sanity check");
+      if (!klass->access_flags().is_value_type()) {
+        THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
+      }
+      ValueKlass* vk = ValueKlass::cast(klass);
+      // Conditions to apply flattening or not should be defined in a single place
+      if ((ValueFieldMaxFlatSize < 0) || (vk->size_helper() * HeapWordSize) <= ValueFieldMaxFlatSize) {
+        nonstatic_value_type_indexes[nonstatic_value_type_count] = fs.index();
+        nonstatic_value_type_klasses[nonstatic_value_type_count] = klass;
+        nonstatic_value_type_count++;
+
+        ValueKlass* vklass = ValueKlass::cast(klass);
+        if (vklass->contains_oops()) {
+          value_type_oop_map_count += vklass->nonstatic_oop_map_count();
+        }
+        fs.set_flattened(true);
+      } else {
+        not_flattened_value_types++;
+        fs.set_flattened(false);
+      }
+    }
+  }
+
+  // Adjusting non_static_oop_count to take into account not flattened value types;
+  nonstatic_oop_count += not_flattened_value_types;
+
   // Total non-static fields count, including every contended field
   unsigned int nonstatic_fields_count = fac->count[NONSTATIC_DOUBLE] + fac->count[NONSTATIC_WORD] +
                                         fac->count[NONSTATIC_SHORT] + fac->count[NONSTATIC_BYTE] +
-                                        fac->count[NONSTATIC_OOP];
+                                        fac->count[NONSTATIC_OOP] + fac->count[NONSTATIC_FLATTENABLE];
 
   const bool super_has_nonstatic_fields =
           (_super_klass != NULL && _super_klass->has_nonstatic_fields());
   const bool has_nonstatic_fields =
     super_has_nonstatic_fields || (nonstatic_fields_count != 0);
+  const bool has_nonstatic_value_fields = nonstatic_value_type_count > 0;
 
+  if (is_value_type() && (!has_nonstatic_fields)) {
+    // There are a number of fixes required throughout the type system and JIT
+    throwValueTypeLimitation(THREAD_AND_LOCATION, "Value Types do not support zero instance size yet");
+    return;
+  }
 
   // Prepare list of oops for oop map generation.
   //
   // "offset" and "count" lists are describing the set of contiguous oop
   // regions. offset[i] is the start of the i-th region, which then has
   // count[i] oops following. Before we know how many regions are required,
   // we pessimistically allocate the maps to fit all the oops into the
   // distinct regions.
   //
-  // TODO: We add +1 to always allocate non-zero resource arrays; we need
-  // to figure out if we still need to do this.
-  unsigned int nonstatic_oop_map_count = 0;
-  unsigned int max_nonstatic_oop_maps  = fac->count[NONSTATIC_OOP] + 1;
-
-  int* nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
-            THREAD, int, max_nonstatic_oop_maps);
-  unsigned int* const nonstatic_oop_counts  = NEW_RESOURCE_ARRAY_IN_THREAD(
-            THREAD, unsigned int, max_nonstatic_oop_maps);
+  int super_oop_map_count = (_super_klass == NULL) ? 0 :_super_klass->nonstatic_oop_map_count();
+  int max_oop_map_count =
+      super_oop_map_count +
+      fac->count[NONSTATIC_OOP] +
+      value_type_oop_map_count +
+      not_flattened_value_types;
+
+  OopMapBlocksBuilder* nonstatic_oop_maps = new OopMapBlocksBuilder(max_oop_map_count, THREAD);
+  if (super_oop_map_count > 0) {
+    nonstatic_oop_maps->initialize_inherited_blocks(_super_klass->start_of_nonstatic_oop_maps(),
+                                                    _super_klass->nonstatic_oop_map_count());
+  }
 
   int first_nonstatic_oop_offset = 0; // will be set for first oop field
 
   bool compact_fields   = CompactFields;
   int allocation_style = FieldsAllocationStyle;

@@ -3953,17 +4218,12 @@
   } else if( allocation_style == 1 ) {
     // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
     next_nonstatic_double_offset = next_nonstatic_field_offset;
   } else if( allocation_style == 2 ) {
     // Fields allocation: oops fields in super and sub classes are together.
-    if( nonstatic_field_size > 0 && _super_klass != NULL &&
-        _super_klass->nonstatic_oop_map_size() > 0 ) {
-      const unsigned int map_count = _super_klass->nonstatic_oop_map_count();
-      const OopMapBlock* const first_map = _super_klass->start_of_nonstatic_oop_maps();
-      const OopMapBlock* const last_map = first_map + map_count - 1;
-      const int next_offset = last_map->offset() + (last_map->count() * heapOopSize);
-      if (next_offset == next_nonstatic_field_offset) {
+    if( nonstatic_field_size > 0 && super_oop_map_count > 0 ) {
+      if (next_nonstatic_field_offset == nonstatic_oop_maps->last_oop_map()->end_offset()) {
         allocation_style = 0;   // allocate oops first
         next_nonstatic_oop_offset    = next_nonstatic_field_offset;
         next_nonstatic_double_offset = next_nonstatic_oop_offset +
                                        (nonstatic_oop_count * heapOopSize);
       }

@@ -4042,10 +4302,20 @@
       next_nonstatic_oop_offset = align_up(next_nonstatic_oop_offset, heapOopSize);
     }
     next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
   }
 
+  // Aligning embedded value types
+  // bug below, the current algorithm to layout embedded value types always put them at the
+  // end of the layout, which doesn't match the different allocation policies the VM is
+  // supposed to provide => FixMe
+  // Note also that the current alignment policy is to make each value type starting on a
+  // 64 bits boundary. This could be optimized later. For instance, it could be nice to
+  // align value types according to their most constrained internal type.
+  next_nonstatic_valuetype_offset = align_up(next_nonstatic_padded_offset, BytesPerLong);
+  int next_value_type_index = 0;
+
   // 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).
   for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
 

@@ -4058,10 +4328,12 @@
     int real_offset = 0;
     const FieldAllocationType atype = (const FieldAllocationType) fs.allocation_type();
 
     // pack the rest of the fields
     switch (atype) {
+      // Value types in static fields are handled with oops
+      case STATIC_FLATTENABLE:   // Fallthrough
       case STATIC_OOP:
         real_offset = next_static_oop_offset;
         next_static_oop_offset += heapOopSize;
         break;
       case STATIC_BYTE:

@@ -4078,39 +4350,45 @@
         break;
       case STATIC_DOUBLE:
         real_offset = next_static_double_offset;
         next_static_double_offset += BytesPerLong;
         break;
+      case NONSTATIC_FLATTENABLE:
+        if (fs.is_flattened()) {
+          Klass* klass = nonstatic_value_type_klasses[next_value_type_index];
+          assert(klass != NULL, "Klass should have been loaded and resolved earlier");
+          assert(klass->access_flags().is_value_type(),"Must be a value type");
+          ValueKlass* vklass = ValueKlass::cast(klass);
+          real_offset = next_nonstatic_valuetype_offset;
+          next_nonstatic_valuetype_offset += (vklass->size_helper()) * wordSize - vklass->first_field_offset();
+          // aligning next value type on a 64 bits boundary
+          next_nonstatic_valuetype_offset = align_up(next_nonstatic_valuetype_offset, BytesPerLong);
+          next_value_type_index += 1;
+
+          if (vklass->contains_oops()) { // add flatten oop maps
+            int diff = real_offset - vklass->first_field_offset();
+            const OopMapBlock* map = vklass->start_of_nonstatic_oop_maps();
+            const OopMapBlock* const last_map = map + vklass->nonstatic_oop_map_count();
+            while (map < last_map) {
+              nonstatic_oop_maps->add(map->offset() + diff, map->count());
+              map++;
+            }
+          }
+          break;
+        } else {
+          // Fall through
+        }
       case NONSTATIC_OOP:
         if( nonstatic_oop_space_count > 0 ) {
           real_offset = nonstatic_oop_space_offset;
           nonstatic_oop_space_offset += heapOopSize;
           nonstatic_oop_space_count  -= 1;
         } else {
           real_offset = next_nonstatic_oop_offset;
           next_nonstatic_oop_offset += heapOopSize;
         }
-
-        // Record this oop in the oop maps
-        if( nonstatic_oop_map_count > 0 &&
-            nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
-            real_offset -
-            int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
-            heapOopSize ) {
-          // This oop is adjacent to the previous one, add to current oop map
-          assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
-          nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
-        } else {
-          // This oop is not adjacent to the previous one, create new oop map
-          assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
-          nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
-          nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
-          nonstatic_oop_map_count += 1;
-          if( first_nonstatic_oop_offset == 0 ) { // Undefined
-            first_nonstatic_oop_offset = real_offset;
-          }
-        }
+        nonstatic_oop_maps->add(real_offset, 1);
         break;
       case NONSTATIC_BYTE:
         if( nonstatic_byte_space_count > 0 ) {
           real_offset = nonstatic_byte_space_offset;
           nonstatic_byte_space_offset += 1;

@@ -4215,34 +4493,21 @@
             next_nonstatic_padded_offset = align_up(next_nonstatic_padded_offset, BytesPerLong);
             real_offset = next_nonstatic_padded_offset;
             next_nonstatic_padded_offset += BytesPerLong;
             break;
 
+            // Value types in static fields are handled with oops
+          case NONSTATIC_FLATTENABLE:
+            throwValueTypeLimitation(THREAD_AND_LOCATION,
+                                     "@Contended annotation not supported for value types yet", fs.name(), fs.signature());
+            return;
+
           case NONSTATIC_OOP:
             next_nonstatic_padded_offset = align_up(next_nonstatic_padded_offset, heapOopSize);
             real_offset = next_nonstatic_padded_offset;
             next_nonstatic_padded_offset += heapOopSize;
-
-            // Record this oop in the oop maps
-            if( nonstatic_oop_map_count > 0 &&
-                nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
-                real_offset -
-                int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
-                heapOopSize ) {
-              // This oop is adjacent to the previous one, add to current oop map
-              assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
-              nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
-            } else {
-              // This oop is not adjacent to the previous one, create new oop map
-              assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
-              nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
-              nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
-              nonstatic_oop_map_count += 1;
-              if( first_nonstatic_oop_offset == 0 ) { // Undefined
-                first_nonstatic_oop_offset = real_offset;
-              }
-            }
+            nonstatic_oop_maps->add(real_offset, 1);
             break;
 
           default:
             ShouldNotReachHere();
         }

@@ -4273,16 +4538,28 @@
 
   // Entire class is contended, pad in the back.
   // This helps to alleviate memory contention effects for subclass fields
   // and/or adjacent object.
   if (is_contended_class) {
+    assert(!is_value_type(), "@Contended not supported for value types yet");
     next_nonstatic_padded_offset += ContendedPaddingWidth;
   }
 
-  int notaligned_nonstatic_fields_end = next_nonstatic_padded_offset;
+  int notaligned_nonstatic_fields_end;
+  if (nonstatic_value_type_count != 0) {
+    notaligned_nonstatic_fields_end = next_nonstatic_valuetype_offset;
+  } else {
+    notaligned_nonstatic_fields_end = next_nonstatic_padded_offset;
+  }
 
-  int nonstatic_fields_end      = align_up(notaligned_nonstatic_fields_end, heapOopSize);
+  int nonstatic_field_sz_align = heapOopSize;
+  if (is_value_type()) {
+    if ((notaligned_nonstatic_fields_end - nonstatic_fields_start) > heapOopSize) {
+      nonstatic_field_sz_align = BytesPerLong; // value copy of fields only uses jlong copy
+    }
+  }
+  int nonstatic_fields_end      = align_up(notaligned_nonstatic_fields_end, nonstatic_field_sz_align);
   int instance_end              = align_up(notaligned_nonstatic_fields_end, wordSize);
   int static_fields_end         = align_up(next_static_byte_offset, wordSize);
 
   int static_field_size         = (static_fields_end -
                                    InstanceMirrorKlass::offset_of_static_fields()) / wordSize;

@@ -4290,92 +4567,54 @@
                                   (nonstatic_fields_end - nonstatic_fields_start) / heapOopSize;
 
   int instance_size             = align_object_size(instance_end / wordSize);
 
   assert(instance_size == align_object_size(align_up(
-         (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize),
-          wordSize) / wordSize), "consistent layout helper value");
+         (instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize)
+         + initial_value_type_padding, wordSize) / wordSize), "consistent layout helper value");
+
 
   // Invariant: nonstatic_field end/start should only change if there are
   // nonstatic fields in the class, or if the class is contended. We compare
   // against the non-aligned value, so that end alignment will not fail the
   // assert without actually having the fields.
   assert((notaligned_nonstatic_fields_end == nonstatic_fields_start) ||
          is_contended_class ||
          (nonstatic_fields_count > 0), "double-check nonstatic start/end");
 
   // Number of non-static oop map blocks allocated at end of klass.
-  const unsigned int total_oop_map_count =
-    compute_oop_map_count(_super_klass, nonstatic_oop_map_count,
-                          first_nonstatic_oop_offset);
+  nonstatic_oop_maps->compact(THREAD);
 
 #ifndef PRODUCT
-  if (PrintFieldLayout) {
+  if ((PrintFieldLayout && !is_value_type()) ||
+      (PrintValueLayout && (is_value_type() || has_nonstatic_value_fields))) {
     print_field_layout(_class_name,
           _fields,
           cp,
           instance_size,
           nonstatic_fields_start,
           nonstatic_fields_end,
           static_fields_end);
+    nonstatic_oop_maps->print_on(tty);
+    tty->print("\n");
+    tty->print_cr("Instance size = %d", instance_size);
+    tty->print_cr("Nonstatic_field_size = %d", nonstatic_field_size);
+    tty->print_cr("Static_field_size = %d", static_field_size);
+    tty->print_cr("Has nonstatic fields = %d", has_nonstatic_fields);
+    tty->print_cr("---");
   }
 
 #endif
   // Pass back information needed for InstanceKlass creation
-  info->nonstatic_oop_offsets = nonstatic_oop_offsets;
-  info->nonstatic_oop_counts = nonstatic_oop_counts;
-  info->nonstatic_oop_map_count = nonstatic_oop_map_count;
-  info->total_oop_map_count = total_oop_map_count;
+  info->oop_map_blocks = nonstatic_oop_maps;
   info->instance_size = instance_size;
   info->static_field_size = static_field_size;
   info->nonstatic_field_size = nonstatic_field_size;
   info->has_nonstatic_fields = has_nonstatic_fields;
 }
 
-static void fill_oop_maps(const InstanceKlass* k,
-                          unsigned int nonstatic_oop_map_count,
-                          const int* nonstatic_oop_offsets,
-                          const unsigned int* nonstatic_oop_counts) {
-
-  assert(k != NULL, "invariant");
-
-  OopMapBlock* this_oop_map = k->start_of_nonstatic_oop_maps();
-  const InstanceKlass* const super = k->superklass();
-  const unsigned int super_count = super ? super->nonstatic_oop_map_count() : 0;
-  if (super_count > 0) {
-    // Copy maps from superklass
-    OopMapBlock* super_oop_map = super->start_of_nonstatic_oop_maps();
-    for (unsigned int i = 0; i < super_count; ++i) {
-      *this_oop_map++ = *super_oop_map++;
-    }
-  }
-
-  if (nonstatic_oop_map_count > 0) {
-    if (super_count + nonstatic_oop_map_count > k->nonstatic_oop_map_count()) {
-      // The counts differ because there is no gap between superklass's last oop
-      // field and the first local oop field.  Extend the last oop map copied
-      // from the superklass instead of creating new one.
-      nonstatic_oop_map_count--;
-      nonstatic_oop_offsets++;
-      this_oop_map--;
-      this_oop_map->set_count(this_oop_map->count() + *nonstatic_oop_counts++);
-      this_oop_map++;
-    }
-
-    // Add new map blocks, fill them
-    while (nonstatic_oop_map_count-- > 0) {
-      this_oop_map->set_offset(*nonstatic_oop_offsets++);
-      this_oop_map->set_count(*nonstatic_oop_counts++);
-      this_oop_map++;
-    }
-    assert(k->start_of_nonstatic_oop_maps() + k->nonstatic_oop_map_count() ==
-           this_oop_map, "sanity");
-  }
-}
-
-
-void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) {
+void ClassFileParser::set_precomputed_flags(InstanceKlass* ik, TRAPS) {
   assert(ik != NULL, "invariant");
 
   const Klass* const super = ik->super();
 
   // Check if this klass has an empty finalize method (i.e. one with return bytecode only),

@@ -4404,10 +4643,14 @@
 #endif
 
   // Check if this klass supports the java.lang.Cloneable interface
   if (SystemDictionary::Cloneable_klass_loaded()) {
     if (ik->is_subtype_of(SystemDictionary::Cloneable_klass())) {
+      if (ik->is_value()) {
+        throwValueTypeLimitation(THREAD_AND_LOCATION, "Value Types do not support Cloneable");
+        return;
+      }
       ik->set_is_cloneable();
     }
   }
 
   // Check if this klass has a vanilla default constructor

@@ -4444,10 +4687,15 @@
     const jint lh = Klass::instance_layout_helper(ik->size_helper(), true);
     ik->set_layout_helper(lh);
   }
 }
 
+bool ClassFileParser::supports_value_types() const {
+  // Value types are only supported by class file version 55 and later
+  return _major_version >= JAVA_11_VERSION;
+}
+
 // utility methods for appending an array with check for duplicates
 
 static void append_interfaces(GrowableArray<InstanceKlass*>* result,
                               const Array<InstanceKlass*>* const ifs) {
   // iterate over new interfaces

@@ -4706,21 +4954,33 @@
 
 // utility methods for format checking
 
 void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const {
   const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+  const bool is_value_type = (flags & JVM_ACC_VALUE) != 0;
   assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set");
+  assert(supports_value_types() || !is_value_type, "JVM_ACC_VALUE should not be set");
   if (is_module) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
       vmSymbols::java_lang_NoClassDefFoundError(),
       "%s is not a class because access_flag ACC_MODULE is set",
       _class_name->as_C_string());
     return;
   }
 
+  if (is_value_type && !EnableValhalla) {
+    ResourceMark rm(THREAD);
+    Exceptions::fthrow(
+      THREAD_AND_LOCATION,
+      vmSymbols::java_lang_ClassFormatError(),
+      "Class modifier ACC_VALUE in class %s requires option -XX:+EnableValhalla",
+      _class_name->as_C_string()
+    );
+  }
+
   if (!_need_verify) { return; }
 
   const bool is_interface  = (flags & JVM_ACC_INTERFACE)  != 0;
   const bool is_abstract   = (flags & JVM_ACC_ABSTRACT)   != 0;
   const bool is_final      = (flags & JVM_ACC_FINAL)      != 0;

@@ -4730,17 +4990,20 @@
   const bool major_gte_15  = _major_version >= JAVA_1_5_VERSION;
 
   if ((is_abstract && is_final) ||
       (is_interface && !is_abstract) ||
       (is_interface && major_gte_15 && (is_super || is_enum)) ||
-      (!is_interface && major_gte_15 && is_annotation)) {
+      (!is_interface && major_gte_15 && is_annotation) ||
+      (is_value_type && (is_interface || is_abstract || is_enum || !is_final))) {
     ResourceMark rm(THREAD);
+    const char* class_note = "";
+    if (is_value_type)  class_note = " (an inline class)";
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
       vmSymbols::java_lang_ClassFormatError(),
-      "Illegal class modifiers in class %s: 0x%X",
-      _class_name->as_C_string(), flags
+      "Illegal class modifiers in class %s%s: 0x%X",
+      _class_name->as_C_string(), class_note, flags
     );
     return;
   }
 }
 

@@ -4815,10 +5078,11 @@
   }
 }
 
 void ClassFileParser::verify_legal_field_modifiers(jint flags,
                                                    bool is_interface,
+                                                   bool is_value_type,
                                                    TRAPS) const {
   if (!_need_verify) { return; }
 
   const bool is_public    = (flags & JVM_ACC_PUBLIC)    != 0;
   const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0;

@@ -4839,10 +5103,14 @@
       is_illegal = true;
     }
   } else { // not interface
     if (has_illegal_visibility(flags) || (is_final && is_volatile)) {
       is_illegal = true;
+    } else {
+      if (is_value_type && !is_static && !is_final) {
+        is_illegal = true;
+      }
     }
   }
 
   if (is_illegal) {
     ResourceMark rm(THREAD);

@@ -4855,10 +5123,11 @@
   }
 }
 
 void ClassFileParser::verify_legal_method_modifiers(jint flags,
                                                     bool is_interface,
+                                                    bool is_value_type,
                                                     const Symbol* name,
                                                     TRAPS) const {
   if (!_need_verify) { return; }
 
   const bool is_public       = (flags & JVM_ACC_PUBLIC)       != 0;

@@ -4875,10 +5144,12 @@
   const bool major_gte_8     = _major_version >= JAVA_8_VERSION;
   const bool is_initializer  = (name == vmSymbols::object_initializer_name());
 
   bool is_illegal = false;
 
+  const char* class_note = "";
+
   if (is_interface) {
     if (major_gte_8) {
       // Class file version is JAVA_8_VERSION or later Methods of
       // interfaces may set any of the flags except ACC_PROTECTED,
       // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must

@@ -4909,19 +5180,33 @@
   } else { // not interface
     if (has_illegal_visibility(flags)) {
       is_illegal = true;
     } else {
       if (is_initializer) {
-        if (is_static || is_final || is_synchronized || is_native ||
+        if (is_final || is_synchronized || is_native ||
             is_abstract || (major_gte_15 && is_bridge)) {
           is_illegal = true;
         }
+        if (!is_static && !is_value_type) {
+          // OK, an object constructor in a regular class
+        } else if (is_static && is_value_type) {
+          // OK, a static init factory in an inline class
+        } else {
+          // but no other combinations are allowed
+          is_illegal = true;
+          class_note = (is_value_type ? " (an inline class)" : " (not an inline class)");
+        }
       } else { // not initializer
-        if (is_abstract) {
-          if ((is_final || is_native || is_private || is_static ||
-              (major_gte_15 && (is_synchronized || is_strict)))) {
-            is_illegal = true;
+        if (is_value_type && is_synchronized && !is_static) {
+          is_illegal = true;
+          class_note = " (an inline class)";
+        } else {
+          if (is_abstract) {
+            if ((is_final || is_native || is_private || is_static ||
+                (major_gte_15 && (is_synchronized || is_strict)))) {
+              is_illegal = true;
+            }
           }
         }
       }
     }
   }

@@ -4929,12 +5214,12 @@
   if (is_illegal) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
       vmSymbols::java_lang_ClassFormatError(),
-      "Method %s in class %s has illegal modifiers: 0x%X",
-      name->as_C_string(), _class_name->as_C_string(), flags);
+      "Method %s in class %s%s has illegal modifiers: 0x%X",
+      name->as_C_string(), _class_name->as_C_string(), class_note, flags);
     return;
   }
 }
 
 void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,

@@ -5087,22 +5372,31 @@
     case JVM_SIGNATURE_INT:
     case JVM_SIGNATURE_FLOAT:
     case JVM_SIGNATURE_LONG:
     case JVM_SIGNATURE_DOUBLE:
       return signature + 1;
-    case JVM_SIGNATURE_CLASS: {
+    case JVM_SIGNATURE_VALUETYPE:
+      // Can't enable this check until JDK upgrades the bytecode generators
+      // if (_major_version < CONSTANT_CLASS_DESCRIPTORS ) {
+      //   classfile_parse_error("Class name contains illegal Q-signature "
+      //                                    "in descriptor in class file %s",
+      //                                    CHECK_0);
+      // }
+      // fall through
+    case JVM_SIGNATURE_CLASS:
+    {
       if (_major_version < JAVA_1_5_VERSION) {
         // Skip over the class name if one is there
         const char* const p = skip_over_field_name(signature + 1, true, --length);
 
         // The next character better be a semicolon
         if (p && (p - signature) > 1 && p[0] == ';') {
           return p + 1;
         }
       }
       else {
-        // Skip leading 'L' and ignore first appearance of ';'
+        // Skip leading 'L' or 'Q' and ignore first appearance of ';'
         signature++;
         const char* c = (const char*) memchr(signature, ';', length - 1);
         // Format check signature
         if (c != NULL) {
           int newlen = c - (char*) signature;

@@ -5153,10 +5447,13 @@
     } else if (_major_version < JAVA_1_5_VERSION) {
       if (bytes[0] != '<') {
         p = skip_over_field_name(bytes, true, length);
         legal = (p != NULL) && ((p - bytes) == (int)length);
       }
+    } else if (_major_version >= CONSTANT_CLASS_DESCRIPTORS && bytes[length - 1] == ';' ) {
+      // Support for L...; and Q...; descriptors
+      legal = verify_unqualified_name(bytes + 1, length - 2, LegalClass);
     } else {
       // 4900761: relax the constraints based on JSR202 spec
       // Class names may be drawn from the entire Unicode character set.
       // Identifiers between '/' must be unqualified names.
       // The utf8 string has been verified when parsing cpool entries.

@@ -5302,14 +5599,30 @@
     }
     // The first non-signature thing better be a ')'
     if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) {
       length--;
       if (name->utf8_length() > 0 && name->char_at(0) == '<') {
-        // All internal methods must return void
+        // All constructor methods must return void
         if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) {
           return args_size;
         }
+        // All static init methods must return the current class
+        if ((length >= 3) && (p[length-1] == JVM_SIGNATURE_ENDCLASS)
+            && name == vmSymbols::object_initializer_name()) {
+          nextp = skip_over_field_signature(p, true, length, CHECK_0);
+          if (nextp && ((int)length == (nextp - p))) {
+            // The actual class will be checked against current class
+            // when the method is defined (see parse_method).
+            // A reference to a static init with a bad return type
+            // will load and verify OK, but will fail to link.
+            return args_size;
+          }
+        }
+        // The distinction between static factory methods and
+        // constructors depends on the JVM_ACC_STATIC modifier.
+        // This distinction must be reflected in a void or non-void
+        // return. For declared methods, the check is in parse_method.
       } else {
         // Now we better just have a return value
         nextp = skip_over_field_signature(p, true, length, CHECK_0);
         if (nextp && ((int)length == (nextp - p))) {
           return args_size;

@@ -5327,11 +5640,11 @@
   return _field_info->static_field_size;
 }
 
 int ClassFileParser::total_oop_map_count() const {
   assert(_field_info != NULL, "invariant");
-  return _field_info->total_oop_map_count;
+  return _field_info->oop_map_blocks->nonstatic_oop_map_count;
 }
 
 jint ClassFileParser::layout_size() const {
   assert(_field_info != NULL, "invariant");
   return _field_info->instance_size;

@@ -5457,10 +5770,16 @@
       log_info(class, fingerprint)("%s :  expected = " PTR64_FORMAT " actual = " PTR64_FORMAT,
                                  ik->external_name(), aot_fp, _stream->compute_fingerprint());
     }
   }
 
+  if (ik->is_value()) {
+    ValueKlass* vk = ValueKlass::cast(ik);
+    oop val = ik->allocate_instance(CHECK_NULL);
+    vk->set_default_value(val);
+  }
+
   return ik;
 }
 
 void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) {
   assert(ik != NULL, "invariant");

@@ -5477,11 +5796,11 @@
 
   set_klass_to_deallocate(ik);
 
   assert(_field_info != NULL, "invariant");
   assert(ik->static_field_size() == _field_info->static_field_size, "sanity");
-  assert(ik->nonstatic_oop_map_count() == _field_info->total_oop_map_count,
+  assert(ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->nonstatic_oop_map_count,
     "sanity");
 
   assert(ik->is_instance_klass(), "sanity");
   assert(ik->size_helper() == _field_info->instance_size, "sanity");
 

@@ -5489,12 +5808,15 @@
   ik->set_should_verify_class(_need_verify);
 
   // Not yet: supers are done below to support the new subtype-checking fields
   ik->set_nonstatic_field_size(_field_info->nonstatic_field_size);
   ik->set_has_nonstatic_fields(_field_info->has_nonstatic_fields);
+  if (_is_empty_value) {
+    ik->set_is_empty_value();
+  }
   assert(_fac != NULL, "invariant");
-  ik->set_static_oop_field_count(_fac->count[STATIC_OOP]);
+  ik->set_static_oop_field_count(_fac->count[STATIC_OOP] + _fac->count[STATIC_FLATTENABLE]);
 
   // this transfers ownership of a lot of arrays from
   // the parser onto the InstanceKlass*
   apply_parsed_class_metadata(ik, _java_fields_count, CHECK);
 

@@ -5578,17 +5900,17 @@
   // Initialize itable offset tables
   klassItable::setup_itable_offset_table(ik);
 
   // Compute transitive closure of interfaces this class implements
   // Do final class setup
-  fill_oop_maps(ik,
-                _field_info->nonstatic_oop_map_count,
-                _field_info->nonstatic_oop_offsets,
-                _field_info->nonstatic_oop_counts);
+  OopMapBlocksBuilder* oop_map_blocks = _field_info->oop_map_blocks;
+  if (oop_map_blocks->nonstatic_oop_map_count > 0) {
+    oop_map_blocks->copy(ik->start_of_nonstatic_oop_maps());
+  }
 
   // Fill in has_finalizer, has_vanilla_constructor, and layout_helper
-  set_precomputed_flags(ik);
+  set_precomputed_flags(ik, CHECK);
 
   // check if this class can access its super class
   check_super_class_access(ik, CHECK);
 
   // check if this class can access its superinterfaces

@@ -5634,10 +5956,44 @@
       // We won a potential race
       JvmtiExport::add_default_read_edges(module_handle, THREAD);
     }
   }
 
+  int nfields = ik->java_fields_count();
+  if (ik->is_value()) nfields++;
+  for (int i = 0; i < nfields; i++) {
+    if (ik->field_is_flattenable(i)) {
+      Symbol* klass_name = ik->field_signature(i)->fundamental_name(CHECK);
+      // Inline classes for instance fields must have been pre-loaded
+      // Inline classes for static fields might not have been loaded yet
+      Klass* klass = SystemDictionary::find(klass_name,
+          Handle(THREAD, ik->class_loader()),
+          Handle(THREAD, ik->protection_domain()), CHECK);
+      if (klass != NULL) {
+        assert(klass->access_flags().is_value_type(), "Value type expected");
+        ik->set_value_field_klass(i, klass);
+      }
+      klass_name->decrement_refcount();
+    } else
+      if (is_value_type() && ((ik->field_access_flags(i) & JVM_ACC_FIELD_INTERNAL) != 0)
+        && ((ik->field_access_flags(i) & JVM_ACC_STATIC) != 0)) {
+      ValueKlass::cast(ik)->set_default_value_offset(ik->field_offset(i));
+    }
+  }
+
+  if (is_value_type()) {
+    ValueKlass* vk = ValueKlass::cast(ik);
+    if (UseNewLayout) {
+      vk->set_alignment(_alignment);
+      vk->set_first_field_offset(_first_field_offset);
+      vk->set_exact_size_in_bytes(_exact_size_in_bytes);
+    } else {
+      vk->set_first_field_offset(vk->first_field_offset_old());
+    }
+    ValueKlass::cast(ik)->initialize_calling_convention(CHECK);
+  }
+
   ClassLoadingService::notify_class_loaded(ik, false /* not shared class */);
 
   if (!is_internal()) {
     if (log_is_enabled(Info, class, load)) {
       ResourceMark rm;

@@ -5823,10 +6179,12 @@
   _need_verify(false),
   _relax_verify(false),
   _has_nonstatic_concrete_methods(false),
   _declares_nonstatic_concrete_methods(false),
   _has_final_method(false),
+  _has_flattenable_fields(false),
+  _is_empty_value(false),
   _has_finalizer(false),
   _has_empty_finalizer(false),
   _has_vanilla_constructor(false),
   _max_bootstrap_specifier_index(-1) {
 

@@ -6018,19 +6376,23 @@
   assert(cp_size == (const u2)cp->length(), "invariant");
 
   // ACCESS FLAGS
   stream->guarantee_more(8, CHECK);  // flags, this_class, super_class, infs_len
 
-  // Access flags
-  jint flags;
+  jint recognized_modifiers = JVM_RECOGNIZED_CLASS_MODIFIERS;
   // JVM_ACC_MODULE is defined in JDK-9 and later.
   if (_major_version >= JAVA_9_VERSION) {
-    flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE);
-  } else {
-    flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
+    recognized_modifiers |= JVM_ACC_MODULE;
+  }
+  // JVM_ACC_VALUE is defined for class file version 55 and later
+  if (supports_value_types()) {
+    recognized_modifiers |= JVM_ACC_VALUE;
   }
 
+  // Access flags
+  jint flags = stream->get_u2_fast() & recognized_modifiers;
+
   if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
     // Set abstract bit for old class files for backward compatibility
     flags |= JVM_ACC_ABSTRACT;
   }
 

@@ -6161,10 +6523,11 @@
 
   // Fields (offsets are filled in later)
   _fac = new FieldAllocationCount();
   parse_fields(stream,
                _access_flags.is_interface(),
+               _access_flags.is_value_type(),
                _fac,
                cp,
                cp_size,
                &_java_fields_count,
                CHECK);

@@ -6173,10 +6536,11 @@
 
   // Methods
   AccessFlags promoted_flags;
   parse_methods(stream,
                 _access_flags.is_interface(),
+                _access_flags.is_value_type(),
                 &promoted_flags,
                 &_has_final_method,
                 &_declares_nonstatic_concrete_methods,
                 CHECK);
 

@@ -6254,10 +6618,18 @@
         _class_name->as_klass_external_name(),
         _super_klass->external_name()
       );
       return;
     }
+
+    // For a value class, only java/lang/Object is an acceptable super class
+    if (_access_flags.get_flags() & JVM_ACC_VALUE) {
+      guarantee_property(_super_klass->name() == vmSymbols::java_lang_Object(),
+        "Value type must have java.lang.Object as superclass in class file %s",
+        CHECK);
+    }
+
     // Make sure super class is not final
     if (_super_klass->is_final()) {
       THROW_MSG(vmSymbols::java_lang_VerifyError(), "Cannot inherit from final class");
     }
   }

@@ -6294,14 +6666,39 @@
     klassItable::compute_itable_size(_transitive_interfaces);
 
   assert(_fac != NULL, "invariant");
   assert(_parsed_annotations != NULL, "invariant");
 
+
+  for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
+    if (fs.is_flattenable() && !fs.access_flags().is_static()) {
+      // Pre-load value class
+      Klass* klass = SystemDictionary::resolve_flattenable_field_or_fail(&fs,
+          Handle(THREAD, _loader_data->class_loader()),
+          _protection_domain, true, CHECK);
+      assert(klass != NULL, "Sanity check");
+      assert(klass->access_flags().is_value_type(), "Value type expected");
+      _has_flattenable_fields = true;
+    }
+  }
+
   _field_info = new FieldLayoutInfo();
-  layout_fields(cp, _fac, _parsed_annotations, _field_info, CHECK);
+  if (UseNewLayout) {
+    FieldLayoutBuilder lb(this, _field_info);
+    if (this->is_value_type()) {
+      lb.compute_inline_class_layout(CHECK);
+      _alignment = lb.get_alignment();
+      _first_field_offset = lb.get_first_field_offset();
+      _exact_size_in_bytes = lb.get_exact_size_in_byte();
+    } else {
+      lb.compute_regular_layout(CHECK);
+    }
+  } else {
+    layout_fields(cp, _fac, _parsed_annotations, _field_info, CHECK);
+  }
 
-  // Compute reference typ
+  // Compute reference type
   _rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();
 
 }
 
 void ClassFileParser::set_klass(InstanceKlass* klass) {

@@ -6331,10 +6728,11 @@
 const ClassFileStream* ClassFileParser::clone_stream() const {
   assert(_stream != NULL, "invariant");
 
   return _stream->clone();
 }
+
 // ----------------------------------------------------------------------------
 // debugging
 
 #ifdef ASSERT
 
< prev index next >