< prev index next >

src/hotspot/share/oops/klass.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.

*** 268,24 ***
  #endif
    ShouldNotReachHere();
    return nullptr;
  }
  
- static markWord make_prototype(const Klass* kls) {
-   markWord prototype = markWord::prototype();
- #ifdef _LP64
-   if (UseCompactObjectHeaders) {
-     // With compact object headers, the narrow Klass ID is part of the mark word.
-     // We therefore seed the mark word with the narrow Klass ID.
-     precond(CompressedKlassPointers::is_encodable(kls));
-     const narrowKlass nk = CompressedKlassPointers::encode(const_cast<Klass*>(kls));
-     prototype = prototype.set_narrow_klass(nk);
-   }
- #endif
-   return prototype;
- }
- 
  void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() {
    return Metaspace::allocate(loader_data, word_size, MetaspaceObj::ClassType, THREAD);
  }
  
  Klass::Klass() : _kind(UnknownKlassKind) {
--- 268,10 ---

*** 294,13 ***
  
  // "Normal" instantiation is preceded by a MetaspaceObj allocation
  // which zeros out memory - calloc equivalent.
  // The constructor is also used from CppVtableCloner,
  // which doesn't zero out the memory before calling the constructor.
! Klass::Klass(KlassKind kind) : _kind(kind),
-                                _prototype_header(make_prototype(this)),
                                 _shared_class_path_index(-1) {
    CDS_ONLY(_aot_class_flags = 0;)
    CDS_JAVA_HEAP_ONLY(_archived_mirror_index = -1;)
    _primary_supers[0] = this;
    set_super_check_offset(in_bytes(primary_supers_offset()));
  }
--- 280,13 ---
  
  // "Normal" instantiation is preceded by a MetaspaceObj allocation
  // which zeros out memory - calloc equivalent.
  // The constructor is also used from CppVtableCloner,
  // which doesn't zero out the memory before calling the constructor.
! Klass::Klass(KlassKind kind, markWord prototype_header) : _kind(kind),
                                 _shared_class_path_index(-1) {
+   set_prototype_header(make_prototype_header(this, prototype_header));
    CDS_ONLY(_aot_class_flags = 0;)
    CDS_JAVA_HEAP_ONLY(_archived_mirror_index = -1;)
    _primary_supers[0] = this;
    set_super_check_offset(in_bytes(primary_supers_offset()));
  }

*** 309,16 ***
    assert(etype >= T_BOOLEAN && etype <= T_OBJECT, "valid etype");
    // Note that T_ARRAY is not allowed here.
    int  hsize = arrayOopDesc::base_offset_in_bytes(etype);
    int  esize = type2aelembytes(etype);
    bool isobj = (etype == T_OBJECT);
!   int  tag   =  isobj ? _lh_array_tag_obj_value : _lh_array_tag_type_value;
!   int lh = array_layout_helper(tag, hsize, etype, exact_log2(esize));
  
    assert(lh < (int)_lh_neutral_value, "must look like an array layout");
    assert(layout_helper_is_array(lh), "correct kind");
!   assert(layout_helper_is_objArray(lh) == isobj, "correct kind");
    assert(layout_helper_is_typeArray(lh) == !isobj, "correct kind");
    assert(layout_helper_header_size(lh) == hsize, "correct decode");
    assert(layout_helper_element_type(lh) == etype, "correct decode");
    assert(1 << layout_helper_log2_element_size(lh) == esize, "correct decode");
  
--- 295,16 ---
    assert(etype >= T_BOOLEAN && etype <= T_OBJECT, "valid etype");
    // Note that T_ARRAY is not allowed here.
    int  hsize = arrayOopDesc::base_offset_in_bytes(etype);
    int  esize = type2aelembytes(etype);
    bool isobj = (etype == T_OBJECT);
!   int  tag   =  isobj ? _lh_array_tag_ref_value : _lh_array_tag_type_value;
!   int lh = array_layout_helper(tag, false, hsize, etype, exact_log2(esize));
  
    assert(lh < (int)_lh_neutral_value, "must look like an array layout");
    assert(layout_helper_is_array(lh), "correct kind");
!   assert(layout_helper_is_refArray(lh) == isobj, "correct kind");
    assert(layout_helper_is_typeArray(lh) == !isobj, "correct kind");
    assert(layout_helper_header_size(lh) == hsize, "correct decode");
    assert(layout_helper_element_type(lh) == etype, "correct decode");
    assert(1 << layout_helper_log2_element_size(lh) == esize, "correct decode");
  

*** 605,11 ***
    assert(transitive_interfaces == nullptr, "sanity");
    set_secondary_supers(Universe::the_empty_klass_array(), Universe::the_empty_klass_bitmap());
    return nullptr;
  }
  
