< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page
*** 54,26 ***
--- 54,29 ---
  #include "memory/metaspaceClosure.hpp"
  #include "memory/oopFactory.hpp"
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/access.inline.hpp"
+ #include "oops/fieldStreams.inline.hpp"
  #include "oops/instanceKlass.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/method.inline.hpp"
  #include "oops/objArrayKlass.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/oop.inline.hpp"
  #include "oops/oopHandle.inline.hpp"
  #include "oops/symbol.hpp"
  #include "oops/typeArrayKlass.hpp"
+ #include "oops/inlineKlass.inline.hpp"
  #include "prims/jvmtiExport.hpp"
  #include "prims/methodHandles.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/java.hpp"
  #include "runtime/javaCalls.hpp"
  #include "runtime/mutexLocker.hpp"
+ #include "runtime/os.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/signature.hpp"
  #include "services/classLoadingService.hpp"
  #include "services/diagnosticCommand.hpp"
  #include "services/threadService.hpp"

*** 283,11 ***
                                                                         Handle protection_domain,
                                                                         TRAPS) {
    assert(class_name != NULL && !Signature::is_array(class_name), "must be");
    if (Signature::has_envelope(class_name)) {
      ResourceMark rm(THREAD);
!     // Ignore wrapping L and ;.
      TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
                                                   class_name->utf8_length() - 2);
      return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
    } else {
      return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);
--- 286,11 ---
                                                                         Handle protection_domain,
                                                                         TRAPS) {
    assert(class_name != NULL && !Signature::is_array(class_name), "must be");
    if (Signature::has_envelope(class_name)) {
      ResourceMark rm(THREAD);
!     // Ignore wrapping L and ;. (and Q and ; for value types);
      TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
                                                   class_name->utf8_length() - 2);
      return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
    } else {
      return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);

*** 311,11 ***
      k = SystemDictionary::resolve_instance_class_or_null(obj_class,
                                                           class_loader,
                                                           protection_domain,
                                                           CHECK_NULL);
      if (k != NULL) {
!       k = k->array_klass(ndims, CHECK_NULL);
      }
    } else {
      k = Universe::typeArrayKlassObj(t);
      k = TypeArrayKlass::cast(k)->array_klass(ndims, CHECK_NULL);
    }
--- 314,18 ---
      k = SystemDictionary::resolve_instance_class_or_null(obj_class,
                                                           class_loader,
                                                           protection_domain,
                                                           CHECK_NULL);
      if (k != NULL) {
!       if (class_name->is_Q_array_signature()) {
+         if (!k->is_inline_klass()) {
+           THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), "L/Q mismatch on bottom type");
+         }
+         k = InlineKlass::cast(k)->null_free_inline_array_klass(ndims, CHECK_NULL);
+       } else {
+         k = k->array_klass(ndims, CHECK_NULL);
+       }
      }
    } else {
      k = Universe::typeArrayKlassObj(t);
      k = TypeArrayKlass::cast(k)->array_klass(ndims, CHECK_NULL);
    }

*** 441,10 ***
--- 451,54 ---
    }
  
    return superk;
  }
  
+ Klass* SystemDictionary::resolve_inline_type_field_or_fail(AllFieldStream* fs,
+                                                            Handle class_loader,
+                                                            Handle protection_domain,
+                                                            bool throw_error,
+                                                            TRAPS) {
+   Symbol* class_name = fs->signature()->fundamental_name(THREAD);
+   class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
+   ClassLoaderData* loader_data = class_loader_data(class_loader);
+   unsigned int p_hash = placeholders()->compute_hash(class_name);
+   bool throw_circularity_error = false;
+   PlaceholderEntry* oldprobe;
+ 
+   {
+     MutexLocker mu(THREAD, SystemDictionary_lock);
+     oldprobe = placeholders()->get_entry(p_hash, class_name, loader_data);
+     if (oldprobe != NULL &&
+       oldprobe->check_seen_thread(THREAD, PlaceholderTable::INLINE_TYPE_FIELD)) {
+       throw_circularity_error = true;
+ 
+     } else {
+       placeholders()->find_and_add(p_hash, class_name, loader_data,
+                                    PlaceholderTable::INLINE_TYPE_FIELD, NULL, THREAD);
+     }
+   }
+ 
+   Klass* klass = NULL;
+   if (!throw_circularity_error) {
+     klass = SystemDictionary::resolve_or_fail(class_name, class_loader,
+                                                protection_domain, true, THREAD);
+   } else {
+     ResourceMark rm(THREAD);
+     THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), class_name->as_C_string());
+   }
+ 
+   {
+     MutexLocker mu(THREAD, SystemDictionary_lock);
+     placeholders()->find_and_remove(p_hash, class_name, loader_data,
+                                     PlaceholderTable::INLINE_TYPE_FIELD, THREAD);
+   }
+ 
+   class_name->decrement_refcount();
+   return klass;
+ }
+ 
  // We only get here if this thread finds that another thread
  // has already claimed the placeholder token for the current operation,
  // but that other thread either never owned or gave up the
  // object lock
  // Waits on SystemDictionary_lock to indicate placeholder table updated

