< prev index next >

src/hotspot/share/classfile/classFileParser.cpp

Print this page
@@ -19,10 +19,12 @@
   * 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 "oops/inlineKlass.hpp"
  #include "precompiled.hpp"
  #include "cds/cdsConfig.hpp"
  #include "classfile/classFileParser.hpp"
  #include "classfile/classFileStream.hpp"
  #include "classfile/classLoader.hpp"

@@ -49,10 +51,11 @@
  #include "memory/universe.hpp"
  #include "oops/annotations.hpp"
  #include "oops/constantPool.inline.hpp"
  #include "oops/fieldInfo.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"

@@ -83,10 +86,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
  #if INCLUDE_JFR

@@ -149,10 +153,12 @@
  
  #define JAVA_22_VERSION                   66
  
  #define JAVA_23_VERSION                   67
  
+ #define CONSTANT_CLASS_DESCRIPTORS        68
+ 
  #define JAVA_24_VERSION                   68
  
  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,

@@ -189,11 +195,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;
        }

@@ -493,10 +499,13 @@
        case JVM_CONSTANT_ClassIndex: {
          const int class_index = cp->klass_index_at(index);
          guarantee_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();
          cp->unresolved_klass_at_put(index, class_index, num_klasses++);
          break;
        }
        case JVM_CONSTANT_StringIndex: {
          const int string_index = cp->string_index_at(index);

@@ -702,11 +711,11 @@
              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.
+             } else if (!Signature::is_void_method(signature)) {  // must have void signature.
                throwIllegalSignature("Method", name, signature, CHECK);
              }
            }
          }
          break;

