< prev index next >

src/hotspot/share/classfile/classFileParser.cpp

Print this page
*** 19,10 ***
--- 19,11 ---
   * 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 "classfile/classFileParser.hpp"
  #include "classfile/classFileStream.hpp"
  #include "classfile/classLoader.hpp"

*** 47,10 ***
--- 48,11 ---
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/annotations.hpp"
  #include "oops/constantPool.inline.hpp"
  #include "oops/fieldStreams.inline.hpp"
+ #include "oops/inlineKlass.inline.hpp"
  #include "oops/instanceKlass.inline.hpp"
  #include "oops/instanceMirrorKlass.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/klassVtable.hpp"
  #include "oops/metadata.hpp"

*** 80,10 ***
--- 82,11 ---
  #include "utilities/globalDefinitions.hpp"
  #include "utilities/growableArray.hpp"
  #include "utilities/macros.hpp"
  #include "utilities/ostream.hpp"
  #include "utilities/resourceHash.hpp"
+ #include "utilities/stringUtils.hpp"
  #include "utilities/utf8.hpp"
  
  #if INCLUDE_CDS
  #include "classfile/systemDictionaryShared.hpp"
  #endif

*** 137,10 ***
--- 140,13 ---
  
  #define JAVA_17_VERSION                   61
  
  #define JAVA_18_VERSION                   62
  
+ #define CONSTANT_CLASS_DESCRIPTORS        62
+ 
+ 
  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;

*** 176,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 : {
          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;
        }
--- 182,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: {
          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;
        }

*** 497,11 ***
        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++);
          break;
        }
        case JVM_CONSTANT_StringIndex: {
          const int string_index = cp->string_index_at(index);
          check_property(valid_symbol_at(string_index),
--- 503,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);
! 
+         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),

*** 697,21 ***
              // the right type.
              if (!Signature::is_method(signature)) {
                throwIllegalSignature("Method", name, signature, CHECK);
              }
            }
!           // If a class method name begins with '<', it must be "<init>" and have void signature.
            const unsigned int name_len = name->utf8_length();
            if (tag == JVM_CONSTANT_Methodref && name_len != 0 &&
                name->char_at(0) == JVM_SIGNATURE_SPECIAL) {
              if (name != vmSymbols::object_initializer_name()) {
                classfile_parse_error(
                  "Bad method name at constant pool index %u in class file %s",
                  name_ref_index, THREAD);
                return;
!             } else if (!Signature::is_void_method(signature)) { // must have void signature.
!               throwIllegalSignature("Method", name, signature, CHECK);
              }
            }
          }
          break;
        }
--- 710,26 ---
              // the right type.
              if (!Signature::is_method(signature)) {
                throwIllegalSignature("Method", name, signature, CHECK);
              }
            }
!           // If a class method name begins with '<', it must be "<init>" and have void signature
+           // unless it's an inline type.
            const unsigned int name_len = name->utf8_length();
            if (tag == JVM_CONSTANT_Methodref && name_len != 0 &&
                name->char_at(0) == JVM_SIGNATURE_SPECIAL) {
              if (name != vmSymbols::object_initializer_name()) {
                classfile_parse_error(
                  "Bad method name at constant pool index %u in class file %s",
                  name_ref_index, THREAD);
                return;
!             } else if (!Signature::is_void_method(signature)) {
!               // if return type is non-void then it cannot be a basic primitive
+               // and primitve types must be supported.
+               if (!signature->ends_with(JVM_SIGNATURE_ENDCLASS) || !EnableValhalla) {
+                 throwIllegalSignature("Method", name, signature, CHECK);
+               }
              }
            }
          }
          break;
        }

*** 726,19 ***
              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()) {
                  classfile_parse_error(
                    "Bad constructor name at constant pool index %u in class file %s",
                      name_ref_index, THREAD);
                  return;
                }
              } else {
!               if (name == vmSymbols::object_initializer_name()) {
                  classfile_parse_error(
                    "Bad method name at constant pool index %u in class file %s",
                    name_ref_index, THREAD);
                  return;
                }
--- 744,30 ---
              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 (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, THREAD);
                  return;
                }
              } else {
!               // 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, THREAD);
                  return;
                }

*** 812,26 ***
  
    return true;
  }
  
  // Side-effects: populates the _local_interfaces field
! void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
!                                        const int itfs_len,
!                                        ConstantPool* const cp,
                                         bool* const has_nonstatic_concrete_methods,
                                         TRAPS) {
    assert(stream != NULL, "invariant");
    assert(cp != NULL, "invariant");
    assert(has_nonstatic_concrete_methods != NULL, "invariant");
  
    if (itfs_len == 0) {
!     _local_interfaces = Universe::the_empty_instance_klass_array();
    } else {
      assert(itfs_len > 0, "only called for len>0");
!     _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, NULL, CHECK);
! 
-     int index;
      for (index = 0; index < itfs_len; index++) {
        const u2 interface_index = stream->get_u2(CHECK);
        Klass* interf;
        check_property(
          valid_klass_reference_at(interface_index),
--- 841,32 ---
  
    return true;
  }
  
  // Side-effects: populates the _local_interfaces field
! void ClassFileParser::parse_interfaces(const ClassFileStream* stream,
!                                        int itfs_len,
!                                        ConstantPool* cp,
                                         bool* const has_nonstatic_concrete_methods,
+                                        // FIXME: lots of these functions
+                                        // declare their parameters as const,
+                                        // which adds only noise to the code.
+                                        // Remove the spurious const modifiers.
+                                        // Many are of the form "const int x"
+                                        // or "T* const x".
+                                        bool* const is_declared_atomic,
                                         TRAPS) {
    assert(stream != NULL, "invariant");
    assert(cp != NULL, "invariant");
    assert(has_nonstatic_concrete_methods != NULL, "invariant");
  
    if (itfs_len == 0) {
!     _temp_local_interfaces = new GrowableArray<InstanceKlass*>(0);
    } else {
      assert(itfs_len > 0, "only called for len>0");
!     _temp_local_interfaces = new GrowableArray<InstanceKlass*>(itfs_len);
!     int index = 0;
      for (index = 0; index < itfs_len; index++) {
        const u2 interface_index = stream->get_u2(CHECK);
        Klass* interf;
        check_property(
          valid_klass_reference_at(interface_index),

*** 863,14 ***
                            _class_name->as_klass_external_name(),
                            interf->external_name(),
                            interf->class_in_module_of_loader()));
        }
  
!       if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
          *has_nonstatic_concrete_methods = true;
        }
!       _local_interfaces->at_put(index, InstanceKlass::cast(interf));
      }
  
      if (!_need_verify || itfs_len <= 1) {
        return;
      }
--- 898,38 ---
                            _class_name->as_klass_external_name(),
                            interf->external_name(),
                            interf->class_in_module_of_loader()));
        }
  
