Skip to content
Closed
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
4 changes: 2 additions & 2 deletions src/hotspot/share/opto/doCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
Node* ex_klass_node = nullptr;
if (has_exception_handler() && !ex_type->klass_is_exact()) {
Node* p = basic_plus_adr( ex_node, ex_node, oopDesc::klass_offset_in_bytes());
ex_klass_node = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(), p, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT));
ex_klass_node = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT));

// Compute the exception klass a little more cleverly.
// Obvious solution is to simple do a LoadKlass from the 'ex_node'.
Expand All @@ -965,7 +965,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
continue;
}
Node* p = basic_plus_adr(ex_in, ex_in, oopDesc::klass_offset_in_bytes());
Node* k = _gvn.transform( LoadKlassNode::make(_gvn, nullptr, immutable_memory(), p, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT));
Node* k = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT));
ex_klass_node->init_req( i, k );
}
ex_klass_node = _gvn.transform(ex_klass_node);
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/opto/graphKit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ Node* GraphKit::load_object_klass(Node* obj) {
Node* akls = AllocateNode::Ideal_klass(obj, &_gvn);
if (akls != nullptr) return akls;
Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
return _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(), k_adr, TypeInstPtr::KLASS));
return _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), k_adr, TypeInstPtr::KLASS));
}

//-------------------------load_array_length-----------------------------------
Expand Down Expand Up @@ -2779,7 +2779,7 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, No
if (might_be_cache && mem != nullptr) {
kmem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(C->get_alias_index(gvn.type(p2)->is_ptr())) : mem;
}
Node *nkls = gvn.transform(LoadKlassNode::make(gvn, nullptr, kmem, p2, gvn.type(p2)->is_ptr(), TypeInstKlassPtr::OBJECT_OR_NULL));
Node* nkls = gvn.transform(LoadKlassNode::make(gvn, kmem, p2, gvn.type(p2)->is_ptr(), TypeInstKlassPtr::OBJECT_OR_NULL));

// Compile speed common case: ARE a subtype and we canNOT fail
if (superklass == nkls) {
Expand Down
10 changes: 5 additions & 5 deletions src/hotspot/share/opto/library_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3006,7 +3006,7 @@ bool LibraryCallKit::inline_native_classID() {
IdealKit ideal(this);
#define __ ideal.
IdealVariable result(ideal); __ declarations_done();
Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(),
Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(),
basic_plus_adr(cls, java_lang_Class::klass_offset()),
TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));

Expand Down Expand Up @@ -3036,7 +3036,7 @@ bool LibraryCallKit::inline_native_classID() {

ideal.set(result, _gvn.transform(new URShiftLNode(kls_trace_id_raw, ideal.ConI(TRACE_ID_SHIFT))));
} __ else_(); {
Node* array_kls = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(),
Node* array_kls = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(),
basic_plus_adr(cls, java_lang_Class::array_klass_offset()),
TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));
__ if_then(array_kls, BoolTest::ne, null()); {
Expand Down Expand Up @@ -3830,7 +3830,7 @@ Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror,
if (region == nullptr) never_see_null = true;
Node* p = basic_plus_adr(mirror, offset);
const TypeKlassPtr* kls_type = TypeInstKlassPtr::OBJECT_OR_NULL;
Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type));
Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type));
Node* null_ctl = top();
kls = null_check_oop(kls, &null_ctl, never_see_null);
if (region != nullptr) {
Expand Down Expand Up @@ -4026,7 +4026,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror())));
// If we fall through, it's a plain class. Get its _super.
p = basic_plus_adr(kls, in_bytes(Klass::super_offset()));
kls = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));
kls = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));
null_ctl = top();
kls = null_check_oop(kls, &null_ctl);
if (null_ctl != top()) {
Expand Down Expand Up @@ -4180,7 +4180,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
args[which_arg] = arg;

Node* p = basic_plus_adr(arg, class_klass_offset);
Node* kls = LoadKlassNode::make(_gvn, nullptr, immutable_memory(), p, adr_type, kls_type);
Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type);
klasses[which_arg] = _gvn.transform(kls);
}

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/macro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2338,7 +2338,7 @@ void PhaseMacroExpand::expand_subtypecheck_node(SubTypeCheckNode *check) {
subklass = obj_or_subklass;
} else {
Node* k_adr = basic_plus_adr(obj_or_subklass, oopDesc::klass_offset_in_bytes());
subklass = _igvn.transform(LoadKlassNode::make(_igvn, nullptr, C->immutable_memory(), k_adr, TypeInstPtr::KLASS));
subklass = _igvn.transform(LoadKlassNode::make(_igvn, C->immutable_memory(), k_adr, TypeInstPtr::KLASS));
}