@@ -722,19 +731,28 @@
              const int name_and_type_ref_index =
                cp->uncached_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()) { // !<init>
+               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 {
-               if (name == vmSymbols::object_initializer_name()) {
+             } else { // <init>
+               // 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 {
                  classfile_parse_error(
                    "Bad method name at constant pool index %u in class file %s",
                    name_ref_index, THREAD);
                  return;
                }

@@ -782,64 +800,49 @@
  using NameSigHashtable = ResourceHashtable<NameSigHash, int,
                                             NameSigHash::HASH_ROW_SIZE,
                                             AnyObj::RESOURCE_AREA, mtInternal,
                                             &NameSigHash::hash, &NameSigHash::equals>;
  
- // Side-effects: populates the _local_interfaces field
- void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
-                                        const int itfs_len,
-                                        ConstantPool* const cp,
+ static void check_identity_and_value_modifiers(ClassFileParser* current, const InstanceKlass* super_type, TRAPS) {
+   assert(super_type != nullptr,"Method doesn't support null super type");
+   if (super_type->access_flags().is_identity_class() && !current->access_flags().is_identity_class()
+       && super_type->name() != vmSymbols::java_lang_Object()) {
+       THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                 err_msg("Value type %s has an identity type as supertype",
+                 current->class_name()->as_klass_external_name()));
+   }
+ }
+ 
+ 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".
                                         TRAPS) {
    assert(stream != nullptr, "invariant");
    assert(cp != nullptr, "invariant");
    assert(has_nonstatic_concrete_methods != nullptr, "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, nullptr, CHECK);
- 
-     int index;
+     _local_interface_indexes = new GrowableArray<u2>(itfs_len);
+     int index = 0;
      for (index = 0; index < itfs_len; index++) {
        const u2 interface_index = stream->get_u2(CHECK);
-       Klass* interf;
        guarantee_property(
          valid_klass_reference_at(interface_index),
          "Interface name has bad constant pool index %u in class file %s",
          interface_index, CHECK);
-       if (cp->tag_at(interface_index).is_klass()) {
-         interf = cp->resolved_klass_at(interface_index);
-       } else {
-         Symbol* const unresolved_klass  = cp->klass_name_at(interface_index);
- 
-         // Don't need to check legal name because it's checked when parsing constant pool.
-         // But need to make sure it's not an array type.
-         guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY,
-                            "Bad interface name in class file %s", CHECK);
- 
-         // Call resolve on the interface class name with class circularity checking
-         interf = SystemDictionary::resolve_super_or_fail(_class_name,
-                                                          unresolved_klass,
-                                                          Handle(THREAD, _loader_data->class_loader()),
-                                                          _protection_domain,
-                                                          false, CHECK);
-       }
- 
-       if (!interf->is_interface()) {
-         THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
-                   err_msg("class %s can not implement %s, because it is not an interface (%s)",
-                           _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));
+       _local_interface_indexes->at_put_grow(index, interface_index);
      }
  
      if (!_need_verify || itfs_len <= 1) {
        return;
      }

@@ -847,12 +850,11 @@
      // Check if there's any duplicates in interfaces
      ResourceMark rm(THREAD);
      // Set containing interface names
      ResourceHashtable<Symbol*, int>* interface_names = new ResourceHashtable<Symbol*, int>();
      for (index = 0; index < itfs_len; index++) {
-       const InstanceKlass* const k = _local_interfaces->at(index);
-       Symbol* interface_name = k->name();
+       Symbol* interface_name = cp->klass_name_at(_local_interface_indexes->at(index));
        // If no duplicates, add (name, nullptr) in hashtable interface_names.
        if (!interface_names->put(interface_name, 0)) {
          classfile_parse_error("Duplicate interface name \"%s\" in class file %s",
                                 interface_name->as_C_string(), THREAD);
          return;

@@ -935,10 +937,13 @@
      _method_IntrinsicCandidate,
      _jdk_internal_vm_annotation_Contended,
      _field_Stable,
      _jdk_internal_vm_annotation_ReservedStackAccess,
      _jdk_internal_ValueBased,
+     _jdk_internal_ImplicitlyConstructible,
+     _jdk_internal_LooselyConsistentValue,
+     _jdk_internal_NullRestricted,
      _java_lang_Deprecated,
      _java_lang_Deprecated_for_removal,
      _annotation_LIMIT
    };
    const Location _location;

@@ -1357,11 +1362,11 @@
  
  
  // Side-effects: populates the _fields, _fields_annotations,
  // _fields_type_annotations fields
  void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
-                                    bool is_interface,
+                                    AccessFlags class_access_flags,
                                     ConstantPool* cp,
                                     const int cp_size,
                                     u2* const java_fields_count_ptr,
                                     TRAPS) {
  

@@ -1370,31 +1375,42 @@
    assert(java_fields_count_ptr != nullptr, "invariant");
  
    assert(nullptr == _fields_annotations, "invariant");
    assert(nullptr == _fields_type_annotations, "invariant");
  
+   bool is_inline_type = !class_access_flags.is_identity_class() && !class_access_flags.is_abstract();
    cfs->guarantee_more(2, CHECK);  // length
    const u2 length = cfs->get_u2_fast();
    *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_inline_type ? 2 : 0);
  
    // Allocate a temporary resource array to collect field data.
    // After parsing all fields, data are stored in a UNSIGNED5 compressed stream.
    _temp_field_info = new GrowableArray<FieldInfo>(total_fields);
  
+   int instance_fields_count = 0;
    ResourceMark rm(THREAD);
    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;
+     if (!supports_inline_types()) {
+       recognized_modifiers &= ~JVM_ACC_STRICT;
+     }
+ 
+     const jint flags = cfs->get_u2_fast() & recognized_modifiers;
+     verify_legal_field_modifiers(flags, class_access_flags, 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);
      FieldInfo::FieldFlags fieldFlags(0);
  
      const u2 name_index = cfs->get_u2_fast();
      guarantee_property(valid_symbol_at(name_index),

@@ -1407,17 +1423,20 @@
      guarantee_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();
      FieldAnnotationCollector parsed_annotations(_loader_data);
  
+     bool is_null_restricted = false;
+ 
      const u2 attributes_count = cfs->get_u2_fast();
      if (attributes_count > 0) {
        parse_field_attributes(cfs,
                               attributes_count,
                               is_static,

@@ -1433,10 +1452,20 @@
            _fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
                                               _loader_data, length, nullptr,
                                               CHECK);
          }
          _fields_annotations->at_put(n, parsed_annotations.field_annotations());
+         if (parsed_annotations.has_annotation(AnnotationCollector::_jdk_internal_NullRestricted)) {
+           if (!Signature::has_envelope(sig)) {
+             Exceptions::fthrow(
+               THREAD_AND_LOCATION,
+               vmSymbols::java_lang_ClassFormatError(),
+               "Illegal use of @jdk.internal.vm.annotation.NullRestricted annotation on field %s with signature %s (primitive types can never be null)",
+               name->as_C_string(), sig->as_C_string());
+           }
+           is_null_restricted = true;
+         }
          parsed_annotations.set_field_annotations(nullptr);
        }
        if (parsed_annotations.field_type_annotations() != nullptr) {
          if (_fields_type_annotations == nullptr) {
            _fields_type_annotations =

@@ -1455,10 +1484,14 @@
        if (generic_signature_index != 0) {
          fieldFlags.update_generic(true);
        }
      }
  
+     if (is_null_restricted) {
+       fieldFlags.update_null_free_inline_type(true);
+     }
+ 
      const BasicType type = cp->basic_type_for_signature_at(signature_index);
  
      // Update number of static oop fields.
      if (is_static && is_reference_type(type)) {
        _static_oop_count++;

@@ -1475,11 +1508,10 @@
      }
      _temp_field_info->append(fi);
    }
    assert(_temp_field_info->length() == length, "Must be");
  
-   int index = length;
    if (num_injected != 0) {
      for (int n = 0; n < num_injected; n++) {
        // Check for duplicates
        if (injected[n].may_be_java) {
          const Symbol* const name      = injected[n].name();

@@ -1503,17 +1535,41 @@
        // Injected field
        FieldInfo::FieldFlags fflags(0);
        fflags.update_injected(true);
        AccessFlags aflags;
        FieldInfo fi(aflags, (u2)(injected[n].name_index), (u2)(injected[n].signature_index), 0, fflags);
-       fi.set_index(index);
-       _temp_field_info->append(fi);
-       index++;
+       int idx = _temp_field_info->append(fi);
+       _temp_field_info->adr_at(idx)->set_index(idx);
      }
    }
  
-   assert(_temp_field_info->length() == index, "Must be");
+   if (is_inline_type) {
+     // Inject static ".default" field
+     FieldInfo::FieldFlags fflags(0);
+     fflags.update_injected(true);
+     AccessFlags aflags(JVM_ACC_STATIC);
+     FieldInfo fi(aflags,
+                  (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(default_value_name)),
+                  (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(object_signature)),
+                  0,
+                  fflags);
+     int idx = _temp_field_info->append(fi);
+     _temp_field_info->adr_at(idx)->set_index(idx);
+     _static_oop_count++;
+     // Inject static ".null_reset" field. This is the same as the .default field but will never have its null-channel set to non-zero.
+     FieldInfo::FieldFlags fflags2(0);
+     fflags2.update_injected(true);
+     AccessFlags aflags2(JVM_ACC_STATIC);
+     FieldInfo fi2(aflags2,
+                  (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(null_reset_value_name)),
+                  (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(object_signature)),
+                  0,
+                  fflags2);
+     int idx2 = _temp_field_info->append(fi2);
+     _temp_field_info->adr_at(idx2)->set_index(idx2);
+     _static_oop_count++;
+   }
  
    if (_need_verify && length > 1) {
      // Check duplicated fields
      ResourceMark rm(THREAD);
      // Set containing name-signature pairs

@@ -1888,10 +1944,22 @@
      case VM_SYMBOL_ENUM_NAME(jdk_internal_ValueBased_signature): {
        if (_location != _in_class)   break;  // only allow for classes
        if (!privileged)              break;  // only allow in privileged code
        return _jdk_internal_ValueBased;
      }
+     case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ImplicitlyConstructible_signature): {
+       if (_location != _in_class)   break; // only allow for classes
+       return _jdk_internal_ImplicitlyConstructible;
+     }
+     case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_LooselyConsistentValue_signature): {
+       if (_location != _in_class)   break; // only allow for classes
+       return _jdk_internal_LooselyConsistentValue;
+     }
+     case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_NullRestricted_signature): {
+       if (_location != _in_field)   break; // only allow for fields
+       return _jdk_internal_NullRestricted;
+     }
      case VM_SYMBOL_ENUM_NAME(java_lang_Deprecated): {
        return _java_lang_Deprecated;
      }
      default: {
        break;

@@ -2111,10 +2179,12 @@
  //
  // The has_localvariable_table parameter is used to pass up the value to InstanceKlass.
  
  Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
                                        bool is_interface,
+                                       bool is_value_class,
+                                       bool is_abstract_class,
                                        const ConstantPool* cp,
                                        bool* const has_localvariable_table,
                                        TRAPS) {
    assert(cfs != nullptr, "invariant");
    assert(cp != nullptr, "invariant");

@@ -2152,18 +2222,27 @@
      } else {
        classfile_parse_error("Method <clinit> is not static in class file %s", THREAD);
        return nullptr;
      }
    } else {
-     verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL);
+     verify_legal_method_modifiers(flags, access_flags() , 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 nullptr;
    }
  
+   if (EnableValhalla) {
+     if (((flags & JVM_ACC_SYNCHRONIZED) == JVM_ACC_SYNCHRONIZED)
+         && ((flags & JVM_ACC_STATIC) == 0 )
+         && !_access_flags.is_identity_class()) {
+       classfile_parse_error("Invalid synchronized method in non-identity class %s", THREAD);
+         return nullptr;
+     }
+   }
+ 
    int args_size = -1;  // only used when _need_verify is true
    if (_need_verify) {
      verify_legal_name_with_signature(name, signature, CHECK_NULL);
      args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
                   verify_legal_method_signature(name, signature, CHECK_NULL);

@@ -2687,10 +2766,12 @@
  
  
  // Side-effects: populates the _methods field in the parser
  void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
                                      bool is_interface,
+                                     bool is_value_class,
+                                     bool is_abstract_type,
                                      bool* const has_localvariable_table,
                                      bool* has_final_method,
                                      bool* declares_nonstatic_concrete_methods,
                                      TRAPS) {
    assert(cfs != nullptr, "invariant");

@@ -2711,10 +2792,12 @@
                                                     CHECK);
  
      for (int index = 0; index < length; index++) {
        Method* method = parse_method(cfs,
                                      is_interface,
+                                     is_value_class,
+                                     is_abstract_type,
                                      _cp,
                                      has_localvariable_table,
                                      CHECK);
  
        if (method->is_final()) {

@@ -2976,23 +3059,35 @@
        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;
      }
+ 
+     // 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);
+ 
+     if (!supports_inline_types()) {
+       const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+       const bool is_interface = (flags & JVM_ACC_INTERFACE) != 0;
+       if (!is_module && !is_interface) {
+         flags |= JVM_ACC_IDENTITY;
+       }
+     }
+ 
+     const char* name = inner_name_index == 0 ? "unnamed" : cp->symbol_at(inner_name_index)->as_utf8();
+     verify_legal_class_modifiers(flags, name, false, CHECK_0);
      AccessFlags inner_access_flags(flags);
  
      inner_classes->at_put(index++, inner_class_info_index);
      inner_classes->at_put(index++, outer_class_info_index);
      inner_classes->at_put(index++, inner_name_index);

@@ -3092,10 +3187,53 @@
    cfs->set_current(current_mark);
  
    return length;
  }
  