!       InstanceKlass* ik = InstanceKlass::cast(interf);
+       if (is_inline_type() && ik->invalid_inline_super()) {
+         ResourceMark rm(THREAD);
+         Exceptions::fthrow(
+           THREAD_AND_LOCATION,
+           vmSymbols::java_lang_IncompatibleClassChangeError(),
+           "Inline type %s attempts to implement interface java.lang.IdentityObject",
+           _class_name->as_klass_external_name());
+         return;
+       }
+       if (ik->invalid_inline_super()) {
+         set_invalid_inline_super();
+       }
+       if (ik->has_nonstatic_concrete_methods()) {
          *has_nonstatic_concrete_methods = true;
        }
!       if (ik->is_declared_atomic()) {
+         *is_declared_atomic = true;
+       }
+       if (ik->name() == vmSymbols::java_lang_IdentityObject()) {
+         _implements_identityObject = true;
+       }
+       if (ik->name() == vmSymbols::java_lang_PrimitiveObject()) {
+         // further checks for "is_invalid_super_for_inline_type()" needed later
+         // needs field parsing, delay unitl post_process_parse_stream()
+         _implements_primitiveObject = true;
+       }
+       _temp_local_interfaces->append(ik);
      }
  
      if (!_need_verify || itfs_len <= 1) {
        return;
      }

