Skip to content

Commit

Permalink
8275201: C2: hide klass() accessor from TypeOopPtr and typeKlassPtr s…
Browse files Browse the repository at this point in the history
…ubclasses

Reviewed-by: vlivanov, iveresov
  • Loading branch information
rwestrel committed May 11, 2022
1 parent 6586e5a commit aa7ccdf
Show file tree
Hide file tree
Showing 33 changed files with 1,041 additions and 661 deletions.
8 changes: 8 additions & 0 deletions src/hotspot/share/ci/ciObjArrayKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass) {
GUARDED_VM_ENTRY(return make_impl(element_klass);)
}

ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass, int dims) {
ciKlass* klass = element_klass;
for (int i = 0; i < dims; i++) {
klass = ciObjArrayKlass::make(klass);
}
return klass->as_obj_array_klass();
}

ciKlass* ciObjArrayKlass::exact_klass() {
ciType* base = base_element_type();
if (base->is_instance_klass()) {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/ci/ciObjArrayKlass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class ciObjArrayKlass : public ciArrayKlass {
bool is_obj_array_klass() const { return true; }

static ciObjArrayKlass* make(ciKlass* element_klass);
static ciObjArrayKlass* make(ciKlass* element_klass, int dims);

virtual ciKlass* exact_klass();
};
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,8 @@ void G1BarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, Node* off
if (itype != NULL) {
// Can the klass of base_oop be statically determined to be
// _not_ a sub-class of Reference and _not_ Object?
ciKlass* klass = itype->klass();
if ( klass->is_loaded() &&
ciKlass* klass = itype->instance_klass();
if (klass->is_loaded() &&
!klass->is_subtype_of(kit->env()->Reference_klass()) &&
!kit->env()->Object_klass()->is_subtype_of(klass)) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/shared/c2/barrierSetC2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ void C2Access::fixup_decorators() {
intptr_t offset = Type::OffsetBot;
AddPNode::Ideal_base_and_offset(adr, &gvn(), offset);
if (offset >= 0) {
int s = Klass::layout_helper_size_in_bytes(adr_type->isa_instptr()->klass()->layout_helper());
int s = Klass::layout_helper_size_in_bytes(adr_type->isa_instptr()->instance_klass()->layout_helper());
if (offset < s) {
// Guaranteed to be a valid access, no need to pin it
_decorators ^= C2_CONTROL_DEPENDENT_LOAD;
Expand Down
12 changes: 6 additions & 6 deletions src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,8 @@ void ShenandoahBarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, N
if (itype != NULL) {
// Can the klass of base_oop be statically determined to be
// _not_ a sub-class of Reference and _not_ Object?
ciKlass* klass = itype->klass();
if ( klass->is_loaded() &&
ciKlass* klass = itype->instance_klass();
if (klass->is_loaded() &&
!klass->is_subtype_of(kit->env()->Reference_klass()) &&
!kit->env()->Object_klass()->is_subtype_of(klass)) {
return;
Expand Down Expand Up @@ -783,8 +783,8 @@ bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_couple
bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
const TypeOopPtr* src_type = gvn.type(src)->is_oopptr();
if (src_type->isa_instptr() != NULL) {
ciInstanceKlass* ik = src_type->klass()->as_instance_klass();
if ((src_type->klass_is_exact() || (!ik->is_interface() && !ik->has_subklass())) && !ik->has_injected_fields()) {
ciInstanceKlass* ik = src_type->is_instptr()->instance_klass();
if ((src_type->klass_is_exact() || !ik->has_subklass()) && !ik->has_injected_fields()) {
if (ik->has_object_fields()) {
return true;
} else {
Expand All @@ -796,8 +796,8 @@ bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
return true;
}
} else if (src_type->isa_aryptr()) {
BasicType src_elem = src_type->klass()->as_array_klass()->element_type()->basic_type();
if (is_reference_type(src_elem)) {
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(src_elem, true)) {
return true;
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) {
if (adr_type->isa_oopptr() && adr_type->is_oopptr()->offset() == oopDesc::mark_offset_in_bytes()) {
if (trace) {tty->print_cr("Mark load");}
} else if (adr_type->isa_instptr() &&
adr_type->is_instptr()->klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&
adr_type->is_instptr()->instance_klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&
adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset()) {
if (trace) {tty->print_cr("Reference.get()");}
} else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
Expand Down
28 changes: 15 additions & 13 deletions src/hotspot/share/opto/arraycopynode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ int ArrayCopyNode::get_count(PhaseGVN *phase) const {
if (is_clonebasic()) {
if (src_type->isa_instptr()) {
const TypeInstPtr* inst_src = src_type->is_instptr();
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
ciInstanceKlass* ik = inst_src->instance_klass();
// ciInstanceKlass::nof_nonstatic_fields() doesn't take injected
// fields into account. They are rare anyway so easier to simply
// skip instances with injected fields.
Expand Down Expand Up @@ -193,8 +193,10 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c
phase->is_IterGVN()->_worklist.push(mem);
}


ciInstanceKlass* ik = inst_src->instance_klass();

if (!inst_src->klass_is_exact()) {
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
assert(!ik->is_interface(), "inconsistent klass hierarchy");
if (ik->has_subklass()) {
// Concurrent class loading.
Expand All @@ -205,7 +207,6 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c
}
}

ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields");

BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
Expand Down Expand Up @@ -263,17 +264,16 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,

// newly allocated object is guaranteed to not overlap with source object
disjoint_bases = is_alloc_tightly_coupled();

if (ary_src == NULL || ary_src->klass() == NULL ||
ary_dest == NULL || ary_dest->klass() == NULL) {
if (ary_src == NULL || ary_src->elem() == Type::BOTTOM ||
ary_dest == NULL || ary_dest->elem() == Type::BOTTOM) {
// We don't know if arguments are arrays
return false;
}

BasicType src_elem = ary_src->klass()->as_array_klass()->element_type()->basic_type();
BasicType dest_elem = ary_dest->klass()->as_array_klass()->element_type()->basic_type();
if (is_reference_type(src_elem)) src_elem = T_OBJECT;
if (is_reference_type(dest_elem)) dest_elem = T_OBJECT;
BasicType src_elem = ary_src->elem()->array_element_basic_type();
BasicType dest_elem = ary_dest->elem()->array_element_basic_type();
if (is_reference_type(src_elem, true)) src_elem = T_OBJECT;
if (is_reference_type(dest_elem, true)) dest_elem = T_OBJECT;

if (src_elem != dest_elem || dest_elem == T_VOID) {
// We don't know if arguments are arrays of the same type
Expand Down Expand Up @@ -323,8 +323,8 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,

disjoint_bases = true;

BasicType elem = ary_src->klass()->as_array_klass()->element_type()->basic_type();
if (is_reference_type(elem)) {
BasicType elem = ary_src->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(elem, true)) {
elem = T_OBJECT;
}

Expand Down Expand Up @@ -734,7 +734,9 @@ bool ArrayCopyNode::modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransf
return !must_modify;
}

BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
BasicType ary_elem = ary_t->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(ary_elem, true)) ary_elem = T_OBJECT;

uint header = arrayOopDesc::base_offset_in_bytes(ary_elem);
uint elemsize = type2aelembytes(ary_elem);

Expand Down
16 changes: 8 additions & 8 deletions src/hotspot/share/opto/callnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c
case Type::KlassPtr:
case Type::AryKlassPtr:
case Type::InstKlassPtr:
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_klassptr()->klass()));
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_klassptr()->exact_klass()));
break;
case Type::MetadataPtr:
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_metadataptr()->metadata()));
Expand Down Expand Up @@ -471,7 +471,7 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st)
st->cr();
st->print(" # ScObj" INT32_FORMAT " ", i);
SafePointScalarObjectNode* spobj = scobjs.at(i);
ciKlass* cik = spobj->bottom_type()->is_oopptr()->klass();
ciKlass* cik = spobj->bottom_type()->is_oopptr()->exact_klass();
assert(cik->is_instance_klass() ||
cik->is_array_klass(), "Not supported allocation.");
ciInstanceKlass *iklass = NULL;
Expand Down Expand Up @@ -807,11 +807,11 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
return false;
}
if (t_oop->is_ptr_to_boxed_value()) {
ciKlass* boxing_klass = t_oop->klass();
ciKlass* boxing_klass = t_oop->is_instptr()->instance_klass();
if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) {
// Skip unrelated boxing methods.
Node* proj = proj_out_or_null(TypeFunc::Parms);
if ((proj == NULL) || (phase->type(proj)->is_instptr()->klass() != boxing_klass)) {
if ((proj == NULL) || (phase->type(proj)->is_instptr()->instance_klass() != boxing_klass)) {
return false;
}
}
Expand All @@ -826,15 +826,15 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
if (proj != NULL) {
const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr();
if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
(inst_t->klass() == boxing_klass))) {
(inst_t->instance_klass() == boxing_klass))) {
return true;
}
}
const TypeTuple* d = tf()->domain();
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr();
if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
(inst_t->klass() == boxing_klass))) {
(inst_t->instance_klass() == boxing_klass))) {
return true;
}
}
Expand Down Expand Up @@ -2309,15 +2309,15 @@ bool CallNode::may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeO
return dest_t->instance_id() == t_oop->instance_id();
}

if (dest_t->isa_instptr() && !dest_t->klass()->equals(phase->C->env()->Object_klass())) {
if (dest_t->isa_instptr() && !dest_t->is_instptr()->instance_klass()->equals(phase->C->env()->Object_klass())) {
// clone
if (t_oop->isa_aryptr()) {
return false;
}
if (!t_oop->isa_instptr()) {
return true;
}
if (dest_t->klass()->is_subtype_of(t_oop->klass()) || t_oop->klass()->is_subtype_of(dest_t->klass())) {
if (dest_t->maybe_java_subtype_of(t_oop) || t_oop->maybe_java_subtype_of(dest_t)) {
return true;
}
// unrelated
Expand Down
31 changes: 14 additions & 17 deletions src/hotspot/share/opto/cfgnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1177,16 +1177,14 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
// convert the one to the other.
const TypePtr* ttp = _type->make_ptr();
const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL;
const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_instklassptr() : NULL;
const TypeInstKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_instklassptr() : NULL;
bool is_intf = false;
if (ttip != NULL) {
ciKlass* k = ttip->klass();
if (k->is_loaded() && k->is_interface())
if (ttip->is_interface())
is_intf = true;
}
if (ttkp != NULL) {
ciKlass* k = ttkp->klass();
if (k->is_loaded() && k->is_interface())
if (ttkp->is_interface())
is_intf = true;
}

Expand All @@ -1205,8 +1203,7 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
const TypeInstPtr* tiip = (tip != NULL) ? tip->isa_instptr() : NULL;
if (tiip) {
bool ti_is_intf = false;
ciKlass* k = tiip->klass();
if (k->is_loaded() && k->is_interface())
if (tiip->is_interface())
ti_is_intf = true;
if (is_intf != ti_is_intf)
{ t = _type; break; }
Expand Down Expand Up @@ -1244,14 +1241,14 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
// be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows
// into a Phi which "knows" it's an Interface type we'll have to
// uplift the type.
if (!t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface()) {
if (!t->empty() && ttip && ttip->is_interface()) {
assert(ft == _type, ""); // Uplift to interface
} else if (!t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
} else if (!t->empty() && ttkp && ttkp->is_interface()) {
assert(ft == _type, ""); // Uplift to interface
} else {
// We also have to handle 'evil cases' of interface- vs. class-arrays
Type::get_arrays_base_elements(jt, _type, NULL, &ttip);
if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
if (!t->empty() && ttip != NULL && ttip->is_interface()) {
assert(ft == _type, ""); // Uplift to array of interface
} else {
// Otherwise it's something stupid like non-overlapping int ranges
Expand All @@ -1270,19 +1267,19 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
// because the type system doesn't interact well with interfaces.
const TypePtr *jtp = jt->make_ptr();
const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL;
const TypeKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_instklassptr() : NULL;
if( jtip && ttip ) {
if( jtip->is_loaded() && jtip->klass()->is_interface() &&
ttip->is_loaded() && !ttip->klass()->is_interface() ) {
const TypeInstKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_instklassptr() : NULL;
if (jtip && ttip) {
if (jtip->is_interface() &&
!ttip->is_interface()) {
assert(ft == ttip->cast_to_ptr_type(jtip->ptr()) ||
ft->isa_narrowoop() && ft->make_ptr() == ttip->cast_to_ptr_type(jtip->ptr()), "");
jt = ft;
}
}
if( jtkp && ttkp ) {
if( jtkp->is_loaded() && jtkp->klass()->is_interface() &&
if (jtkp && ttkp) {
if (jtkp->is_interface() &&
!jtkp->klass_is_exact() && // Keep exact interface klass (6894807)
ttkp->is_loaded() && !ttkp->klass()->is_interface() ) {
ttkp->is_loaded() && !ttkp->is_interface()) {
assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) ||
ft->isa_narrowklass() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), "");
jt = ft;
Expand Down

1 comment on commit aa7ccdf

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.