+ u2 ClassFileParser::parse_classfile_loadable_descriptors_attribute(const ClassFileStream* const cfs,
+                                                                    const u1* const loadable_descriptors_attribute_start,
+                                                                    TRAPS) {
+   const u1* const current_mark = cfs->current();
+   u2 length = 0;
+   if (loadable_descriptors_attribute_start != nullptr) {
+     cfs->set_current(loadable_descriptors_attribute_start);
+     cfs->guarantee_more(2, CHECK_0);  // length
+     length = cfs->get_u2_fast();
+   }
+   const int size = length;
+   Array<u2>* const loadable_descriptors = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
+   _loadable_descriptors = loadable_descriptors;
+   if (length > 0) {
+     int index = 0;
+     cfs->guarantee_more(2 * length, CHECK_0);
+     for (int n = 0; n < length; n++) {
+       const u2 descriptor_index = cfs->get_u2_fast();
+       guarantee_property(
+         valid_symbol_at(descriptor_index),
+         "LoadableDescriptors descriptor_index %u has bad constant type in class file %s",
+         descriptor_index, CHECK_0);
+       Symbol* descriptor = _cp->symbol_at(descriptor_index);
+       bool valid = legal_field_signature(descriptor, CHECK_0);
+       if(!valid) {
+         ResourceMark rm(THREAD);
+         Exceptions::fthrow(THREAD_AND_LOCATION,
+           vmSymbols::java_lang_ClassFormatError(),
+           "Descriptor from LoadableDescriptors attribute at index \"%d\" in class %s has illegal signature \"%s\"",
+           descriptor_index, _class_name->as_C_string(), descriptor->as_C_string());
+         return 0;
+       }
+       loadable_descriptors->at_put(index++, descriptor_index);
+     }
+     assert(index == size, "wrong size");
+   }
+ 
+   // Restore buffer's current position.
+   cfs->set_current(current_mark);
+ 
+   return length;
+ }
+ 
  //  Record {
  //    u2 attribute_name_index;
  //    u4 attribute_length;
  //    u2 components_count;
  //    component_info components[components_count];

@@ -3357,16 +3495,19 @@
    _inner_classes = Universe::the_empty_short_array();
    // Set nest members attribute to default sentinel
    _nest_members = Universe::the_empty_short_array();
    // Set _permitted_subclasses attribute to default sentinel
    _permitted_subclasses = Universe::the_empty_short_array();
+   // Set _loadable_descriptors attribute to default sentinel
+   _loadable_descriptors = Universe::the_empty_short_array();
    cfs->guarantee_more(2, CHECK);  // attributes_count
    u2 attributes_count = cfs->get_u2_fast();
    bool parsed_sourcefile_attribute = false;
    bool parsed_innerclasses_attribute = false;
    bool parsed_nest_members_attribute = false;
    bool parsed_permitted_subclasses_attribute = false;
+   bool parsed_loadable_descriptors_attribute = false;
    bool parsed_nest_host_attribute = false;
    bool parsed_record_attribute = false;
    bool parsed_enclosingmethod_attribute = false;
    bool parsed_bootstrap_methods_attribute = false;
    const u1* runtime_visible_annotations = nullptr;

@@ -3384,10 +3525,12 @@
    u4  nest_members_attribute_length = 0;
    const u1* record_attribute_start = nullptr;
    u4  record_attribute_length = 0;
    const u1* permitted_subclasses_attribute_start = nullptr;
    u4  permitted_subclasses_attribute_length = 0;
+   const u1* loadable_descriptors_attribute_start = nullptr;
+   u4  loadable_descriptors_attribute_length = 0;
  
    // Iterate over attributes
    while (attributes_count--) {
      cfs->guarantee_more(6, CHECK);  // attribute_name_index, attribute_length
      const u2 attribute_name_index = cfs->get_u2_fast();

@@ -3599,10 +3742,19 @@
                }
                parsed_permitted_subclasses_attribute = true;
                permitted_subclasses_attribute_start = cfs->current();
                permitted_subclasses_attribute_length = attribute_length;
              }
+             if (EnableValhalla && tag == vmSymbols::tag_loadable_descriptors()) {
+               if (parsed_loadable_descriptors_attribute) {
+                 classfile_parse_error("Multiple LoadableDescriptors attributes in class file %s", CHECK);
+                 return;
+               }
+               parsed_loadable_descriptors_attribute = true;
+               loadable_descriptors_attribute_start = cfs->current();
+               loadable_descriptors_attribute_length = attribute_length;
+             }
            }
            // Skip attribute_length for any attribute where major_verson >= JAVA_17_VERSION
            cfs->skip_u1(attribute_length, CHECK);
          } else {
            // Unknown attribute

@@ -3675,10 +3827,22 @@
          permitted_subclasses_attribute_length == sizeof(num_subclasses) + sizeof(u2) * num_subclasses,
          "Wrong PermittedSubclasses attribute length in class file %s", CHECK);
      }
    }
  
+   if (parsed_loadable_descriptors_attribute) {
+     const u2 num_classes = parse_classfile_loadable_descriptors_attribute(
+                             cfs,
+                             loadable_descriptors_attribute_start,
+                             CHECK);
+     if (_need_verify) {
+       guarantee_property(
+         loadable_descriptors_attribute_length == sizeof(num_classes) + sizeof(u2) * num_classes,
+         "Wrong LoadableDescriptors attribute length in class file %s", CHECK);
+     }
+   }
+ 
    if (_max_bootstrap_specifier_index >= 0) {
      guarantee_property(parsed_bootstrap_methods_attribute,
                         "Missing BootstrapMethods attribute in class file %s", CHECK);
    }
  }

@@ -3740,13 +3904,15 @@
    this_klass->set_fields_status(_fields_status);
    this_klass->set_methods(_methods);
    this_klass->set_inner_classes(_inner_classes);
    this_klass->set_nest_members(_nest_members);
    this_klass->set_nest_host_index(_nest_host);
+   this_klass->set_loadable_descriptors(_loadable_descriptors);
    this_klass->set_annotations(_combined_annotations);
    this_klass->set_permitted_subclasses(_permitted_subclasses);
    this_klass->set_record_components(_record_components);