*** 884,11 ***
      bool dup = false;
      const Symbol* name = NULL;
      {
        debug_only(NoSafepointVerifier nsv;)
        for (index = 0; index < itfs_len; index++) {
!         const InstanceKlass* const k = _local_interfaces->at(index);
          name = k->name();
          // If no duplicates, add (name, NULL) in hashtable interface_names.
          if (!put_after_lookup(name, NULL, interface_names)) {
            dup = true;
            break;
--- 943,11 ---
      bool dup = false;
      const Symbol* name = NULL;
      {
        debug_only(NoSafepointVerifier nsv;)
        for (index = 0; index < itfs_len; index++) {
!         const InstanceKlass* const k = _temp_local_interfaces->at(index);
          name = k->name();
          // If no duplicates, add (name, NULL) in hashtable interface_names.
          if (!put_after_lookup(name, NULL, interface_names)) {
            dup = true;
            break;

*** 1369,15 ***
--- 1428,17 ---
    STATIC_OOP,           // Oops
    STATIC_BYTE,          // Boolean, Byte, char
    STATIC_SHORT,         // shorts
    STATIC_WORD,          // ints
    STATIC_DOUBLE,        // aligned long or double
+   STATIC_INLINE,        // inline type field
    NONSTATIC_OOP,
    NONSTATIC_BYTE,
    NONSTATIC_SHORT,
    NONSTATIC_WORD,
    NONSTATIC_DOUBLE,
+   NONSTATIC_INLINE,
    MAX_FIELD_ALLOCATION_TYPE,
    BAD_ALLOCATION_TYPE = -1
  };
  
  static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {

*** 1393,16 ***
    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,
    BAD_ALLOCATION_TYPE, // 0
    BAD_ALLOCATION_TYPE, // 1
    BAD_ALLOCATION_TYPE, // 2
    BAD_ALLOCATION_TYPE, // 3
    STATIC_BYTE ,        // T_BOOLEAN     =  4,
--- 1454,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,
!   NONSTATIC_OOP,       // T_INLINE_TYPE = 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,

*** 1413,22 ***
    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 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 ClassFileParser::FieldAllocationCount : public ResourceObj {
   public:
--- 1475,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,
!   STATIC_OOP,          // T_INLINE_TYPE = 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, bool is_inline_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");
+   if (is_inline_type) {
+     result = is_static ? STATIC_INLINE : NONSTATIC_INLINE;
+   }
    return result;
  }
  
  class ClassFileParser::FieldAllocationCount : public ResourceObj {
   public:

*** 1438,12 ***
      for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) {
        count[i] = 0;
      }
    }
  
!   void update(bool is_static, BasicType type) {
!     FieldAllocationType atype = basic_type_to_atype(is_static, type);
      if (atype != BAD_ALLOCATION_TYPE) {
        // Make sure there is no overflow with injected fields.
        assert(count[atype] < 0xFFFF, "More than 65535 fields");
        count[atype]++;
      }
--- 1504,12 ---
      for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) {
        count[i] = 0;
      }
    }
  
!   void update(bool is_static, BasicType type, bool is_inline_type) {
!     FieldAllocationType atype = basic_type_to_atype(is_static, type, is_inline_type);
      if (atype != BAD_ALLOCATION_TYPE) {
        // Make sure there is no overflow with injected fields.
        assert(count[atype] < 0xFFFF, "More than 65535 fields");
        count[atype]++;
      }

*** 1452,10 ***
--- 1518,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_inline_type,
                                     FieldAllocationCount* const fac,
                                     ConstantPool* cp,
                                     const int cp_size,
                                     u2* const java_fields_count_ptr,
                                     TRAPS) {

*** 1474,11 ***
    *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;
  
    // 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
--- 1541,15 ---
    *java_fields_count_ptr = length;
  
    int num_injected = 0;
    const InjectedField* const injected = JavaClasses::get_injected(_class_name,
                                                                    &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_inline_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

*** 1504,17 ***
                                                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;
    for (int n = 0; n < length; n++) {
      // access_flags, name_index, descriptor_index, attributes_count
      cfs->guarantee_more(8, 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",
--- 1575,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_inline_type, CHECK);
      AccessFlags access_flags;
      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",

*** 1526,10 ***
--- 1600,11 ---
      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);
+     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();

*** 1585,11 ***
                        signature_index,
                        constantvalue_index);
      const BasicType type = cp->basic_type_for_signature_at(signature_index);
  
      // Update FieldAllocationCount for this kind of field
!     fac->update(is_static, type);
  
      // After field is initialized with type, we can augment it with aux info
      if (parsed_annotations.has_any_annotations()) {
        parsed_annotations.apply_to(field);
        if (field->is_contended()) {
--- 1660,11 ---
                        signature_index,
                        constantvalue_index);
      const BasicType type = cp->basic_type_for_signature_at(signature_index);
  
      // Update FieldAllocationCount for this kind of field
!     fac->update(is_static, type, type == T_INLINE_TYPE);
  
      // After field is initialized with type, we can augment it with aux info
      if (parsed_annotations.has_any_annotations()) {
        parsed_annotations.apply_to(field);
        if (field->is_contended()) {

*** 1629,15 ***
                          0);
  
        const BasicType type = Signature::basic_type(injected[n].signature());
  
        // Update FieldAllocationCount for this kind of field
!       fac->update(false, type);
        index++;
      }
    }
  
    assert(NULL == _fields, "invariant");
  
    _fields =
      MetadataFactory::new_array<u2>(_loader_data,
                                     index * FieldInfo::field_slots + num_generic_signature,
--- 1704,42 ---
                          0);
  
        const BasicType type = Signature::basic_type(injected[n].signature());
  
        // Update FieldAllocationCount for this kind of field
!       fac->update(false, type, false);
        index++;
      }
    }
  
+   if (is_inline_type) {
+     FieldInfo* const field = FieldInfo::from_field_array(fa, index);
+     field->initialize(JVM_ACC_FIELD_INTERNAL | JVM_ACC_STATIC,
+                       (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(default_value_name)),
+                       (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(object_signature)),
+                       0);
+     const BasicType type = Signature::basic_type(vmSymbols::object_signature());
+     fac->update(true, type, false);
+     index++;
+   }
+ 
+   if (is_inline_type && instance_fields_count == 0) {
+     _is_empty_inline_type = true;
+     FieldInfo* const field = FieldInfo::from_field_array(fa, index);
+     field->initialize(JVM_ACC_FIELD_INTERNAL,
+         (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(empty_marker_name)),
+         (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(byte_signature)),
+         0);
+     const BasicType type = Signature::basic_type(vmSymbols::byte_signature());
+     fac->update(false, type, false);
+     index++;
+   }
+ 
+   if (instance_fields_count > 0) {
+     _has_nonstatic_fields = true;
+   }
+ 
    assert(NULL == _fields, "invariant");
  
    _fields =
      MetadataFactory::new_array<u2>(_loader_data,
                                     index * FieldInfo::field_slots + num_generic_signature,

*** 1951,15 ***
                                              const Symbol* sig,
                                              TRAPS) const {
    assert(name != NULL, "invariant");
    assert(sig != NULL, "invariant");
  
    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());
  }
  
  AnnotationCollector::ID
  AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
                                        const Symbol* name,
--- 2053,20 ---
                                              const Symbol* sig,
                                              TRAPS) const {
    assert(name != NULL, "invariant");
    assert(sig != NULL, "invariant");
  
+   const char* class_note = "";
+   if (is_inline_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%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,

*** 2244,10 ***
--- 2351,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_inline_type,
                                        const ConstantPool* cp,
                                        AccessFlags* const promoted_flags,
                                        TRAPS) {
    assert(cfs != NULL, "invariant");
    assert(cp != NULL, "invariant");

*** 2285,16 ***
      } else {
        classfile_parse_error("Method <clinit> is not static in class file %s", THREAD);
        return NULL;
      }
    } else {
!     verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL);
    }
  
!   if (name == vmSymbols::object_initializer_name() && is_interface) {
!     classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD);
!     return NULL;
    }
  
    int args_size = -1;  // only used when _need_verify is true
    if (_need_verify) {
      verify_legal_name_with_signature(name, signature, CHECK_NULL);
--- 2393,61 ---
      } else {
        classfile_parse_error("Method <clinit> is not static in class file %s", THREAD);
        return NULL;
      }
    } else {
!     verify_legal_method_modifiers(flags, is_interface, is_inline_type, name, CHECK_NULL);
    }
  
!   if (name == vmSymbols::object_initializer_name()) {
!     if (is_interface) {
!       classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD);
+       return NULL;
+     } else if (!is_inline_type && signature->is_void_method_signature()) {
+       // OK, a constructor
+     } else if (is_inline_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_reference()) {
+         Symbol* ret = ss.as_symbol();
+         const Symbol* required = class_name();
+         if (is_hidden()) {
+           // The original class name in hidden classes gets changed.  So using
+           // the original name in the return type is no longer valid.
+           // Note that expecting the return type for inline hidden class factory
+           // methods to be java.lang.Object works around a JVM Spec issue for
+           // hidden classes.
+           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) {
      verify_legal_name_with_signature(name, signature, CHECK_NULL);

*** 2858,10 ***
--- 3011,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_inline_type,
                                      AccessFlags* promoted_flags,
                                      bool* has_final_method,
                                      bool* declares_nonstatic_concrete_methods,
                                      TRAPS) {
    assert(cfs != NULL, "invariant");

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

*** 3149,18 ***
        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;
      // 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;
      }
      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);
--- 3304,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);
      }
! 
!     jint recognized_modifiers = RECOGNIZED_INNER_CLASS_MODIFIERS;
      // JVM_ACC_MODULE is defined in JDK-9 and later.
      if (_major_version >= JAVA_9_VERSION) {
!       recognized_modifiers |= JVM_ACC_MODULE;
      }