Node* not_subtype_ctrl = Phase::gen_subtype_check(subklass, superklass, &ctrl, nullptr, _igvn, check->method(), check->bci());
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/macroArrayCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode*
// (At this point we can assume disjoint_bases, since types differ.)
int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset());
Node* p1 = basic_plus_adr(dest_klass, ek_offset);
Node* n1 = LoadKlassNode::make(_igvn, nullptr, C->immutable_memory(), p1, TypeRawPtr::BOTTOM);
Node* n1 = LoadKlassNode::make(_igvn, C->immutable_memory(), p1, TypeRawPtr::BOTTOM);
Node* dest_elem_klass = transform_later(n1);
Node* cv = generate_checkcast_arraycopy(&local_ctrl, &local_mem,
adr_type,
Expand Down
14 changes: 4 additions & 10 deletions src/hotspot/share/opto/memnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2398,32 +2398,26 @@ const Type* LoadSNode::Value(PhaseGVN* phase) const {
//=============================================================================
//----------------------------LoadKlassNode::make------------------------------
// Polymorphic factory method:
Node* LoadKlassNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* at, const TypeKlassPtr* tk) {
Node* LoadKlassNode::make(PhaseGVN& gvn, Node* mem, Node* adr, const TypePtr* at, const TypeKlassPtr* tk) {
// sanity check the alias category against the created node type
const TypePtr *adr_type = adr->bottom_type()->isa_ptr();
const TypePtr* adr_type = adr->bottom_type()->isa_ptr();
assert(adr_type != nullptr, "expecting TypeKlassPtr");
#ifdef _LP64
if (adr_type->is_ptr_to_narrowklass()) {
assert(UseCompressedClassPointers, "no compressed klasses");
Node* load_klass = gvn.transform(new LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass(), MemNode::unordered));
Node* load_klass = gvn.transform(new LoadNKlassNode(mem, adr, at, tk->make_narrowklass(), MemNode::unordered));
return new DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr());
}
#endif
assert(!adr_type->is_ptr_to_narrowklass() && !adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop");
return new LoadKlassNode(ctl, mem, adr, at, tk, MemNode::unordered);
return new LoadKlassNode(mem, adr, at, tk, MemNode::unordered);
}

//------------------------------Value------------------------------------------
const Type* LoadKlassNode::Value(PhaseGVN* phase) const {
return klass_value_common(phase);
}

// In most cases, LoadKlassNode does not have the control input set. If the control
// input is set, it must not be removed (by LoadNode::Ideal()).
bool LoadKlassNode::can_remove_control() const {
return false;
}

const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
// Either input is TOP ==> the result is TOP
const Type *t1 = phase->type( in(MemNode::Memory) );
Expand Down
21 changes: 11 additions & 10 deletions src/hotspot/share/opto/memnode.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Alibaba Group Holding Limited. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -522,20 +522,18 @@ class LoadNNode : public LoadNode {
//------------------------------LoadKlassNode----------------------------------
// Load a Klass from an object
class LoadKlassNode : public LoadPNode {
protected:
// In most cases, LoadKlassNode does not have the control input set. If the control
// input is set, it must not be removed (by LoadNode::Ideal()).
virtual bool can_remove_control() const;
private:
LoadKlassNode(Node* mem, Node* adr, const TypePtr* at, const TypeKlassPtr* tk, MemOrd mo)
: LoadPNode(nullptr, mem, adr, at, tk, mo) {}

public:
LoadKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk, MemOrd mo)
: LoadPNode(c, mem, adr, at, tk, mo) {}
virtual int Opcode() const;
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node* Identity(PhaseGVN* phase);
virtual bool depends_only_on_test() const { return true; }

// Polymorphic factory method:
static Node* make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* at,
static Node* make(PhaseGVN& gvn, Node* mem, Node* adr, const TypePtr* at,
const TypeKlassPtr* tk = TypeInstKlassPtr::OBJECT);
};

Expand All @@ -548,9 +546,12 @@ class LoadKlassNode : public LoadPNode {
// extract the actual class pointer. C2's type system is agnostic on whether the
// input address directly points into the class pointer.
class LoadNKlassNode : public LoadNNode {
private:
friend Node* LoadKlassNode::make(PhaseGVN&, Node*, Node*, const TypePtr*, const TypeKlassPtr*);
LoadNKlassNode(Node* mem, Node* adr, const TypePtr* at, const TypeNarrowKlass* tk, MemOrd mo)
: LoadNNode(nullptr, mem, adr, at, tk, mo) {}

public:
LoadNKlassNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk, MemOrd mo)
: LoadNNode(c, mem, adr, at, tk, mo) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegN; }
virtual int store_Opcode() const { return Op_StoreNKlass; }
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/parse1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,7 @@ void Parse::call_register_finalizer() {
// finalization. In general this will fold up since the concrete
// class is often visible so the access flags are constant.
Node* klass_addr = basic_plus_adr( receiver, receiver, oopDesc::klass_offset_in_bytes() );
Node* klass = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(), klass_addr, TypeInstPtr::KLASS));
Node* klass = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), klass_addr, TypeInstPtr::KLASS));

