mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-21 12:20:29 +00:00
8373248: C2: CastPP should not change the type of the oop
Reviewed-by: bmaillard, dfenacci, rcastanedalo, mchevalier
This commit is contained in:
parent
e82f871871
commit
a06f3cd469
@ -413,6 +413,43 @@ Node* CastLLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// CastPPNodes are removed before matching, while alias classes are needed in global code motion.
|
||||
// As a result, it is not valid for a CastPPNode to change the oop such that the derived pointers
|
||||
// lie in different alias classes with and without the node. For example, a CastPPNode c may not
|
||||
// cast an Object to a Bottom[], because later removal of c would affect the alias class of c's
|
||||
// array length field (c + arrayOopDesc::length_offset_in_bytes()).
|
||||
//
|
||||
// This function verifies that a CastPPNode on an oop does not violate the aforementioned property.
|
||||
//
|
||||
// TODO 8382147: Currently, this verification only applies during the construction of a CastPPNode,
|
||||
// we may want to apply the same verification during IGVN transformations, as well as final graph
|
||||
// reshaping.
|
||||
void CastPPNode::verify_type(const Type* in_type, const Type* out_type) {
|
||||
#ifdef ASSERT
|
||||
out_type = out_type->join(in_type);
|
||||
if (in_type->empty() || out_type->empty()) {
|
||||
return;
|
||||
}
|
||||
if (in_type == TypePtr::NULL_PTR || out_type == TypePtr::NULL_PTR) {
|
||||
return;
|
||||
}
|
||||
if (!in_type->isa_oopptr() && !out_type->isa_oopptr()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(in_type->isa_oopptr() && out_type->isa_oopptr(), "must be both oops or both non-oops");
|
||||
if (in_type->isa_aryptr() && out_type->isa_aryptr()) {
|
||||
const Type* e1 = in_type->is_aryptr()->elem();
|
||||
const Type* e2 = out_type->is_aryptr()->elem();
|
||||
assert(e1->basic_type() == e2->basic_type(), "must both be arrays of the same primitive type or both be oops arrays");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(in_type->isa_instptr() && out_type->isa_instptr(), "must be both array oops or both non-array oops");
|
||||
assert(in_type->is_instptr()->instance_klass() == out_type->is_instptr()->instance_klass(), "must not cast to a different type");
|
||||
#endif // ASSERT
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
// Take 'join' of input and cast-up type, unless working with an Interface
|
||||
const Type* CheckCastPPNode::Value(PhaseGVN* phase) const {
|
||||
@ -440,6 +477,11 @@ const Type* CheckCastPPNode::Value(PhaseGVN* phase) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
Node* CheckCastPPNode::pin_node_under_control_impl() const {
|
||||
assert(_dependency.is_floating(), "already pinned");
|
||||
return new CheckCastPPNode(in(0), in(1), bottom_type(), _dependency.with_pinned_dependency(), _extra_types);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CastX2PNode::Value(PhaseGVN* phase) const {
|
||||
|
||||
@ -303,14 +303,18 @@ public:
|
||||
|
||||
//------------------------------CastPPNode-------------------------------------
|
||||
// cast pointer to pointer (different type)
|
||||
class CastPPNode: public ConstraintCastNode {
|
||||
public:
|
||||
CastPPNode (Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr)
|
||||
class CastPPNode : public ConstraintCastNode {
|
||||
public:
|
||||
CastPPNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr)
|
||||
: ConstraintCastNode(ctrl, n, t, dependency, types) {
|
||||
init_class_id(Class_CastPP);
|
||||
verify_type(n->bottom_type(), t);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegP; }
|
||||
|
||||
private:
|
||||
static void verify_type(const Type* in_type, const Type* out_type);
|
||||
};
|
||||
|
||||
//------------------------------CheckCastPPNode--------------------------------
|
||||
@ -329,6 +333,7 @@ class CheckCastPPNode: public ConstraintCastNode {
|
||||
|
||||
private:
|
||||
virtual bool depends_only_on_test_impl() const { return !type()->isa_rawptr() && ConstraintCastNode::depends_only_on_test_impl(); }
|
||||
virtual Node* pin_node_under_control_impl() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -4311,7 +4311,7 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
|
||||
if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) {
|
||||
// Keep track of the fact that 'obj' is an array to prevent
|
||||
// array specific accesses from floating above the guard.
|
||||
*obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM));
|
||||
*obj = _gvn.transform(new CheckCastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM));
|
||||
}
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
@ -1186,6 +1186,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
assert(!res->depends_only_on_test(), "the result must not depends_only_on_test");
|
||||
assert(Opcode() == res->Opcode(), "pinning must result in the same kind of node %s - %s", Name(), res->Name());
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 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
|
||||
@ -455,14 +455,12 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
|
||||
gvn.record_for_igvn(local_mem);
|
||||
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||
C2OptAccess access(gvn, ctrl, local_mem, decorators, T_OBJECT, obj, addr);
|
||||
const Type* type = TypeOopPtr::make_from_klass(field->type()->as_klass());
|
||||
vec_field_ld = bs->load_at(access, type);
|
||||
}
|
||||
|
||||
// For proper aliasing, attach concrete payload type.
|
||||
ciKlass* payload_klass = ciTypeArrayKlass::make(bt);
|
||||
const Type* payload_type = TypeAryPtr::make_from_klass(payload_klass)->cast_to_ptr_type(TypePtr::NotNull);
|
||||
vec_field_ld = gvn.transform(new CastPPNode(nullptr, vec_field_ld, payload_type));
|
||||
// For proper aliasing, attach concrete payload type.
|
||||
ciKlass* payload_klass = ciTypeArrayKlass::make(bt);
|
||||
const Type* payload_type = TypeAryPtr::make_from_klass(payload_klass)->cast_to_ptr_type(TypePtr::NotNull);
|
||||
vec_field_ld = bs->load_at(access, payload_type);
|
||||
}
|
||||
|
||||
Node* adr = kit.array_element_address(vec_field_ld, gvn.intcon(0), bt);
|
||||
const TypePtr* adr_type = adr->bottom_type()->is_ptr();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user