+     // JVM_ACC_INLINE is defined for class file version 55 and later
+     if (supports_inline_types()) {
+       recognized_modifiers |= JVM_ACC_INLINE;
+     }
+ 
+     // 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);

*** 4002,12 ***
    assert(cp != NULL, "invariant");
    const InstanceKlass* super_klass = NULL;
  
    if (super_class_index == 0) {
      check_property(_class_name == vmSymbols::java_lang_Object(),
!                    "Invalid superclass index %u in class file %s",
-                    super_class_index,
                     CHECK_NULL);
    } else {
      check_property(valid_klass_reference_at(super_class_index),
                     "Invalid superclass index %u in class file %s",
                     super_class_index,
--- 4163,11 ---
    assert(cp != NULL, "invariant");
    const InstanceKlass* super_klass = NULL;
  
    if (super_class_index == 0) {
      check_property(_class_name == vmSymbols::java_lang_Object(),
!                    "Invalid superclass index 0 in class file %s",
                     CHECK_NULL);
    } else {
      check_property(valid_klass_reference_at(super_class_index),
                     "Invalid superclass index %u in class file %s",
                     super_class_index,

*** 4144,10 ***
--- 4304,29 ---
  
  void OopMapBlocksBuilder::print_value_on(outputStream* st) const {
    print_on(st);
  }
  
+ void ClassFileParser::throwInlineTypeLimitation(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);
+   }
+ }
+ 
  void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) {
    assert(ik != NULL, "invariant");
  
    const Klass* const super = ik->super();
  

*** 4177,10 ***
--- 4356,15 ---
  #endif
  
    // Check if this klass supports the java.lang.Cloneable interface
    if (vmClasses::Cloneable_klass_loaded()) {
      if (ik->is_subtype_of(vmClasses::Cloneable_klass())) {
+       if (ik->is_inline_klass()) {
+         JavaThread *THREAD = JavaThread::current();
+         throwInlineTypeLimitation(THREAD_AND_LOCATION, "Inline Types do not support Cloneable");
+         return;
+       }
        ik->set_is_cloneable();
      }
    }
  
    // Check if this klass has a vanilla default constructor

*** 4217,10 ***
--- 4401,15 ---
      const jint lh = Klass::instance_layout_helper(ik->size_helper(), true);
      ik->set_layout_helper(lh);
    }
  }
  
+ bool ClassFileParser::supports_inline_types() const {
+   // Inline 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

*** 4260,13 ***
      // no interfaces, use canonicalized array
      return Universe::the_empty_instance_klass_array();
    } else if (max_transitive_size == super_size) {
      // no new local interfaces added, share superklass' transitive interface array
      return super->transitive_interfaces();
!   } else if (max_transitive_size == local_size) {
!     // only local interfaces added, share local interface array
!     return local_ifs;
    } else {
      ResourceMark rm;
      GrowableArray<InstanceKlass*>* const result = new GrowableArray<InstanceKlass*>(max_transitive_size);
  
      // Copy down from superclass
--- 4449,14 ---
      // no interfaces, use canonicalized array
      return Universe::the_empty_instance_klass_array();
    } else if (max_transitive_size == super_size) {
      // no new local interfaces added, share superklass' transitive interface array
      return super->transitive_interfaces();
!     // The three lines below are commented to work around bug JDK-8245487
! //  } else if (max_transitive_size == local_size) {
! //    // only local interfaces added, share local interface array
+ //    return local_ifs;
    } else {
      ResourceMark rm;
      GrowableArray<InstanceKlass*>* const result = new GrowableArray<InstanceKlass*>(max_transitive_size);
  
      // Copy down from superclass

*** 4283,10 ***
--- 4473,18 ---
      append_interfaces(result, local_ifs);
  
      // length will be less than the max_transitive_size if duplicates were removed
      const int length = result->length();
      assert(length <= max_transitive_size, "just checking");
+ 
+     if (length == 1 && result->at(0) == vmClasses::IdentityObject_klass()) {
+       return Universe::the_single_IdentityObject_klass_array();
+     }
+     if (length == 1 && result->at(0) == vmClasses::PrimitiveObject_klass()) {
+       return Universe::the_single_PrimitiveObject_klass_array();
+     }
+ 
      Array<InstanceKlass*>* const new_result =
        MetadataFactory::new_array<InstanceKlass*>(loader_data, length, CHECK_NULL);
      for (int i = 0; i < length; i++) {
        InstanceKlass* const e = result->at(i);
        assert(e != NULL, "just checking");

*** 4496,21 ***
--- 4694,34 ---
  
  // 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_inline_type = (flags & JVM_ACC_INLINE) != 0;
    assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set");
+   assert(supports_inline_types() || !is_inline_type, "JVM_ACC_INLINE 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_inline_type && !EnableValhalla) {
+     ResourceMark rm(THREAD);
+     Exceptions::fthrow(
+       THREAD_AND_LOCATION,
+       vmSymbols::java_lang_ClassFormatError(),
+       "Class modifier ACC_INLINE in class %s requires option -XX:+EnableValhalla",
+       _class_name->as_C_string()
+     );
+     return;
+   }
+ 
    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;

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

*** 4597,10 ***
--- 4811,11 ---
    }
  }
  
  void ClassFileParser::verify_legal_field_modifiers(jint flags,
                                                     bool is_interface,
+                                                    bool is_inline_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;

*** 4621,10 ***
--- 4836,14 ---
        is_illegal = true;
      }
    } else { // not interface
      if (has_illegal_visibility(flags) || (is_final && is_volatile)) {
        is_illegal = true;
+     } else {
+       if (is_inline_type && !is_static && !is_final) {
+         is_illegal = true;
+       }
      }
    }
  
    if (is_illegal) {
      ResourceMark rm(THREAD);

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

*** 4658,10 ***
--- 4878,11 ---
    const bool major_gte_17    = _major_version >= JAVA_17_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

*** 4692,19 ***
    } else { // not interface
      if (has_illegal_visibility(flags)) {
        is_illegal = true;
      } else {
        if (is_initializer) {
!         if (is_static || is_final || is_synchronized || is_native ||
              is_abstract || (major_gte_1_5 && is_bridge)) {
            is_illegal = true;
          }
        } else { // not initializer
!         if (is_abstract) {
!           if ((is_final || is_native || is_private || is_static ||
!               (major_gte_1_5 && (is_synchronized || (!major_gte_17 && is_strict))))) {
!             is_illegal = true;
            }
          }
        }
      }
    }
