< prev index next >

src/hotspot/share/memory/universe.cpp

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
--- 1,7 ---
  /*
!  * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

*** 63,11 ***
--- 63,13 ---
  #include "oops/jmethodIDTable.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/objLayout.hpp"
  #include "oops/oop.inline.hpp"
+ #include "oops/oopCast.inline.hpp"
  #include "oops/oopHandle.inline.hpp"
+ #include "oops/refArrayKlass.hpp"
  #include "oops/typeArrayKlass.hpp"
  #include "prims/resolvedMethodTable.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/atomicAccess.hpp"
  #include "runtime/cpuTimeCounters.hpp"

*** 111,10 ***
--- 113,12 ---
  static LatestMethodCache _finalizer_register_cache;         // Finalizer.register()
  static LatestMethodCache _loader_addClass_cache;            // ClassLoader.addClass()
  static LatestMethodCache _throw_illegal_access_error_cache; // Unsafe.throwIllegalAccessError()
  static LatestMethodCache _throw_no_such_method_error_cache; // Unsafe.throwNoSuchMethodError()
  static LatestMethodCache _do_stack_walk_cache;              // AbstractStackWalker.doStackWalk()
+ static LatestMethodCache _is_substitutable_cache;           // ValueObjectMethods.isSubstitutable()
+ static LatestMethodCache _value_object_hash_code_cache;     // ValueObjectMethods.valueObjectHashCode()
  
  // Known objects
  TypeArrayKlass* Universe::_typeArrayKlasses[T_LONG+1] = { nullptr /*, nullptr...*/ };
  ObjArrayKlass* Universe::_objectArrayKlass            = nullptr;
  Klass* Universe::_fillerArrayKlass                    = nullptr;

*** 507,20 ***
    // Since some of the old system object arrays have been converted to
    // ordinary object arrays, _objectArrayKlass will be loaded when
    // SystemDictionary::initialize(CHECK); is run. See the extra check
    // for Object_klass_is_loaded in ObjArrayKlass::allocate_objArray_klass.
    {
!     Klass* oak = vmClasses::Object_klass()->array_klass(CHECK);
!     _objectArrayKlass = ObjArrayKlass::cast(oak);
    }
-   // OLD
-   // Add the class to the class hierarchy manually to make sure that
-   // its vtable is initialized after core bootstrapping is completed.
-   // ---
-   // New
-   // Have already been initialized.
-   _objectArrayKlass->append_to_sibling_list();
  
    #ifdef ASSERT
    if (FullGCALot) {
      // Allocate an array of dummy objects.
      // We'd like these to be at the bottom of the old generation,
--- 511,17 ---
    // Since some of the old system object arrays have been converted to
    // ordinary object arrays, _objectArrayKlass will be loaded when
    // SystemDictionary::initialize(CHECK); is run. See the extra check
    // for Object_klass_is_loaded in ObjArrayKlass::allocate_objArray_klass.
    {
!     ArrayKlass* oak = vmClasses::Object_klass()->array_klass(CHECK);
!     oak->append_to_sibling_list();
+ 
+     // Create a RefArrayKlass (which is the default) and initialize.
+     ObjArrayKlass* rak = ObjArrayKlass::cast(oak)->klass_with_properties(ArrayProperties::Default(), THREAD);
+     _objectArrayKlass = rak;
    }
  
    #ifdef ASSERT
    if (FullGCALot) {
      // Allocate an array of dummy objects.
      // We'd like these to be at the bottom of the old generation,

*** 651,10 ***
--- 652,13 ---
    // classes are always initialized first.
    for (ClassHierarchyIterator iter(vmClasses::Object_klass()); !iter.done(); iter.next()) {
      Klass* sub = iter.klass();
      sub->vtable().initialize_vtable();
    }
+ 
+   // This isn't added to the subclass list, so need to reinitialize vtables directly.
+   Universe::objectArrayKlass()->vtable().initialize_vtable();
  }
  
  static void reinitialize_itables() {
  
    class ReinitTableClosure : public KlassClosure {

*** 674,15 ***
  bool Universe::on_page_boundary(void* addr) {
    return is_aligned(addr, os::vm_page_size());
  }
  
  // the array of preallocated errors with backtraces
! objArrayOop Universe::preallocated_out_of_memory_errors() {
!   return (objArrayOop)_preallocated_out_of_memory_error_array.resolve();
  }
  
! objArrayOop Universe::out_of_memory_errors() { return (objArrayOop)_out_of_memory_errors.resolve(); }
  
  oop Universe::out_of_memory_error_java_heap() {
    return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap));
  }
  
--- 678,15 ---
  bool Universe::on_page_boundary(void* addr) {
    return is_aligned(addr, os::vm_page_size());
  }
  
  // the array of preallocated errors with backtraces
! refArrayOop Universe::preallocated_out_of_memory_errors() {
!   return oop_cast<refArrayOop>(_preallocated_out_of_memory_error_array.resolve());
  }
  
! refArrayOop Universe::out_of_memory_errors() { return oop_cast<refArrayOop>(_out_of_memory_errors.resolve()); }
  
  oop Universe::out_of_memory_error_java_heap() {
    return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap));
  }
  

*** 723,11 ***
    // never attempt to fill in the stack trace of preallocated errors that do not have
    // backtrace. These errors are kept alive forever and may be "re-used" when all
    // preallocated errors with backtrace have been consumed. Also need to avoid
    // a potential loop which could happen if an out of memory occurs when attempting
    // to allocate the backtrace.
!   objArrayOop preallocated_oom = out_of_memory_errors();
    for (int i = 0; i < _oom_count; i++) {
      if (throwable() == preallocated_oom->obj_at(i)) {
        return false;
      }
    }