- 
  // subklass links.  Used by the compiler (and vtable initialization)
  // May be cleaned concurrently, so must use the Compile_lock.
  Klass* Klass::subklass() const {
    // Need load_acquire on the _subklass, because it races with inserts that
    // publishes freshly initialized data.
--- 591,10 ---

*** 1027,14 ***
  
    if (WizardMode) {
       // print header
       obj->mark().print_on(st);
       st->cr();
!      if (UseCompactObjectHeaders) {
!        st->print(BULLET"prototype_header: " INTPTR_FORMAT, _prototype_header.value());
-        st->cr();
-      }
    }
  
    // print class
    st->print(BULLET"klass: ");
    obj->klass()->print_value_on(st);
--- 1012,12 ---
  
    if (WizardMode) {
       // print header
       obj->mark().print_on(st);
       st->cr();
!      st->print(BULLET"prototype_header: " INTPTR_FORMAT, _prototype_header.value());
!      st->cr();
    }
  
    // print class
    st->print(BULLET"klass: ");
    obj->klass()->print_value_on(st);

*** 1088,10 ***
--- 1071,44 ---
  void Klass::oop_verify_on(oop obj, outputStream* st) {
    guarantee(oopDesc::is_oop(obj),  "should be oop");
    guarantee(obj->klass()->is_klass(), "klass field is not a klass");
  }
  
+ #ifdef ASSERT
+ void Klass::validate_array_description(const ArrayDescription& ad) {
+   if (is_identity_class() || is_array_klass() || is_interface() ||
+       (is_instance_klass() && InstanceKlass::cast(this)->access_flags().is_abstract())) {
+     assert(ad._layout_kind == LayoutKind::REFERENCE, "Cannot support flattening");
+     assert(ad._kind == KlassKind::RefArrayKlassKind, "Must be a reference array");
+   } else {
+     assert(is_inline_klass(), "Must be");
+     InlineKlass* ik = InlineKlass::cast(this);
+     switch(ad._layout_kind) {
+       case LayoutKind::BUFFERED:
+         fatal("Invalid layout for an array");
+         break;
+       case LayoutKind::NULL_FREE_ATOMIC_FLAT:
+         assert(ik->has_null_free_atomic_layout(), "Sanity check");
+         break;
+       case LayoutKind::NULL_FREE_NON_ATOMIC_FLAT:
+         assert(ik->has_null_free_non_atomic_layout(), "Sanity check");
+         break;
+       case LayoutKind::NULLABLE_ATOMIC_FLAT:
+         assert(ik->has_nullable_atomic_layout(), "Sanity check");
+         break;
+       case LayoutKind::NULLABLE_NON_ATOMIC_FLAT:
+         assert(ik->has_nullable_non_atomic_layout(), "Sanity check)");
+         break;
+       case LayoutKind::REFERENCE:
+         break;
+       default:
+         ShouldNotReachHere();
+     }
+   }
+ }
+ #endif // ASSERT
+ 
  // Note: this function is called with an address that may or may not be a Klass.
  // The point is not to assert it is but to check if it could be.
  bool Klass::is_valid(Klass* k) {
    if (!is_aligned(k, sizeof(MetaWord))) return false;
    if ((size_t)k < os::min_page_size()) return false;
< prev index next >