--- 4913,33 ---
    } else { // not interface
      if (has_illegal_visibility(flags)) {
        is_illegal = true;
      } else {
        if (is_initializer) {
!         if (is_final || is_synchronized || is_native ||
              is_abstract || (major_gte_1_5 && is_bridge)) {
            is_illegal = true;
          }
+         if (!is_static && !is_inline_type) {
+           // OK, an object constructor in a regular class
+         } else if (is_static && is_inline_type) {
+           // OK, a static init factory in an inline class
+         } else {
+           // but no other combinations are allowed
+           is_illegal = true;
+           class_note = (is_inline_type ? " (an inline class)" : " (not an inline class)");
+         }
        } else { // not initializer
!         if (is_inline_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_1_5 && (is_synchronized || (!major_gte_17 && is_strict))))) {
+               is_illegal = true;
+             }
            }
          }
        }
      }
    }

*** 4712,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);
      return;
    }
  }
  
  void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
--- 4947,12 ---
    if (is_illegal) {
      ResourceMark rm(THREAD);
      Exceptions::fthrow(
        THREAD_AND_LOCATION,
        vmSymbols::java_lang_ClassFormatError(),
!       "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,

*** 4871,22 ***
      case JVM_SIGNATURE_INT:
      case JVM_SIGNATURE_FLOAT:
      case JVM_SIGNATURE_LONG:
      case JVM_SIGNATURE_DOUBLE:
        return signature + 1;
!     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] == JVM_SIGNATURE_ENDCLASS) {
            return p + 1;
          }
        }
        else {
!         // Skip leading 'L' and ignore first appearance of ';'
          signature++;
          const char* c = (const char*) memchr(signature, JVM_SIGNATURE_ENDCLASS, length - 1);
          // Format check signature
          if (c != NULL) {
            int newlen = c - (char*) signature;
--- 5106,31 ---
      case JVM_SIGNATURE_INT:
      case JVM_SIGNATURE_FLOAT:
      case JVM_SIGNATURE_LONG:
      case JVM_SIGNATURE_DOUBLE:
        return signature + 1;
!     case JVM_SIGNATURE_INLINE_TYPE:
+       // 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] == JVM_SIGNATURE_ENDCLASS) {
            return p + 1;
          }
        }
        else {
!         // Skip leading 'L' or 'Q' and ignore first appearance of ';'
          signature++;
          const char* c = (const char*) memchr(signature, JVM_SIGNATURE_ENDCLASS, length - 1);
          // Format check signature
          if (c != NULL) {
            int newlen = c - (char*) signature;

*** 4938,10 ***
--- 5182,14 ---
      } else if (_major_version < JAVA_1_5_VERSION) {
        if (bytes[0] != JVM_SIGNATURE_SPECIAL) {
          p = skip_over_field_name(bytes, true, length);
          legal = (p != NULL) && ((p - bytes) == (int)length);
        }
+     } else if ((_major_version >= CONSTANT_CLASS_DESCRIPTORS || _class_name->starts_with("jdk/internal/reflect/"))
+                    && 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.

*** 5035,10 ***
--- 5283,13 ---
  // Checks if signature is a legal field signature.
  void ClassFileParser::verify_legal_field_signature(const Symbol* name,
                                                     const Symbol* signature,
                                                     TRAPS) const {
    if (!_need_verify) { return; }
+   if (!supports_inline_types() && (signature->is_Q_signature() || signature->is_Q_array_signature())) {
+     throwIllegalSignature("Field", name, signature, CHECK);
+   }
  
    const char* const bytes = (const char* const)signature->bytes();
    const unsigned int length = signature->utf8_length();
    const char* const p = skip_over_field_signature(bytes, false, length, CHECK);
  

*** 5062,16 ***
        _major_version >= JAVA_7_VERSION) {
      throwIllegalSignature("Method", name, signature, THREAD);
      return;
    }
  
!   int sig_length = signature->utf8_length();
!   if (name->utf8_length() > 0 &&
        name->char_at(0) == JVM_SIGNATURE_SPECIAL &&
        sig_length > 0 &&
        signature->char_at(sig_length - 1) != JVM_SIGNATURE_VOID) {
!     throwIllegalSignature("Method", name, signature, THREAD);
    }
  }
  
  // Checks if signature is a legal method signature.
  // Returns number of parameters
--- 5313,18 ---
        _major_version >= JAVA_7_VERSION) {
      throwIllegalSignature("Method", name, signature, THREAD);
      return;
    }
  
!   if (!is_inline_type()) {
!     int sig_length = signature->utf8_length();
+     if (name->utf8_length() > 0 &&
        name->char_at(0) == JVM_SIGNATURE_SPECIAL &&
        sig_length > 0 &&
        signature->char_at(sig_length - 1) != JVM_SIGNATURE_VOID) {
!       throwIllegalSignature("Method", name, signature, THREAD);
+     }
    }
  }
  
  // Checks if signature is a legal method signature.
  // Returns number of parameters

*** 5244,13 ***
--- 5497,53 ---
  
    fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL);
  
    assert(_klass == ik, "invariant");
  
+   if (ik->is_inline_klass()) {
+     InlineKlass* vk = InlineKlass::cast(ik);
+     oop val = ik->allocate_instance(CHECK_NULL);
+     vk->set_default_value(val);
+   }
+ 
    return ik;
  }
  