Node* access_flags_addr = basic_plus_adr(klass, klass, in_bytes(Klass::misc_flags_offset()));
Node* access_flags = make_load(nullptr, access_flags_addr, TypeInt::UBYTE, T_BOOLEAN, MemNode::unordered);
Expand Down
34 changes: 13 additions & 21 deletions src/hotspot/share/opto/parseHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,18 @@ void Parse::array_store_check() {
int klass_offset = oopDesc::klass_offset_in_bytes();
Node* p = basic_plus_adr( ary, ary, klass_offset );
// p's type is array-of-OOPS plus klass_offset
Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, nullptr, immutable_memory(), p, TypeInstPtr::KLASS));
Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS));
// Get the array klass
const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr();

// The type of array_klass is usually INexact array-of-oop. Heroically
// cast array_klass to EXACT array and uncommon-trap if the cast fails.
// Make constant out of the inexact array klass, but use it only if the cast
// succeeds.
bool always_see_exact_class = false;
if (MonomorphicArrayCheck
&& !too_many_traps(Deoptimization::Reason_array_check)
&& !tak->klass_is_exact()
&& tak != TypeInstKlassPtr::OBJECT) {
if (MonomorphicArrayCheck &&
!too_many_traps(Deoptimization::Reason_array_check) &&
!tak->klass_is_exact() &&
tak->isa_aryklassptr()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like an implicit nullptr check. Not allowed by code style ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you quickly explain this change from tak != TypeInstKlassPtr::OBJECT so I don't need to investigate myself, please?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like an implicit nullptr check. Not allowed by code style ;)

But the verb here is isa and we use these as a bool a lot, though :/

Can you quickly explain this change from tak != TypeInstKlassPtr::OBJECT so I don't need to investigate myself, please?

The bottom type of an array can be either Object or an array of some kind, so tak != TypeInstKlassPtr::OBJECT is the same as tak->isa_aryklassptr().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah great, thanks for the explanation!

// Regarding the fourth condition in the if-statement from above:
//
// If the compiler has determined that the type of array 'ary' (represented
Expand All @@ -190,16 +189,12 @@ void Parse::array_store_check() {
//
// See issue JDK-8057622 for details.

always_see_exact_class = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it ok to remove this?
If this branch is not taken, it used to be false, and would lead to something different below...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only use of this is to decide if we need to attach a control input to the LoadKlass. As the control input is not needed, this can be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks!

// (If no MDO at all, hope for the best, until a trap actually occurs.)

// Make a constant out of the inexact array klass
const TypeKlassPtr *extak = tak->cast_to_exactness(true);

// Make a constant out of the exact array klass
const TypeAryKlassPtr* extak = tak->cast_to_exactness(true)->is_aryklassptr();
if (extak->exact_klass(true) != nullptr) {
Node* con = makecon(extak);
Node* cmp = _gvn.transform(new CmpPNode( array_klass, con ));
Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq ));
Node* cmp = _gvn.transform(new CmpPNode(array_klass, con));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
Node* ctrl= control();
{ BuildCutout unless(this, bol, PROB_MAX);
uncommon_trap(Deoptimization::Reason_array_check,
Expand All @@ -210,7 +205,7 @@ void Parse::array_store_check() {
set_control(ctrl); // Then Don't Do It, just fall into the normal checking
} else { // Cast array klass to exactness:
// Use the exact constant value we know it is.
replace_in_map(array_klass,con);
replace_in_map(array_klass, con);
CompileLog* log = C->log();
if (log != nullptr) {
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
Expand All @@ -225,12 +220,9 @@ void Parse::array_store_check() {

// Extract the array element class
int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset());
Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset);
// We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true,
// we must set a control edge from the IfTrue node created by the uncommon_trap above to the
// LoadKlassNode.
Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : nullptr,
immutable_memory(), p2, tak));
Node* p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset);
Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, immutable_memory(), p2, tak));
assert(array_klass->is_Con() == a_e_klass->is_Con() || StressReflectiveCode, "a constant array type must come with a constant element type");