+   this_klass->set_inline_layout_info_array(_inline_layout_info_array);
    // Delay the setting of _local_interfaces and _transitive_interfaces until after
    // initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could
    // be shared with _transitive_interfaces and _transitive_interfaces may be shared with
    // its _super. If an OOM occurs while loading the current klass, its _super field
    // may not have been set. When GC tries to free the klass, the _transitive_interfaces

@@ -3779,29 +3945,24 @@
    assert(cp != nullptr, "invariant");
    const InstanceKlass* super_klass = nullptr;
  
    if (super_class_index == 0) {
      guarantee_property(_class_name == vmSymbols::java_lang_Object(),
-                        "Invalid superclass index %u in class file %s",
-                        super_class_index,
-                        CHECK_NULL);
+                    "Invalid superclass index 0 in class file %s",
+                    CHECK_NULL);
    } else {
      guarantee_property(valid_klass_reference_at(super_class_index),
                         "Invalid superclass index %u in class file %s",
                         super_class_index,
                         CHECK_NULL);
      // The class name should be legal because it is checked when parsing constant pool.
      // However, make sure it is not an array type.
-     bool is_array = false;
      if (cp->tag_at(super_class_index).is_klass()) {
        super_klass = InstanceKlass::cast(cp->resolved_klass_at(super_class_index));
-       if (need_verify)
-         is_array = super_klass->is_array_klass();
-     } else if (need_verify) {
-       is_array = (cp->klass_name_at(super_class_index)->char_at(0) == JVM_SIGNATURE_ARRAY);
      }
      if (need_verify) {
+       bool is_array = (cp->klass_name_at(super_class_index)->char_at(0) == JVM_SIGNATURE_ARRAY);
        guarantee_property(!is_array,
                          "Bad superclass name in class file %s", CHECK_NULL);
      }
    }
    return super_klass;

@@ -3971,10 +4132,16 @@
      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 68.65535 and later
+   return _major_version > JAVA_24_VERSION ||
+          (_major_version == JAVA_24_VERSION && _minor_version == JAVA_PREVIEW_MINOR_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

@@ -4014,13 +4181,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();
-   } else if (max_transitive_size == local_size) {
-     // only local interfaces added, share local interface array
-     return local_ifs;
+     // 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

@@ -4037,10 +4205,11 @@
      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");
+ 
      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 != nullptr, "just checking");

@@ -4065,10 +4234,20 @@
      if (super_ik->is_sealed() && !super_ik->has_as_permitted_subclass(this_klass)) {
        classfile_icce_error("class %s cannot inherit from sealed class %s", super_ik, THREAD);
        return;
      }
  
+     // The JVMS says that super classes for value types must not have the ACC_IDENTITY
+     // flag set. But, java.lang.Object must still be allowed to be a direct super class
+     // for a value classes.  So, it is treated as a special case for now.
+     if (!this_klass->access_flags().is_identity_class() &&
+         super_ik->name() != vmSymbols::java_lang_Object() &&
+         super_ik->is_identity_class()) {
+       classfile_icce_error("value class %s cannot inherit from class %s", super_ik, THREAD);
+       return;
+     }
+ 
      Reflection::VerifyClassAccessResults vca_result =
        Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false);
      if (vca_result != Reflection::ACCESS_OK) {
        ResourceMark rm(THREAD);
        char* msg = Reflection::verify_class_access_msg(this_klass,

@@ -4230,12 +4409,13 @@
    }
  }
  
  // utility methods for format checking
  
- void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const {
+ void ClassFileParser::verify_legal_class_modifiers(jint flags, const char* name, bool is_Object, TRAPS) const {
    const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+   const bool is_inner_class = name != nullptr;
    assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set");
    if (is_module) {
      ResourceMark rm(THREAD);
      Exceptions::fthrow(
        THREAD_AND_LOCATION,

@@ -4248,27 +4428,44 @@
    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;
-   const bool is_super      = (flags & JVM_ACC_SUPER)      != 0;
+   const bool is_identity   = (flags & JVM_ACC_IDENTITY)   != 0;
    const bool is_enum       = (flags & JVM_ACC_ENUM)       != 0;
    const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0;
    const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION;
+   const bool valid_value_class = is_identity || is_interface ||
+                                  (supports_inline_types() && (!is_identity && (is_abstract || is_final)));
  
    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_interface && major_gte_1_5 && (is_identity || is_enum)) ||   //  ACC_SUPER (now ACC_IDENTITY) was illegal for interfaces
+       (!is_interface && major_gte_1_5 && is_annotation) ||
+       (!valid_value_class)) {
      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;
+     const char* class_note = "";
+     if (!valid_value_class) {
+       class_note = " (a value class must be final or else abstract)";
+     }
+     if (name == nullptr) { // Not an inner 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;
+     } else {
+       Exceptions::fthrow(
+         THREAD_AND_LOCATION,
+         vmSymbols::java_lang_ClassFormatError(),
+         "Illegal class modifiers in declaration of inner class %s%s of class %s: 0x%X",
+         name, class_note, _class_name->as_C_string(), flags
+       );
+       return;
+     }
    }
  }
  
  static bool has_illegal_visibility(jint flags) {
    const bool is_public    = (flags & JVM_ACC_PUBLIC)    != 0;

@@ -4330,12 +4527,12 @@
      classfile_ucve_error("%s (class file version %u.%u) was compiled with an invalid non-zero minor version",
                           class_name, major, minor, THREAD);
    }
  }
  