+ // Return true if the specified class is not a valid super class for an inline type.
+ // A valid super class for an inline type is abstract, has no instance fields,
+ // does not implement interface java.lang.IdentityObject (checked elsewhere), has
+ // an empty body-less no-arg constructor, and no synchronized instance methods.
+ // This function doesn't check if the class's super types are invalid.  Those checks
+ // are done elsewhere.  The final determination of whether or not a class is an
+ // invalid super type for an inline class is done in fill_instance_klass().
+ bool ClassFileParser::is_invalid_super_for_inline_type() {
+   if (class_name() == vmSymbols::java_lang_IdentityObject()) {
+     return true;
+   }
+   if (is_interface() || class_name() == vmSymbols::java_lang_Object()) {
+     return false;
+   }
+   if (!access_flags().is_abstract() || _has_nonstatic_fields) {
+     return true;
+   } else {
+     // Look at each method
+     for (int x = 0; x < _methods->length(); x++) {
+       const Method* const method = _methods->at(x);
+       if (method->is_synchronized() && !method->is_static()) {
+         return true;
+ 
+       } else if (method->name() == vmSymbols::object_initializer_name()) {
+         if (method->signature() != vmSymbols::void_method_signature() ||
+             !method->is_vanilla_constructor()) {
+           return true;
+         }
+       }
+     }
+   }
+   return false;
+ }
+ 
  void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
                                            bool changed_by_loadhook,
                                            const ClassInstanceInfo& cl_inst_info,
                                            TRAPS) {
    assert(ik != NULL, "invariant");

*** 5279,12 ***
    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);
    assert(_fac != NULL, "invariant");
!   ik->set_static_oop_field_count(_fac->count[STATIC_OOP]);
  
    // this transfers ownership of a lot of arrays from
    // the parser onto the InstanceKlass*
    apply_parsed_class_metadata(ik, _java_fields_count);
  
--- 5572,27 ---
    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 (_field_info->_is_naturally_atomic && ik->is_inline_klass()) {
+     ik->set_is_naturally_atomic();
+   }
+ 
+   if (this->_invalid_inline_super) {
+     ik->set_invalid_inline_super();
+   }
+ 
+   if (_has_injected_identityObject) {
+     ik->set_has_injected_identityObject();
+   }
+   if (_has_injected_primitiveObject) {
+     ik->set_has_injected_primitiveObject();
+   }
+ 
    assert(_fac != NULL, "invariant");
!   ik->set_static_oop_field_count(_fac->count[STATIC_OOP] + _fac->count[STATIC_INLINE]);
  
    // this transfers ownership of a lot of arrays from
    // the parser onto the InstanceKlass*
    apply_parsed_class_metadata(ik, _java_fields_count);
  

*** 5330,10 ***
--- 5638,13 ---
  
    ik->set_minor_version(_minor_version);
    ik->set_major_version(_major_version);
    ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);
    ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods);
+   if (_is_declared_atomic) {
+     ik->set_is_declared_atomic();
+   }
  
    if (_is_hidden) {
      ik->set_is_hidden();
    }
  

*** 5437,10 ***
--- 5748,47 ---
        // We won a potential race
        JvmtiExport::add_default_read_edges(module_handle, THREAD);
      }
    }
  
+   bool all_fields_empty = true;
+   int nfields = ik->java_fields_count();
+   if (ik->is_inline_klass()) nfields++;
+   for (int i = 0; i < nfields; i++) {
+     if (((ik->field_access_flags(i) & JVM_ACC_STATIC) == 0)) {
+       if (ik->field_is_null_free_inline_type(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
+         InstanceKlass* klass = SystemDictionary::find_instance_klass(klass_name,
+             Handle(THREAD, ik->class_loader()),
+             Handle(THREAD, ik->protection_domain()));
+         assert(klass != NULL, "Just checking");
+         assert(klass->access_flags().is_inline_type(), "Inline type expected");
+         ik->set_inline_type_field_klass(i, klass);
+         klass_name->decrement_refcount();
+         if (!InlineKlass::cast(klass)->is_empty_inline_type()) { all_fields_empty = false; }
+       } else {
+         all_fields_empty = false;
+       }
+     } else if (is_inline_type() && ((ik->field_access_flags(i) & JVM_ACC_FIELD_INTERNAL) != 0)) {
+       InlineKlass::cast(ik)->set_default_value_offset(ik->field_offset(i));
+     }
+   }
+ 
+   if (_is_empty_inline_type || (is_inline_type() && all_fields_empty)) {
+     ik->set_is_empty_inline_type();
+   }
+ 
+   if (is_inline_type()) {
+     InlineKlass* vk = InlineKlass::cast(ik);
+     vk->set_alignment(_alignment);
+     vk->set_first_field_offset(_first_field_offset);
+     vk->set_exact_size_in_bytes(_exact_size_in_bytes);
+     InlineKlass::cast(ik)->initialize_calling_convention(CHECK);
+   }
+ 
    ClassLoadingService::notify_class_loaded(ik, false /* not shared class */);
  
    if (!is_internal()) {
      ik->print_class_load_logging(_loader_data, module_entry, _stream);
  

*** 5482,10 ***
--- 5830,20 ---
    set_klass_to_deallocate(NULL);
  
    // it's official
    set_klass(ik);
  
+   // the common single interface arrays need setup here to provide the
+   // correct answer to "compute_transitive_interfaces()", during
+   // "SystemDictionary::initialize()"
+   if (ik->name() == vmSymbols::java_lang_IdentityObject()) {
+     Universe::initialize_the_single_IdentityObject_klass_array(ik, CHECK);
+   }
+   if (ik->name() == vmSymbols::java_lang_PrimitiveObject()) {
+     Universe::initialize_the_single_PrimitiveObject_klass_array(ik, CHECK);
+   }
+ 
    debug_only(ik->verify();)
  }
  
  void ClassFileParser::update_class_name(Symbol* new_class_name) {
    // Decrement the refcount in the old name, since we're clobbering it.

*** 5528,10 ***
--- 5886,11 ---
    _inner_classes(NULL),
    _nest_members(NULL),
    _nest_host(0),
    _permitted_subclasses(NULL),
    _record_components(NULL),
+   _temp_local_interfaces(NULL),
    _local_interfaces(NULL),
    _transitive_interfaces(NULL),
    _combined_annotations(NULL),
    _class_annotations(NULL),
    _class_type_annotations(NULL),

*** 5567,10 ***
--- 5926,21 ---
    _relax_verify(false),
    _has_nonstatic_concrete_methods(false),
    _declares_nonstatic_concrete_methods(false),
    _has_final_method(false),
    _has_contended_fields(false),
+   _has_inline_type_fields(false),
+   _has_nonstatic_fields(false),
+   _is_empty_inline_type(false),
+   _is_naturally_atomic(false),
+   _is_declared_atomic(false),
+   _invalid_inline_super(false),
+   _invalid_identity_super(false),
+   _implements_identityObject(false),
+   _has_injected_identityObject(false),
+   _implements_primitiveObject(false),
+   _has_injected_primitiveObject(false),
    _has_finalizer(false),
    _has_empty_finalizer(false),
    _has_vanilla_constructor(false),
    _max_bootstrap_specifier_index(-1) {
  

*** 5739,18 ***
    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;
    // 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;
    }
  
    if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
      // Set abstract bit for old class files for backward compatibility
      flags |= JVM_ACC_ABSTRACT;
    }
--- 6109,22 ---
    assert(cp_size == (const u2)cp->length(), "invariant");
  
    // ACCESS FLAGS
    stream->guarantee_more(8, CHECK);  // flags, this_class, super_class, infs_len
  
!   jint recognized_modifiers = JVM_RECOGNIZED_CLASS_MODIFIERS;
    // JVM_ACC_MODULE is defined in JDK-9 and later.
    if (_major_version >= JAVA_9_VERSION) {
!     recognized_modifiers |= JVM_ACC_MODULE;
    }
+   // JVM_ACC_INLINE is defined for class file version 55 and later
+   if (supports_inline_types()) {
+     recognized_modifiers |= JVM_ACC_INLINE;
+   }
+ 
+   // 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;
    }