// Check (the hard way) and throw if not a subklass.
// Result is ignored, we just need the CFG effects.
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/opto/subtypenode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ bool SubTypeCheckNode::verify(PhaseGVN* phase) {
chk_off_X = phase->transform(new ConvI2LNode(chk_off_X));
#endif
Node* p2 = phase->transform(new AddPNode(subklass, subklass, chk_off_X));
Node* nkls = phase->transform(LoadKlassNode::make(*phase, nullptr, C->immutable_memory(), p2, phase->type(p2)->is_ptr(), TypeInstKlassPtr::OBJECT_OR_NULL));
Node* nkls = phase->transform(LoadKlassNode::make(*phase, C->immutable_memory(), p2, phase->type(p2)->is_ptr(), TypeInstKlassPtr::OBJECT_OR_NULL));

return verify_helper(phase, nkls, cached_t);
}
Expand All @@ -218,7 +218,7 @@ Node* SubTypeCheckNode::load_klass(PhaseGVN* phase) const {
Node* subklass = nullptr;
if (sub_t->isa_oopptr()) {
Node* adr = phase->transform(new AddPNode(obj_or_subklass, obj_or_subklass, phase->MakeConX(oopDesc::klass_offset_in_bytes())));
subklass = phase->transform(LoadKlassNode::make(*phase, nullptr, phase->C->immutable_memory(), adr, TypeInstPtr::KLASS));
subklass = phase->transform(LoadKlassNode::make(*phase, phase->C->immutable_memory(), adr, TypeInstPtr::KLASS));
record_for_cleanup(subklass, phase);
} else {
subklass = obj_or_subklass;
Expand Down