Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
LIR_Opr len = length.result();

CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass());
ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass(), true);
if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
__ asrw(t0, t0, Klass::_lh_array_tag_shift);
int tag = ((id == StubId::c1_new_type_array_id)
? Klass::_lh_array_tag_type_value
: Klass::_lh_array_tag_obj_value);
: Klass::_lh_array_tag_ref_value);
__ mov(rscratch1, tag);
__ cmpw(t0, rscratch1);
__ br(Assembler::EQ, ok);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
LIR_Opr tmp4 = LIR_OprFact::illegalOpr;

CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciMetadata* obj = ciObjArrayKlass::make(x->klass());
ciMetadata* obj = ciObjArrayKlass::make(x->klass(), true);
if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
LIR_Opr len = length.result();

CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciMetadata* obj = ciObjArrayKlass::make(x->klass());
ciMetadata* obj = ciObjArrayKlass::make(x->klass(), true);
if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
#ifdef ASSERT
// Assert object type is really an array of the proper kind.
{
int tag = (id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value;
int tag = (id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_ref_value;
Label ok;
__ lwz(R0, in_bytes(Klass::layout_helper_offset()), R4_ARG2);
__ srawi(R0, R0, Klass::_lh_array_tag_shift);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
LIR_Opr len = length.result();

CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass());
ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass(), true);
if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
Register tmp = obj;
__ lwu(tmp, Address(klass, Klass::layout_helper_offset()));
__ sraiw(tmp, tmp, Klass::_lh_array_tag_shift);
int tag = ((id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value);
int tag = ((id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_ref_obj_value);
__ mv(t0, tag);
__ beq(t0, tmp, ok);
__ stop("assert(is an array klass)");
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
LIR_Opr len = length.result();

CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciKlass* obj = ciObjArrayKlass::make(x->klass());
ciKlass* obj = ciObjArrayKlass::make(x->klass(), true);
if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
__ z_sra(t0, Klass::_lh_array_tag_shift);
int tag = ((id == StubId::c1_new_type_array_id)
? Klass::_lh_array_tag_type_value
: Klass::_lh_array_tag_obj_value);
: Klass::_lh_array_tag_ref_value);
__ compare32_and_branch(t0, tag, Assembler::bcondEqual, ok);
__ stop("assert(is an array klass)");
__ should_not_reach_here();
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
__ verify_oop(obj);

if (op->fast_check()) {
// TODO 8366668 Is this correct? I don't think so. Probably we now always go to the slow path here. Same on AArch64.
// get object class
// not a safepoint as obj null check happens earlier
if (UseCompressedClassPointers) {
Expand Down Expand Up @@ -2663,6 +2664,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// subtype which we can't check or src is the same array as dst
// but not necessarily exactly of type default_type.
Label known_ok, halt;

__ mov_metadata(tmp, default_type->constant_encoding());
if (UseCompressedClassPointers) {
__ encode_klass_not_null(tmp, rscratch1);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
LIR_Opr len = length.result();

CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass());
ciKlass* obj = (ciKlass*) ciObjArrayKlass::make(x->klass(), true);
if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
__ sarl(t0, Klass::_lh_array_tag_shift);
int tag = ((id == StubId::c1_new_type_array_id)
? Klass::_lh_array_tag_type_value
: Klass::_lh_array_tag_obj_value);
: Klass::_lh_array_tag_ref_value);
__ cmpl(t0, tag);
__ jcc(Assembler::equal, ok);
__ stop("assert(is an array klass)");
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/c1/c1_Instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ ciType* NewTypeArray::exact_type() const {
}

ciType* NewObjectArray::exact_type() const {
return ciObjArrayKlass::make(klass());
return ciObjArrayKlass::make(klass(), true);
}

ciType* NewArray::declared_type() const {
Expand Down
18 changes: 18 additions & 0 deletions src/hotspot/share/c1/c1_LIRGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArray.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "compiler/compilerDefinitions.inline.hpp"
#include "compiler/compilerOracle.hpp"
Expand Down Expand Up @@ -875,6 +876,12 @@ void LIRGenerator::arraycopy_helper(Intrinsic* x, int* flagsp, ciArrayKlass** ex
}
}
*flagsp = flags;

// TODO 8366668
if (expected_type != nullptr && expected_type->is_obj_array_klass()) {
expected_type = ciArrayKlass::make(expected_type->as_array_klass()->element_klass(), true);
}

*expected_typep = (ciArrayKlass*)expected_type;
}

Expand Down Expand Up @@ -2425,6 +2432,11 @@ ciKlass* LIRGenerator::profile_type(ciMethodData* md, int md_base_offset, int md
assert(type == nullptr || type->is_klass(), "type should be class");
exact_klass = (type != nullptr && type->is_loaded()) ? (ciKlass*)type : nullptr;

// TODO 8366668
if (exact_klass != nullptr && exact_klass->is_obj_array_klass()) {
exact_klass = ciObjArrayKlass::make(exact_klass->as_array_klass()->element_klass(), true);
}

do_update = exact_klass == nullptr || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass;
}

Expand Down Expand Up @@ -2462,6 +2474,12 @@ ciKlass* LIRGenerator::profile_type(ciMethodData* md, int md_base_offset, int md
exact_klass = exact_signature_k;
}
}

// TODO 8366668
if (exact_klass != nullptr && exact_klass->is_obj_array_klass()) {
exact_klass = ciObjArrayKlass::make(exact_klass->as_array_klass()->element_klass(), true);
}

do_update = exact_klass == nullptr || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass;
}

Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/c1/c1_Runtime1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,10 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, StubId stub_id ))
{ Bytecode_anewarray anew(caller_method(), caller_method->bcp_from(bci));
Klass* ek = caller_method->constants()->klass_at(anew.index(), CHECK);
k = ek->array_klass(CHECK);
if (k->is_objArray_klass()) {
// Return specialized array klass type.
k = ObjArrayKlass::cast(k)->default_ref_array_klass(CHECK);
}
}
break;
case Bytecodes::_ldc:
Expand Down
7 changes: 5 additions & 2 deletions src/hotspot/share/cds/archiveBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,11 +857,14 @@ void ArchiveBuilder::make_klasses_shareable() {
k->set_prototype_header(markWord::prototype().set_narrow_klass(nk));
}
#endif //_LP64
if (k->is_objArray_klass()) {
if (k->is_refArray_klass()) {
num_obj_array_klasses ++;
type = "ref array";
} else if (k->is_objArray_klass()) {
// InstanceKlass and TypeArrayKlass will in turn call remove_unshareable_info
// on their array classes.
num_obj_array_klasses ++;
type = "array";
type = "obj array";
} else if (k->is_typeArray_klass()) {
num_type_array_klasses ++;
type = "array";
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/cds/archiveHeapWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ void ArchiveHeapWriter::ensure_buffer_space(size_t min_bytes) {

objArrayOop ArchiveHeapWriter::allocate_root_segment(size_t offset, int element_count) {
HeapWord* mem = offset_to_buffered_address<HeapWord *>(offset);
memset(mem, 0, objArrayOopDesc::object_size(element_count));
memset(mem, 0, refArrayOopDesc::object_size(element_count));

// The initialization code is copied from MemAllocator::finish and ObjArrayAllocator::initialize.
if (UseCompactObjectHeaders) {
Expand Down Expand Up @@ -265,7 +265,7 @@ void ArchiveHeapWriter::copy_roots_to_buffer(GrowableArrayCHeap<oop, mtClassShar
"Pre-condition: Roots start at aligned boundary: %zu", _buffer_used);

int max_elem_count = ((MIN_GC_REGION_ALIGNMENT - arrayOopDesc::header_size_in_bytes()) / heapOopSize);
assert(objArrayOopDesc::object_size(max_elem_count)*HeapWordSize == MIN_GC_REGION_ALIGNMENT,
assert(refArrayOopDesc::object_size(max_elem_count)*HeapWordSize == MIN_GC_REGION_ALIGNMENT,
"Should match exactly");

HeapRootSegments segments(_buffer_used,
Expand Down Expand Up @@ -380,7 +380,7 @@ void ArchiveHeapWriter::copy_source_objs_to_buffer(GrowableArrayCHeap<oop, mtCla
}

size_t ArchiveHeapWriter::filler_array_byte_size(int length) {
size_t byte_size = objArrayOopDesc::object_size(length) * HeapWordSize;
size_t byte_size = refArrayOopDesc::object_size(length) * HeapWordSize;
return byte_size;
}

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/cds/archiveUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ bool ArchiveUtils::has_aot_initialized_mirror(InstanceKlass* src_ik) {

size_t HeapRootSegments::size_in_bytes(size_t seg_idx) {
assert(seg_idx < _count, "In range");
return objArrayOopDesc::object_size(size_in_elems(seg_idx)) * HeapWordSize;
return refArrayOopDesc::object_size(size_in_elems(seg_idx)) * HeapWordSize;
}

int HeapRootSegments::size_in_elems(size_t seg_idx) {
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/share/cds/cdsEnumKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,13 @@ void CDSEnumKlass::archive_static_field(int level, KlassSubGraphInfo* subgraph_i
ik->external_name(), fd.name()->as_C_string());
}
oop oop_field = mirror->obj_field(fd.offset());
// There should be no oops for ObjArrayKlass but InstanceKlass::array_klasses holds a list of ObjArrayKlass,
// therefore we need the super of the refined array klass.
Klass* oop_field_klass = oop_field->is_refined_objArray() ? oop_field->klass()->super() : oop_field->klass();
if (oop_field == nullptr) {
guarantee(false, "static field %s::%s must not be null",
ik->external_name(), fd.name()->as_C_string());
} else if (oop_field->klass() != ik && oop_field->klass() != ik->array_klass_or_null()) {
} else if (oop_field_klass != ik && oop_field_klass != ik->array_klass_or_null()) {
guarantee(false, "static field %s::%s is of the wrong type",
ik->external_name(), fd.name()->as_C_string());
}
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/cds/cdsProtectionDomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/refArrayOop.hpp"
#include "oops/symbol.hpp"
#include "runtime/javaCalls.hpp"

Expand Down Expand Up @@ -294,7 +295,7 @@ void CDSProtectionDomain::atomic_set_array_index(OopHandle array, int index, oop
// The important thing here is that all threads pick up the same result.
// It doesn't matter which racing thread wins, as long as only one
// result is used by all threads, and all future queries.
((objArrayOop)array.resolve())->replace_if_null(index, o);
refArrayOopDesc::cast(array.resolve())->replace_if_null(index, o);
}

oop CDSProtectionDomain::shared_protection_domain(int index) {
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/cds/cppVtables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "oops/methodCounters.hpp"
#include "oops/methodData.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/refArrayKlass.hpp"
#include "oops/trainingData.hpp"
#include "oops/typeArrayKlass.hpp"
#include "runtime/arguments.hpp"
Expand Down Expand Up @@ -65,6 +66,7 @@
f(MethodData) \
f(MethodCounters) \
f(ObjArrayKlass) \
f(RefArrayKlass) \
f(TypeArrayKlass) \
f(KlassTrainingData) \
f(MethodTrainingData) \
Expand Down
20 changes: 13 additions & 7 deletions src/hotspot/share/cds/dynamicArchive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,9 @@ void DynamicArchiveBuilder::gather_array_klasses() {
for (int i = 0; i < klasses()->length(); i++) {
if (klasses()->at(i)->is_objArray_klass()) {
ObjArrayKlass* oak = ObjArrayKlass::cast(klasses()->at(i));
if (oak->is_refined_objArray_klass()) {
oak = ObjArrayKlass::cast(oak->super());
}
Klass* elem = oak->element_klass();
if (AOTMetaspace::in_aot_cache_static_region(elem)) {
// Only capture the array klass whose element_klass is in the static archive.
Expand Down Expand Up @@ -441,13 +444,16 @@ void DynamicArchive::setup_array_klasses() {
Klass* elm = oak->element_klass();
assert(AOTMetaspace::in_aot_cache_static_region((void*)elm), "must be");

if (elm->is_instance_klass()) {
assert(InstanceKlass::cast(elm)->array_klasses() == nullptr, "must be");
InstanceKlass::cast(elm)->set_array_klasses(oak);
} else {
assert(elm->is_array_klass(), "sanity");
assert(ArrayKlass::cast(elm)->higher_dimension() == nullptr, "must be");
ArrayKlass::cast(elm)->set_higher_dimension(oak);
// Higher dimension may have been set when doing setup on ObjArrayKlass
if (!oak->is_refined_objArray_klass()) {
if (elm->is_instance_klass()) {
assert(InstanceKlass::cast(elm)->array_klasses() == nullptr, "must be");
InstanceKlass::cast(elm)->set_array_klasses(oak);
} else {
assert(elm->is_array_klass(), "sanity");
assert(ArrayKlass::cast(elm)->higher_dimension() == nullptr, "must be");
ArrayKlass::cast(elm)->set_higher_dimension(oak);
}
}
}
log_debug(aot)("Total array klasses read from dynamic archive: %d", _dynamic_archive_array_klasses->length());
Expand Down
6 changes: 5 additions & 1 deletion src/hotspot/share/cds/heapShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,7 +1339,11 @@ void HeapShared::resolve_or_init(Klass* k, bool do_init, TRAPS) {
if (!do_init) {
if (k->class_loader_data() == nullptr) {
Klass* resolved_k = SystemDictionary::resolve_or_null(k->name(), CHECK);
assert(resolved_k == k, "classes used by archived heap must not be replaced by JVMTI ClassFileLoadHook");
if (resolved_k->is_array_klass()) {
assert(resolved_k == k || resolved_k == k->super(), "classes used by archived heap must not be replaced by JVMTI ClassFileLoadHook");
} else {
assert(resolved_k == k, "classes used by archived heap must not be replaced by JVMTI ClassFileLoadHook");
}
}
} else {
assert(k->class_loader_data() != nullptr, "must have been resolved by HeapShared::resolve_classes");
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/ci/ciArrayKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ bool ciArrayKlass::is_leaf_type() {
// ciArrayKlass::make
//
// Make an array klass of the specified element type.
ciArrayKlass* ciArrayKlass::make(ciType* element_type) {
ciArrayKlass* ciArrayKlass::make(ciType* element_type, bool vm_type) {
if (element_type->is_primitive_type()) {
return ciTypeArrayKlass::make(element_type->basic_type());
} else {
return ciObjArrayKlass::make(element_type->as_klass());
return ciObjArrayKlass::make(element_type->as_klass(), vm_type);
}
}

7 changes: 5 additions & 2 deletions src/hotspot/share/ci/ciArrayKlass.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
Expand Down Expand Up @@ -55,7 +55,10 @@ class ciArrayKlass : public ciKlass {
// What kind of vmObject is this?
bool is_array_klass() const { return true; }

static ciArrayKlass* make(ciType* element_type);
// The one-level type of the array elements.
virtual ciKlass* element_klass() { return nullptr; }

static ciArrayKlass* make(ciType* element_type, bool vm_type);
};

#endif // SHARE_CI_CIARRAYKLASS_HPP
2 changes: 1 addition & 1 deletion src/hotspot/share/ci/ciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
require_local);
if (elem_klass != nullptr && elem_klass->is_loaded()) {
// Now make an array for it
return ciObjArrayKlass::make_impl(elem_klass);
return ciObjArrayKlass::make_impl(elem_klass, false);
}
}

Expand Down
Loading