*** 5853,18 ***
    _itfs_len = stream->get_u2_fast();
    parse_interfaces(stream,
                     _itfs_len,
                     cp,
                     &_has_nonstatic_concrete_methods,
                     CHECK);
  
!   assert(_local_interfaces != NULL, "invariant");
  
    // Fields (offsets are filled in later)
    _fac = new FieldAllocationCount();
    parse_fields(stream,
!                _access_flags.is_interface(),
                 _fac,
                 cp,
                 cp_size,
                 &_java_fields_count,
                 CHECK);
--- 6227,20 ---
    _itfs_len = stream->get_u2_fast();
    parse_interfaces(stream,
                     _itfs_len,
                     cp,
                     &_has_nonstatic_concrete_methods,
+                    &_is_declared_atomic,
                     CHECK);
  
!   assert(_temp_local_interfaces != NULL, "invariant");
  
    // Fields (offsets are filled in later)
    _fac = new FieldAllocationCount();
    parse_fields(stream,
!                is_interface(),
+                is_inline_type(),
                 _fac,
                 cp,
                 cp_size,
                 &_java_fields_count,
                 CHECK);

*** 5872,11 ***
    assert(_fields != NULL, "invariant");
  
    // Methods
    AccessFlags promoted_flags;
    parse_methods(stream,
!                 _access_flags.is_interface(),
                  &promoted_flags,
                  &_has_final_method,
                  &_declares_nonstatic_concrete_methods,
                  CHECK);
  
--- 6248,12 ---
    assert(_fields != NULL, "invariant");
  
    // Methods
    AccessFlags promoted_flags;
    parse_methods(stream,
!                 is_interface(),
+                 is_inline_type(),
                  &promoted_flags,
                  &_has_final_method,
                  &_declares_nonstatic_concrete_methods,
                  CHECK);
  