- void ClassFileParser::verify_legal_field_modifiers(jint flags,
-                                                    bool is_interface,
+ void ClassFileParser:: verify_legal_field_modifiers(jint flags,
+                                                    AccessFlags class_access_flags,
                                                     TRAPS) const {
    if (!_need_verify) { return; }
  
    const bool is_public    = (flags & JVM_ACC_PUBLIC)    != 0;
    const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0;

@@ -4343,39 +4540,73 @@
    const bool is_static    = (flags & JVM_ACC_STATIC)    != 0;
    const bool is_final     = (flags & JVM_ACC_FINAL)     != 0;
    const bool is_volatile  = (flags & JVM_ACC_VOLATILE)  != 0;
    const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0;
    const bool is_enum      = (flags & JVM_ACC_ENUM)      != 0;
+   const bool is_strict    = (flags & JVM_ACC_STRICT)    != 0;
    const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION;
  
+   const bool is_interface = class_access_flags.is_interface();
+   const bool is_identity_class = class_access_flags.is_identity_class();
+ 
    bool is_illegal = false;
+   const char* error_msg = "";
  
-   if (is_interface) {
-     if (!is_public || !is_static || !is_final || is_private ||
-         is_protected || is_volatile || is_transient ||
-         (major_gte_1_5 && is_enum)) {
+   // There is some overlap in the checks that apply, for example interface fields
+   // must be static, static fields can't be strict, and therefore interfaces can't
+   // have strict fields. So we don't have to check every possible invalid combination
+   // individually as long as all are covered. Once we have found an illegal combination
+   // we can stop checking.
+ 
+   if (supports_inline_types()) {
+     if (is_strict && is_static) {
        is_illegal = true;
+       error_msg = "field cannot be strict and static";
      }
-   } else { // not interface
-     if (has_illegal_visibility(flags) || (is_final && is_volatile)) {
+     else if (is_strict && !is_final) {
        is_illegal = true;
+       error_msg = "strict field must be final";
+     }
+   }
+ 
+   if (!is_illegal) {
+     if (is_interface) {
+       if (!is_public || !is_static || !is_final || is_private ||
+           is_protected || is_volatile || is_transient ||
+           (major_gte_1_5 && is_enum)) {
+         is_illegal = true;
+         error_msg = "interface fields must be public, static and final, and may be synthetic";
+       }
+     } else { // not interface
+       if (has_illegal_visibility(flags)) {
+         is_illegal = true;
+         error_msg = "invalid visibility flags for class field";
+       } else if (is_final && is_volatile) {
+         is_illegal = true;
+         error_msg = "fields cannot be final and volatile";
+       } else if (supports_inline_types()) {
+         if (!is_identity_class && !is_static && !is_strict) {
+           is_illegal = true;
+           error_msg = "value class fields must be either strict or static";
+         }
+       }
      }
    }
  
    if (is_illegal) {
      ResourceMark rm(THREAD);
      Exceptions::fthrow(
        THREAD_AND_LOCATION,
        vmSymbols::java_lang_ClassFormatError(),
-       "Illegal field modifiers in class %s: 0x%X",
-       _class_name->as_C_string(), flags);
+       "Illegal field modifiers (%s) in class %s: 0x%X",
+       error_msg, _class_name->as_C_string(), flags);
      return;
    }
  }
  
  void ClassFileParser::verify_legal_method_modifiers(jint flags,
-                                                     bool is_interface,
+                                                     AccessFlags class_access_flags,
                                                      const Symbol* name,
                                                      TRAPS) const {
    if (!_need_verify) { return; }
  
    const bool is_public       = (flags & JVM_ACC_PUBLIC)       != 0;

@@ -4390,13 +4621,18 @@
    const bool is_protected    = (flags & JVM_ACC_PROTECTED)    != 0;
    const bool major_gte_1_5   = _major_version >= JAVA_1_5_VERSION;
    const bool major_gte_8     = _major_version >= JAVA_8_VERSION;
    const bool major_gte_17    = _major_version >= JAVA_17_VERSION;
    const bool is_initializer  = (name == vmSymbols::object_initializer_name());
+   // LW401 CR required: removal of value factories support
+   const bool is_interface    = class_access_flags.is_interface();
+   const bool is_identity_class = class_access_flags.is_identity_class();
+   const bool is_abstract_class = class_access_flags.is_abstract();
  
    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

@@ -4432,14 +4668,19 @@
          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;
+         if (!is_identity_class && is_synchronized && !is_static) {
+           is_illegal = true;
+           class_note = " (not an identity 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;
+             }
            }
          }
        }
      }
    }

@@ -4447,12 +4688,13 @@
    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,

@@ -4506,10 +4748,19 @@
      }
    }
    return true;
  }
  
+ bool ClassFileParser::is_class_in_loadable_descriptors_attribute(Symbol *klass) {
+   if (_loadable_descriptors == nullptr) return false;
+   for (int i = 0; i < _loadable_descriptors->length(); i++) {
+         Symbol* class_name = _cp->symbol_at(_loadable_descriptors->at(i));
+         if (class_name == klass) return true;
+   }
+   return false;
+ }
+ 
  // Take pointer to a UTF8 byte string (not NUL-terminated).
  // Skip over the longest part of the string that could
  // be taken as a fieldname. Allow non-trailing '/'s if slash_ok is true.
  // Return a pointer to just past the fieldname.
  // Return null if no fieldname at all was found, or in the case of slash_ok

@@ -4607,22 +4858,23 @@
      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_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 ';'
+         // 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 != nullptr) {
            int newlen = pointer_delta_as_int(c, (char*) signature);

@@ -4674,10 +4926,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 != nullptr) && ((p - bytes) == (int)length);
        }
+     } else if ((_major_version >= CONSTANT_CLASS_DESCRIPTORS || _class_name->starts_with("jdk/internal/reflect/"))
+                    && bytes[length - 1] == ';' ) {
+       // Support for L...; 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.

@@ -4739,11 +4995,12 @@
    unsigned int length = name->utf8_length();
    bool legal = false;
  
    if (length > 0) {
      if (bytes[0] == JVM_SIGNATURE_SPECIAL) {
-       if (name == vmSymbols::object_initializer_name() || name == vmSymbols::class_initializer_name()) {
+       if (name == vmSymbols::object_initializer_name() ||
+           name == vmSymbols::class_initializer_name()) {
          legal = true;
        }
      } else if (_major_version < JAVA_1_5_VERSION) {
        const char* p;
        p = skip_over_field_name(bytes, false, length);

@@ -4765,10 +5022,20 @@
      );
      return;
    }
  }
  
+ bool ClassFileParser::legal_field_signature(const Symbol* signature, TRAPS) const {
+   const char* const bytes = (const char*)signature->bytes();
+   const unsigned int length = signature->utf8_length();
+   const char* const p = skip_over_field_signature(bytes, false, length, CHECK_false);
+ 
+   if (p == nullptr || (p - bytes) != (int)length) {
+     return false;
+   }
+   return true;
+ }
  
  // Checks if signature is a legal field signature.
  void ClassFileParser::verify_legal_field_signature(const Symbol* name,
                                                     const Symbol* signature,
                                                     TRAPS) const {

@@ -4800,13 +5067,13 @@
      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) {
+     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.

@@ -4853,22 +5120,22 @@
    throwIllegalSignature("Method", name, signature, THREAD);
    return 0;
  }
  
  int ClassFileParser::static_field_size() const {
-   assert(_field_info != nullptr, "invariant");
-   return _field_info->_static_field_size;
+   assert(_layout_info != nullptr, "invariant");
+   return _layout_info->_static_field_size;
  }
  
  int ClassFileParser::total_oop_map_count() const {
-   assert(_field_info != nullptr, "invariant");
-   return _field_info->oop_map_blocks->_nonstatic_oop_map_count;
+   assert(_layout_info != nullptr, "invariant");
+   return _layout_info->oop_map_blocks->_nonstatic_oop_map_count;
  }
  
  jint ClassFileParser::layout_size() const {
-   assert(_field_info != nullptr, "invariant");
-   return _field_info->_instance_size;
+   assert(_layout_info != nullptr, "invariant");
+   return _layout_info->_instance_size;
  }
  
  static void check_methods_for_intrinsics(const InstanceKlass* ik,
                                           const Array<Method*>* methods) {
    assert(ik != nullptr, "invariant");

@@ -4979,11 +5246,10 @@
    }
  
    fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL);
  
    assert(_klass == ik, "invariant");
- 
    return ik;
  }
  
  void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
                                            bool changed_by_loadhook,

@@ -5001,29 +5267,44 @@
  
    _loader_data->add_class(ik, publicize);
  
    set_klass_to_deallocate(ik);
  
