8275201: C2: hide klass() accessor from TypeOopPtr and typeKlassPtr subclasses

Reviewed-by: vlivanov, iveresov
This commit is contained in:
Roland Westrelin 2022-05-11 07:25:49 +00:00
parent 6586e5ae37
commit aa7ccdf445
33 changed files with 1046 additions and 666 deletions

@ -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()) {

@ -73,6 +73,7 @@ public:
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();
};

@ -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;

@ -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;

@ -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;
@ -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 {
@ -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 {

@ -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)) {

@ -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.
@ -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.
@ -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();
@ -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
@ -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;
}
@ -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);

@ -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()));
@ -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;
@ -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;
}
}
@ -826,7 +826,7 @@ 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;
}
}
@ -834,7 +834,7 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
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;
}
}
@ -2309,7 +2309,7 @@ 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;
@ -2317,7 +2317,7 @@ bool CallNode::may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeO
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

@ -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;
}
@ -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; }
@ -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
@ -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;

@ -1303,7 +1303,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
}
// Array pointers need some flattening
const TypeAryPtr *ta = tj->isa_aryptr();
const TypeAryPtr* ta = tj->isa_aryptr();
if (ta && ta->is_stable()) {
// Erase stability property for alias analysis.
tj = ta = ta->cast_to_stable(false);
@ -1312,7 +1312,10 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
if ( offset != Type::OffsetBot &&
offset > arrayOopDesc::length_offset_in_bytes() ) {
offset = Type::OffsetBot; // Flatten constant access into array body only
tj = ta = TypeAryPtr::make(ptr, ta->ary(), ta->klass(), true, offset, ta->instance_id());
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
with_offset(offset);
}
} else if( ta && _AliasLevel >= 2 ) {
// For arrays indexed by constant indices, we flatten the alias
@ -1321,7 +1324,11 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
if( offset != Type::OffsetBot ) {
if( ta->const_oop() ) { // MethodData* or Method*
offset = Type::OffsetBot; // Flatten constant access into array body
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,offset);
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
cast_to_exactness(false)->
with_offset(offset);
} else if( offset == arrayOopDesc::length_offset_in_bytes() ) {
// range is OK as-is.
tj = ta = TypeAryPtr::RANGE;
@ -1335,13 +1342,21 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
ptr = TypePtr::BotPTR;
} else { // Random constant offset into array body
offset = Type::OffsetBot; // Flatten constant access into array body
tj = ta = TypeAryPtr::make(ptr,ta->ary(),ta->klass(),false,offset);
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
cast_to_exactness(false)->
with_offset(offset);
}
}
// Arrays of fixed size alias with arrays of unknown size.
if (ta->size() != TypeInt::POS) {
const TypeAry *tary = TypeAry::make(ta->elem(), TypeInt::POS);
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset);
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
with_ary(tary)->
cast_to_exactness(false);
}
// Arrays of known objects become arrays of unknown objects.
if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) {
@ -1363,21 +1378,29 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
// Make sure the Bottom and NotNull variants alias the same.
// Also, make sure exact and non-exact variants alias the same.
if (ptr == TypePtr::NotNull || ta->klass_is_exact() || ta->speculative() != NULL) {
tj = ta = TypeAryPtr::make(TypePtr::BotPTR,ta->ary(),ta->klass(),false,offset);
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(TypePtr::BotPTR)->
cast_to_exactness(false)->
with_offset(offset);
}
}
// Oop pointers need some flattening
const TypeInstPtr *to = tj->isa_instptr();
if( to && _AliasLevel >= 2 && to != TypeOopPtr::BOTTOM ) {
ciInstanceKlass *k = to->klass()->as_instance_klass();
ciInstanceKlass* ik = to->instance_klass();
if( ptr == TypePtr::Constant ) {
if (to->klass() != ciEnv::current()->Class_klass() ||
offset < k->layout_helper_size_in_bytes()) {
if (ik != ciEnv::current()->Class_klass() ||
offset < ik->layout_helper_size_in_bytes()) {
// No constant oop pointers (such as Strings); they alias with
// unknown strings.
assert(!is_known_inst, "not scalarizable allocation");
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
tj = to = to->
cast_to_instance_id(TypeOopPtr::InstanceBot)->
remove_speculative()->
cast_to_ptr_type(TypePtr::BotPTR)->
cast_to_exactness(false);
}
} else if( is_known_inst ) {
tj = to; // Keep NotNull and klass_is_exact for instance type
@ -1385,10 +1408,14 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
// During the 2nd round of IterGVN, NotNull castings are removed.
// Make sure the Bottom and NotNull variants alias the same.
// Also, make sure exact and non-exact variants alias the same.
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
tj = to = to->
remove_speculative()->
cast_to_instance_id(TypeOopPtr::InstanceBot)->
cast_to_ptr_type(TypePtr::BotPTR)->
cast_to_exactness(false);
}
if (to->speculative() != NULL) {
tj = to = TypeInstPtr::make(to->ptr(),to->klass(),to->klass_is_exact(),to->const_oop(),to->offset(), to->instance_id());
tj = to = to->remove_speculative();
}
// Canonicalize the holder of this field
if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) {
@ -1397,18 +1424,18 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
if (!is_known_inst) { // Do it only for non-instance types
tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset);
}
} else if (offset < 0 || offset >= k->layout_helper_size_in_bytes()) {
} else if (offset < 0 || offset >= ik->layout_helper_size_in_bytes()) {
// Static fields are in the space above the normal instance
// fields in the java.lang.Class instance.
if (to->klass() != ciEnv::current()->Class_klass()) {
if (ik != ciEnv::current()->Class_klass()) {
to = NULL;
tj = TypeOopPtr::BOTTOM;
offset = tj->offset();
}
} else {
ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset);
ciInstanceKlass *canonical_holder = ik->get_canonical_holder(offset);
assert(offset < canonical_holder->layout_helper_size_in_bytes(), "");
if (!k->equals(canonical_holder) || tj->offset() != offset) {
if (!ik->equals(canonical_holder) || tj->offset() != offset) {
if( is_known_inst ) {
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, NULL, offset, to->instance_id());
} else {
@ -1426,18 +1453,18 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
// inexact types must flatten to the same alias class so
// use NotNull as the PTR.
if ( offset == Type::OffsetBot || (offset >= 0 && (size_t)offset < sizeof(Klass)) ) {
tj = tk = TypeKlassPtr::make(TypePtr::NotNull,
TypeInstKlassPtr::OBJECT->klass(),
offset);
tj = tk = TypeInstKlassPtr::make(TypePtr::NotNull,
env()->Object_klass(),
offset);
}
ciKlass* klass = tk->klass();
if( klass->is_obj_array_klass() ) {
ciKlass* k = TypeAryPtr::OOPS->klass();
if( !k || !k->is_loaded() ) // Only fails for some -Xcomp runs
k = TypeInstPtr::BOTTOM->klass();
tj = tk = TypeKlassPtr::make( TypePtr::NotNull, k, offset );
if (tk->isa_aryklassptr() && tk->is_aryklassptr()->elem()->isa_klassptr()) {
ciKlass* k = ciObjArrayKlass::make(env()->Object_klass());
if (!k || !k->is_loaded()) { // Only fails for some -Xcomp runs
tj = tk = TypeInstKlassPtr::make(TypePtr::NotNull, env()->Object_klass(), offset);
} else {
tj = tk = TypeAryKlassPtr::make(TypePtr::NotNull, tk->is_aryklassptr()->elem(), k, offset);
}
}
// Check for precise loads from the primary supertype array and force them
@ -1453,7 +1480,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
offset < (int)(primary_supers_offset + Klass::primary_super_limit() * wordSize)) ||
offset == (int)in_bytes(Klass::secondary_super_cache_offset())) {
offset = in_bytes(Klass::secondary_super_cache_offset());
tj = tk = TypeKlassPtr::make( TypePtr::NotNull, tk->klass(), offset );
tj = tk = tk->with_offset(offset);
}
}
@ -1552,7 +1579,7 @@ void Compile::AliasType::print_on(outputStream* st) {
adr_type()->dump_on(st);
const TypeOopPtr* tjp = adr_type()->isa_oopptr();
if (field() != NULL && tjp) {
if (tjp->klass() != field()->holder() ||
if (tjp->is_instptr()->instance_klass() != field()->holder() ||
tjp->offset() != field()->offset_in_bytes()) {
st->print(" != ");
field()->print();
@ -1647,7 +1674,7 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
if (flat == TypeAryPtr::RANGE) alias_type(idx)->set_rewritable(false);
if (flat->isa_instptr()) {
if (flat->offset() == java_lang_Class::klass_offset()
&& flat->is_instptr()->klass() == env()->Class_klass())
&& flat->is_instptr()->instance_klass() == env()->Class_klass())
alias_type(idx)->set_rewritable(false);
}
if (flat->isa_aryptr()) {
@ -1681,13 +1708,13 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
if (tinst && tinst->offset() >= instanceOopDesc::base_offset_in_bytes()) {
ciField* field;
if (tinst->const_oop() != NULL &&
tinst->klass() == ciEnv::current()->Class_klass() &&
tinst->offset() >= (tinst->klass()->as_instance_klass()->layout_helper_size_in_bytes())) {
tinst->instance_klass() == ciEnv::current()->Class_klass() &&
tinst->offset() >= (tinst->instance_klass()->layout_helper_size_in_bytes())) {
// static field
ciInstanceKlass* k = tinst->const_oop()->as_instance()->java_lang_Class_klass()->as_instance_klass();
field = k->get_field_by_offset(tinst->offset(), true);
} else {
ciInstanceKlass *k = tinst->klass()->as_instance_klass();
ciInstanceKlass *k = tinst->instance_klass();
field = k->get_field_by_offset(tinst->offset(), false);
}
assert(field == NULL ||
@ -4238,46 +4265,35 @@ Compile::TracePhase::~TracePhase() {
// (1) subklass is already limited to a subtype of superklass => always ok
// (2) subklass does not overlap with superklass => always fail
// (3) superklass has NO subtypes and we can check with a simple compare.
int Compile::static_subtype_check(ciKlass* superk, ciKlass* subk) {
Compile::SubTypeCheckResult Compile::static_subtype_check(const TypeKlassPtr* superk, const TypeKlassPtr* subk) {
if (StressReflectiveCode) {
return SSC_full_test; // Let caller generate the general case.
}
if (superk == env()->Object_klass()) {
return SSC_always_true; // (0) this test cannot fail
if (subk->is_java_subtype_of(superk)) {
return SSC_always_true; // (0) and (1) this test cannot fail
}
ciType* superelem = superk;
ciType* subelem = subk;
if (superelem->is_array_klass()) {
superelem = superelem->as_array_klass()->base_element_type();
}
if (subelem->is_array_klass()) {
subelem = subelem->as_array_klass()->base_element_type();
if (!subk->maybe_java_subtype_of(superk)) {
return SSC_always_false; // (2) true path dead; no dynamic test needed
}
if (!subk->is_interface()) { // cannot trust static interface types yet
if (subk->is_subtype_of(superk)) {
return SSC_always_true; // (1) false path dead; no dynamic test needed
}
if (!(superelem->is_klass() && superelem->as_klass()->is_interface()) &&
!(subelem->is_klass() && subelem->as_klass()->is_interface()) &&
!superk->is_subtype_of(subk)) {
return SSC_always_false; // (2) true path dead; no dynamic test needed
}
const Type* superelem = superk;
if (superk->isa_aryklassptr()) {
int ignored;
superelem = superk->is_aryklassptr()->base_element_type(ignored);
}
// If casting to an instance klass, it must have no subtypes
if (superk->is_interface()) {
// Cannot trust interfaces yet.
// %%% S.B. superk->nof_implementors() == 1
} else if (superelem->is_instance_klass()) {
ciInstanceKlass* ik = superelem->as_instance_klass();
if (!ik->has_subklass() && !ik->is_interface()) {
if (superelem->isa_instklassptr()) {
ciInstanceKlass* ik = superelem->is_instklassptr()->instance_klass();
if (!ik->has_subklass()) {
if (!ik->is_final()) {
// Add a dependency if there is a chance of a later subclass.
dependencies()->assert_leaf_type(ik);
}
if (!superk->maybe_java_subtype_of(subk)) {
return SSC_always_false;
}
return SSC_easy_test; // (3) caller can do a simple ptr comparison
}
} else {

@ -84,6 +84,7 @@ class Type;
class TypeData;
class TypeInt;
class TypeInteger;
class TypeKlassPtr;
class TypePtr;
class TypeOopPtr;
class TypeFunc;
@ -1172,8 +1173,8 @@ class Compile : public Phase {
static void pd_compiler2_init();
// Static parse-time type checking logic for gen_subtype_check:
enum { SSC_always_false, SSC_always_true, SSC_easy_test, SSC_full_test };
int static_subtype_check(ciKlass* superk, ciKlass* subk);
enum SubTypeCheckResult { SSC_always_false, SSC_always_true, SSC_easy_test, SSC_full_test };
SubTypeCheckResult static_subtype_check(const TypeKlassPtr* superk, const TypeKlassPtr* subk);
static Node* conv_I2X_index(PhaseGVN* phase, Node* offset, const TypeInt* sizetype,
// Optional control dependency (for example, on range check)

@ -859,7 +859,7 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
method()->print_name(); tty->cr();
} else if (PrintOpto && (Verbose || WizardMode)) {
tty->print("Bailing out on unloaded exception type ");
extype->klass()->print_name();
extype->instance_klass()->print_name();
tty->print(" at bci:%d in ", bci());
method()->print_name(); tty->cr();
}
@ -869,7 +869,7 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
push_ex_oop(ex_oop);
uncommon_trap(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret,
extype->klass(), "!loaded exception");
extype->instance_klass(), "!loaded exception");
set_bci(iter().cur_bci()); // put it back
continue;
}
@ -916,7 +916,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
// determine potential exception handlers
ciExceptionHandlerStream handlers(method(), bci(),
ex_type->klass()->as_instance_klass(),
ex_type->instance_klass(),
ex_type->klass_is_exact());
// Start executing from the given throw state. (Keep its stack, for now.)
@ -1138,7 +1138,7 @@ ciMethod* Compile::optimize_inlining(ciMethod* caller, ciInstanceKlass* klass, c
return NULL;
}
ciInstanceKlass* receiver_klass = receiver_type->klass()->as_instance_klass();
ciInstanceKlass* receiver_klass = receiver_type->is_instptr()->instance_klass();
if (receiver_klass->is_loaded() && receiver_klass->is_initialized() && !receiver_klass->is_interface() &&
(receiver_klass == actual_receiver || receiver_klass->is_subtype_of(actual_receiver))) {
// ikl is a same or better type than the original actual_receiver,

@ -941,12 +941,11 @@ void ConnectionGraph::add_call_node(CallNode* call) {
Node* k = call->in(AllocateNode::KlassNode);
const TypeKlassPtr* kt = k->bottom_type()->isa_klassptr();
assert(kt != NULL, "TypeKlassPtr required.");
ciKlass* cik = kt->klass();
PointsToNode::EscapeState es = PointsToNode::NoEscape;
bool scalar_replaceable = true;
NOT_PRODUCT(const char* nsr_reason = "");
if (call->is_AllocateArray()) {
if (!cik->is_array_klass()) { // StressReflectiveCode
if (!kt->isa_aryklassptr()) { // StressReflectiveCode
es = PointsToNode::GlobalEscape;
} else {
int length = call->in(AllocateNode::ALength)->find_int_con(-1);
@ -961,18 +960,23 @@ void ConnectionGraph::add_call_node(CallNode* call) {
}
}
} else { // Allocate instance
if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
cik->is_subclass_of(_compile->env()->Reference_klass()) ||
!cik->is_instance_klass() || // StressReflectiveCode
!cik->as_instance_klass()->can_be_instantiated() ||
cik->as_instance_klass()->has_finalizer()) {
if (!kt->isa_instklassptr()) { // StressReflectiveCode
es = PointsToNode::GlobalEscape;
} else {
int nfields = cik->as_instance_klass()->nof_nonstatic_fields();
if (nfields > EliminateAllocationFieldsLimit) {
// Not scalar replaceable if there are too many fields.
scalar_replaceable = false;
NOT_PRODUCT(nsr_reason = "has too many fields");
const TypeInstKlassPtr* ikt = kt->is_instklassptr();
ciInstanceKlass* ik = ikt->klass_is_exact() ? ikt->exact_klass()->as_instance_klass() : ikt->instance_klass();
if (ik->is_subclass_of(_compile->env()->Thread_klass()) ||
ik->is_subclass_of(_compile->env()->Reference_klass()) ||
!ik->can_be_instantiated() ||
ik->has_finalizer()) {
es = PointsToNode::GlobalEscape;
} else {
int nfields = ik->as_instance_klass()->nof_nonstatic_fields();
if (nfields > EliminateAllocationFieldsLimit) {
// Not scalar replaceable if there are too many fields.
scalar_replaceable = false;
NOT_PRODUCT(nsr_reason = "has too many fields");
}
}
}
}
@ -1113,8 +1117,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
aat->isa_ptr() != NULL, "expecting an Ptr");
bool arg_has_oops = aat->isa_oopptr() &&
(aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
(aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
(aat->isa_instptr() ||
(aat->isa_aryptr() && (aat->isa_aryptr()->elem() == Type::BOTTOM || aat->isa_aryptr()->elem()->make_oopptr() != NULL)));
if (i == TypeFunc::Parms) {
src_has_oops = arg_has_oops;
}
@ -2236,8 +2240,8 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
if (offset == Type::OffsetBot) {
// Check only oop fields.
if (!adr_type->isa_aryptr() ||
(adr_type->isa_aryptr()->klass() == NULL) ||
adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
adr_type->isa_aryptr()->elem() == Type::BOTTOM ||
adr_type->isa_aryptr()->elem()->make_oopptr() != NULL) {
// OffsetBot is used to reference array's element. Ignore first AddP.
if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
bt = T_OBJECT;
@ -2628,7 +2632,7 @@ bool ConnectionGraph::split_AddP(Node *addp, Node *base) {
// this code branch will go away.
//
if (!t->is_known_instance() &&
!base_t->klass()->is_subtype_of(t->klass())) {
!t->maybe_java_subtype_of(base_t)) {
return false; // bail out
}
const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr();
@ -2794,8 +2798,8 @@ Node* ConnectionGraph::step_through_mergemem(MergeMemNode *mmem, int alias_idx,
// means an array I have not precisely typed yet. Do not do any
// alias stuff with it any time soon.
if (toop->base() != Type::AnyPtr &&
!(toop->klass() != NULL &&
toop->klass()->is_java_lang_Object() &&
!(toop->isa_instptr() &&
toop->is_instptr()->instance_klass()->is_java_lang_Object() &&
toop->offset() == Type::OffsetBot)) {
mem = mmem->memory_at(alias_idx);
// Update input if it is progress over what we have now
@ -3312,7 +3316,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
} else {
tn_t = tn_type->isa_oopptr();
}
if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) {
if (tn_t != NULL && tn_t->maybe_java_subtype_of(tinst)) {
if (tn_type->isa_narrowoop()) {
tn_type = tinst->make_narrowoop();
} else {
@ -3325,7 +3329,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
record_for_optimizer(n);
} else {
assert(tn_type == TypePtr::NULL_PTR ||
tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()),
tn_t != NULL && !tinst->is_java_subtype_of(tn_t),
"unexpected type");
continue; // Skip dead path with different type
}

@ -1242,7 +1242,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
const Type *t = _gvn.type( value );
const TypeOopPtr* tp = t->isa_oopptr();
if (tp != NULL && tp->klass() != NULL && !tp->klass()->is_loaded()
if (tp != NULL && !tp->is_loaded()
// Only for do_null_check, not any of its siblings:
&& !assert_null && null_control == NULL) {
// Usually, any field access or invocation on an unloaded oop type
@ -1256,12 +1256,13 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
// Our access to the unloaded class will only be correct
// after it has been loaded and initialized, which requires
// a trip through the interpreter.
ciKlass* klass = tp->unloaded_klass();
#ifndef PRODUCT
if (WizardMode) { tty->print("Null check of unloaded "); tp->klass()->print(); tty->cr(); }
if (WizardMode) { tty->print("Null check of unloaded "); klass->print(); tty->cr(); }
#endif
uncommon_trap(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret,
tp->klass(), "!loaded");
klass, "!loaded");
return top();
}
@ -2778,8 +2779,8 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, No
return C->top(); // false path is dead; no test needed.
if (gvn.type(superklass)->singleton()) {
ciKlass* superk = gvn.type(superklass)->is_klassptr()->klass();
ciKlass* subk = gvn.type(subklass)->is_klassptr()->klass();
const TypeKlassPtr* superk = gvn.type(superklass)->is_klassptr();
const TypeKlassPtr* subk = gvn.type(subklass)->is_klassptr();
// In the common case of an exact superklass, try to fold up the
// test before generating code. You may ask, why not just generate
@ -3091,7 +3092,7 @@ void GraphKit::clinit_barrier(ciInstanceKlass* ik, ciMethod* context) {
// If the profile has seen exactly one type, narrow to exactly that type.
// Subsequent type checks will always fold up.
Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
ciKlass* require_klass,
const TypeKlassPtr* require_klass,
ciKlass* spec_klass,
bool safe_for_replace) {
if (!UseTypeProfile || !TypeProfileCasts) return NULL;
@ -3109,7 +3110,7 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass;
if (exact_kls != NULL) {// no cast failures here
if (require_klass == NULL ||
C->static_subtype_check(require_klass, exact_kls) == Compile::SSC_always_true) {
C->static_subtype_check(require_klass, TypeKlassPtr::make(exact_kls)) == Compile::SSC_always_true) {
// If we narrow the type to match what the type profile sees or
// the speculative type, we can then remove the rest of the
// cast.
@ -3234,9 +3235,9 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac
// Do we know the type check always succeed?
bool known_statically = false;
if (_gvn.type(superklass)->singleton()) {
ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass();
ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass();
if (subk != NULL && subk->is_loaded()) {
const TypeKlassPtr* superk = _gvn.type(superklass)->is_klassptr();
const TypeKlassPtr* subk = _gvn.type(obj)->is_oopptr()->as_klass_type();
if (subk->is_loaded()) {
int static_res = C->static_subtype_check(superk, subk);
known_statically = (static_res == Compile::SSC_always_true || static_res == Compile::SSC_always_false);
}
@ -3296,7 +3297,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
Node* *failure_control) {
kill_dead_locals(); // Benefit all the uncommon traps
const TypeKlassPtr *tk = _gvn.type(superklass)->is_klassptr();
const Type *toop = TypeOopPtr::make_from_klass(tk->klass());
const Type *toop = tk->cast_to_exactness(false)->as_instance_type();
// Fast cutout: Check the case that the cast is vacuously true.
// This detects the common cases where the test will short-circuit
@ -3306,8 +3307,8 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
// for example, in some objArray manipulations, such as a[i]=a[j].)
if (tk->singleton()) {
const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr();
if (objtp != NULL && objtp->klass() != NULL) {
switch (C->static_subtype_check(tk->klass(), objtp->klass())) {
if (objtp != NULL) {
switch (C->static_subtype_check(tk, objtp->as_klass_type())) {
case Compile::SSC_always_true:
// If we know the type check always succeed then we don't use
// the profiling data at this bytecode. Don't lose it, feed it
@ -3326,6 +3327,8 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
return null_assert(obj);
}
break; // Fall through to full check
default:
break;
}
}
}
@ -3381,7 +3384,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
// a speculative type use it to perform an exact cast.
ciKlass* spec_obj_type = obj_type->speculative_type();
if (spec_obj_type != NULL || data != NULL) {
cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk->klass(), spec_obj_type, safe_for_replace);
cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk, spec_obj_type, safe_for_replace);
if (cast_obj != NULL) {
if (failure_control != NULL) // failure is now impossible
(*failure_control) = top();
@ -3607,10 +3610,18 @@ void GraphKit::shared_unlock(Node* box, Node* obj) {
Node* GraphKit::get_layout_helper(Node* klass_node, jint& constant_value) {
const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr();
if (!StressReflectiveCode && inst_klass != NULL) {
ciKlass* klass = inst_klass->klass();
bool xklass = inst_klass->klass_is_exact();
if (xklass || klass->is_array_klass()) {
jint lhelper = klass->layout_helper();
if (xklass || inst_klass->isa_aryklassptr()) {
jint lhelper;
if (inst_klass->isa_aryklassptr()) {
BasicType elem = inst_klass->as_instance_type()->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(elem, true)) {
elem = T_OBJECT;
}
lhelper = Klass::array_layout_helper(elem);
} else {
lhelper = inst_klass->is_instklassptr()->exact_klass()->layout_helper();
}
if (lhelper != Klass::_lh_neutral_value) {
constant_value = lhelper;
return (Node*) NULL;
@ -3682,7 +3693,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
int elemidx = C->get_alias_index(telemref);
hook_memory_on_init(*this, elemidx, minit_in, minit_out);
} else if (oop_type->isa_instptr()) {
ciInstanceKlass* ik = oop_type->klass()->as_instance_klass();
ciInstanceKlass* ik = oop_type->is_instptr()->instance_klass();
for (int i = 0, len = ik->nof_nonstatic_fields(); i < len; i++) {
ciField* field = ik->nonstatic_field_at(i);
if (field->offset() >= TrackedInitializationLimit * HeapWordSize)
@ -3959,8 +3970,8 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
Node* valid_length_test = _gvn.intcon(1);
if (ary_type->klass()->is_array_klass()) {
BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type();
if (ary_type->isa_aryptr()) {
BasicType bt = ary_type->isa_aryptr()->elem()->array_element_basic_type();
jint max = TypeAryPtr::max_array_length(bt);
Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max)));
valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le));

@ -420,7 +420,7 @@ class GraphKit : public Phase {
// Use the type profile to narrow an object type.
Node* maybe_cast_profiled_receiver(Node* not_null_obj,
ciKlass* require_klass,
const TypeKlassPtr* require_klass,
ciKlass* spec,
bool safe_for_replace);

@ -491,15 +491,14 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
stringStream s2(buffer, sizeof(buffer) - 1);
node->dump_spec(&s2);
if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) {
if (t != NULL && (t->isa_instptr() || t->isa_instklassptr())) {
const TypeInstPtr *toop = t->isa_instptr();
const TypeKlassPtr *tkls = t->isa_klassptr();
ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL );
if( klass && klass->is_loaded() && klass->is_interface() ) {
const TypeInstKlassPtr *tkls = t->isa_instklassptr();
if ((toop != NULL && toop->is_interface()) || (tkls != NULL && tkls->is_interface())) {
s2.print(" Interface:");
} else if( toop ) {
} else if (toop) {
s2.print(" Oop:");
} else if( tkls ) {
} else if (tkls) {
s2.print(" Klass:");
}
t->dump_on(&s2);

@ -1341,8 +1341,8 @@ bool LibraryCallKit::inline_string_copy(bool compress) {
// Figure out the size and type of the elements we will be copying.
const Type* src_type = src->Value(&_gvn);
const Type* dst_type = dst->Value(&_gvn);
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType dst_elem = dst_type->isa_aryptr()->elem()->array_element_basic_type();
assert((compress && dst_elem == T_BYTE && (src_elem == T_BYTE || src_elem == T_CHAR)) ||
(!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)),
"Unsupported array types for inline_string_copy");
@ -2282,31 +2282,33 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
}
}
const TypeOopPtr* result = NULL;
// See if it is a narrow oop array.
if (adr_type->isa_aryptr()) {
if (adr_type->offset() >= objArrayOopDesc::base_offset_in_bytes()) {
const TypeOopPtr* elem_type = adr_type->is_aryptr()->elem()->make_oopptr();
if (elem_type != NULL) {
sharpened_klass = elem_type->klass();
if (elem_type != NULL && elem_type->is_loaded()) {
// Sharpen the value type.
result = elem_type;
}
}
}
// The sharpened class might be unloaded if there is no class loader
// constraint in place.
if (sharpened_klass != NULL && sharpened_klass->is_loaded()) {
const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass);
// contraint in place.
if (result == NULL && sharpened_klass != NULL && sharpened_klass->is_loaded()) {
// Sharpen the value type.
result = TypeOopPtr::make_from_klass(sharpened_klass);
}
if (result != NULL) {
#ifndef PRODUCT
if (C->print_intrinsics() || C->print_inlining()) {
tty->print(" from base type: "); adr_type->dump(); tty->cr();
tty->print(" sharpened value: "); tjp->dump(); tty->cr();
tty->print(" sharpened value: "); result->dump(); tty->cr();
}
#endif
// Sharpen the value type.
return tjp;
}
return NULL;
return result;
}
DecoratorSet LibraryCallKit::mo_decorator_for_access_kind(AccessKind kind) {
@ -2441,7 +2443,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
// Use address type to get the element type.
bt = adr_type->is_aryptr()->elem()->array_element_basic_type();
}
if (bt == T_ARRAY || bt == T_NARROWOOP) {
if (is_reference_type(bt, true)) {
// accessing an array field with getReference is not a mismatch
bt = T_OBJECT;
}
@ -2821,11 +2823,11 @@ bool LibraryCallKit::klass_needs_init_guard(Node* kls) {
if (!kls->is_Con()) {
return true;
}
const TypeKlassPtr* klsptr = kls->bottom_type()->isa_klassptr();
const TypeInstKlassPtr* klsptr = kls->bottom_type()->isa_instklassptr();
if (klsptr == NULL) {
return true;
}
ciInstanceKlass* ik = klsptr->klass()->as_instance_klass();
ciInstanceKlass* ik = klsptr->instance_klass();
// don't need a guard for a klass that is already initialized
return !ik->is_initialized();
}
@ -3762,12 +3764,12 @@ bool LibraryCallKit::inline_Class_cast() {
// java_mirror_type() returns non-null for compile-time Class constants.
ciType* tm = mirror_con->java_mirror_type();
if (tm != NULL && tm->is_klass() &&
tp != NULL && tp->klass() != NULL) {
if (!tp->klass()->is_loaded()) {
tp != NULL) {
if (!tp->is_loaded()) {
// Don't use intrinsic when class is not loaded.
return false;
} else {
int static_res = C->static_subtype_check(tm->as_klass(), tp->klass());
int static_res = C->static_subtype_check(TypeKlassPtr::make(tm->as_klass()), tp->as_klass_type());
if (static_res == Compile::SSC_always_true) {
// isInstance() is true - fold the code.
set_result(obj);
@ -4176,8 +4178,8 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) {
// check can be optimized if we know something on the type of
// the input array from type speculation.
if (_gvn.type(klass_node)->singleton()) {
ciKlass* subk = _gvn.type(load_object_klass(original))->is_klassptr()->klass();
ciKlass* superk = _gvn.type(klass_node)->is_klassptr()->klass();
const TypeKlassPtr* subk = _gvn.type(load_object_klass(original))->is_klassptr();
const TypeKlassPtr* superk = _gvn.type(klass_node)->is_klassptr();
int test = C->static_subtype_check(superk, subk);
if (test != Compile::SSC_always_true && test != Compile::SSC_always_false) {
@ -4798,10 +4800,8 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
ciInstanceKlass* spec_ik = obj_type->speculative_type()->as_instance_klass();
if (spec_ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem &&
!spec_ik->has_injected_fields()) {
ciKlass* k = obj_type->klass();
if (!k->is_instance_klass() ||
k->as_instance_klass()->is_interface() ||
k->as_instance_klass()->has_subklass()) {
if (!obj_type->isa_instptr() ||
obj_type->is_instptr()->instance_klass()->has_subklass()) {
obj = maybe_cast_profiled_obj(obj, obj_type->speculative_type(), false);
}
}
@ -5176,9 +5176,9 @@ bool LibraryCallKit::inline_arraycopy() {
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
// Do we have the type of src?
bool has_src = (top_src != NULL && top_src->klass() != NULL);
bool has_src = (top_src != NULL && top_src->elem() != Type::BOTTOM);
// Do we have the type of dest?
bool has_dest = (top_dest != NULL && top_dest->klass() != NULL);
bool has_dest = (top_dest != NULL && top_dest->elem() != Type::BOTTOM);
// Is the type for src from speculation?
bool src_spec = false;
// Is the type for dest from speculation?
@ -5216,24 +5216,24 @@ bool LibraryCallKit::inline_arraycopy() {
src = maybe_cast_profiled_obj(src, src_k, true);
src_type = _gvn.type(src);
top_src = src_type->isa_aryptr();
has_src = (top_src != NULL && top_src->klass() != NULL);
has_src = (top_src != NULL && top_src->elem() != Type::BOTTOM);
src_spec = true;
}
if (!has_dest) {
dest = maybe_cast_profiled_obj(dest, dest_k, true);
dest_type = _gvn.type(dest);
top_dest = dest_type->isa_aryptr();
has_dest = (top_dest != NULL && top_dest->klass() != NULL);
has_dest = (top_dest != NULL && top_dest->elem() != Type::BOTTOM);
dest_spec = true;
}
}
}
if (has_src && has_dest && can_emit_guards) {
BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type();
BasicType dest_elem = top_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 = top_src->isa_aryptr()->elem()->array_element_basic_type();
BasicType dest_elem = top_dest->isa_aryptr()->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 && src_elem == T_OBJECT) {
// If both arrays are object arrays then having the exact types
@ -5244,8 +5244,8 @@ bool LibraryCallKit::inline_arraycopy() {
bool could_have_src = src_spec;
// Do we have the exact type of dest?
bool could_have_dest = dest_spec;
ciKlass* src_k = top_src->klass();
ciKlass* dest_k = top_dest->klass();
ciKlass* src_k = NULL;
ciKlass* dest_k = NULL;
if (!src_spec) {
src_k = src_type->speculative_type_not_null();
if (src_k != NULL && src_k->is_array_klass()) {
@ -5342,7 +5342,7 @@ bool LibraryCallKit::inline_arraycopy() {
}
const TypeKlassPtr* dest_klass_t = _gvn.type(dest_klass)->is_klassptr();
const Type *toop = TypeOopPtr::make_from_klass(dest_klass_t->klass());
const Type *toop = dest_klass_t->cast_to_exactness(false)->as_instance_type();
src = _gvn.transform(new CheckCastPPNode(control(), src, toop));
}
@ -5462,15 +5462,15 @@ bool LibraryCallKit::inline_encodeISOArray(bool ascii) {
const Type* dst_type = dst->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
const TypeAryPtr* top_dest = dst_type->isa_aryptr();
if (top_src == NULL || top_src->klass() == NULL ||
top_dest == NULL || top_dest->klass() == NULL) {
if (top_src == NULL || top_src->elem() == Type::BOTTOM ||
top_dest == NULL || top_dest->elem() == Type::BOTTOM) {
// failed array check
return false;
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType dst_elem = dst_type->isa_aryptr()->elem()->array_element_basic_type();
if (!((src_elem == T_CHAR) || (src_elem== T_BYTE)) || dst_elem != T_BYTE) {
return false;
}
@ -5517,14 +5517,14 @@ bool LibraryCallKit::inline_multiplyToLen() {
const Type* y_type = y->Value(&_gvn);
const TypeAryPtr* top_x = x_type->isa_aryptr();
const TypeAryPtr* top_y = y_type->isa_aryptr();
if (top_x == NULL || top_x->klass() == NULL ||
top_y == NULL || top_y->klass() == NULL) {
if (top_x == NULL || top_x->elem() == Type::BOTTOM ||
top_y == NULL || top_y->elem() == Type::BOTTOM) {
// failed array check
return false;
}
BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType y_elem = y_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType x_elem = x_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType y_elem = y_type->isa_aryptr()->elem()->array_element_basic_type();
if (x_elem != T_INT || y_elem != T_INT) {
return false;
}
@ -5625,14 +5625,14 @@ bool LibraryCallKit::inline_squareToLen() {
const Type* z_type = z->Value(&_gvn);
const TypeAryPtr* top_x = x_type->isa_aryptr();
const TypeAryPtr* top_z = z_type->isa_aryptr();
if (top_x == NULL || top_x->klass() == NULL ||
top_z == NULL || top_z->klass() == NULL) {
if (top_x == NULL || top_x->elem() == Type::BOTTOM ||
top_z == NULL || top_z->elem() == Type::BOTTOM) {
// failed array check
return false;
}
BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType z_elem = z_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType x_elem = x_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType z_elem = z_type->isa_aryptr()->elem()->array_element_basic_type();
if (x_elem != T_INT || z_elem != T_INT) {
return false;
}
@ -5674,14 +5674,14 @@ bool LibraryCallKit::inline_mulAdd() {
const Type* in_type = in->Value(&_gvn);
const TypeAryPtr* top_out = out_type->isa_aryptr();
const TypeAryPtr* top_in = in_type->isa_aryptr();
if (top_out == NULL || top_out->klass() == NULL ||
top_in == NULL || top_in->klass() == NULL) {
if (top_out == NULL || top_out->elem() == Type::BOTTOM ||
top_in == NULL || top_in->elem() == Type::BOTTOM) {
// failed array check
return false;
}
BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType out_elem = out_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType in_elem = in_type->isa_aryptr()->elem()->array_element_basic_type();
if (out_elem != T_INT || in_elem != T_INT) {
return false;
}
@ -5727,18 +5727,18 @@ bool LibraryCallKit::inline_montgomeryMultiply() {
const TypeAryPtr* top_n = n_type->isa_aryptr();
const Type* m_type = a->Value(&_gvn);
const TypeAryPtr* top_m = m_type->isa_aryptr();
if (top_a == NULL || top_a->klass() == NULL ||
top_b == NULL || top_b->klass() == NULL ||
top_n == NULL || top_n->klass() == NULL ||
top_m == NULL || top_m->klass() == NULL) {
if (top_a == NULL || top_a->elem() == Type::BOTTOM ||
top_b == NULL || top_b->elem() == Type::BOTTOM ||
top_n == NULL || top_n->elem() == Type::BOTTOM ||
top_m == NULL || top_m->elem() == Type::BOTTOM) {
// failed array check
return false;
}
BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType b_elem = b_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType a_elem = a_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType b_elem = b_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType n_elem = n_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType m_elem = m_type->isa_aryptr()->elem()->array_element_basic_type();
if (a_elem != T_INT || b_elem != T_INT || n_elem != T_INT || m_elem != T_INT) {
return false;
}
@ -5784,16 +5784,16 @@ bool LibraryCallKit::inline_montgomerySquare() {
const TypeAryPtr* top_n = n_type->isa_aryptr();
const Type* m_type = a->Value(&_gvn);
const TypeAryPtr* top_m = m_type->isa_aryptr();
if (top_a == NULL || top_a->klass() == NULL ||
top_n == NULL || top_n->klass() == NULL ||
top_m == NULL || top_m->klass() == NULL) {
if (top_a == NULL || top_a->elem() == Type::BOTTOM ||
top_n == NULL || top_n->elem() == Type::BOTTOM ||
top_m == NULL || top_m->elem() == Type::BOTTOM) {
// failed array check
return false;
}
BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType a_elem = a_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType n_elem = n_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType m_elem = m_type->isa_aryptr()->elem()->array_element_basic_type();
if (a_elem != T_INT || n_elem != T_INT || m_elem != T_INT) {
return false;
}
@ -5838,13 +5838,13 @@ bool LibraryCallKit::inline_bigIntegerShift(bool isRightShift) {
const TypeAryPtr* top_newArr = newArr_type->isa_aryptr();
const Type* oldArr_type = oldArr->Value(&_gvn);
const TypeAryPtr* top_oldArr = oldArr_type->isa_aryptr();
if (top_newArr == NULL || top_newArr->klass() == NULL || top_oldArr == NULL
|| top_oldArr->klass() == NULL) {
if (top_newArr == NULL || top_newArr->elem() == Type::BOTTOM || top_oldArr == NULL
|| top_oldArr->elem() == Type::BOTTOM) {
return false;
}
BasicType newArr_elem = newArr_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType oldArr_elem = oldArr_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType newArr_elem = newArr_type->isa_aryptr()->elem()->array_element_basic_type();
BasicType oldArr_elem = oldArr_type->isa_aryptr()->elem()->array_element_basic_type();
if (newArr_elem != T_INT || oldArr_elem != T_INT) {
return false;
}
@ -5883,8 +5883,8 @@ bool LibraryCallKit::inline_vectorizedMismatch() {
const TypeAryPtr* obja_t = _gvn.type(obja)->isa_aryptr();
const TypeAryPtr* objb_t = _gvn.type(objb)->isa_aryptr();
if (obja_t == NULL || obja_t->klass() == NULL ||
objb_t == NULL || objb_t->klass() == NULL ||
if (obja_t == NULL || obja_t->elem() == Type::BOTTOM ||
objb_t == NULL || objb_t->elem() == Type::BOTTOM ||
scale == top()) {
return false; // failed input validation
}
@ -6051,13 +6051,13 @@ bool LibraryCallKit::inline_updateBytesCRC32() {
const Type* src_type = src->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
if (top_src == NULL || top_src->klass() == NULL) {
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
// failed array check
return false;
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (src_elem != T_BYTE) {
return false;
}
@ -6140,13 +6140,13 @@ bool LibraryCallKit::inline_updateBytesCRC32C() {
const Type* src_type = src->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
if (top_src == NULL || top_src->klass() == NULL) {
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
// failed array check
return false;
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (src_elem != T_BYTE) {
return false;
}
@ -6233,13 +6233,13 @@ bool LibraryCallKit::inline_updateBytesAdler32() {
const Type* src_type = src->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
if (top_src == NULL || top_src->klass() == NULL) {
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
// failed array check
return false;
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (src_elem != T_BYTE) {
return false;
}
@ -6366,8 +6366,8 @@ Node* LibraryCallKit::load_field_from_object(Node* fromObj, const char* fieldNam
if (fromKls == NULL) {
const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
assert(tinst != NULL, "obj is null");
assert(tinst->klass()->is_loaded(), "obj is not loaded");
fromKls = tinst->klass()->as_instance_klass();
assert(tinst->is_loaded(), "obj is not loaded");
fromKls = tinst->instance_klass();
} else {
assert(is_static, "only for static field access");
}
@ -6415,9 +6415,9 @@ Node * LibraryCallKit::field_address_from_object(Node * fromObj, const char * fi
if (fromKls == NULL) {
const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
assert(tinst != NULL, "obj is null");
assert(tinst->klass()->is_loaded(), "obj is not loaded");
assert(tinst->is_loaded(), "obj is not loaded");
assert(!is_exact || tinst->klass_is_exact(), "klass not exact");
fromKls = tinst->klass()->as_instance_klass();
fromKls = tinst->instance_klass();
}
else {
assert(is_static, "only for static field access");
@ -6477,7 +6477,7 @@ bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) {
const Type* dest_type = dest->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
assert (top_src != NULL && top_src->klass() != NULL && top_dest != NULL && top_dest->klass() != NULL, "args are strange");
assert (top_src != NULL && top_src->elem() != Type::BOTTOM && top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
// for the quick and dirty code we will skip all the checks.
// we are just trying to get the call to be generated.
@ -6538,8 +6538,8 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
const Type* dest_type = dest->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
assert (top_src != NULL && top_src->klass() != NULL
&& top_dest != NULL && top_dest->klass() != NULL, "args are strange");
assert (top_src != NULL && top_src->elem() != Type::BOTTOM
&& top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
// checks are the responsibility of the caller
Node* src_start = src;
@ -6561,8 +6561,8 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
// cast it to what we know it will be at runtime
const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr();
assert(tinst != NULL, "CBC obj is null");
assert(tinst->klass()->is_loaded(), "CBC obj is not loaded");
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(tinst->is_loaded(), "CBC obj is not loaded");
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
@ -6626,8 +6626,8 @@ bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) {
const Type* dest_type = dest->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
assert(top_src != NULL && top_src->klass() != NULL
&& top_dest != NULL && top_dest->klass() != NULL, "args are strange");
assert(top_src != NULL && top_src->elem() != Type::BOTTOM
&& top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
// checks are the responsibility of the caller
Node* src_start = src;
@ -6649,8 +6649,8 @@ bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) {
// cast it to what we know it will be at runtime
const TypeInstPtr* tinst = _gvn.type(electronicCodeBook_object)->isa_instptr();
assert(tinst != NULL, "ECB obj is null");
assert(tinst->klass()->is_loaded(), "ECB obj is not loaded");
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(tinst->is_loaded(), "ECB obj is not loaded");
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
@ -6700,8 +6700,8 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
const Type* dest_type = dest->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
assert(top_src != NULL && top_src->klass() != NULL &&
top_dest != NULL && top_dest->klass() != NULL, "args are strange");
assert(top_src != NULL && top_src->elem() != Type::BOTTOM &&
top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
// checks are the responsibility of the caller
Node* src_start = src;
@ -6721,8 +6721,8 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
// cast it to what we know it will be at runtime
const TypeInstPtr* tinst = _gvn.type(counterMode_object)->isa_instptr();
assert(tinst != NULL, "CTR obj is null");
assert(tinst->klass()->is_loaded(), "CTR obj is not loaded");
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(tinst->is_loaded(), "CTR obj is not loaded");
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
@ -6802,10 +6802,10 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
// will have same classloader as CipherBlockChaining object
const TypeInstPtr* tinst = _gvn.type(objCBC)->isa_instptr();
assert(tinst != NULL, "CBCobj is null");
assert(tinst->klass()->is_loaded(), "CBCobj is not loaded");
assert(tinst->is_loaded(), "CBCobj is not loaded");
// we want to do an instanceof comparison against the AESCrypt class
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
if (!klass_AESCrypt->is_loaded()) {
// if AESCrypt is not even loaded, we never take the intrinsic fast path
Node* ctrl = control();
@ -6865,10 +6865,10 @@ Node* LibraryCallKit::inline_electronicCodeBook_AESCrypt_predicate(bool decrypti
// will have same classloader as ElectronicCodeBook object
const TypeInstPtr* tinst = _gvn.type(objECB)->isa_instptr();
assert(tinst != NULL, "ECBobj is null");
assert(tinst->klass()->is_loaded(), "ECBobj is not loaded");
assert(tinst->is_loaded(), "ECBobj is not loaded");
// we want to do an instanceof comparison against the AESCrypt class
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
if (!klass_AESCrypt->is_loaded()) {
// if AESCrypt is not even loaded, we never take the intrinsic fast path
Node* ctrl = control();
@ -6925,10 +6925,10 @@ Node* LibraryCallKit::inline_counterMode_AESCrypt_predicate() {
// will have same classloader as CipherBlockChaining object
const TypeInstPtr* tinst = _gvn.type(objCTR)->isa_instptr();
assert(tinst != NULL, "CTRobj is null");
assert(tinst->klass()->is_loaded(), "CTRobj is not loaded");
assert(tinst->is_loaded(), "CTRobj is not loaded");
// we want to do an instanceof comparison against the AESCrypt class
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
if (!klass_AESCrypt->is_loaded()) {
// if AESCrypt is not even loaded, we never take the intrinsic fast path
Node* ctrl = control();
@ -7071,12 +7071,12 @@ bool LibraryCallKit::inline_digestBase_implCompress(vmIntrinsics::ID id) {
const Type* src_type = src->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
if (top_src == NULL || top_src->klass() == NULL) {
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
// failed array check
return false;
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (src_elem != T_BYTE) {
return false;
}
@ -7163,12 +7163,12 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
const Type* src_type = src->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
if (top_src == NULL || top_src->klass() == NULL) {
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
// failed array check
return false;
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (src_elem != T_BYTE) {
return false;
}
@ -7229,9 +7229,9 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
// get DigestBase klass to lookup for SHA klass
const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr();
assert(tinst != NULL, "digestBase_obj is not instance???");
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
assert(tinst->is_loaded(), "DigestBase is not loaded");
ciKlass* klass_digestBase = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_digestBase_name));
ciKlass* klass_digestBase = tinst->instance_klass()->find_klass(ciSymbol::make(klass_digestBase_name));
assert(klass_digestBase->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_digestBase = klass_digestBase->as_instance_klass();
return inline_digestBase_implCompressMB(digestBase_obj, instklass_digestBase, elem_type, stub_addr, stub_name, src_start, ofs, limit);
@ -7305,9 +7305,9 @@ bool LibraryCallKit::inline_galoisCounterMode_AESCrypt() {
const TypeAryPtr* top_in = in_type->isa_aryptr();
const TypeAryPtr* top_ct = ct_type->isa_aryptr();
const TypeAryPtr* top_out = out_type->isa_aryptr();
assert(top_in != NULL && top_in->klass() != NULL &&
top_ct != NULL && top_ct->klass() != NULL &&
top_out != NULL && top_out->klass() != NULL, "args are strange");
assert(top_in != NULL && top_in->elem() != Type::BOTTOM &&
top_ct != NULL && top_ct->elem() != Type::BOTTOM &&
top_out != NULL && top_out->elem() != Type::BOTTOM, "args are strange");
// checks are the responsibility of the caller
Node* in_start = in;
@ -7335,8 +7335,8 @@ bool LibraryCallKit::inline_galoisCounterMode_AESCrypt() {
// cast it to what we know it will be at runtime
const TypeInstPtr* tinst = _gvn.type(gctr_object)->isa_instptr();
assert(tinst != NULL, "GCTR obj is null");
assert(tinst->klass()->is_loaded(), "GCTR obj is not loaded");
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(tinst->is_loaded(), "GCTR obj is not loaded");
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
@ -7387,10 +7387,10 @@ Node* LibraryCallKit::inline_galoisCounterMode_AESCrypt_predicate() {
// will have same classloader as CipherBlockChaining object
const TypeInstPtr* tinst = _gvn.type(objGCTR)->isa_instptr();
assert(tinst != NULL, "GCTR obj is null");
assert(tinst->klass()->is_loaded(), "GCTR obj is not loaded");
assert(tinst->is_loaded(), "GCTR obj is not loaded");
// we want to do an instanceof comparison against the AESCrypt class
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
if (!klass_AESCrypt->is_loaded()) {
// if AESCrypt is not even loaded, we never take the intrinsic fast path
Node* ctrl = control();
@ -7448,7 +7448,7 @@ Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate)
// get DigestBase klass for instanceOf check
const TypeInstPtr* tinst = _gvn.type(digestBaseObj)->isa_instptr();
assert(tinst != NULL, "digestBaseObj is null");
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
assert(tinst->is_loaded(), "DigestBase is not loaded");
const char* klass_name = NULL;
switch (predicate) {
@ -7488,7 +7488,7 @@ Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate)
ciKlass* klass = NULL;
if (klass_name != NULL) {
klass = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_name));
klass = tinst->instance_klass()->find_klass(ciSymbol::make(klass_name));
}
if ((klass == NULL) || !klass->is_loaded()) {
// if none of MD5/SHA/SHA2/SHA5 is loaded, we never take the intrinsic fast path

@ -678,13 +678,12 @@ bool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArr
bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) {
GrowableArray <SafePointNode *> safepoints_done;
ciKlass* klass = NULL;
ciInstanceKlass* iklass = NULL;
int nfields = 0;
int array_base = 0;
int element_size = 0;
BasicType basic_elem_type = T_ILLEGAL;
ciType* elem_type = NULL;
const Type* field_type = NULL;
Node* res = alloc->result_cast();
assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result");
@ -694,20 +693,18 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <Sa
}
if (res != NULL) {
klass = res_type->klass();
if (res_type->isa_instptr()) {
// find the fields of the class which will be needed for safepoint debug information
assert(klass->is_instance_klass(), "must be an instance klass.");
iklass = klass->as_instance_klass();
iklass = res_type->is_instptr()->instance_klass();
nfields = iklass->nof_nonstatic_fields();
} else {
// find the array's elements which will be needed for safepoint debug information
nfields = alloc->in(AllocateNode::ALength)->find_int_con(-1);
assert(klass->is_array_klass() && nfields >= 0, "must be an array klass.");
elem_type = klass->as_array_klass()->element_type();
basic_elem_type = elem_type->basic_type();
assert(nfields >= 0, "must be an array klass.");
basic_elem_type = res_type->is_aryptr()->elem()->array_element_basic_type();
array_base = arrayOopDesc::base_offset_in_bytes(basic_elem_type);
element_size = type2aelembytes(basic_elem_type);
field_type = res_type->is_aryptr()->elem();
}
}
//
@ -737,35 +734,33 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <Sa
if (iklass != NULL) {
field = iklass->nonstatic_field_at(j);
offset = field->offset();
elem_type = field->type();
ciType* elem_type = field->type();
basic_elem_type = field->layout_type();
// The next code is taken from Parse::do_get_xxx().
if (is_reference_type(basic_elem_type)) {
if (!elem_type->is_loaded()) {
field_type = TypeInstPtr::BOTTOM;
} else if (field != NULL && field->is_static_constant()) {
ciObject* con = field->constant_value().as_object();
// Do not "join" in the previous type; it doesn't add value,
// and may yield a vacuous result if the field is of interface type.
field_type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
assert(field_type != NULL, "field singleton type must be consistent");
} else {
field_type = TypeOopPtr::make_from_klass(elem_type->as_klass());
}
if (UseCompressedOops) {
field_type = field_type->make_narrowoop();
basic_elem_type = T_NARROWOOP;
}
} else {
field_type = Type::get_const_basic_type(basic_elem_type);
}
} else {
offset = array_base + j * (intptr_t)element_size;
}
const Type *field_type;
// The next code is taken from Parse::do_get_xxx().
if (is_reference_type(basic_elem_type)) {
if (!elem_type->is_loaded()) {
field_type = TypeInstPtr::BOTTOM;
} else if (field != NULL && field->is_static_constant()) {
// This can happen if the constant oop is non-perm.
ciObject* con = field->constant_value().as_object();
// Do not "join" in the previous type; it doesn't add value,
// and may yield a vacuous result if the field is of interface type.
field_type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
assert(field_type != NULL, "field singleton type must be consistent");
} else {
field_type = TypeOopPtr::make_from_klass(elem_type->as_klass());
}
if (UseCompressedOops) {
field_type = field_type->make_narrowoop();
basic_elem_type = T_NARROWOOP;
}
} else {
field_type = Type::get_const_basic_type(basic_elem_type);
}
const TypeOopPtr *field_addr_type = res_type->add_offset(offset)->isa_oopptr();
Node *field_val = value_from_mem(mem, ctl, basic_elem_type, field_type, field_addr_type, alloc);
@ -1024,8 +1019,8 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
// Eliminate boxing allocations which are not used
// regardless scalar replaceable status.
bool boxing_alloc = C->eliminate_boxing() &&
tklass->klass()->is_instance_klass() &&
tklass->klass()->as_instance_klass()->is_box_klass();
tklass->isa_instklassptr() &&
tklass->is_instklassptr()->instance_klass()->is_box_klass();
if (!alloc->_is_scalar_replaceable && (!boxing_alloc || (res != NULL))) {
return false;
}
@ -1054,7 +1049,7 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
CompileLog* log = C->log();
if (log != NULL) {
log->head("eliminate_allocation type='%d'",
log->identify(tklass->klass()));
log->identify(tklass->exact_klass()));
JVMState* p = alloc->jvms();
while (p != NULL) {
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
@ -1095,7 +1090,7 @@ bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) {
CompileLog* log = C->log();
if (log != NULL) {
log->head("eliminate_boxing type='%d'",
log->identify(t->klass()));
log->identify(t->instance_klass()));
JVMState* p = boxing->jvms();
while (p != NULL) {
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
@ -1689,9 +1684,13 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc,
rawmem = make_store(control, rawmem, object, arrayOopDesc::length_offset_in_bytes(), length, T_INT);
// conservatively small header size:
header_size = arrayOopDesc::base_offset_in_bytes(T_BYTE);
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass();
if (k->is_array_klass()) // we know the exact header size in most cases:
header_size = Klass::layout_helper_header_size(k->layout_helper());
if (_igvn.type(klass_node)->isa_aryklassptr()) { // we know the exact header size in most cases:
BasicType elem = _igvn.type(klass_node)->is_klassptr()->as_instance_type()->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(elem, true)) {
elem = T_OBJECT;
}
header_size = Klass::layout_helper_header_size(Klass::array_layout_helper(elem));
}
}
// Clear the object body, if necessary.
@ -1891,10 +1890,10 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest);
InitializeNode* init = alloc->initialization();
Node* klass_node = alloc->in(AllocateNode::KlassNode);
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass();
const TypeAryKlassPtr* ary_klass_t = _igvn.type(klass_node)->isa_aryklassptr();
address slow_call_address; // Address of slow call
if (init != NULL && init->is_complete_with_arraycopy() &&
k->is_type_array_klass()) {
ary_klass_t && ary_klass_t->elem()->isa_klassptr() == NULL) {
// Don't zero type array during slow allocation in VM since
// it will be initialized later by arraycopy in compiled code.
slow_call_address = OptoRuntime::new_array_nozero_Java();

@ -1292,14 +1292,14 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
BasicType src_elem = T_CONFLICT;
BasicType dest_elem = T_CONFLICT;
if (top_dest != NULL && top_dest->klass() != NULL) {
dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type();
if (top_src != NULL && top_src->elem() != Type::BOTTOM) {
src_elem = top_src->elem()->array_element_basic_type();
}
if (top_src != NULL && top_src->klass() != NULL) {
src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type();
if (top_dest != NULL && top_dest->elem() != Type::BOTTOM) {
dest_elem = top_dest->elem()->array_element_basic_type();
}
if (is_reference_type(src_elem)) src_elem = T_OBJECT;
if (is_reference_type(dest_elem)) dest_elem = T_OBJECT;
if (is_reference_type(src_elem, true)) src_elem = T_OBJECT;
if (is_reference_type(dest_elem, true)) dest_elem = T_OBJECT;
if (ac->is_arraycopy_validated() &&
dest_elem != T_CONFLICT &&

@ -177,7 +177,7 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oo
} else if (is_boxed_value_load) {
Node* klass = alloc->in(AllocateNode::KlassNode);
const TypeKlassPtr* tklass = phase->type(klass)->is_klassptr();
if (tklass->klass_is_exact() && !tklass->klass()->equals(t_oop->klass())) {
if (tklass->klass_is_exact() && !tklass->exact_klass()->equals(t_oop->is_instptr()->exact_klass())) {
result = proj_in->in(TypeFunc::Memory); // not related allocation
}
}
@ -265,11 +265,11 @@ static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const T
// means an array I have not precisely typed yet. Do not do any
// alias stuff with it any time soon.
const TypeOopPtr *toop = tp->isa_oopptr();
if( tp->base() != Type::AnyPtr &&
if (tp->base() != Type::AnyPtr &&
!(toop &&
toop->klass() != NULL &&
toop->klass()->is_java_lang_Object() &&
toop->offset() == Type::OffsetBot) ) {
toop->isa_instptr() &&
toop->is_instptr()->instance_klass()->is_java_lang_Object() &&
toop->offset() == Type::OffsetBot)) {
// compress paths and change unreachable cycles to TOP
// If not, we can update the input infinitely along a MergeMem cycle
// Equivalent code in PhiNode::Ideal
@ -550,7 +550,7 @@ Node* LoadNode::find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, N
// is known to be within bounds. This is checked below.
if (ary_t != NULL && ld_addp->is_AddP()) {
Node* ld_offs = ld_addp->in(AddPNode::Offset);
BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
BasicType ary_elem = ary_t->elem()->array_element_basic_type();
jlong header = arrayOopDesc::base_offset_in_bytes(ary_elem);
jlong elemsize = type2aelembytes(ary_elem);
@ -992,7 +992,9 @@ Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const {
addp->set_req(AddPNode::Address, src);
const TypeAryPtr* ary_t = phase->type(in(MemNode::Address))->isa_aryptr();
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 shift = exact_log2(type2aelembytes(ary_elem));
@ -1942,7 +1944,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
} else if (tp->base() == Type::InstPtr) {
assert( off != Type::OffsetBot ||
// arrays can be cast to Objects
tp->is_oopptr()->klass()->is_java_lang_Object() ||
!tp->isa_instptr() ||
tp->is_instptr()->instance_klass()->is_java_lang_Object() ||
// unsafe field access may not have a constant offset
C->has_unsafe_access(),
"Field accesses must be precise" );
@ -1958,13 +1961,14 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
}
}
} else if (tp->base() == Type::KlassPtr || tp->base() == Type::InstKlassPtr || tp->base() == Type::AryKlassPtr) {
assert( off != Type::OffsetBot ||
// arrays can be cast to Objects
tp->is_klassptr()->klass()->is_java_lang_Object() ||
// also allow array-loading from the primary supertype
// array during subtype checks
Opcode() == Op_LoadKlass,
"Field accesses must be precise" );
assert(off != Type::OffsetBot ||
!tp->isa_instklassptr() ||
// arrays can be cast to Objects
tp->isa_instklassptr()->instance_klass()->is_java_lang_Object() ||
// also allow array-loading from the primary supertype
// array during subtype checks
Opcode() == Op_LoadKlass,
"Field accesses must be precise");
// For klass/static loads, we expect the _type to be precise
} else if (tp->base() == Type::RawPtr && adr->is_Load() && off == 0) {
/* With mirrors being an indirect in the Klass*
@ -1976,8 +1980,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
Node* adr2 = adr->in(MemNode::Address);
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
if (tkls != NULL && !StressReflectiveCode) {
ciKlass* klass = tkls->klass();
if (klass->is_loaded() && tkls->klass_is_exact() && tkls->offset() == in_bytes(Klass::java_mirror_offset())) {
if (tkls->is_loaded() && tkls->klass_is_exact() && tkls->offset() == in_bytes(Klass::java_mirror_offset())) {
ciKlass* klass = tkls->exact_klass();
assert(adr->Opcode() == Op_LoadP, "must load an oop from _java_mirror");
assert(Opcode() == Op_LoadP, "must load an oop from _java_mirror");
return TypeInstPtr::make(klass->java_mirror());
@ -1987,8 +1991,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
const TypeKlassPtr *tkls = tp->isa_klassptr();
if (tkls != NULL && !StressReflectiveCode) {
ciKlass* klass = tkls->klass();
if (klass->is_loaded() && tkls->klass_is_exact()) {
if (tkls->is_loaded() && tkls->klass_is_exact()) {
ciKlass* klass = tkls->exact_klass();
// We are loading a field from a Klass metaobject whose identity
// is known at compile time (the type is "exact" or "precise").
// Check for fields we know are maintained as constants by the VM.
@ -2015,17 +2019,24 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
// We can still check if we are loading from the primary_supers array at a
// shallow enough depth. Even though the klass is not exact, entries less
// than or equal to its super depth are correct.
if (klass->is_loaded() ) {
ciType *inner = klass;
while( inner->is_obj_array_klass() )
inner = inner->as_obj_array_klass()->base_element_type();
if( inner->is_instance_klass() &&
!inner->as_instance_klass()->flags().is_interface() ) {
if (tkls->is_loaded()) {
ciKlass* klass = NULL;
if (tkls->isa_instklassptr()) {
klass = tkls->is_instklassptr()->instance_klass();
} else {
int dims;
const Type* inner = tkls->is_aryklassptr()->base_element_type(dims);
if (inner->isa_instklassptr()) {
klass = inner->is_instklassptr()->instance_klass();
klass = ciObjArrayKlass::make(klass, dims);
}
}
if (klass != NULL) {
// Compute index into primary_supers array
juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*);
// Check for overflowing; use unsigned compare to handle the negative case.
if( depth < ciKlass::primary_super_limit() &&
depth <= klass->super_depth() ) { // allow self-depth checks to handle self-check case
if (depth < ciKlass::primary_super_limit() &&
depth <= klass->super_depth()) { // allow self-depth checks to handle self-check case
// The field is an element of Klass::_primary_supers. Return its (constant) value.
// (Folds up type checking code.)
assert(Opcode() == Op_LoadKlass, "must load a klass from _primary_supers");
@ -2038,10 +2049,9 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
// If the type is enough to determine that the thing is not an array,
// we can give the layout_helper a positive interval type.
// This will help short-circuit some reflective code.
if (tkls->offset() == in_bytes(Klass::layout_helper_offset())
&& !klass->is_array_klass() // not directly typed as an array
&& !klass->is_interface() // specifically not Serializable & Cloneable
&& !klass->is_java_lang_Object() // not the supertype of all T[]
if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) &&
tkls->isa_instklassptr() && // not directly typed as an array
!tkls->is_instklassptr()->instance_klass()->is_java_lang_Object() // not the supertype of all T[] and specifically not Serializable & Cloneable
) {
// Note: When interfaces are reliable, we can narrow the interface
// test to (klass != Serializable && klass != Cloneable).
@ -2274,7 +2284,7 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
// Return a more precise klass, if possible
const TypeInstPtr *tinst = tp->isa_instptr();
if (tinst != NULL) {
ciInstanceKlass* ik = tinst->klass()->as_instance_klass();
ciInstanceKlass* ik = tinst->instance_klass();
int offset = tinst->offset();
if (ik == phase->C->env()->Class_klass()
&& (offset == java_lang_Class::klass_offset() ||
@ -2302,84 +2312,38 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
}
// non-constant mirror, so we can't tell what's going on
}
if( !ik->is_loaded() )
if (!tinst->is_loaded())
return _type; // Bail out if not loaded
if (offset == oopDesc::klass_offset_in_bytes()) {
if (tinst->klass_is_exact()) {
return TypeKlassPtr::make(ik);
}
// See if we can become precise: no subklasses and no interface
// (Note: We need to support verified interfaces.)
if (!ik->is_interface() && !ik->has_subklass()) {
// Add a dependence; if any subclass added we need to recompile
if (!ik->is_final()) {
// %%% should use stronger assert_unique_concrete_subtype instead
phase->C->dependencies()->assert_leaf_type(ik);
}
// Return precise klass
return TypeKlassPtr::make(ik);
}
// Return root of possible klass
return TypeKlassPtr::make(TypePtr::NotNull, ik, 0/*offset*/);
return tinst->as_klass_type(true);
}
}
// Check for loading klass from an array
const TypeAryPtr *tary = tp->isa_aryptr();
if( tary != NULL ) {
ciKlass *tary_klass = tary->klass();
if (tary_klass != NULL // can be NULL when at BOTTOM or TOP
&& tary->offset() == oopDesc::klass_offset_in_bytes()) {
if (tary->klass_is_exact()) {
return TypeKlassPtr::make(tary_klass);
}
ciArrayKlass *ak = tary->klass()->as_array_klass();
// If the klass is an object array, we defer the question to the
// array component klass.
if( ak->is_obj_array_klass() ) {
assert( ak->is_loaded(), "" );
ciKlass *base_k = ak->as_obj_array_klass()->base_element_klass();
if( base_k->is_loaded() && base_k->is_instance_klass() ) {
ciInstanceKlass* ik = base_k->as_instance_klass();
// See if we can become precise: no subklasses and no interface
if (!ik->is_interface() && !ik->has_subklass()) {
// Add a dependence; if any subclass added we need to recompile
if (!ik->is_final()) {
phase->C->dependencies()->assert_leaf_type(ik);
}
// Return precise array klass
return TypeKlassPtr::make(ak);
}
}
return TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/);
} else { // Found a type-array?
assert( ak->is_type_array_klass(), "" );
return TypeKlassPtr::make(ak); // These are always precise
}
}
if (tary != NULL && tary->elem() != Type::BOTTOM &&
tary->offset() == oopDesc::klass_offset_in_bytes()) {
return tary->as_klass_type(true);
}
// Check for loading klass from an array klass
const TypeKlassPtr *tkls = tp->isa_klassptr();
if (tkls != NULL && !StressReflectiveCode) {
ciKlass* klass = tkls->klass();
if( !klass->is_loaded() )
return _type; // Bail out if not loaded
if( klass->is_obj_array_klass() &&
if (!tkls->is_loaded())
return _type; // Bail out if not loaded
if (tkls->isa_aryklassptr() && tkls->is_aryklassptr()->elem()->isa_klassptr() &&
tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) {
ciKlass* elem = klass->as_obj_array_klass()->element_klass();
// // Always returning precise element type is incorrect,
// // e.g., element type could be object and array may contain strings
// return TypeKlassPtr::make(TypePtr::Constant, elem, 0);
// The array's TypeKlassPtr was declared 'precise' or 'not precise'
// according to the element type's subclassing.
return TypeKlassPtr::make(tkls->ptr(), elem, 0/*offset*/);
return tkls->is_aryklassptr()->elem();
}
if( klass->is_instance_klass() && tkls->klass_is_exact() &&
if (tkls->isa_instklassptr() != NULL && tkls->klass_is_exact() &&
tkls->offset() == in_bytes(Klass::super_offset())) {
ciKlass* sup = klass->as_instance_klass()->super();
ciKlass* sup = tkls->is_instklassptr()->instance_klass()->super();
// The field is Klass::_super. Return its (constant) value.
// (Folds up the 2nd indirection in aClassConstant.getSuperClass().)
return sup ? TypeKlassPtr::make(sup) : TypePtr::NULL_PTR;
@ -2434,7 +2398,7 @@ Node* LoadNode::klass_identity_common(PhaseGVN* phase) {
// mirrors may appear in debug info, but we could clean them out by
// introducing a new debug info operator for Klass.java_mirror).
if (toop->isa_instptr() && toop->klass() == phase->C->env()->Class_klass()
if (toop->isa_instptr() && toop->is_instptr()->instance_klass() == phase->C->env()->Class_klass()
&& offset == java_lang_Class::klass_offset()) {
if (base->is_Load()) {
Node* base2 = base->in(MemNode::Address);
@ -2442,8 +2406,7 @@ Node* LoadNode::klass_identity_common(PhaseGVN* phase) {
Node* adr2 = base2->in(MemNode::Address);
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
if (tkls != NULL && !tkls->empty()
&& (tkls->klass()->is_instance_klass() ||
tkls->klass()->is_array_klass())
&& (tkls->isa_instklassptr() || tkls->isa_aryklassptr())
&& adr2->is_AddP()
) {
int mirror_field = in_bytes(Klass::java_mirror_offset());
@ -4497,7 +4460,7 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr,
assert(alloc != NULL, "must be present");
if (alloc != NULL && alloc->Opcode() == Op_Allocate) {
Node* klass_node = alloc->in(AllocateNode::KlassNode);
ciKlass* k = phase->type(klass_node)->is_klassptr()->klass();
ciKlass* k = phase->type(klass_node)->is_instklassptr()->instance_klass();
if (zeroes_done == k->layout_helper())
zeroes_done = size_limit;
}

@ -1807,11 +1807,11 @@ void Node::dump(const char* suffix, bool mark, outputStream *st) const {
const Type *t = bottom_type();
if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) {
if (t != NULL && (t->isa_instptr() || t->isa_instklassptr())) {
const TypeInstPtr *toop = t->isa_instptr();
const TypeKlassPtr *tkls = t->isa_klassptr();
ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL );
if (klass && klass->is_loaded() && klass->is_interface()) {
const TypeInstKlassPtr *tkls = t->isa_instklassptr();
ciKlass* klass = toop ? toop->instance_klass() : (tkls ? tkls->instance_klass() : NULL );
if (klass && klass->is_loaded() && ((toop && toop->is_interface()) || (tkls && tkls->is_interface()))) {
st->print(" Interface:");
} else if (toop) {
st->print(" Oop:");

@ -816,7 +816,7 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
ObjectValue* sv = sv_for_node_id(objs, spobj->_idx);
if (sv == NULL) {
ciKlass* cik = t->is_oopptr()->klass();
ciKlass* cik = t->is_oopptr()->exact_klass();
assert(cik->is_instance_klass() ||
cik->is_array_klass(), "Not supported allocation.");
sv = new ObjectValue(spobj->_idx,
@ -1089,7 +1089,7 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
scval = PhaseOutput::sv_for_node_id(objs, spobj->_idx);
if (scval == NULL) {
const Type *t = spobj->bottom_type();
ciKlass* cik = t->is_oopptr()->klass();
ciKlass* cik = t->is_oopptr()->exact_klass();
assert(cik->is_instance_klass() ||
cik->is_array_klass(), "Not supported allocation.");
ObjectValue* sv = new ObjectValue(spobj->_idx,

@ -153,7 +153,7 @@ Node* Parse::check_interpreter_type(Node* l, const Type* type,
// TypeFlow may assert null-ness if a type appears unloaded.
if (type == TypePtr::NULL_PTR ||
(tp != NULL && !tp->klass()->is_loaded())) {
(tp != NULL && !tp->is_loaded())) {
// Value must be null, not a real oop.
Node* chk = _gvn.transform( new CmpPNode(l, null()) );
Node* tst = _gvn.transform( new BoolNode(chk, BoolTest::eq) );
@ -169,10 +169,10 @@ Node* Parse::check_interpreter_type(Node* l, const Type* type,
// When paths are cut off, values at later merge points can rise
// toward more specific classes. Make sure these specific classes
// are still in effect.
if (tp != NULL && tp->klass() != C->env()->Object_klass()) {
if (tp != NULL && !tp->is_same_java_type_as(TypeInstPtr::BOTTOM)) {
// TypeFlow asserted a specific object type. Value must have that type.
Node* bad_type_ctrl = NULL;
l = gen_checkcast(l, makecon(TypeKlassPtr::make(tp->klass())), &bad_type_ctrl);
l = gen_checkcast(l, makecon(tp->as_klass_type()->cast_to_exactness(true)), &bad_type_ctrl);
bad_type_exit->control()->add_req(bad_type_ctrl);
}
@ -798,7 +798,7 @@ void Parse::build_exits() {
// becomes loaded during the subsequent parsing, the loaded and unloaded
// types will not join when we transform and push in do_exits().
const TypeOopPtr* ret_oop_type = ret_type->isa_oopptr();
if (ret_oop_type && !ret_oop_type->klass()->is_loaded()) {
if (ret_oop_type && !ret_oop_type->is_loaded()) {
ret_type = TypeOopPtr::BOTTOM;
}
int ret_size = type2size[ret_type->basic_type()];
@ -2080,9 +2080,9 @@ void Parse::call_register_finalizer() {
"must have non-null instance type");
const TypeInstPtr *tinst = receiver->bottom_type()->isa_instptr();
if (tinst != NULL && tinst->klass()->is_loaded() && !tinst->klass_is_exact()) {
if (tinst != NULL && tinst->is_loaded() && !tinst->klass_is_exact()) {
// The type isn't known exactly so see if CHA tells us anything.
ciInstanceKlass* ik = tinst->klass()->as_instance_klass();
ciInstanceKlass* ik = tinst->instance_klass();
if (!Dependencies::has_finalizable_subclass(ik)) {
// No finalizable subclasses so skip the dynamic check.
C->dependencies()->assert_has_no_finalizable_subclasses(ik);
@ -2255,11 +2255,11 @@ void Parse::return_current(Node* value) {
// here.
Node* phi = _exits.argument(0);
const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
if (tr && tr->klass()->is_loaded() &&
tr->klass()->is_interface()) {
if (tr && tr->is_loaded() &&
tr->is_interface()) {
const TypeInstPtr *tp = value->bottom_type()->isa_instptr();
if (tp && tp->klass()->is_loaded() &&
!tp->klass()->is_interface()) {
if (tp && tp->is_loaded() &&
!tp->is_interface()) {
// sharpen the type eagerly; this eases certain assert checking
if (tp->higher_equal(TypeInstPtr::NOTNULL))
tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr();
@ -2270,8 +2270,8 @@ void Parse::return_current(Node* value) {
const TypeInstPtr* phi_tip;
const TypeInstPtr* val_tip;
Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tip, &val_tip);
if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->klass()->is_interface() &&
val_tip != NULL && val_tip->is_loaded() && !val_tip->klass()->is_interface()) {
if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->is_interface() &&
val_tip != NULL && val_tip->is_loaded() && !val_tip->is_interface()) {
value = _gvn.transform(new CheckCastPPNode(0, value, phi->bottom_type()));
}
}

@ -124,9 +124,9 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) {
const Type* el = elemtype->make_ptr();
if (el && el->isa_instptr()) {
const TypeInstPtr* toop = el->is_instptr();
if (toop->klass()->as_instance_klass()->unique_concrete_subklass()) {
if (toop->instance_klass()->unique_concrete_subklass()) {
// If we load from "AbstractClass[]" we must see "ConcreteSubClass".
const Type* subklass = Type::get_const_type(toop->klass());
const Type* subklass = Type::get_const_type(toop->instance_klass());
elemtype = subklass->join_speculative(el);
}
}
@ -143,13 +143,14 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) {
if (C->log() != NULL) C->log()->elem("observe that='!need_range_check'");
}
ciKlass * arytype_klass = arytype->klass();
if ((arytype_klass != NULL) && (!arytype_klass->is_loaded())) {
if (!arytype->is_loaded()) {
// Only fails for some -Xcomp runs
// The class is unloaded. We have to run this bytecode in the interpreter.
ciKlass* klass = arytype->unloaded_klass();
uncommon_trap(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret,
arytype->klass(), "!loaded array");
klass, "!loaded array");
return top();
}

@ -72,16 +72,17 @@ void Parse::do_checkcast() {
// _from_ is not loaded, and value is not null. If the value _is_ NULL,
// then the checkcast does nothing.
const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr();
if (!will_link || (tp && tp->klass() && !tp->klass()->is_loaded())) {
if (!will_link || (tp && !tp->is_loaded())) {
if (C->log() != NULL) {
if (!will_link) {
C->log()->elem("assert_null reason='checkcast' klass='%d'",
C->log()->identify(klass));
}
if (tp && tp->klass() && !tp->klass()->is_loaded()) {
if (tp && !tp->is_loaded()) {
// %%% Cannot happen?
ciKlass* klass = tp->unloaded_klass();
C->log()->elem("assert_null reason='checkcast source' klass='%d'",
C->log()->identify(tp->klass()));
C->log()->identify(klass));
}
}
null_assert(obj);
@ -194,27 +195,30 @@ void Parse::array_store_check() {
// (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)->is_klassptr();
Node* con = makecon(extak);
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,
Deoptimization::Action_maybe_recompile,
tak->klass());
}
if (stopped()) { // MUST uncommon-trap?
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);
CompileLog* log = C->log();
if (log != NULL) {
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
log->identify(tak->klass()));
const TypeKlassPtr *extak = tak->cast_to_exactness(true);
if (extak->exact_klass(true) != NULL) {
Node* con = makecon(extak);
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,
Deoptimization::Action_maybe_recompile,
extak->exact_klass());
}
if (stopped()) { // MUST uncommon-trap?
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);
CompileLog* log = C->log();
if (log != NULL) {
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
log->identify(extak->exact_klass()));
}
array_klass = con; // Use cast value moving forward
}
array_klass = con; // Use cast value moving forward
}
}
@ -298,4 +302,3 @@ void Parse::dump_map_adr_mem() const {
}
#endif

@ -970,77 +970,44 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
}
// See if it is 2 unrelated classes.
const TypeOopPtr* oop_p0 = r0->isa_oopptr();
const TypeOopPtr* oop_p1 = r1->isa_oopptr();
bool both_oop_ptr = oop_p0 && oop_p1;
if (both_oop_ptr) {
Node* in1 = in(1)->uncast();
Node* in2 = in(2)->uncast();
AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL);
AllocateNode* alloc2 = AllocateNode::Ideal_allocation(in2, NULL);
if (MemNode::detect_ptr_independence(in1, alloc1, in2, alloc2, NULL)) {
return TypeInt::CC_GT; // different pointers
}
}
const TypeKlassPtr* klass_p0 = r0->isa_klassptr();
const TypeKlassPtr* klass_p1 = r1->isa_klassptr();
if (both_oop_ptr || (klass_p0 && klass_p1)) { // both or neither are klass pointers
ciKlass* klass0 = NULL;
bool xklass0 = false;
ciKlass* klass1 = NULL;
bool xklass1 = false;
if (oop_p0) {
klass0 = oop_p0->klass();
xklass0 = oop_p0->klass_is_exact();
} else {
assert(klass_p0, "must be non-null if oop_p0 is null");
klass0 = klass_p0->klass();
xklass0 = klass_p0->klass_is_exact();
}
if (oop_p1) {
klass1 = oop_p1->klass();
xklass1 = oop_p1->klass_is_exact();
} else {
assert(klass_p1, "must be non-null if oop_p1 is null");
klass1 = klass_p1->klass();
xklass1 = klass_p1->klass_is_exact();
}
if (klass0 && klass1 &&
klass0->is_loaded() && !klass0->is_interface() && // do not trust interfaces
klass1->is_loaded() && !klass1->is_interface() &&
(!klass0->is_obj_array_klass() ||
!klass0->as_obj_array_klass()->base_element_klass()->is_interface()) &&
(!klass1->is_obj_array_klass() ||
!klass1->as_obj_array_klass()->base_element_klass()->is_interface())) {
bool unrelated_classes = false;
// See if neither subclasses the other, or if the class on top
// is precise. In either of these cases, the compare is known
// to fail if at least one of the pointers is provably not null.
if (klass0->equals(klass1)) { // if types are unequal but klasses are equal
// Do nothing; we know nothing for imprecise types
} else if (klass0->is_subtype_of(klass1)) {
// If klass1's type is PRECISE, then classes are unrelated.
unrelated_classes = xklass1;
} else if (klass1->is_subtype_of(klass0)) {
// If klass0's type is PRECISE, then classes are unrelated.
unrelated_classes = xklass0;
} else { // Neither subtypes the other
unrelated_classes = true;
const TypeOopPtr* p0 = r0->isa_oopptr();
const TypeOopPtr* p1 = r1->isa_oopptr();
const TypeKlassPtr* k0 = r0->isa_klassptr();
const TypeKlassPtr* k1 = r1->isa_klassptr();
if ((p0 && p1) || (k0 && k1)) {
if (p0 && p1) {
Node* in1 = in(1)->uncast();
Node* in2 = in(2)->uncast();
AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL);
AllocateNode* alloc2 = AllocateNode::Ideal_allocation(in2, NULL);
if (MemNode::detect_ptr_independence(in1, alloc1, in2, alloc2, NULL)) {
return TypeInt::CC_GT; // different pointers
}
if (unrelated_classes) {
// The oops classes are known to be unrelated. If the joined PTRs of
// two oops is not Null and not Bottom, then we are sure that one
// of the two oops is non-null, and the comparison will always fail.
TypePtr::PTR jp = r0->join_ptr(r1->_ptr);
if (jp != TypePtr::Null && jp != TypePtr::BotPTR) {
return TypeInt::CC_GT;
}
}
bool xklass0 = p0 ? p0->klass_is_exact() : k0->klass_is_exact();
bool xklass1 = p1 ? p1->klass_is_exact() : k1->klass_is_exact();
bool unrelated_classes = false;
if ((p0 && p0->is_same_java_type_as(p1)) ||
(k0 && k0->is_same_java_type_as(k1))) {
} else if ((p0 && !p1->maybe_java_subtype_of(p0) && !p0->maybe_java_subtype_of(p1)) ||
(k0 && !k1->maybe_java_subtype_of(k0) && !k0->maybe_java_subtype_of(k1))) {
unrelated_classes = true;
} else if ((p0 && !p1->maybe_java_subtype_of(p0)) ||
(k0 && !k1->maybe_java_subtype_of(k0))) {
unrelated_classes = xklass1;
} else if ((p0 && !p0->maybe_java_subtype_of(p1)) ||
(k0 && !k0->maybe_java_subtype_of(k1))) {
unrelated_classes = xklass0;
}
if (unrelated_classes) {
// The oops classes are known to be unrelated. If the joined PTRs of
// two oops is not Null and not Bottom, then we are sure that one
// of the two oops is non-null, and the comparison will always fail.
TypePtr::PTR jp = r0->join_ptr(r1->_ptr);
if (jp != TypePtr::Null && jp != TypePtr::BotPTR) {
return TypeInt::CC_GT;
}
}
}
@ -1070,7 +1037,7 @@ static inline Node* isa_java_mirror_load(PhaseGVN* phase, Node* n) {
if (n->Opcode() != Op_LoadP) return NULL;
const TypeInstPtr* tp = phase->type(n)->isa_instptr();
if (!tp || tp->klass() != phase->C->env()->Class_klass()) return NULL;
if (!tp || tp->instance_klass() != phase->C->env()->Class_klass()) return NULL;
Node* adr = n->in(MemNode::Address);
// First load from OopHandle: ((OopHandle)mirror)->resolve(); may need barrier.
@ -1150,7 +1117,7 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
if (t2 == NULL || !t2->klass_is_exact())
return NULL;
// Get the constant klass we are comparing to.
ciKlass* superklass = t2->klass();
ciKlass* superklass = t2->exact_klass();
// Now check for LoadKlass on left.
Node* ldk1 = in(1);

@ -33,60 +33,21 @@
#include "opto/subtypenode.hpp"
const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const {
ciKlass* superk = super_t->is_klassptr()->klass();
ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass();
bool xsubk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass_is_exact() : sub_t->is_oopptr()->klass_is_exact();
const TypeKlassPtr* superk = super_t->isa_klassptr();
const TypeKlassPtr* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr() : sub_t->is_oopptr()->as_klass_type();
// Oop can't be a subtype of abstract type that has no subclass.
if (sub_t->isa_oopptr() && superk->is_instance_klass() &&
!superk->is_interface() && superk->is_abstract() &&
!superk->as_instance_klass()->has_subklass()) {
Compile::current()->dependencies()->assert_leaf_type(superk);
return TypeInt::CC_GT;
}
// Similar to logic in CmpPNode::sub()
// Interfaces can't be trusted unless the subclass is an exact
// interface (it can then only be a constant) or the subclass is an
// exact array of interfaces (a newly allocated array of interfaces
// for instance)
if (superk && subk &&
superk->is_loaded() && !superk->is_interface() &&
subk->is_loaded() && (!subk->is_interface() || xsubk) &&
(!superk->is_obj_array_klass() ||
!superk->as_obj_array_klass()->base_element_klass()->is_interface()) &&
(!subk->is_obj_array_klass() ||
!subk->as_obj_array_klass()->base_element_klass()->is_interface() ||
xsubk)) {
bool unrelated_classes = false;
if (superk->equals(subk)) {
// skip
} else if (superk->is_subtype_of(subk)) {
// If the subclass is exact then the superclass is a subtype of
// the subclass. Given they're no equals, that subtype check can
// only fail.
unrelated_classes = xsubk;
} else if (subk->is_subtype_of(superk)) {
// skip
} else {
// Neither class subtypes the other: they are unrelated and this
// type check is known to fail.
unrelated_classes = true;
}
if (unrelated_classes) {
TypePtr::PTR jp = sub_t->is_ptr()->join_ptr(super_t->is_ptr()->_ptr);
if (jp != TypePtr::Null && jp != TypePtr::BotPTR) {
return TypeInt::CC_GT;
}
if (sub_t->isa_oopptr() && superk->isa_instklassptr() && superk->klass_is_exact()) {
ciKlass* superklass = superk->exact_klass();
if (!superklass->is_interface() && superklass->is_abstract() &&
!superklass->as_instance_klass()->has_subklass()) {
Compile::current()->dependencies()->assert_leaf_type(superklass);
return TypeInt::CC_GT;
}
}
if (super_t->singleton()) {
if (subk != NULL) {
switch (Compile::current()->static_subtype_check(superk, subk)) {
if (subk != NULL) {
switch (Compile::current()->static_subtype_check(superk, subk)) {
case Compile::SSC_always_false:
return TypeInt::CC_GT;
case Compile::SSC_always_true:
@ -96,7 +57,6 @@ const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const
break;
default:
ShouldNotReachHere();
}
}
}
@ -203,8 +163,8 @@ bool SubTypeCheckNode::verify(PhaseGVN* phase) {
const Type* sub_t = phase->type(obj_or_subklass);
const Type* super_t = phase->type(superklass);
ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass(); // can be NULL for bottom[]
ciKlass* superk = super_t->is_klassptr()->klass();
const TypeKlassPtr* superk = super_t->isa_klassptr();
const TypeKlassPtr* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr() : sub_t->is_oopptr()->as_klass_type();
if (super_t->singleton() && subk != NULL) {
Node* subklass = NULL;

@ -791,8 +791,8 @@ bool Type::interface_vs_oop_helper(const Type *t) const {
const TypeInstPtr* this_inst = this_ptr->isa_instptr();
const TypeInstPtr* t_inst = t_ptr->isa_instptr();
if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
bool this_interface = this_inst->klass()->is_interface();
bool t_interface = t_inst->klass()->is_interface();
bool this_interface = this_inst->is_interface();
bool t_interface = t_inst->is_interface();
result = this_interface ^ t_interface;
}
@ -2276,7 +2276,7 @@ int TypeAry::hash(void) const {
/**
* Return same type without a speculative part in the element
*/
const Type* TypeAry::remove_speculative() const {
const TypeAry* TypeAry::remove_speculative() const {
return make(_elem->remove_speculative(), _size, _stable);
}
@ -2561,7 +2561,7 @@ const TypePtr *TypePtr::make(TYPES t, enum PTR ptr, int offset, const TypePtr* s
}
//------------------------------cast_to_ptr_type-------------------------------
const Type *TypePtr::cast_to_ptr_type(PTR ptr) const {
const TypePtr* TypePtr::cast_to_ptr_type(PTR ptr) const {
assert(_base == AnyPtr, "subclass must override cast_to_ptr_type");
if( ptr == _ptr ) return this;
return make(_base, ptr, _offset, _speculative, _inline_depth);
@ -2687,6 +2687,10 @@ const TypePtr *TypePtr::add_offset( intptr_t offset ) const {
return make(AnyPtr, _ptr, xadd_offset(offset), _speculative, _inline_depth);
}
const TypePtr *TypePtr::with_offset(intptr_t offset) const {
return make(AnyPtr, _ptr, offset, _speculative, _inline_depth);
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
bool TypePtr::eq( const Type *t ) const {
@ -2704,7 +2708,7 @@ int TypePtr::hash(void) const {
/**
* Return same type without a speculative part
*/
const Type* TypePtr::remove_speculative() const {
const TypePtr* TypePtr::remove_speculative() const {
if (_speculative == NULL) {
return this;
}
@ -2839,6 +2843,13 @@ const TypePtr* TypePtr::add_offset_speculative(intptr_t offset) const {
return _speculative->add_offset(offset)->is_ptr();
}
const TypePtr* TypePtr::with_offset_speculative(intptr_t offset) const {
if (_speculative == NULL) {
return NULL;
}
return _speculative->with_offset(offset)->is_ptr();
}
/**
* return exact klass from the speculative type if there's one
*/
@ -3094,7 +3105,7 @@ const Type *TypeRawPtr::xdual() const {
}
//------------------------------add_offset-------------------------------------
const TypePtr *TypeRawPtr::add_offset( intptr_t offset ) const {
const TypePtr* TypeRawPtr::add_offset(intptr_t offset) const {
if( offset == OffsetTop ) return BOTTOM; // Undefined offset-> undefined pointer
if( offset == OffsetBot ) return BOTTOM; // Unknown offset-> unknown pointer
if( offset == 0 ) return this; // No change
@ -3245,7 +3256,7 @@ const TypeOopPtr *TypeOopPtr::cast_to_instance_id(int instance_id) const {
}
//-----------------------------cast_to_exactness-------------------------------
const Type *TypeOopPtr::cast_to_exactness(bool klass_is_exact) const {
const TypeOopPtr* TypeOopPtr::cast_to_exactness(bool klass_is_exact) const {
// There is no such thing as an exact general oop.
// Return self unchanged.
return this;
@ -3570,10 +3581,14 @@ const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const {
return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth);
}
const TypeOopPtr* TypeOopPtr::with_offset(intptr_t offset) const {
return make(_ptr, offset, _instance_id, with_offset_speculative(offset), _inline_depth);
}
/**
* Return same type without a speculative part
*/
const Type* TypeOopPtr::remove_speculative() const {
const TypeOopPtr* TypeOopPtr::remove_speculative() const {
if (_speculative == NULL) {
return this;
}
@ -3653,11 +3668,14 @@ const TypeInstPtr *TypeInstPtr::MIRROR;
const TypeInstPtr *TypeInstPtr::MARK;
const TypeInstPtr *TypeInstPtr::KLASS;
ciKlass* TypeInstPtr::exact_klass_helper() const {
return _klass;
}
//------------------------------TypeInstPtr-------------------------------------
TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off,
int instance_id, const TypePtr* speculative, int inline_depth)
: TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth),
_name(k->name()) {
: TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth) {
assert(k != NULL &&
(k->is_loaded() || o == NULL),
"cannot have constants with non-loaded klass");
@ -3720,16 +3738,16 @@ const Type* TypeInstPtr::get_const_boxed_value() const {
}
//------------------------------cast_to_ptr_type-------------------------------
const TypeInstPtr *TypeInstPtr::cast_to_ptr_type(PTR ptr) const {
const TypeInstPtr* TypeInstPtr::cast_to_ptr_type(PTR ptr) const {
if( ptr == _ptr ) return this;
// Reconstruct _sig info here since not a problem with later lazy
// construction, _sig will show up on demand.
return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, _inline_depth);
return make(ptr, klass(), klass_is_exact(), ptr == Constant ? const_oop() : NULL, _offset, _instance_id, _speculative, _inline_depth);
}
//-----------------------------cast_to_exactness-------------------------------
const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
const TypeInstPtr* TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
if( klass_is_exact == _klass_is_exact ) return this;
if (!_klass->is_loaded()) return this;
ciInstanceKlass* ik = _klass->as_instance_klass();
@ -3739,7 +3757,7 @@ const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
}
//-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const {
const TypeInstPtr* TypeInstPtr::cast_to_instance_id(int instance_id) const {
if( instance_id == _instance_id ) return this;
return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth);
}
@ -4137,6 +4155,70 @@ int TypeInstPtr::hash(void) const {
return hash;
}
bool TypeInstPtr::is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
if (!is_loaded() || !other->is_loaded()) {
return false;
}
if (!other->isa_instptr()) {
return false;
}
if (!other_exact) {
return false;
}
if (other->klass()->equals(ciEnv::current()->Object_klass())) {
return true;
}
if (!this_exact && klass()->is_interface()) {
return false;
}
return _klass->is_subtype_of(other->klass());
}
bool TypeInstPtr::is_same_java_type_as(const TypeOopPtr* other) const {
if (!is_loaded() || !other->is_loaded()) {
return false;
}
if (!other->isa_instptr()) {
return false;
}
return _klass->equals(other->_klass);
}
bool TypeInstPtr::maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
if (!is_loaded() || !other->is_loaded()) {
return true;
}
if (other->isa_aryptr()) {
return !this_exact && (_klass->equals(ciEnv::current()->Object_klass()) || _klass->is_interface());
}
if ((_klass->is_interface() && !this_exact) || (other->klass()->is_interface() /*&& !other_exact*/)) {
return true;
}
assert(other->isa_instptr(), "unsupported");
if (this_exact && other_exact) {
return is_java_subtype_of(other);
}
if (!_klass->is_subtype_of(other->_klass) && !other->_klass->is_subtype_of(_klass)) {
return false;
}
if (this_exact) {
return _klass->is_subtype_of(other->_klass);
}
return true;
}
//------------------------------dump2------------------------------------------
// Dump oop Type
#ifndef PRODUCT
@ -4191,12 +4273,17 @@ void TypeInstPtr::dump2(Dict &d, uint depth, outputStream* st) const {
#endif
//------------------------------add_offset-------------------------------------
const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
const TypePtr* TypeInstPtr::add_offset(intptr_t offset) const {
return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset),
_instance_id, add_offset_speculative(offset), _inline_depth);
}
const Type *TypeInstPtr::remove_speculative() const {
const TypeInstPtr* TypeInstPtr::with_offset(intptr_t offset) const {
return make(_ptr, klass(), klass_is_exact(), const_oop(), offset,
_instance_id, with_offset_speculative(offset), _inline_depth);
}
const TypeInstPtr* TypeInstPtr::remove_speculative() const {
if (_speculative == NULL) {
return this;
}
@ -4267,19 +4354,19 @@ const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciK
//------------------------------cast_to_ptr_type-------------------------------
const TypeAryPtr* TypeAryPtr::cast_to_ptr_type(PTR ptr) const {
if( ptr == _ptr ) return this;
return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth);
return make(ptr, ptr == Constant ? const_oop() : NULL, _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth);
}
//-----------------------------cast_to_exactness-------------------------------
const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const {
const TypeAryPtr* TypeAryPtr::cast_to_exactness(bool klass_is_exact) const {
if( klass_is_exact == _klass_is_exact ) return this;
if (_ary->ary_must_be_exact()) return this; // cannot clear xk
return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth);
}
//-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const {
const TypeAryPtr* TypeAryPtr::cast_to_instance_id(int instance_id) const {
if( instance_id == _instance_id ) return this;
return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth);
}
@ -4395,6 +4482,73 @@ int TypeAryPtr::hash(void) const {
return (intptr_t)_ary + TypeOopPtr::hash();
}
bool TypeAryPtr::is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
if (other->klass() == ciEnv::current()->Object_klass() && other_exact) {
return true;
}
if (!is_loaded() || !other->is_loaded() || other->klass() == NULL || klass() == NULL) {
return false;
}
if (other->isa_instptr()) {
return _klass->is_subtype_of(other->_klass) && other_exact;
}
if (klass() == NULL) {
return false;
}
assert(other->isa_aryptr(), "");
const TypeAryPtr* other_ary = other->isa_aryptr();
if (other_ary->elem()->make_oopptr() && elem()->make_oopptr()) {
return elem()->make_oopptr()->is_java_subtype_of_helper(other_ary->elem()->make_oopptr(), this_exact, other_exact);
}
if (!other_ary->elem()->make_oopptr() && !elem()->make_oopptr()) {
return _klass->is_subtype_of(other->_klass);
}
return false;
}
bool TypeAryPtr::is_same_java_type_as(const TypeOopPtr* other) const {
if (!other->isa_aryptr() ||
!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
return false;
}
const TypeAryPtr* other_ary = other->isa_aryptr();
if (other_ary->elem()->make_oopptr() && elem()->make_oopptr()) {
return elem()->make_oopptr()->is_same_java_type_as(other_ary->elem()->make_oopptr());
}
if (!other_ary->elem()->make_oopptr() && !elem()->make_oopptr()) {
return _klass->equals(other->_klass);
}
return false;
}
bool TypeAryPtr::maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
if (other->klass() == ciEnv::current()->Object_klass()) {
return true;
}
if (!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
return true;
}
if (other->isa_instptr()) {
return (!other_exact && other->_klass->is_interface()) || _klass->is_subtype_of(other->_klass);
}
assert(other->isa_aryptr(), "");
if (this_exact && other_exact) {
return is_java_subtype_of(other);
}
const TypeAryPtr* other_ary = other->isa_aryptr();
if (other_ary->elem()->make_oopptr() && elem()->make_oopptr()) {
return elem()->make_oopptr()->maybe_java_subtype_of_helper(other_ary->elem()->make_oopptr(), this_exact,
other_exact);
}
if (!other_ary->elem()->make_oopptr() && !elem()->make_oopptr()) {
return _klass->is_subtype_of(other->_klass);
}
return false;
}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
@ -4716,7 +4870,15 @@ const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const {
return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth);
}
const Type *TypeAryPtr::remove_speculative() const {
const TypeAryPtr* TypeAryPtr::with_offset(intptr_t offset) const {
return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, offset, _instance_id, with_offset_speculative(offset), _inline_depth);
}
const TypeAryPtr* TypeAryPtr::with_ary(const TypeAry* ary) const {
return make(_ptr, _const_oop, ary, _klass, _klass_is_exact, _offset, _instance_id, _speculative, _inline_depth);
}
const TypeAryPtr* TypeAryPtr::remove_speculative() const {
if (_speculative == NULL) {
return this;
}
@ -4856,7 +5018,7 @@ const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) {
return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons();
}
const Type* TypeNarrowOop::remove_speculative() const {
const TypeNarrowOop* TypeNarrowOop::remove_speculative() const {
return make(_ptrtype->remove_speculative()->is_ptr());
}
@ -5111,6 +5273,10 @@ TypeKlassPtr::TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, int offset)
: TypePtr(t, ptr, offset), _klass(klass) {
}
ciKlass* TypeKlassPtr::exact_klass_helper() const {
return _klass;
}
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
bool TypeKlassPtr::eq(const Type *t) const {
@ -5178,7 +5344,9 @@ intptr_t TypeKlassPtr::get_con() const {
ShouldNotReachHere();
}
return (intptr_t)klass()->constant_encoding();
ciKlass* k = exact_klass();
return (intptr_t)k->constant_encoding();
}
//------------------------------dump2------------------------------------------
@ -5249,12 +5417,12 @@ const TypePtr *TypeInstKlassPtr::add_offset( intptr_t offset ) const {
return make( _ptr, klass(), xadd_offset(offset) );
}
const TypeKlassPtr *TypeInstKlassPtr::with_offset(intptr_t offset) const {
const TypeInstKlassPtr* TypeInstKlassPtr::with_offset(intptr_t offset) const {
return make(_ptr, klass(), offset);
}
//------------------------------cast_to_ptr_type-------------------------------
const TypePtr* TypeInstKlassPtr::cast_to_ptr_type(PTR ptr) const {
const TypeInstKlassPtr* TypeInstKlassPtr::cast_to_ptr_type(PTR ptr) const {
assert(_base == InstKlassPtr, "subclass must override cast_to_ptr_type");
if( ptr == _ptr ) return this;
return make(ptr, _klass, _offset);
@ -5280,9 +5448,28 @@ const TypeKlassPtr* TypeInstKlassPtr::cast_to_exactness(bool klass_is_exact) con
//-----------------------------as_instance_type--------------------------------
// Corresponding type for an instance of the given class.
// It will be NotNull, and exact if and only if the klass type is exact.
const TypeOopPtr* TypeInstKlassPtr::as_instance_type() const {
const TypeOopPtr* TypeInstKlassPtr::as_instance_type(bool klass_change) const {
ciKlass* k = klass();
bool xk = klass_is_exact();
bool xk = klass_is_exact();
Compile* C = Compile::current();
Dependencies* deps = C->dependencies();
assert((deps != NULL) == (C->method() != NULL && C->method()->code_size() > 0), "sanity");
// Element is an instance
bool klass_is_exact = false;
if (k->is_loaded()) {
// Try to set klass_is_exact.
ciInstanceKlass* ik = k->as_instance_klass();
klass_is_exact = ik->is_final();
if (!klass_is_exact && klass_change
&& deps != NULL && UseUniqueSubclasses) {
ciInstanceKlass* sub = ik->unique_concrete_subklass();
if (sub != NULL) {
deps->assert_abstract_with_unique_concrete_subtype(ik, sub);
k = ik = sub;
xk = sub->is_final();
}
}
}
return TypeInstPtr::make(TypePtr::BotPTR, k, xk, NULL, 0);
}
@ -5434,6 +5621,69 @@ const Type *TypeInstKlassPtr::xdual() const {
return new TypeInstKlassPtr(dual_ptr(), klass(), dual_offset());
}
bool TypeInstKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
if (!is_loaded() || !other->is_loaded()) {
return false;
}
if (!other->isa_instklassptr()) {
return false;
}
if (!other_exact) {
return false;
}
if (other->_klass->equals(ciEnv::current()->Object_klass())) {
return true;
}
if (!this_exact && klass()->is_interface()) {
return false;
}
return _klass->is_subtype_of(other->_klass);
}
bool TypeInstKlassPtr::is_same_java_type_as(const TypeKlassPtr* other) const {
if (!is_loaded() || !other->is_loaded()) {
return false;
}
if (!other->isa_instklassptr()) {
return false;
}
return _klass->equals(other->_klass);
}
bool TypeInstKlassPtr::maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
if (!is_loaded() || !other->is_loaded()) {
return true;
}
if (other->isa_aryklassptr()) {
return !this_exact && (_klass->equals(ciEnv::current()->Object_klass()) || _klass->is_interface());
}
if ((_klass->is_interface() && !this_exact) || (other->klass()->is_interface() /*&& !other_exact*/)) {
return true;
}
assert(other->isa_instklassptr(), "unsupported");
if (this_exact && other_exact) {
return is_java_subtype_of(other);
}
if (!_klass->is_subtype_of(other->_klass) && !other->_klass->is_subtype_of(_klass)) {
return false;
}
if (this_exact) {
return _klass->is_subtype_of(other->_klass);
}
return true;
}
const TypeAryKlassPtr *TypeAryKlassPtr::make(PTR ptr, const Type* elem, ciKlass* k, int offset) {
return (TypeAryKlassPtr*)(new TypeAryKlassPtr(ptr, elem, k, offset))->hashcons();
}
@ -5553,13 +5803,36 @@ ciKlass* TypeAryPtr::klass() const {
// TypeAryPtr::OOPS->klass() are not common enough to matter.
((TypeAryPtr*)this)->_klass = k_ary;
if (UseCompressedOops && k_ary != NULL && k_ary->is_obj_array_klass() &&
_offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes()) {
_offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes() &&
_offset != arrayOopDesc::klass_offset_in_bytes()) {
((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true;
}
}
return k_ary;
}
ciKlass* TypeAryPtr::exact_klass_helper() const {
if (_ary->_elem->make_ptr() && _ary->_elem->make_ptr()->isa_oopptr()) {
ciKlass* k = _ary->_elem->make_ptr()->is_oopptr()->exact_klass_helper();
if (k == NULL) {
return NULL;
}
k = ciObjArrayKlass::make(k);
return k;
}
return klass();
}
const Type* TypeAryPtr::base_element_type(int& dims) const {
const Type* elem = this->elem();
dims = 1;
while (elem->make_ptr() && elem->make_ptr()->isa_aryptr()) {
elem = elem->make_ptr()->is_aryptr()->elem();
dims++;
}
return elem;
}
//------------------------------add_offset-------------------------------------
// Access internals of klass object
@ -5567,12 +5840,12 @@ const TypePtr *TypeAryKlassPtr::add_offset(intptr_t offset) const {
return make(_ptr, elem(), klass(), xadd_offset(offset));
}
const TypeKlassPtr *TypeAryKlassPtr::with_offset(intptr_t offset) const {
const TypeAryKlassPtr* TypeAryKlassPtr::with_offset(intptr_t offset) const {
return make(_ptr, elem(), klass(), offset);
}
//------------------------------cast_to_ptr_type-------------------------------
const TypePtr* TypeAryKlassPtr::cast_to_ptr_type(PTR ptr) const {
const TypeAryKlassPtr* TypeAryKlassPtr::cast_to_ptr_type(PTR ptr) const {
assert(_base == AryKlassPtr, "subclass must override cast_to_ptr_type");
if (ptr == _ptr) return this;
return make(ptr, elem(), _klass, _offset);
@ -5601,11 +5874,17 @@ const TypeKlassPtr *TypeAryKlassPtr::cast_to_exactness(bool klass_is_exact) cons
//-----------------------------as_instance_type--------------------------------
// Corresponding type for an instance of the given class.
// It will be exact if and only if the klass type is exact.
const TypeOopPtr* TypeAryKlassPtr::as_instance_type() const {
// It will be NotNull, and exact if and only if the klass type is exact.
const TypeOopPtr* TypeAryKlassPtr::as_instance_type(bool klass_change) const {
ciKlass* k = klass();
bool xk = klass_is_exact();
const Type* el = elem()->isa_klassptr() ? elem()->is_klassptr()->as_instance_type()->is_oopptr()->cast_to_exactness(false) : elem();
const Type* el = NULL;
if (elem()->isa_klassptr()) {
el = elem()->is_klassptr()->as_instance_type(false)->cast_to_exactness(false);
k = NULL;
} else {
el = elem();
}
return TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(el, TypeInt::POS), k, xk, 0);
}
@ -5737,6 +6016,72 @@ const Type *TypeAryKlassPtr::xmeet( const Type *t ) const {
return this; // Return the double constant
}
bool TypeAryKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
if (other->klass() == ciEnv::current()->Object_klass() && other_exact) {
return true;
}
if (!is_loaded() || !other->is_loaded() || other->klass() == NULL || klass() == NULL) {
return false;
}
if (other->isa_instklassptr()) {
return _klass->is_subtype_of(other->_klass) && other_exact;
}
if (klass() == NULL) {
return false;
}
assert(other->isa_aryklassptr(), "");
const TypeAryKlassPtr* other_ary = other->isa_aryklassptr();
if (other_ary->_elem->isa_klassptr() && _elem->isa_klassptr()) {
return _elem->is_klassptr()->is_java_subtype_of_helper(other_ary->_elem->is_klassptr(), this_exact, other_exact);
}
if (!other_ary->_elem->isa_klassptr() && !_elem->isa_klassptr()) {
return _klass->is_subtype_of(other->_klass);
}
return false;
}
bool TypeAryKlassPtr::is_same_java_type_as(const TypeKlassPtr* other) const {
if (!other->isa_aryklassptr() ||
!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
return false;
}
const TypeAryKlassPtr* other_ary = other->isa_aryklassptr();
if (other_ary->_elem->isa_klassptr() && _elem->isa_klassptr()) {
return _elem->is_klassptr()->is_same_java_type_as(other_ary->_elem->is_klassptr());
}
if (!other_ary->_elem->isa_klassptr() && !_elem->isa_klassptr()) {
return _klass->equals(other->_klass);
}
return false;
}
bool TypeAryKlassPtr::maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
if (other->klass() == ciEnv::current()->Object_klass()) {
return true;
}
if (!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
return true;
}
if (other->isa_instklassptr()) {
return (!other_exact && other->_klass->is_interface()) || _klass->is_subtype_of(other->_klass);
}
assert(other->isa_aryklassptr(), "");
if (this_exact && other_exact) {
return is_java_subtype_of(other);
}
const TypeAryKlassPtr* other_ary = other->isa_aryklassptr();
if (other_ary->_elem->isa_klassptr() && _elem->isa_klassptr()) {
return _elem->is_klassptr()->maybe_java_subtype_of_helper(other_ary->_elem->is_klassptr(), this_exact, other_exact);
}
if (!other_ary->_elem->isa_klassptr() && !_elem->isa_klassptr()) {
return _klass->is_subtype_of(other->_klass);
}
return false;
}
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type *TypeAryKlassPtr::xdual() const {
@ -5744,6 +6089,19 @@ const Type *TypeAryKlassPtr::xdual() const {
}
//------------------------------get_con----------------------------------------
ciKlass* TypeAryKlassPtr::exact_klass_helper() const {
if (elem()->isa_klassptr()) {
ciKlass* k = elem()->is_klassptr()->exact_klass_helper();
if (k == NULL) {
return NULL;
}
k = ciObjArrayKlass::make(k);
return k;
}
return klass();
}
ciKlass* TypeAryKlassPtr::klass() const {
if (_klass != NULL) {
return _klass;

@ -774,7 +774,7 @@ public:
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const; // Compute dual right now.
bool ary_must_be_exact() const; // true if arrays of such are never generic
virtual const Type* remove_speculative() const;
virtual const TypeAry* remove_speculative() const;
virtual const Type* cleanup_speculative() const;
#ifdef ASSERT
// One type is interface, the other is oop
@ -919,6 +919,7 @@ protected:
bool eq_speculative(const TypePtr* other) const;
int hash_speculative() const;
const TypePtr* add_offset_speculative(intptr_t offset) const;
const TypePtr* with_offset_speculative(intptr_t offset) const;
#ifndef PRODUCT
void dump_speculative(outputStream *st) const;
#endif
@ -960,12 +961,13 @@ public:
int inline_depth = InlineDepthBottom);
// Return a 'ptr' version of this type
virtual const Type *cast_to_ptr_type(PTR ptr) const;
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
virtual intptr_t get_con() const;
int xadd_offset( intptr_t offset ) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const TypePtr* add_offset(intptr_t offset) const;
virtual const TypePtr* with_offset(intptr_t offset) const;
virtual bool eq(const Type *t) const;
virtual int hash() const; // Type specific hashing
@ -994,7 +996,7 @@ public:
virtual ciKlass* speculative_type_not_null() const;
virtual bool speculative_maybe_null() const;
virtual bool speculative_always_null() const;
virtual const Type* remove_speculative() const;
virtual const TypePtr* remove_speculative() const;
virtual const Type* cleanup_speculative() const;
virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
virtual bool would_improve_ptr(ProfilePtrKind maybe_null) const;
@ -1034,7 +1036,8 @@ public:
virtual intptr_t get_con() const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const TypePtr* add_offset(intptr_t offset) const;
virtual const TypeRawPtr* with_offset(intptr_t offset) const { ShouldNotReachHere(); return NULL;}
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const; // Compute dual right now.
@ -1049,6 +1052,10 @@ public:
//------------------------------TypeOopPtr-------------------------------------
// Some kind of oop (Java pointer), either instance or array.
class TypeOopPtr : public TypePtr {
friend class TypeAry;
friend class TypePtr;
friend class TypeInstPtr;
friend class TypeAryPtr;
protected:
TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id,
const TypePtr* speculative, int inline_depth);
@ -1085,7 +1092,22 @@ protected:
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
virtual ciKlass* exact_klass_helper() const { return NULL; }
virtual ciKlass* klass() const { return _klass; }
public:
bool is_java_subtype_of(const TypeOopPtr* other) const {
return is_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
}
virtual bool is_same_java_type_as(const TypeOopPtr* other) const { ShouldNotReachHere(); return false; }
bool maybe_java_subtype_of(const TypeOopPtr* other) const {
return maybe_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
}
virtual bool is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
virtual bool maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
// Creates a type given a klass. Correctly handles multi-dimensional arrays
// Respects UseUniqueSubclasses.
// If the klass is final, the resulting type will be exact.
@ -1115,7 +1137,11 @@ public:
int inline_depth = InlineDepthBottom);
ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; }
// Exact klass, possibly an interface or an array of interface
ciKlass* exact_klass(bool maybe_null = false) const { assert(klass_is_exact(), ""); ciKlass* k = exact_klass_helper(); assert(k != NULL || maybe_null, ""); return k; }
ciKlass* unloaded_klass() const { assert(!is_loaded(), "only for unloaded types"); return klass(); }
virtual bool is_loaded() const { return klass()->is_loaded(); }
bool klass_is_exact() const { return _klass_is_exact; }
// Returns true if this pointer points at memory which contains a
@ -1131,17 +1157,18 @@ public:
virtual const TypeOopPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
virtual const TypeOopPtr* cast_to_exactness(bool klass_is_exact) const;
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
// corresponding pointer to klass, for a given instance
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const TypeOopPtr* with_offset(intptr_t offset) const;
virtual const TypePtr* add_offset(intptr_t offset) const;
// Speculative type helper methods.
virtual const Type* remove_speculative() const;
virtual const TypeOopPtr* remove_speculative() const;
virtual const Type* cleanup_speculative() const;
virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
virtual const TypePtr* with_inline_depth(int depth) const;
@ -1168,12 +1195,21 @@ class TypeInstPtr : public TypeOopPtr {
virtual bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing
ciSymbol* _name; // class name
ciKlass* exact_klass_helper() const;
public:
ciSymbol* name() const { return _name; }
public:
bool is_loaded() const { return _klass->is_loaded(); }
// Instance klass, ignoring any interface
ciInstanceKlass* instance_klass() const {
if (klass()->is_loaded() && klass()->is_interface()) {
return Compile::current()->env()->Object_klass();
}
return klass()->as_instance_klass();
}
bool is_same_java_type_as(const TypeOopPtr* other) const;
bool is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
bool maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
// Make a pointer to a constant oop.
static const TypeInstPtr *make(ciObject* o) {
@ -1215,14 +1251,15 @@ class TypeInstPtr : public TypeOopPtr {
virtual const TypeInstPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
virtual const TypeInstPtr* cast_to_exactness(bool klass_is_exact) const;
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
virtual const TypeInstPtr* cast_to_instance_id(int instance_id) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const TypePtr* add_offset(intptr_t offset) const;
virtual const TypeInstPtr* with_offset(intptr_t offset) const;
// Speculative type helper methods.
virtual const Type* remove_speculative() const;
virtual const TypeInstPtr* remove_speculative() const;
virtual const TypePtr* with_inline_depth(int depth) const;
virtual const TypePtr* with_instance_id(int instance_id) const;
@ -1233,6 +1270,8 @@ class TypeInstPtr : public TypeOopPtr {
const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
bool is_interface() const { return is_loaded() && klass()->is_interface(); }
// Convenience common pre-built types.
static const TypeInstPtr *NOTNULL;
static const TypeInstPtr *BOTTOM;
@ -1278,9 +1317,21 @@ class TypeAryPtr : public TypeOopPtr {
ciKlass* compute_klass(DEBUG_ONLY(bool verify = false)) const;
public:
// Accessors
ciKlass* exact_klass_helper() const;
ciKlass* klass() const;
public:
bool is_same_java_type_as(const TypeOopPtr* other) const;
bool is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
bool maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
// returns base element type, an instance klass (and not interface) for object arrays
const Type* base_element_type(int& dims) const;
// Accessors
bool is_loaded() const { return (_ary->_elem->make_oopptr() ? _ary->_elem->make_oopptr()->is_loaded() : true); }
const TypeAry* ary() const { return _ary; }
const Type* elem() const { return _ary->_elem; }
const TypeInt* size() const { return _ary->_size; }
@ -1301,18 +1352,20 @@ public:
// Return a 'ptr' version of this type
virtual const TypeAryPtr* cast_to_ptr_type(PTR ptr) const;
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
virtual const TypeAryPtr* cast_to_exactness(bool klass_is_exact) const;
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
virtual const TypeAryPtr* cast_to_instance_id(int instance_id) const;
virtual const TypeAryPtr* cast_to_size(const TypeInt* size) const;
virtual const TypeInt* narrow_size_type(const TypeInt* size) const;
virtual bool empty(void) const; // TRUE if type is vacuous
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const TypeAryPtr *with_offset( intptr_t offset ) const;
const TypeAryPtr* with_ary(const TypeAry* ary) const;
// Speculative type helper methods.
virtual const Type* remove_speculative() const;
virtual const TypeAryPtr* remove_speculative() const;
virtual const TypePtr* with_inline_depth(int depth) const;
virtual const TypePtr* with_instance_id(int instance_id) const;
@ -1398,6 +1451,8 @@ public:
//------------------------------TypeKlassPtr-----------------------------------
// Class of Java Klass pointers
class TypeKlassPtr : public TypePtr {
friend class TypeInstKlassPtr;
friend class TypeAryKlassPtr;
protected:
TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, int offset);
@ -1407,28 +1462,43 @@ public:
virtual bool eq( const Type *t ) const;
virtual int hash() const;
virtual bool singleton(void) const; // TRUE if type is a singleton
virtual bool must_be_exact() const { ShouldNotReachHere(); return false; }
protected:
ciKlass* _klass;
virtual bool must_be_exact() const { ShouldNotReachHere(); return false; }
virtual ciKlass* exact_klass_helper() const;
virtual ciKlass* klass() const { return _klass; }
public:
virtual ciKlass* klass() const { return _klass; }
bool is_java_subtype_of(const TypeKlassPtr* other) const {
return is_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
}
bool maybe_java_subtype_of(const TypeKlassPtr* other) const {
return maybe_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
}
virtual bool is_same_java_type_as(const TypeKlassPtr* other) const { ShouldNotReachHere(); return false; }
virtual bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
virtual bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
// Exact klass, possibly an interface or an array of interface
ciKlass* exact_klass(bool maybe_null = false) const { assert(klass_is_exact(), ""); ciKlass* k = exact_klass_helper(); assert(k != NULL || maybe_null, ""); return k; }
bool klass_is_exact() const { return _ptr == Constant; }
bool is_loaded() const { return klass()->is_loaded(); }
static const TypeKlassPtr* make(ciKlass* klass);
static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, int offset);
virtual bool is_loaded() const { return _klass->is_loaded(); }
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
virtual const TypeKlassPtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const { ShouldNotReachHere(); return NULL; }
// corresponding pointer to instance, for a given class
virtual const TypeOopPtr* as_instance_type() const { ShouldNotReachHere(); return NULL; }
virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const { ShouldNotReachHere(); return NULL; }
virtual const TypePtr *add_offset( intptr_t offset ) const { ShouldNotReachHere(); return NULL; }
virtual const Type *xmeet( const Type *t ) const { ShouldNotReachHere(); return NULL; }
@ -1454,26 +1524,37 @@ class TypeInstKlassPtr : public TypeKlassPtr {
public:
// Instance klass ignoring any interface
ciInstanceKlass* instance_klass() const { return klass()->as_instance_klass(); }
ciInstanceKlass* instance_klass() const {
if (klass()->is_interface()) {
return Compile::current()->env()->Object_klass();
}
return klass()->as_instance_klass();
}
bool is_same_java_type_as(const TypeKlassPtr* other) const;
bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
static const TypeInstKlassPtr *make(ciKlass* k) {
return make(TypePtr::Constant, k, 0);
}
static const TypeInstKlassPtr *make(PTR ptr, ciKlass* k, int offset);
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
virtual const TypeInstKlassPtr* cast_to_ptr_type(PTR ptr) const;
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
// corresponding pointer to instance, for a given class
virtual const TypeOopPtr* as_instance_type() const;
virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const;
virtual int hash() const;
virtual bool eq(const Type *t) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const;
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
virtual const TypeInstKlassPtr* with_offset(intptr_t offset) const;
bool is_interface() const { return klass()->is_interface(); }
// Convenience common pre-built types.
static const TypeInstKlassPtr* OBJECT; // Not-null object klass or below
@ -1482,21 +1563,31 @@ public:
// Array klass pointer, mirrors TypeAryPtr
class TypeAryKlassPtr : public TypeKlassPtr {
friend class TypeInstKlassPtr;
const Type *_elem;
TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, int offset)
: TypeKlassPtr(AryKlassPtr, ptr, klass, offset), _elem(elem) {
}
virtual ciKlass* exact_klass_helper() const;
virtual ciKlass* klass() const;
virtual bool must_be_exact() const;
public:
virtual ciKlass* klass() const;
// returns base element type, an instance klass (and not interface) for object arrays
const Type* base_element_type(int& dims) const;
static const TypeAryKlassPtr *make(PTR ptr, ciKlass* k, int offset);
bool is_same_java_type_as(const TypeKlassPtr* other) const;
bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
bool is_loaded() const { return (_elem->isa_klassptr() ? _elem->is_klassptr()->is_loaded() : true); }
static const TypeAryKlassPtr *make(PTR ptr, const Type *elem, ciKlass* k, int offset);
static const TypeAryKlassPtr* make(ciKlass* klass);
@ -1505,18 +1596,18 @@ public:
virtual bool eq(const Type *t) const;
virtual int hash() const; // Type specific hashing
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
virtual const TypeAryKlassPtr* cast_to_ptr_type(PTR ptr) const;
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
// corresponding pointer to instance, for a given class
virtual const TypeOopPtr* as_instance_type() const;
virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const; // Compute dual right now.
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
virtual const TypeAryKlassPtr* with_offset(intptr_t offset) const;
virtual bool empty(void) const {
return TypeKlassPtr::empty() || _elem->empty();
@ -1608,7 +1699,7 @@ public:
static const TypeNarrowOop *BOTTOM;
static const TypeNarrowOop *NULL_PTR;
virtual const Type* remove_speculative() const;
virtual const TypeNarrowOop* remove_speculative() const;
virtual const Type* cleanup_speculative() const;
#ifndef PRODUCT
@ -1946,8 +2037,7 @@ inline bool Type::is_floatingpoint() const {
inline bool Type::is_ptr_to_boxing_obj() const {
const TypeInstPtr* tp = isa_instptr();
return (tp != NULL) && (tp->offset() == 0) &&
tp->klass()->is_instance_klass() &&
tp->klass()->as_instance_klass()->is_box_klass();
tp->instance_klass()->is_box_klass();
}

@ -247,7 +247,7 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) {
}
}
ciInstanceKlass* iklass = vec_box->box_type()->klass()->as_instance_klass();
ciInstanceKlass* iklass = vec_box->box_type()->instance_klass();
int n_fields = iklass->nof_nonstatic_fields();
assert(n_fields == 1, "sanity");
@ -348,7 +348,7 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc,
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
ciInstanceKlass* box_klass = box_type->klass()->as_instance_klass();
ciInstanceKlass* box_klass = box_type->instance_klass();
BasicType bt = vect_type->element_basic_type();
int num_elem = vect_type->length();
@ -420,7 +420,7 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
Node* obj = vec_unbox->obj();
const TypeInstPtr* tinst = gvn.type(obj)->isa_instptr();
ciInstanceKlass* from_kls = tinst->klass()->as_instance_klass();
ciInstanceKlass* from_kls = tinst->instance_klass();
const TypeVect* vt = vec_unbox->bottom_type()->is_vect();
BasicType bt = vt->element_basic_type();
BasicType masktype = bt;

@ -39,7 +39,7 @@ static bool is_vector(ciKlass* klass) {
static bool check_vbox(const TypeInstPtr* vbox_type) {
assert(vbox_type->klass_is_exact(), "");
ciInstanceKlass* ik = vbox_type->klass()->as_instance_klass();
ciInstanceKlass* ik = vbox_type->instance_klass();
assert(is_vector(ik), "not a vector");
ciField* fd1 = ik->get_field_by_name(ciSymbols::ETYPE_name(), ciSymbols::class_signature(), /* is_static */ true);
@ -153,7 +153,7 @@ Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType
Node* ret = gvn().transform(new ProjNode(alloc, TypeFunc::Parms));
assert(check_vbox(vbox_type), "");
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->klass()));
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->instance_klass()));
VectorBoxNode* vbox = new VectorBoxNode(C, ret, vector, vbox_type, vt);
return gvn().transform(vbox);
}
@ -161,14 +161,14 @@ Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType
Node* GraphKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector) {
assert(EnableVectorSupport, "");
const TypeInstPtr* vbox_type_v = gvn().type(v)->is_instptr();
if (vbox_type->klass() != vbox_type_v->klass()) {
if (vbox_type->instance_klass() != vbox_type_v->instance_klass()) {
return NULL; // arguments don't agree on vector shapes
}
if (vbox_type_v->maybe_null()) {
return NULL; // no nulls are allowed
}
assert(check_vbox(vbox_type), "");
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->klass()));
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->instance_klass()));
Node* unbox = gvn().transform(new VectorUnboxNode(C, vt, v, merged_memory(), shuffle_to_vector));
return unbox;
}

@ -1438,7 +1438,7 @@ Node* VectorUnboxNode::Ideal(PhaseGVN* phase, bool can_reshape) {
// Handled by VectorUnboxNode::Identity()
} else {
VectorBoxNode* vbox = static_cast<VectorBoxNode*>(n);
ciKlass* vbox_klass = vbox->box_type()->klass();
ciKlass* vbox_klass = vbox->box_type()->instance_klass();
const TypeVect* in_vt = vbox->vec_type();
const TypeVect* out_vt = type()->is_vect();

@ -713,8 +713,8 @@ inline bool is_double_word_type(BasicType t) {
return (t == T_DOUBLE || t == T_LONG);
}
inline bool is_reference_type(BasicType t) {
return (t == T_OBJECT || t == T_ARRAY);
inline bool is_reference_type(BasicType t, bool include_narrow_oop = false) {
return (t == T_OBJECT || t == T_ARRAY || (include_narrow_oop && t == T_NARROWOOP));
}
inline bool is_integral_type(BasicType t) {