*** 5954,18 ***
    assert(stream->at_eos(), "invariant");
    assert(cp != NULL, "invariant");
    assert(_loader_data != NULL, "invariant");
  
    if (_class_name == vmSymbols::java_lang_Object()) {
!     check_property(_local_interfaces == Universe::the_empty_instance_klass_array(),
!                    "java.lang.Object cannot implement an interface in class file %s",
!                    CHECK);
    }
    // We check super class after class file is parsed and format is checked
    if (_super_class_index > 0 && NULL == _super_klass) {
      Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
!     if (_access_flags.is_interface()) {
        // Before attempting to resolve the superclass, check for class format
        // errors not checked yet.
        guarantee_property(super_class_name == vmSymbols::java_lang_Object(),
          "Interfaces must have java.lang.Object as superclass in class file %s",
          CHECK);
--- 6331,18 ---
    assert(stream->at_eos(), "invariant");
    assert(cp != NULL, "invariant");
    assert(_loader_data != NULL, "invariant");
  
    if (_class_name == vmSymbols::java_lang_Object()) {
!     check_property(_temp_local_interfaces->length() == 0,
!         "java.lang.Object cannot implement an interface in class file %s",
!         CHECK);
    }
    // We check super class after class file is parsed and format is checked
    if (_super_class_index > 0 && NULL == _super_klass) {
      Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
!     if (is_interface()) {
        // Before attempting to resolve the superclass, check for class format
        // errors not checked yet.
        guarantee_property(super_class_name == vmSymbols::java_lang_Object(),
          "Interfaces must have java.lang.Object as superclass in class file %s",
          CHECK);

*** 5982,17 ***
--- 6359,84 ---
  
    if (_super_klass != NULL) {
      if (_super_klass->has_nonstatic_concrete_methods()) {
        _has_nonstatic_concrete_methods = true;
      }
+     if (_super_klass->is_declared_atomic()) {
+       _is_declared_atomic = true;
+     }
  
      if (_super_klass->is_interface()) {
        classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD);
        return;
      }
+ 
+     // For an inline class, only java/lang/Object or special abstract classes
+     // are acceptable super classes.
+     if (is_inline_type()) {
+       const InstanceKlass* super_ik = _super_klass;
+       if (super_ik->invalid_inline_super()) {
+         classfile_icce_error("inline class %s has an invalid super class %s", _super_klass, THREAD);
+         return;
+       }
+     }
+   }
+ 
+   if (_class_name == vmSymbols::java_lang_NonTearable() && _loader_data->class_loader() == NULL) {
+     // This is the original source of this condition.
+     // It propagates by inheritance, as if testing "instanceof NonTearable".
+     _is_declared_atomic = true;
+   } else if (*ForceNonTearable != '\0') {
+     // Allow a command line switch to force the same atomicity property:
+     const char* class_name_str = _class_name->as_C_string();
+     if (StringUtils::class_list_match(ForceNonTearable, class_name_str)) {
+       _is_declared_atomic = true;
+     }
+   }
+ 
+   // Set ik->invalid_inline_super field to TRUE if already marked as invalid,
+   // if super is marked invalid, or if is_invalid_super_for_inline_type()
+   // returns true
+   if (invalid_inline_super() ||
+       (_super_klass != NULL && _super_klass->invalid_inline_super()) ||
+       is_invalid_super_for_inline_type()) {
+     set_invalid_inline_super();
    }
  
+   if (EnableValhalla && !is_inline_type() && invalid_inline_super() && (_super_klass == NULL || !_super_klass->invalid_inline_super())
+       && !_implements_identityObject && class_name() != vmSymbols::java_lang_IdentityObject()) {
+     _temp_local_interfaces->append(vmClasses::IdentityObject_klass());
+     _has_injected_identityObject = true;
+   }
+   // Check if declared as PrimitiveObject...else add if needed
+   if (_implements_primitiveObject) {
+     if (!is_inline_type() && invalid_inline_super()) {
+       classfile_icce_error("class %s can not implement %s, neither valid inline classes or valid supertype",
+                             vmClasses::PrimitiveObject_klass(), THREAD);
+       return;
+     }
+   } else if (is_inline_type()) {
+     _temp_local_interfaces->append(vmClasses::PrimitiveObject_klass());
+     _has_injected_primitiveObject = true;
+   }
+ 
+   int itfs_len = _temp_local_interfaces->length();
+   if (itfs_len == 0) {
+     _local_interfaces = Universe::the_empty_instance_klass_array();
+   } else if (itfs_len == 1 && _temp_local_interfaces->at(0) == vmClasses::IdentityObject_klass()) {
+     _local_interfaces = Universe::the_single_IdentityObject_klass_array();
+   } else if (itfs_len == 1 && _temp_local_interfaces->at(0) == vmClasses::PrimitiveObject_klass()) {
+     _local_interfaces = Universe::the_single_PrimitiveObject_klass_array();
+   } else {
+     _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, NULL, CHECK);
+     for (int i = 0; i < itfs_len; i++) {
+       _local_interfaces->at_put(i, _temp_local_interfaces->at(i));
+     }
+   }
+   _temp_local_interfaces = NULL;
+   assert(_local_interfaces != NULL, "invariant");
+ 
    // Compute the transitive list of all unique interfaces implemented by this class
    _transitive_interfaces =
      compute_transitive_interfaces(_super_klass,
                                    _local_interfaces,
                                    _loader_data,

*** 6016,24 ***
                                                      loader,
                                                      _class_name,
                                                      _local_interfaces);
  
    // Size of Java itable (in words)
!   _itable_size = _access_flags.is_interface() ? 0 :
      klassItable::compute_itable_size(_transitive_interfaces);
  
    assert(_fac != NULL, "invariant");
    assert(_parsed_annotations != NULL, "invariant");
  
    _field_info = new FieldLayoutInfo();
    FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields,
!                         _parsed_annotations->is_contended(), _field_info);
!   lb.build_layout();
  
!   // Compute reference typ
    _rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();
- 
  }
  
  void ClassFileParser::set_klass(InstanceKlass* klass) {
  
  #ifdef ASSERT
--- 6460,51 ---
                                                      loader,
                                                      _class_name,
                                                      _local_interfaces);
  
    // Size of Java itable (in words)
!   _itable_size = is_interface() ? 0 :
      klassItable::compute_itable_size(_transitive_interfaces);
  
    assert(_fac != NULL, "invariant");
    assert(_parsed_annotations != NULL, "invariant");
  
+ 
+   if (EnableValhalla) {
+     for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
+       if (Signature::basic_type(fs.signature()) == T_INLINE_TYPE && !fs.access_flags().is_static()) {
+         // Pre-load inline class
+         Klass* klass = SystemDictionary::resolve_inline_type_field_or_fail(&fs,
+             Handle(THREAD, _loader_data->class_loader()),
+             _protection_domain, true, CHECK);
+         assert(klass != NULL, "Sanity check");
+         if (!klass->access_flags().is_inline_type()) {
+           assert(klass->is_instance_klass(), "Sanity check");
+           ResourceMark rm(THREAD);
+             THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                       err_msg("Class %s expects class %s to be an inline type, but it is not",
+                       _class_name->as_C_string(),
+                       InstanceKlass::cast(klass)->external_name()));
+         }
+       }
+     }
+   }
+ 
    _field_info = new FieldLayoutInfo();
    FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields,
!       _parsed_annotations->is_contended(), is_inline_type(),
!       loader_data(), _protection_domain, _field_info);
+   lb.build_layout(CHECK);
+   if (is_inline_type()) {
+     _alignment = lb.get_alignment();
+     _first_field_offset = lb.get_first_field_offset();
+     _exact_size_in_bytes = lb.get_exact_size_in_byte();
+   }
+   _has_inline_type_fields = _field_info->_has_inline_fields;
  
!   // Compute reference type
    _rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();
  }
  
  void ClassFileParser::set_klass(InstanceKlass* klass) {
  
  #ifdef ASSERT

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