-   assert(_field_info != nullptr, "invariant");
-   assert(ik->static_field_size() == _field_info->_static_field_size, "sanity");
-   assert(ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count,
+   assert(_layout_info != nullptr, "invariant");
+   assert(ik->static_field_size() == _layout_info->_static_field_size, "sanity");
+   assert(ik->nonstatic_oop_map_count() == _layout_info->oop_map_blocks->_nonstatic_oop_map_count,
           "sanity");
  
    assert(ik->is_instance_klass(), "sanity");
-   assert(ik->size_helper() == _field_info->_instance_size, "sanity");
+   assert(ik->size_helper() == _layout_info->_instance_size, "sanity");
  
    // Fill in information already parsed
    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);
+   ik->set_nonstatic_field_size(_layout_info->_nonstatic_field_size);
+   ik->set_has_nonstatic_fields(_layout_info->_has_nonstatic_fields);
+ 
+   if (_layout_info->_is_naturally_atomic) {
+     ik->set_is_naturally_atomic();
+   }
+ 
+   if (_layout_info->_must_be_atomic) {
+     ik->set_must_be_atomic();
+   }
+   if (_is_implicitly_constructible) {
+     ik->set_is_implicitly_constructible();
+   }
+ 
    ik->set_static_oop_field_count(_static_oop_count);
  
    // this transfers ownership of a lot of arrays from
    // the parser onto the InstanceKlass*
    apply_parsed_class_metadata(ik, _java_fields_count);
+   if (ik->is_inline_klass()) {
+     InlineKlass::cast(ik)->init_fixed_block();
+   }
  
    // can only set dynamic nest-host after static nest information is set
    if (cl_inst_info.dynamic_nest_host() != nullptr) {
      ik->set_nest_host(cl_inst_info.dynamic_nest_host());
    }

@@ -5033,13 +5314,15 @@
    assert(nullptr == _fieldinfo_stream, "invariant");
    assert(nullptr == _fields_status, "invariant");
    assert(nullptr == _methods, "invariant");
    assert(nullptr == _inner_classes, "invariant");
    assert(nullptr == _nest_members, "invariant");
+   assert(nullptr == _loadable_descriptors, "invariant");
    assert(nullptr == _combined_annotations, "invariant");
    assert(nullptr == _record_components, "invariant");
    assert(nullptr == _permitted_subclasses, "invariant");
+   assert(nullptr == _inline_layout_info_array, "invariant");
  
    if (_has_localvariable_table) {
      ik->set_has_localvariable_table(true);
    }
  

@@ -5113,11 +5396,11 @@
    // Initialize itable offset tables
    klassItable::setup_itable_offset_table(ik);
  
    // Compute transitive closure of interfaces this class implements
    // Do final class setup
-   OopMapBlocksBuilder* oop_map_blocks = _field_info->oop_map_blocks;
+   OopMapBlocksBuilder* oop_map_blocks = _layout_info->oop_map_blocks;
    if (oop_map_blocks->_nonstatic_oop_map_count > 0) {
      oop_map_blocks->copy(ik->start_of_nonstatic_oop_maps());
    }
  
    if (_has_contended_fields || _parsed_annotations->is_contended() ||

@@ -5175,10 +5458,26 @@
        // We won a potential race
        JvmtiExport::add_default_read_edges(module_handle, THREAD);
      }
    }
  
+   if (is_inline_type()) {
+     InlineKlass* vk = InlineKlass::cast(ik);
+     vk->set_payload_alignment(_layout_info->_payload_alignment);
+     vk->set_first_field_offset(_layout_info->_first_field_offset);
+     vk->set_payload_size_in_bytes(_layout_info->_payload_size_in_bytes);
+     vk->set_non_atomic_size_in_bytes(_layout_info->_non_atomic_size_in_bytes);
+     vk->set_non_atomic_alignment(_layout_info->_non_atomic_alignment);
+     vk->set_atomic_size_in_bytes(_layout_info->_atomic_layout_size_in_bytes);
+     vk->set_nullable_size_in_bytes(_layout_info->_nullable_layout_size_in_bytes);
+     vk->set_null_marker_offset(_layout_info->_null_marker_offset);
+     vk->set_default_value_offset(_layout_info->_default_value_offset);
+     vk->set_null_reset_value_offset(_layout_info->_null_reset_value_offset);
+     if (_layout_info->_is_empty_inline_klass) vk->set_is_empty_inline_type();
+     vk->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);
  

@@ -5267,22 +5566,25 @@
    _methods(nullptr),
    _inner_classes(nullptr),
    _nest_members(nullptr),
    _nest_host(0),
    _permitted_subclasses(nullptr),
+   _loadable_descriptors(nullptr),
    _record_components(nullptr),
    _local_interfaces(nullptr),
+   _local_interface_indexes(nullptr),
    _transitive_interfaces(nullptr),
    _combined_annotations(nullptr),
    _class_annotations(nullptr),
    _class_type_annotations(nullptr),
    _fields_annotations(nullptr),
    _fields_type_annotations(nullptr),
    _klass(nullptr),
    _klass_to_deallocate(nullptr),
    _parsed_annotations(nullptr),
-   _field_info(nullptr),
+   _layout_info(nullptr),
+   _inline_layout_info_array(nullptr),
    _temp_field_info(nullptr),
    _method_ordering(nullptr),
    _all_mirandas(nullptr),
    _vtable_size(0),
    _itable_size(0),

@@ -5307,10 +5609,16 @@
    _has_nonstatic_concrete_methods(false),
    _declares_nonstatic_concrete_methods(false),
    _has_localvariable_table(false),
    _has_final_method(false),
    _has_contended_fields(false),