--- 727,11 ---
    // never attempt to fill in the stack trace of preallocated errors that do not have
    // backtrace. These errors are kept alive forever and may be "re-used" when all
    // preallocated errors with backtrace have been consumed. Also need to avoid
    // a potential loop which could happen if an out of memory occurs when attempting
    // to allocate the backtrace.
!   refArrayOop preallocated_oom = out_of_memory_errors();
    for (int i = 0; i < _oom_count; i++) {
      if (throwable() == preallocated_oom->obj_at(i)) {
        return false;
      }
    }

*** 783,12 ***
  }
  
  // Setup preallocated OutOfMemoryError errors
  void Universe::create_preallocated_out_of_memory_errors(TRAPS) {
    InstanceKlass* ik = vmClasses::OutOfMemoryError_klass();
!   objArrayOop oa = oopFactory::new_objArray(ik, _oom_count, CHECK);
!   objArrayHandle oom_array(THREAD, oa);
  
    for (int i = 0; i < _oom_count; i++) {
      oop oom_obj = ik->allocate_instance(CHECK);
      oom_array->obj_at_put(i, oom_obj);
    }
--- 787,12 ---
  }
  
  // Setup preallocated OutOfMemoryError errors
  void Universe::create_preallocated_out_of_memory_errors(TRAPS) {
    InstanceKlass* ik = vmClasses::OutOfMemoryError_klass();
!   refArrayOop ra = oopFactory::new_refArray(ik, _oom_count, CHECK);
!   refArrayHandle oom_array(THREAD, ra);
  
    for (int i = 0; i < _oom_count; i++) {
      oop oom_obj = ik->allocate_instance(CHECK);
      oom_array->obj_at_put(i, oom_obj);
    }

*** 817,13 ***
    msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK);
    java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg());
  
    // Setup the array of errors that have preallocated backtrace
    int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
!   objArrayOop instance = oopFactory::new_objArray(ik, len, CHECK);
    _preallocated_out_of_memory_error_array = OopHandle(vm_global(), instance);
!   objArrayHandle preallocated_oom_array(THREAD, instance);
  
    for (int i=0; i<len; i++) {
      oop err = ik->allocate_instance(CHECK);
      Handle err_h(THREAD, err);
      java_lang_Throwable::allocate_backtrace(err_h, CHECK);
--- 821,13 ---
    msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK);
    java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg());
  
    // Setup the array of errors that have preallocated backtrace
    int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
!   refArrayOop instance = oopFactory::new_refArray(ik, len, CHECK);
    _preallocated_out_of_memory_error_array = OopHandle(vm_global(), instance);
!   refArrayHandle preallocated_oom_array(THREAD, instance);
  
    for (int i=0; i<len; i++) {
      oop err = ik->allocate_instance(CHECK);
      Handle err_h(THREAD, err);
      java_lang_Throwable::allocate_backtrace(err_h, CHECK);

*** 1075,15 ***
      assert(m != nullptr, "sanity check");
      return m;
    }
  }
  
! Method* Universe::finalizer_register_method()     { return _finalizer_register_cache.get_method(); }
! Method* Universe::loader_addClass_method()        { return _loader_addClass_cache.get_method(); }
! Method* Universe::throw_illegal_access_error()    { return _throw_illegal_access_error_cache.get_method(); }
! Method* Universe::throw_no_such_method_error()    { return _throw_no_such_method_error_cache.get_method(); }
! Method* Universe::do_stack_walk_method()          { return _do_stack_walk_cache.get_method(); }
  
  void Universe::initialize_known_methods(JavaThread* current) {
    // Set up static method for registering finalizers
    _finalizer_register_cache.init(current,
                            vmClasses::Finalizer_klass(),
--- 1079,17 ---
      assert(m != nullptr, "sanity check");
      return m;
    }
  }
  
! Method* Universe::finalizer_register_method()        { return _finalizer_register_cache.get_method(); }
! Method* Universe::loader_addClass_method()           { return _loader_addClass_cache.get_method(); }
! Method* Universe::throw_illegal_access_error()       { return _throw_illegal_access_error_cache.get_method(); }
! Method* Universe::throw_no_such_method_error()       { return _throw_no_such_method_error_cache.get_method(); }
! Method* Universe::do_stack_walk_method()             { return _do_stack_walk_cache.get_method(); }
+ Method* Universe::is_substitutable_method()          { return _is_substitutable_cache.get_method(); }
+ Method* Universe::value_object_hash_code_method()    { return _value_object_hash_code_cache.get_method(); }
  
  void Universe::initialize_known_methods(JavaThread* current) {
    // Set up static method for registering finalizers
    _finalizer_register_cache.init(current,
                            vmClasses::Finalizer_klass(),

*** 1109,10 ***
--- 1115,21 ---
    // Set up method for stack walking
    _do_stack_walk_cache.init(current,
                            vmClasses::AbstractStackWalker_klass(),
                            "doStackWalk",
                            vmSymbols::doStackWalk_signature(), false);
+ 
+   // Set up substitutability testing
+   ResourceMark rm(current);
+   _is_substitutable_cache.init(current,
+                           vmClasses::ValueObjectMethods_klass(),
+                           vmSymbols::isSubstitutable_name()->as_C_string(),
+                           vmSymbols::object_object_boolean_signature(), true);
+   _value_object_hash_code_cache.init(current,
+                           vmClasses::ValueObjectMethods_klass(),
+                           vmSymbols::valueObjectHashCode_name()->as_C_string(),
+                           vmSymbols::object_int_signature(), true);
  }
  
  void universe2_init() {
    EXCEPTION_MARK;
    Universe::genesis(CATCH);
< prev index next >