*** 798,17 ***
      // dimension and object_key in FieldArrayInfo are assigned as a
      // side-effect of this call
      SignatureStream ss(class_name, false);
      int ndims = ss.skip_array_prefix();  // skip all '['s
      BasicType t = ss.type();
!     if (t != T_OBJECT) {
        k = Universe::typeArrayKlassObj(t);
      } else {
        k = SystemDictionary::find_instance_klass(ss.as_symbol(), class_loader, protection_domain);
      }
      if (k != NULL) {
!       k = k->array_klass_or_null(ndims);
      }
    } else {
      k = find_instance_klass(class_name, class_loader, protection_domain);
    }
    return k;
--- 852,21 ---
      // dimension and object_key in FieldArrayInfo are assigned as a
      // side-effect of this call
      SignatureStream ss(class_name, false);
      int ndims = ss.skip_array_prefix();  // skip all '['s
      BasicType t = ss.type();
!     if (t != T_OBJECT && t != T_INLINE_TYPE) {
        k = Universe::typeArrayKlassObj(t);
      } else {
        k = SystemDictionary::find_instance_klass(ss.as_symbol(), class_loader, protection_domain);
      }
      if (k != NULL) {
!       if (class_name->is_Q_array_signature()) {
+         k = InlineKlass::cast(k)->null_free_inline_array_klass_or_null(ndims);
+       } else {
+         k = k->array_klass_or_null(ndims);
+       }
      }
    } else {
      k = find_instance_klass(class_name, class_loader, protection_domain);
    }
    return k;

*** 1146,10 ***
--- 1204,28 ---
  
    if (!check_shared_class_super_types(ik, class_loader, protection_domain, THREAD)) {
      return NULL;
    }
  
+ 
+   if (ik->has_inline_type_fields()) {
+     for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
+       if (Signature::basic_type(fs.signature()) == T_INLINE_TYPE) {
+         if (!fs.access_flags().is_static()) {
+           // Pre-load inline class
+           Klass* real_k = SystemDictionary::resolve_inline_type_field_or_fail(&fs,
+             class_loader, protection_domain, true, CHECK_NULL);
+           Klass* k = ik->get_inline_type_field_klass_or_null(fs.index());
+           if (real_k != k) {
+             // oops, the app has substituted a different version of k!
+             return NULL;
+           }
+         }
+       }
+     }
+   }
+ 
    InstanceKlass* new_ik = NULL;
    // CFLH check is skipped for VM hidden classes (see KlassFactory::create_from_stream).
    // It will be skipped for shared VM hidden lambda proxy classes.
    if (!SystemDictionaryShared::is_hidden_lambda_proxy(ik)) {
      new_ik = KlassFactory::check_shared_class_file_load_hook(

*** 1181,10 ***
--- 1257,17 ---
      // restore_unshareable_info which calls ik->set_package()
      ik->restore_unshareable_info(loader_data, protection_domain, pkg_entry, CHECK_NULL);
    }
  
    load_shared_class_misc(ik, loader_data);
+ 
+   if (ik->is_inline_klass()) {
+     InlineKlass* vk = InlineKlass::cast(ik);
+     oop val = ik->allocate_instance(CHECK_NULL);
+     vk->set_default_value(val);
+   }
+ 
    return ik;
  }
  
  void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data) {
    ik->print_class_load_logging(loader_data, NULL, NULL);

*** 1767,19 ***
      // For array classes, their Klass*s are not kept in the
      // constraint table. The element Klass*s are.
      SignatureStream ss(class_name, false);
      int ndims = ss.skip_array_prefix();  // skip all '['s
      BasicType t = ss.type();
!     if (t != T_OBJECT) {
        klass = Universe::typeArrayKlassObj(t);
      } else {
        MutexLocker mu(current, SystemDictionary_lock);
        klass = constraints()->find_constrained_klass(ss.as_symbol(), class_loader);
      }
      // If element class already loaded, allocate array klass
      if (klass != NULL) {
!       klass = klass->array_klass_or_null(ndims);
      }
    } else {
      MutexLocker mu(current, SystemDictionary_lock);
      // Non-array classes are easy: simply check the constraint table.
      klass = constraints()->find_constrained_klass(class_name, class_loader);
--- 1850,23 ---
      // For array classes, their Klass*s are not kept in the
      // constraint table. The element Klass*s are.
      SignatureStream ss(class_name, false);
      int ndims = ss.skip_array_prefix();  // skip all '['s
      BasicType t = ss.type();
!     if (t != T_OBJECT && t != T_INLINE_TYPE) {
        klass = Universe::typeArrayKlassObj(t);
      } else {
        MutexLocker mu(current, SystemDictionary_lock);
        klass = constraints()->find_constrained_klass(ss.as_symbol(), class_loader);
      }
      // If element class already loaded, allocate array klass
      if (klass != NULL) {
!       if (class_name->is_Q_array_signature()) {
+         klass = InlineKlass::cast(klass)->null_free_inline_array_klass_or_null(ndims);
+       } else {
+         klass = klass->array_klass_or_null(ndims);
+       }
      }
    } else {
      MutexLocker mu(current, SystemDictionary_lock);
      // Non-array classes are easy: simply check the constraint table.
      klass = constraints()->find_constrained_klass(class_name, class_loader);
< prev index next >