+   _has_inline_type_fields(false),
+   _is_naturally_atomic(false),
+   _must_be_atomic(true),
+   _is_implicitly_constructible(false),
+   _has_loosely_consistent_annotation(false),
+   _has_implicitly_constructible_annotation(false),
    _has_finalizer(false),
    _has_empty_finalizer(false),
    _max_bootstrap_specifier_index(-1) {
  
    _class_name = name != nullptr ? name : vmSymbols::unknown_class_name();

@@ -5356,14 +5664,16 @@
    _fields_status = nullptr;
    _methods = nullptr;
    _inner_classes = nullptr;
    _nest_members = nullptr;
    _permitted_subclasses = nullptr;
+   _loadable_descriptors = nullptr;
    _combined_annotations = nullptr;
    _class_annotations = _class_type_annotations = nullptr;
    _fields_annotations = _fields_type_annotations = nullptr;
    _record_components = nullptr;
+   _inline_layout_info_array = nullptr;
  }
  
  // Destructor to clean up
  ClassFileParser::~ClassFileParser() {
    _class_name->decrement_refcount();

@@ -5378,10 +5688,14 @@
  
    if (_fields_status != nullptr) {
      MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
    }
  
+   if (_inline_layout_info_array != nullptr) {
+     MetadataFactory::free_array<InlineLayoutInfo>(_loader_data, _inline_layout_info_array);
+   }
+ 
    if (_methods != nullptr) {
      // Free methods
      InstanceKlass::deallocate_methods(_loader_data, _methods);
    }
  

@@ -5400,10 +5714,14 @@
  
    if (_permitted_subclasses != nullptr && _permitted_subclasses != Universe::the_empty_short_array()) {
      MetadataFactory::free_array<u2>(_loader_data, _permitted_subclasses);
    }
  
+   if (_loadable_descriptors != nullptr && _loadable_descriptors != Universe::the_empty_short_array()) {
+     MetadataFactory::free_array<u2>(_loader_data, _loadable_descriptors);
+   }
+ 
    // Free interfaces
    InstanceKlass::deallocate_interfaces(_loader_data, _super_klass,
                                         _local_interfaces, _transitive_interfaces);
  
    if (_combined_annotations != nullptr) {

@@ -5484,35 +5802,33 @@
    assert(cp_size == (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;
    }
  
+   // 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;
    }
  
-   verify_legal_class_modifiers(flags, CHECK);
- 
-   short bad_constant = class_bad_constant_seen();
-   if (bad_constant != 0) {
-     // Do not throw CFE until after the access_flags are checked because if
-     // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
-     classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD);
-     return;
+   // Fixing ACC_SUPER/ACC_IDENTITY for old class files
+   if (!supports_inline_types()) {
+     const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+     const bool is_interface = (flags & JVM_ACC_INTERFACE) != 0;
+     if (!is_module && !is_interface) {
+       flags |= JVM_ACC_IDENTITY;
+     }
    }
  
-   _access_flags.set_flags(flags);
  
    // This class and superclass
    _this_class_index = stream->get_u2_fast();
    guarantee_property(
      valid_cp_range(_this_class_index, cp_size) &&

@@ -5521,10 +5837,24 @@
      _this_class_index, CHECK);
  
    Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index);
    assert(class_name_in_cp != nullptr, "class_name can't be null");
  
+   bool is_java_lang_Object = class_name_in_cp == vmSymbols::java_lang_Object();
+ 
+   verify_legal_class_modifiers(flags, nullptr, is_java_lang_Object, CHECK);
+ 
+   _access_flags.set_flags(flags);
+ 
+   short bad_constant = class_bad_constant_seen();
+   if (bad_constant != 0) {
+     // Do not throw CFE until after the access_flags are checked because if
+     // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
+     classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD);
+     return;
+   }
+ 
    // Don't need to check whether this class name is legal or not.
    // It has been checked when constant pool is parsed.
    // However, make sure it is not an array type.
    if (_need_verify) {
      guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY,

@@ -5600,25 +5930,25 @@
                     _itfs_len,
                     cp,
                     &_has_nonstatic_concrete_methods,
                     CHECK);
  
-   assert(_local_interfaces != nullptr, "invariant");
- 
    // Fields (offsets are filled in later)
    parse_fields(stream,
-                _access_flags.is_interface(),
+                _access_flags,
                 cp,
                 cp_size,
                 &_java_fields_count,
                 CHECK);
  
    assert(_temp_field_info != nullptr, "invariant");
  
    // Methods
    parse_methods(stream,
-                 _access_flags.is_interface(),
+                 is_interface(),
+                 !is_identity_class(),
+                 is_abstract_class(),
                  &_has_localvariable_table,
                  &_has_final_method,
                  &_declares_nonstatic_concrete_methods,
                  CHECK);
  

@@ -5694,17 +6024,17 @@
    assert(cp != nullptr, "invariant");
    assert(_loader_data != nullptr, "invariant");
  
    if (_class_name == vmSymbols::java_lang_Object()) {
      guarantee_property(_local_interfaces == Universe::the_empty_instance_klass_array(),
-                        "java.lang.Object cannot implement an interface in class file %s",
-                        CHECK);
+         "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 && nullptr == _super_klass) {
      Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
-     if (_access_flags.is_interface()) {
+     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);

@@ -5712,30 +6042,123 @@
      Handle loader(THREAD, _loader_data->class_loader());
      if (loader.is_null() && super_class_name == vmSymbols::java_lang_Object()) {
        _super_klass = vmClasses::Object_klass();
      } else {
        _super_klass = (const InstanceKlass*)
-                        SystemDictionary::resolve_super_or_fail(_class_name,
+                        SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name,
                                                                 super_class_name,
                                                                 loader,
                                                                 _protection_domain,
                                                                 true,
                                                                 CHECK);
      }
    }
  
    if (_super_klass != nullptr) {
+     if (_super_klass->is_interface()) {
+       classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD);
+       return;
+     }
+ 
+     if (_super_klass->is_final()) {
+       classfile_icce_error("class %s cannot inherit from final class %s", _super_klass, THREAD);
+       return;
+     }
+ 
+     if (EnableValhalla) {
+       check_identity_and_value_modifiers(this, _super_klass, CHECK);
+     }
+ 
      if (_super_klass->has_nonstatic_concrete_methods()) {
        _has_nonstatic_concrete_methods = true;
      }
+   }
  
-     if (_super_klass->is_interface()) {
-       classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD);
-       return;
+   if (_parsed_annotations->has_annotation(AnnotationCollector::_jdk_internal_LooselyConsistentValue) && _access_flags.is_identity_class()) {
+     THROW_MSG(vmSymbols::java_lang_ClassFormatError(),
+           err_msg("class %s cannot have annotation jdk.internal.vm.annotation.LooselyConsistentValue, because it is not a value class",
+                   _class_name->as_klass_external_name()));
+   }
+   if (_parsed_annotations->has_annotation(AnnotationCollector::_jdk_internal_ImplicitlyConstructible) && _access_flags.is_identity_class()) {
+     THROW_MSG(vmSymbols::java_lang_ClassFormatError(),
+           err_msg("class %s cannot have annotation jdk.internal.vm.annotation.ImplicitlyConstructible, because it is not a value class",
+                   _class_name->as_klass_external_name()));
+   }
+ 
+   // Determining is the class allows tearing or not (default is not)
+   if (EnableValhalla && !_access_flags.is_identity_class()) {
+     if (_parsed_annotations->has_annotation(ClassAnnotationCollector::_jdk_internal_LooselyConsistentValue)
+         && (_super_klass == vmClasses::Object_klass() || !_super_klass->must_be_atomic())) {
+       // Conditions above are not sufficient to determine atomicity requirements,
+       // the presence of fields with atomic requirements could force the current class to have atomicy requirements too
+       // Marking as not needing atomicity for now, can be updated when computing the fields layout
+       // The InstanceKlass must be filled with the value from the FieldLayoutInfo returned by
+       // the FieldLayoutBuilder, not with this _must_be_atomic field.
+       _must_be_atomic = false;
+     }
+     if (_parsed_annotations->has_annotation(ClassAnnotationCollector::_jdk_internal_ImplicitlyConstructible)
+         && (_super_klass == vmClasses::Object_klass() || _super_klass == vmClasses::Record_klass()
+         || _super_klass->is_implicitly_constructible())) {
+       _is_implicitly_constructible = true;
+     }
+     // Apply VM options override
+     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)) {
+         _must_be_atomic = true;
+       }
      }
    }
  
+   int itfs_len = _local_interface_indexes == nullptr ? 0 : _local_interface_indexes->length();
+   _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, nullptr, CHECK);
+   if (_local_interface_indexes != nullptr) {
+     for (int i = 0; i < _local_interface_indexes->length(); i++) {
+       u2 interface_index = _local_interface_indexes->at(i);
+       Klass* interf;
+       if (cp->tag_at(interface_index).is_klass()) {
+         interf = cp->resolved_klass_at(interface_index);
+       } else {
+         Symbol* const unresolved_klass  = cp->klass_name_at(interface_index);
+ 
+         // Don't need to check legal name because it's checked when parsing constant pool.
+         // But need to make sure it's not an array type.
+         guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY,
+                             "Bad interface name in class file %s", CHECK);
+ 
+         // Call resolve on the interface class name with class circularity checking
+         interf = SystemDictionary::resolve_with_circularity_detection_or_fail(
+                                                   _class_name,
+                                                   unresolved_klass,
+                                                   Handle(THREAD, _loader_data->class_loader()),
+                                                   _protection_domain,
+                                                   false,
+                                                   CHECK);
+       }
+ 
+       if (!interf->is_interface()) {
+         THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                   err_msg("class %s can not implement %s, because it is not an interface (%s)",
+                           _class_name->as_klass_external_name(),
+                           interf->external_name(),
+                           interf->class_in_module_of_loader()));
+       }
+ 
+       if (EnableValhalla) {
+         // Check modifiers and set carries_identity_modifier/carries_value_modifier flags
+         check_identity_and_value_modifiers(this, InstanceKlass::cast(interf), CHECK);
+       }
+ 
+       if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
+         _has_nonstatic_concrete_methods = true;
+       }
+       _local_interfaces->at_put(i, InstanceKlass::cast(interf));
+     }
+   }
+   assert(_local_interfaces != nullptr, "invariant");
+ 
    // Compute the transitive list of all unique interfaces implemented by this class
    _transitive_interfaces =
      compute_transitive_interfaces(_super_klass,
                                    _local_interfaces,
                                    _loader_data,

@@ -5759,24 +6182,103 @@
                                                      loader,
                                                      _class_name,
                                                      _local_interfaces);
  
    // Size of Java itable (in words)
-   _itable_size = _access_flags.is_interface() ? 0 :
+   _itable_size = is_interface() ? 0 :
      klassItable::compute_itable_size(_transitive_interfaces);
  
    assert(_parsed_annotations != nullptr, "invariant");
  
-   _field_info = new FieldLayoutInfo();
-   FieldLayoutBuilder lb(class_name(), super_klass(), _cp, /*_fields*/ _temp_field_info,
-                         _parsed_annotations->is_contended(), _field_info);
+   if (EnableValhalla) {
+     _inline_layout_info_array = MetadataFactory::new_array<InlineLayoutInfo>(_loader_data,
+                                                    java_fields_count(),
+                                                    CHECK);
+     for (GrowableArrayIterator<FieldInfo> it = _temp_field_info->begin(); it != _temp_field_info->end(); ++it) {
+       FieldInfo fieldinfo = *it;
+       if (fieldinfo.access_flags().is_static()) continue;  // Only non-static fields are processed at load time
+       Symbol* sig = fieldinfo.signature(cp);
+       if (fieldinfo.field_flags().is_null_free_inline_type()) {
+         // Pre-load classes of null-free fields that are candidate for flattening
+         TempNewSymbol s = Signature::strip_envelope(sig);
+         if (s == _class_name) {
+           THROW_MSG(vmSymbols::java_lang_ClassCircularityError(), err_msg("Class %s cannot have a null-free non-static field of its own type", _class_name->as_C_string()));
+         }
+         log_info(class, preload)("Preloading class %s during loading of class %s. Cause: a null-free non-static field is declared with this type", s->as_C_string(), _class_name->as_C_string());
+         Klass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, s, Handle(THREAD, _loader_data->class_loader()), _protection_domain, false, THREAD);
+         if (HAS_PENDING_EXCEPTION) {
+           log_warning(class, preload)("Preloading of class %s during loading of class %s (cause: null-free non-static field) failed: %s",
+                                       s->as_C_string(), _class_name->as_C_string(), PENDING_EXCEPTION->klass()->name()->as_C_string());
+           return; // Exception is still pending
+         }
+         assert(klass != nullptr, "Sanity check");
+         if (klass->access_flags().is_identity_class()) {
+           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 a value class, but it is an identity class",
+                     _class_name->as_C_string(),
+                     InstanceKlass::cast(klass)->external_name()));
+         }
+         if (klass->is_abstract()) {
+           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 concrete value type, but it is an abstract class",
+                     _class_name->as_C_string(),
+                     InstanceKlass::cast(klass)->external_name()));
+         }
+         InlineKlass* vk = InlineKlass::cast(klass);
+         if (!vk->is_implicitly_constructible()) {
+           THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                     err_msg("class %s is not implicitly constructible and it is used in a null restricted non-static field (not supported)",
+                     klass->name()->as_C_string()));
+         }
+         _inline_layout_info_array->adr_at(fieldinfo.index())->set_klass(vk);
+         log_info(class, preload)("Preloading of class %s during loading of class %s (cause: null-free non-static field) succeeded", s->as_C_string(), _class_name->as_C_string());
+       } else if (Signature::has_envelope(sig)) {
+         // Preloading classes for nullable fields that are listed in the LoadableDescriptors attribute
+         // Those classes would be required later for the flattening of nullable inline type fields
+         TempNewSymbol name = Signature::strip_envelope(sig);
+         if (name != _class_name && is_class_in_loadable_descriptors_attribute(sig)) {
+           log_info(class, preload)("Preloading class %s during loading of class %s. Cause: field type in LoadableDescriptors attribute", name->as_C_string(), _class_name->as_C_string());
+           oop loader = loader_data()->class_loader();
+           Klass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, name, Handle(THREAD, loader), _protection_domain, false, THREAD);
+           if (klass != nullptr) {
+             if (klass->is_inline_klass()) {
+               _inline_layout_info_array->adr_at(fieldinfo.index())->set_klass(InlineKlass::cast(klass));
+               log_info(class, preload)("Preloading of class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) succeeded", name->as_C_string(), _class_name->as_C_string());
+             } else {
+               // Non value class are allowed by the current spec, but it could be an indication of an issue so let's log a warning
+               log_warning(class, preload)("Preloading class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) but loaded class is not a value class", name->as_C_string(), _class_name->as_C_string());
+             }
+             } else {
+             log_warning(class, preload)("Preloading of class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) failed : %s",
+                                           name->as_C_string(), _class_name->as_C_string(), PENDING_EXCEPTION->klass()->name()->as_C_string());
+           }
+           // Loads triggered by the LoadableDescriptors attribute are speculative, failures must not impact loading of current class
+           if (HAS_PENDING_EXCEPTION) {
+             CLEAR_PENDING_EXCEPTION;
+           }
+         }
+       }
+     }
+   }
+ 
+   _layout_info = new FieldLayoutInfo();
+   FieldLayoutBuilder lb(class_name(), loader_data(), super_klass(), _cp, /*_fields*/ _temp_field_info,
+       _parsed_annotations->is_contended(), is_inline_type(),
+       access_flags().is_abstract() && !access_flags().is_identity_class() && !access_flags().is_interface(),
+       _must_be_atomic, _layout_info, _inline_layout_info_array);
    lb.build_layout();
+   _has_inline_type_fields = _layout_info->_has_inline_fields;
  
    int injected_fields_count = _temp_field_info->length() - _java_fields_count;
    _fieldinfo_stream =
      FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
                                              injected_fields_count, loader_data(), CHECK);
+ 
    _fields_status =
      MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
                                              FieldStatus(0), CHECK);
  }
  
< prev index next >