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

View file

@ -167,6 +167,14 @@ ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass) {
GUARDED_VM_ENTRY(return make_impl(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() { ciKlass* ciObjArrayKlass::exact_klass() {
ciType* base = base_element_type(); ciType* base = base_element_type();
if (base->is_instance_klass()) { if (base->is_instance_klass()) {

View file

@ -73,6 +73,7 @@ public:
bool is_obj_array_klass() const { return true; } bool is_obj_array_klass() const { return true; }
static ciObjArrayKlass* make(ciKlass* element_klass); static ciObjArrayKlass* make(ciKlass* element_klass);
static ciObjArrayKlass* make(ciKlass* element_klass, int dims);
virtual ciKlass* exact_klass(); virtual ciKlass* exact_klass();
}; };

View file

@ -528,8 +528,8 @@ void G1BarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, Node* off
if (itype != NULL) { if (itype != NULL) {
// Can the klass of base_oop be statically determined to be // Can the klass of base_oop be statically determined to be
// _not_ a sub-class of Reference and _not_ Object? // _not_ a sub-class of Reference and _not_ Object?
ciKlass* klass = itype->klass(); ciKlass* klass = itype->instance_klass();
if ( klass->is_loaded() && if (klass->is_loaded() &&
!klass->is_subtype_of(kit->env()->Reference_klass()) && !klass->is_subtype_of(kit->env()->Reference_klass()) &&
!kit->env()->Object_klass()->is_subtype_of(klass)) { !kit->env()->Object_klass()->is_subtype_of(klass)) {
return; return;

View file

@ -372,7 +372,7 @@ void C2Access::fixup_decorators() {
intptr_t offset = Type::OffsetBot; intptr_t offset = Type::OffsetBot;
AddPNode::Ideal_base_and_offset(adr, &gvn(), offset); AddPNode::Ideal_base_and_offset(adr, &gvn(), offset);
if (offset >= 0) { 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) { if (offset < s) {
// Guaranteed to be a valid access, no need to pin it // Guaranteed to be a valid access, no need to pin it
_decorators ^= C2_CONTROL_DEPENDENT_LOAD; _decorators ^= C2_CONTROL_DEPENDENT_LOAD;

View file

@ -389,8 +389,8 @@ void ShenandoahBarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, N
if (itype != NULL) { if (itype != NULL) {
// Can the klass of base_oop be statically determined to be // Can the klass of base_oop be statically determined to be
// _not_ a sub-class of Reference and _not_ Object? // _not_ a sub-class of Reference and _not_ Object?
ciKlass* klass = itype->klass(); ciKlass* klass = itype->instance_klass();
if ( klass->is_loaded() && if (klass->is_loaded() &&
!klass->is_subtype_of(kit->env()->Reference_klass()) && !klass->is_subtype_of(kit->env()->Reference_klass()) &&
!kit->env()->Object_klass()->is_subtype_of(klass)) { !kit->env()->Object_klass()->is_subtype_of(klass)) {
return; return;
@ -783,8 +783,8 @@ bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_couple
bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) { bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
const TypeOopPtr* src_type = gvn.type(src)->is_oopptr(); const TypeOopPtr* src_type = gvn.type(src)->is_oopptr();
if (src_type->isa_instptr() != NULL) { if (src_type->isa_instptr() != NULL) {
ciInstanceKlass* ik = src_type->klass()->as_instance_klass(); ciInstanceKlass* ik = src_type->is_instptr()->instance_klass();
if ((src_type->klass_is_exact() || (!ik->is_interface() && !ik->has_subklass())) && !ik->has_injected_fields()) { if ((src_type->klass_is_exact() || !ik->has_subklass()) && !ik->has_injected_fields()) {
if (ik->has_object_fields()) { if (ik->has_object_fields()) {
return true; return true;
} else { } else {
@ -796,8 +796,8 @@ bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
return true; return true;
} }
} else if (src_type->isa_aryptr()) { } else if (src_type->isa_aryptr()) {
BasicType src_elem = src_type->klass()->as_array_klass()->element_type()->basic_type(); BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(src_elem)) { if (is_reference_type(src_elem, true)) {
return true; return true;
} }
} else { } else {

View file

@ -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 (adr_type->isa_oopptr() && adr_type->is_oopptr()->offset() == oopDesc::mark_offset_in_bytes()) {
if (trace) {tty->print_cr("Mark load");} if (trace) {tty->print_cr("Mark load");}
} else if (adr_type->isa_instptr() && } 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()) { adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset()) {
if (trace) {tty->print_cr("Reference.get()");} if (trace) {tty->print_cr("Reference.get()");}
} else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) { } else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {

View file

@ -120,7 +120,7 @@ int ArrayCopyNode::get_count(PhaseGVN *phase) const {
if (is_clonebasic()) { if (is_clonebasic()) {
if (src_type->isa_instptr()) { if (src_type->isa_instptr()) {
const TypeInstPtr* inst_src = src_type->is_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 // ciInstanceKlass::nof_nonstatic_fields() doesn't take injected
// fields into account. They are rare anyway so easier to simply // fields into account. They are rare anyway so easier to simply
// skip instances with injected fields. // 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); phase->is_IterGVN()->_worklist.push(mem);
} }
ciInstanceKlass* ik = inst_src->instance_klass();
if (!inst_src->klass_is_exact()) { if (!inst_src->klass_is_exact()) {
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
assert(!ik->is_interface(), "inconsistent klass hierarchy"); assert(!ik->is_interface(), "inconsistent klass hierarchy");
if (ik->has_subklass()) { if (ik->has_subklass()) {
// Concurrent class loading. // 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"); assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields");
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); 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 // newly allocated object is guaranteed to not overlap with source object
disjoint_bases = is_alloc_tightly_coupled(); disjoint_bases = is_alloc_tightly_coupled();
if (ary_src == NULL || ary_src->elem() == Type::BOTTOM ||
if (ary_src == NULL || ary_src->klass() == NULL || ary_dest == NULL || ary_dest->elem() == Type::BOTTOM) {
ary_dest == NULL || ary_dest->klass() == NULL) {
// We don't know if arguments are arrays // We don't know if arguments are arrays
return false; return false;
} }
BasicType src_elem = ary_src->klass()->as_array_klass()->element_type()->basic_type(); BasicType src_elem = ary_src->elem()->array_element_basic_type();
BasicType dest_elem = ary_dest->klass()->as_array_klass()->element_type()->basic_type(); BasicType dest_elem = ary_dest->elem()->array_element_basic_type();
if (is_reference_type(src_elem)) src_elem = T_OBJECT; if (is_reference_type(src_elem, true)) src_elem = T_OBJECT;
if (is_reference_type(dest_elem)) dest_elem = T_OBJECT; if (is_reference_type(dest_elem, true)) dest_elem = T_OBJECT;
if (src_elem != dest_elem || dest_elem == T_VOID) { if (src_elem != dest_elem || dest_elem == T_VOID) {
// We don't know if arguments are arrays of the same type // 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; disjoint_bases = true;
BasicType elem = ary_src->klass()->as_array_klass()->element_type()->basic_type(); BasicType elem = ary_src->isa_aryptr()->elem()->array_element_basic_type();
if (is_reference_type(elem)) { if (is_reference_type(elem, true)) {
elem = T_OBJECT; elem = T_OBJECT;
} }
@ -734,7 +734,9 @@ bool ArrayCopyNode::modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransf
return !must_modify; 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 header = arrayOopDesc::base_offset_in_bytes(ary_elem);
uint elemsize = type2aelembytes(ary_elem); uint elemsize = type2aelembytes(ary_elem);

View file

@ -380,7 +380,7 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c
case Type::KlassPtr: case Type::KlassPtr:
case Type::AryKlassPtr: case Type::AryKlassPtr:
case Type::InstKlassPtr: 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; break;
case Type::MetadataPtr: case Type::MetadataPtr:
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_metadataptr()->metadata())); 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->cr();
st->print(" # ScObj" INT32_FORMAT " ", i); st->print(" # ScObj" INT32_FORMAT " ", i);
SafePointScalarObjectNode* spobj = scobjs.at(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() || assert(cik->is_instance_klass() ||
cik->is_array_klass(), "Not supported allocation."); cik->is_array_klass(), "Not supported allocation.");
ciInstanceKlass *iklass = NULL; ciInstanceKlass *iklass = NULL;
@ -807,11 +807,11 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
return false; return false;
} }
if (t_oop->is_ptr_to_boxed_value()) { 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()) { if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) {
// Skip unrelated boxing methods. // Skip unrelated boxing methods.
Node* proj = proj_out_or_null(TypeFunc::Parms); 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; return false;
} }
} }
@ -826,7 +826,7 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
if (proj != NULL) { if (proj != NULL) {
const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr(); const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr();
if ((inst_t != NULL) && (!inst_t->klass_is_exact() || if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
(inst_t->klass() == boxing_klass))) { (inst_t->instance_klass() == boxing_klass))) {
return true; 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++) { for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr(); const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr();
if ((inst_t != NULL) && (!inst_t->klass_is_exact() || if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
(inst_t->klass() == boxing_klass))) { (inst_t->instance_klass() == boxing_klass))) {
return true; 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(); 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 // clone
if (t_oop->isa_aryptr()) { if (t_oop->isa_aryptr()) {
return false; return false;
@ -2317,7 +2317,7 @@ bool CallNode::may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeO
if (!t_oop->isa_instptr()) { if (!t_oop->isa_instptr()) {
return true; 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; return true;
} }
// unrelated // unrelated

View file

@ -1177,16 +1177,14 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
// convert the one to the other. // convert the one to the other.
const TypePtr* ttp = _type->make_ptr(); const TypePtr* ttp = _type->make_ptr();
const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL; 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; bool is_intf = false;
if (ttip != NULL) { if (ttip != NULL) {
ciKlass* k = ttip->klass(); if (ttip->is_interface())
if (k->is_loaded() && k->is_interface())
is_intf = true; is_intf = true;
} }
if (ttkp != NULL) { if (ttkp != NULL) {
ciKlass* k = ttkp->klass(); if (ttkp->is_interface())
if (k->is_loaded() && k->is_interface())
is_intf = true; is_intf = true;
} }
@ -1205,8 +1203,7 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
const TypeInstPtr* tiip = (tip != NULL) ? tip->isa_instptr() : NULL; const TypeInstPtr* tiip = (tip != NULL) ? tip->isa_instptr() : NULL;
if (tiip) { if (tiip) {
bool ti_is_intf = false; bool ti_is_intf = false;
ciKlass* k = tiip->klass(); if (tiip->is_interface())
if (k->is_loaded() && k->is_interface())
ti_is_intf = true; ti_is_intf = true;
if (is_intf != ti_is_intf) if (is_intf != ti_is_intf)
{ t = _type; break; } { 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 // 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 // into a Phi which "knows" it's an Interface type we'll have to
// uplift the type. // 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 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 assert(ft == _type, ""); // Uplift to interface
} else { } else {
// We also have to handle 'evil cases' of interface- vs. class-arrays // We also have to handle 'evil cases' of interface- vs. class-arrays
Type::get_arrays_base_elements(jt, _type, NULL, &ttip); 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 assert(ft == _type, ""); // Uplift to array of interface
} else { } else {
// Otherwise it's something stupid like non-overlapping int ranges // 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. // because the type system doesn't interact well with interfaces.
const TypePtr *jtp = jt->make_ptr(); const TypePtr *jtp = jt->make_ptr();
const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL; const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL;
const TypeKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_instklassptr() : NULL; const TypeInstKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_instklassptr() : NULL;
if( jtip && ttip ) { if (jtip && ttip) {
if( jtip->is_loaded() && jtip->klass()->is_interface() && if (jtip->is_interface() &&
ttip->is_loaded() && !ttip->klass()->is_interface() ) { !ttip->is_interface()) {
assert(ft == ttip->cast_to_ptr_type(jtip->ptr()) || assert(ft == ttip->cast_to_ptr_type(jtip->ptr()) ||
ft->isa_narrowoop() && ft->make_ptr() == ttip->cast_to_ptr_type(jtip->ptr()), ""); ft->isa_narrowoop() && ft->make_ptr() == ttip->cast_to_ptr_type(jtip->ptr()), "");
jt = ft; jt = ft;
} }
} }
if( jtkp && ttkp ) { if (jtkp && ttkp) {
if( jtkp->is_loaded() && jtkp->klass()->is_interface() && if (jtkp->is_interface() &&
!jtkp->klass_is_exact() && // Keep exact interface klass (6894807) !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()) || assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) ||
ft->isa_narrowklass() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), ""); ft->isa_narrowklass() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), "");
jt = ft; jt = ft;

View file

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

View file

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

View file

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

View file

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

View file

@ -1242,7 +1242,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
const Type *t = _gvn.type( value ); const Type *t = _gvn.type( value );
const TypeOopPtr* tp = t->isa_oopptr(); 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: // Only for do_null_check, not any of its siblings:
&& !assert_null && null_control == NULL) { && !assert_null && null_control == NULL) {
// Usually, any field access or invocation on an unloaded oop type // 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 // Our access to the unloaded class will only be correct
// after it has been loaded and initialized, which requires // after it has been loaded and initialized, which requires
// a trip through the interpreter. // a trip through the interpreter.
ciKlass* klass = tp->unloaded_klass();
#ifndef PRODUCT #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 #endif
uncommon_trap(Deoptimization::Reason_unloaded, uncommon_trap(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret, Deoptimization::Action_reinterpret,
tp->klass(), "!loaded"); klass, "!loaded");
return top(); 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. return C->top(); // false path is dead; no test needed.
if (gvn.type(superklass)->singleton()) { if (gvn.type(superklass)->singleton()) {
ciKlass* superk = gvn.type(superklass)->is_klassptr()->klass(); const TypeKlassPtr* superk = gvn.type(superklass)->is_klassptr();
ciKlass* subk = gvn.type(subklass)->is_klassptr()->klass(); const TypeKlassPtr* subk = gvn.type(subklass)->is_klassptr();
// In the common case of an exact superklass, try to fold up the // In the common case of an exact superklass, try to fold up the
// test before generating code. You may ask, why not just generate // 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. // If the profile has seen exactly one type, narrow to exactly that type.
// Subsequent type checks will always fold up. // Subsequent type checks will always fold up.
Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
ciKlass* require_klass, const TypeKlassPtr* require_klass,
ciKlass* spec_klass, ciKlass* spec_klass,
bool safe_for_replace) { bool safe_for_replace) {
if (!UseTypeProfile || !TypeProfileCasts) return NULL; 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; ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass;
if (exact_kls != NULL) {// no cast failures here if (exact_kls != NULL) {// no cast failures here
if (require_klass == NULL || 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 // If we narrow the type to match what the type profile sees or
// the speculative type, we can then remove the rest of the // the speculative type, we can then remove the rest of the
// cast. // 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? // Do we know the type check always succeed?
bool known_statically = false; bool known_statically = false;
if (_gvn.type(superklass)->singleton()) { if (_gvn.type(superklass)->singleton()) {
ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass(); const TypeKlassPtr* superk = _gvn.type(superklass)->is_klassptr();
ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass(); const TypeKlassPtr* subk = _gvn.type(obj)->is_oopptr()->as_klass_type();
if (subk != NULL && subk->is_loaded()) { if (subk->is_loaded()) {
int static_res = C->static_subtype_check(superk, subk); int static_res = C->static_subtype_check(superk, subk);
known_statically = (static_res == Compile::SSC_always_true || static_res == Compile::SSC_always_false); 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) { Node* *failure_control) {
kill_dead_locals(); // Benefit all the uncommon traps kill_dead_locals(); // Benefit all the uncommon traps
const TypeKlassPtr *tk = _gvn.type(superklass)->is_klassptr(); 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. // Fast cutout: Check the case that the cast is vacuously true.
// This detects the common cases where the test will short-circuit // 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].) // for example, in some objArray manipulations, such as a[i]=a[j].)
if (tk->singleton()) { if (tk->singleton()) {
const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr(); const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr();
if (objtp != NULL && objtp->klass() != NULL) { if (objtp != NULL) {
switch (C->static_subtype_check(tk->klass(), objtp->klass())) { switch (C->static_subtype_check(tk, objtp->as_klass_type())) {
case Compile::SSC_always_true: case Compile::SSC_always_true:
// If we know the type check always succeed then we don't use // 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 // 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); return null_assert(obj);
} }
break; // Fall through to full check 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. // a speculative type use it to perform an exact cast.
ciKlass* spec_obj_type = obj_type->speculative_type(); ciKlass* spec_obj_type = obj_type->speculative_type();
if (spec_obj_type != NULL || data != NULL) { 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 (cast_obj != NULL) {
if (failure_control != NULL) // failure is now impossible if (failure_control != NULL) // failure is now impossible
(*failure_control) = top(); (*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) { Node* GraphKit::get_layout_helper(Node* klass_node, jint& constant_value) {
const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr(); const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr();
if (!StressReflectiveCode && inst_klass != NULL) { if (!StressReflectiveCode && inst_klass != NULL) {
ciKlass* klass = inst_klass->klass();
bool xklass = inst_klass->klass_is_exact(); bool xklass = inst_klass->klass_is_exact();
if (xklass || klass->is_array_klass()) { if (xklass || inst_klass->isa_aryklassptr()) {
jint lhelper = klass->layout_helper(); 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) { if (lhelper != Klass::_lh_neutral_value) {
constant_value = lhelper; constant_value = lhelper;
return (Node*) NULL; return (Node*) NULL;
@ -3682,7 +3693,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
int elemidx = C->get_alias_index(telemref); int elemidx = C->get_alias_index(telemref);
hook_memory_on_init(*this, elemidx, minit_in, minit_out); hook_memory_on_init(*this, elemidx, minit_in, minit_out);
} else if (oop_type->isa_instptr()) { } 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++) { for (int i = 0, len = ik->nof_nonstatic_fields(); i < len; i++) {
ciField* field = ik->nonstatic_field_at(i); ciField* field = ik->nonstatic_field_at(i);
if (field->offset() >= TrackedInitializationLimit * HeapWordSize) 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(); const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
Node* valid_length_test = _gvn.intcon(1); Node* valid_length_test = _gvn.intcon(1);
if (ary_type->klass()->is_array_klass()) { if (ary_type->isa_aryptr()) {
BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type(); BasicType bt = ary_type->isa_aryptr()->elem()->array_element_basic_type();
jint max = TypeAryPtr::max_array_length(bt); jint max = TypeAryPtr::max_array_length(bt);
Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max))); Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max)));
valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le)); valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -177,7 +177,7 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oo
} else if (is_boxed_value_load) { } else if (is_boxed_value_load) {
Node* klass = alloc->in(AllocateNode::KlassNode); Node* klass = alloc->in(AllocateNode::KlassNode);
const TypeKlassPtr* tklass = phase->type(klass)->is_klassptr(); 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 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 // means an array I have not precisely typed yet. Do not do any
// alias stuff with it any time soon. // alias stuff with it any time soon.
const TypeOopPtr *toop = tp->isa_oopptr(); const TypeOopPtr *toop = tp->isa_oopptr();
if( tp->base() != Type::AnyPtr && if (tp->base() != Type::AnyPtr &&
!(toop && !(toop &&
toop->klass() != NULL && toop->isa_instptr() &&
toop->klass()->is_java_lang_Object() && toop->is_instptr()->instance_klass()->is_java_lang_Object() &&
toop->offset() == Type::OffsetBot) ) { toop->offset() == Type::OffsetBot)) {
// compress paths and change unreachable cycles to TOP // compress paths and change unreachable cycles to TOP
// If not, we can update the input infinitely along a MergeMem cycle // If not, we can update the input infinitely along a MergeMem cycle
// Equivalent code in PhiNode::Ideal // 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. // is known to be within bounds. This is checked below.
if (ary_t != NULL && ld_addp->is_AddP()) { if (ary_t != NULL && ld_addp->is_AddP()) {
Node* ld_offs = ld_addp->in(AddPNode::Offset); 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 header = arrayOopDesc::base_offset_in_bytes(ary_elem);
jlong elemsize = type2aelembytes(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); addp->set_req(AddPNode::Address, src);
const TypeAryPtr* ary_t = phase->type(in(MemNode::Address))->isa_aryptr(); 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 header = arrayOopDesc::base_offset_in_bytes(ary_elem);
uint shift = exact_log2(type2aelembytes(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) { } else if (tp->base() == Type::InstPtr) {
assert( off != Type::OffsetBot || assert( off != Type::OffsetBot ||
// arrays can be cast to Objects // 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 // unsafe field access may not have a constant offset
C->has_unsafe_access(), C->has_unsafe_access(),
"Field accesses must be precise" ); "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) { } else if (tp->base() == Type::KlassPtr || tp->base() == Type::InstKlassPtr || tp->base() == Type::AryKlassPtr) {
assert( off != Type::OffsetBot || assert(off != Type::OffsetBot ||
!tp->isa_instklassptr() ||
// arrays can be cast to Objects // arrays can be cast to Objects
tp->is_klassptr()->klass()->is_java_lang_Object() || tp->isa_instklassptr()->instance_klass()->is_java_lang_Object() ||
// also allow array-loading from the primary supertype // also allow array-loading from the primary supertype
// array during subtype checks // array during subtype checks
Opcode() == Op_LoadKlass, Opcode() == Op_LoadKlass,
"Field accesses must be precise" ); "Field accesses must be precise");
// For klass/static loads, we expect the _type to be precise // For klass/static loads, we expect the _type to be precise
} else if (tp->base() == Type::RawPtr && adr->is_Load() && off == 0) { } else if (tp->base() == Type::RawPtr && adr->is_Load() && off == 0) {
/* With mirrors being an indirect in the Klass* /* 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); Node* adr2 = adr->in(MemNode::Address);
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr(); const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
if (tkls != NULL && !StressReflectiveCode) { if (tkls != NULL && !StressReflectiveCode) {
ciKlass* klass = tkls->klass(); if (tkls->is_loaded() && tkls->klass_is_exact() && tkls->offset() == in_bytes(Klass::java_mirror_offset())) {
if (klass->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(adr->Opcode() == Op_LoadP, "must load an oop from _java_mirror");
assert(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()); return TypeInstPtr::make(klass->java_mirror());
@ -1987,8 +1991,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
const TypeKlassPtr *tkls = tp->isa_klassptr(); const TypeKlassPtr *tkls = tp->isa_klassptr();
if (tkls != NULL && !StressReflectiveCode) { if (tkls != NULL && !StressReflectiveCode) {
ciKlass* klass = tkls->klass(); if (tkls->is_loaded() && tkls->klass_is_exact()) {
if (klass->is_loaded() && tkls->klass_is_exact()) { ciKlass* klass = tkls->exact_klass();
// We are loading a field from a Klass metaobject whose identity // We are loading a field from a Klass metaobject whose identity
// is known at compile time (the type is "exact" or "precise"). // is known at compile time (the type is "exact" or "precise").
// Check for fields we know are maintained as constants by the VM. // 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 // 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 // shallow enough depth. Even though the klass is not exact, entries less
// than or equal to its super depth are correct. // than or equal to its super depth are correct.
if (klass->is_loaded() ) { if (tkls->is_loaded()) {
ciType *inner = klass; ciKlass* klass = NULL;
while( inner->is_obj_array_klass() ) if (tkls->isa_instklassptr()) {
inner = inner->as_obj_array_klass()->base_element_type(); klass = tkls->is_instklassptr()->instance_klass();
if( inner->is_instance_klass() && } else {
!inner->as_instance_klass()->flags().is_interface() ) { 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 // Compute index into primary_supers array
juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*); juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*);
// Check for overflowing; use unsigned compare to handle the negative case. // Check for overflowing; use unsigned compare to handle the negative case.
if( depth < ciKlass::primary_super_limit() && if (depth < ciKlass::primary_super_limit() &&
depth <= klass->super_depth() ) { // allow self-depth checks to handle self-check case 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. // The field is an element of Klass::_primary_supers. Return its (constant) value.
// (Folds up type checking code.) // (Folds up type checking code.)
assert(Opcode() == Op_LoadKlass, "must load a klass from _primary_supers"); 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, // If the type is enough to determine that the thing is not an array,
// we can give the layout_helper a positive interval type. // we can give the layout_helper a positive interval type.
// This will help short-circuit some reflective code. // This will help short-circuit some reflective code.
if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) &&
&& !klass->is_array_klass() // not directly typed as an array tkls->isa_instklassptr() && // not directly typed as an array
&& !klass->is_interface() // specifically not Serializable & Cloneable !tkls->is_instklassptr()->instance_klass()->is_java_lang_Object() // not the supertype of all T[] and specifically not Serializable & Cloneable
&& !klass->is_java_lang_Object() // not the supertype of all T[]
) { ) {
// Note: When interfaces are reliable, we can narrow the interface // Note: When interfaces are reliable, we can narrow the interface
// test to (klass != Serializable && klass != Cloneable). // 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 // Return a more precise klass, if possible
const TypeInstPtr *tinst = tp->isa_instptr(); const TypeInstPtr *tinst = tp->isa_instptr();
if (tinst != NULL) { if (tinst != NULL) {
ciInstanceKlass* ik = tinst->klass()->as_instance_klass(); ciInstanceKlass* ik = tinst->instance_klass();
int offset = tinst->offset(); int offset = tinst->offset();
if (ik == phase->C->env()->Class_klass() if (ik == phase->C->env()->Class_klass()
&& (offset == java_lang_Class::klass_offset() || && (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 // 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 return _type; // Bail out if not loaded
if (offset == oopDesc::klass_offset_in_bytes()) { if (offset == oopDesc::klass_offset_in_bytes()) {
if (tinst->klass_is_exact()) { return tinst->as_klass_type(true);
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*/);
} }
} }
// Check for loading klass from an array // Check for loading klass from an array
const TypeAryPtr *tary = tp->isa_aryptr(); const TypeAryPtr *tary = tp->isa_aryptr();
if( tary != NULL ) { if (tary != NULL && tary->elem() != Type::BOTTOM &&
ciKlass *tary_klass = tary->klass(); tary->offset() == oopDesc::klass_offset_in_bytes()) {
if (tary_klass != NULL // can be NULL when at BOTTOM or TOP return tary->as_klass_type(true);
&& 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
}
}
} }
// Check for loading klass from an array klass // Check for loading klass from an array klass
const TypeKlassPtr *tkls = tp->isa_klassptr(); const TypeKlassPtr *tkls = tp->isa_klassptr();
if (tkls != NULL && !StressReflectiveCode) { if (tkls != NULL && !StressReflectiveCode) {
ciKlass* klass = tkls->klass(); if (!tkls->is_loaded())
if( !klass->is_loaded() )
return _type; // Bail out if not loaded return _type; // Bail out if not loaded
if( klass->is_obj_array_klass() && if (tkls->isa_aryklassptr() && tkls->is_aryklassptr()->elem()->isa_klassptr() &&
tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) { tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) {
ciKlass* elem = klass->as_obj_array_klass()->element_klass();
// // Always returning precise element type is incorrect, // // Always returning precise element type is incorrect,
// // e.g., element type could be object and array may contain strings // // e.g., element type could be object and array may contain strings
// return TypeKlassPtr::make(TypePtr::Constant, elem, 0); // return TypeKlassPtr::make(TypePtr::Constant, elem, 0);
// The array's TypeKlassPtr was declared 'precise' or 'not precise' // The array's TypeKlassPtr was declared 'precise' or 'not precise'
// according to the element type's subclassing. // 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())) { 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. // The field is Klass::_super. Return its (constant) value.
// (Folds up the 2nd indirection in aClassConstant.getSuperClass().) // (Folds up the 2nd indirection in aClassConstant.getSuperClass().)
return sup ? TypeKlassPtr::make(sup) : TypePtr::NULL_PTR; 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 // mirrors may appear in debug info, but we could clean them out by
// introducing a new debug info operator for Klass.java_mirror). // 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()) { && offset == java_lang_Class::klass_offset()) {
if (base->is_Load()) { if (base->is_Load()) {
Node* base2 = base->in(MemNode::Address); Node* base2 = base->in(MemNode::Address);
@ -2442,8 +2406,7 @@ Node* LoadNode::klass_identity_common(PhaseGVN* phase) {
Node* adr2 = base2->in(MemNode::Address); Node* adr2 = base2->in(MemNode::Address);
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr(); const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
if (tkls != NULL && !tkls->empty() if (tkls != NULL && !tkls->empty()
&& (tkls->klass()->is_instance_klass() || && (tkls->isa_instklassptr() || tkls->isa_aryklassptr())
tkls->klass()->is_array_klass())
&& adr2->is_AddP() && adr2->is_AddP()
) { ) {
int mirror_field = in_bytes(Klass::java_mirror_offset()); 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"); assert(alloc != NULL, "must be present");
if (alloc != NULL && alloc->Opcode() == Op_Allocate) { if (alloc != NULL && alloc->Opcode() == Op_Allocate) {
Node* klass_node = alloc->in(AllocateNode::KlassNode); 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()) if (zeroes_done == k->layout_helper())
zeroes_done = size_limit; zeroes_done = size_limit;
} }

View file

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

View file

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

View file

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

View file

@ -124,9 +124,9 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) {
const Type* el = elemtype->make_ptr(); const Type* el = elemtype->make_ptr();
if (el && el->isa_instptr()) { if (el && el->isa_instptr()) {
const TypeInstPtr* toop = el->is_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". // 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); 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'"); if (C->log() != NULL) C->log()->elem("observe that='!need_range_check'");
} }
ciKlass * arytype_klass = arytype->klass(); if (!arytype->is_loaded()) {
if ((arytype_klass != NULL) && (!arytype_klass->is_loaded())) {
// Only fails for some -Xcomp runs // Only fails for some -Xcomp runs
// The class is unloaded. We have to run this bytecode in the interpreter. // The class is unloaded. We have to run this bytecode in the interpreter.
ciKlass* klass = arytype->unloaded_klass();
uncommon_trap(Deoptimization::Reason_unloaded, uncommon_trap(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret, Deoptimization::Action_reinterpret,
arytype->klass(), "!loaded array"); klass, "!loaded array");
return top(); return top();
} }

View file

@ -72,16 +72,17 @@ void Parse::do_checkcast() {
// _from_ is not loaded, and value is not null. If the value _is_ NULL, // _from_ is not loaded, and value is not null. If the value _is_ NULL,
// then the checkcast does nothing. // then the checkcast does nothing.
const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr(); 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 (C->log() != NULL) {
if (!will_link) { if (!will_link) {
C->log()->elem("assert_null reason='checkcast' klass='%d'", C->log()->elem("assert_null reason='checkcast' klass='%d'",
C->log()->identify(klass)); C->log()->identify(klass));
} }
if (tp && tp->klass() && !tp->klass()->is_loaded()) { if (tp && !tp->is_loaded()) {
// %%% Cannot happen? // %%% Cannot happen?
ciKlass* klass = tp->unloaded_klass();
C->log()->elem("assert_null reason='checkcast source' klass='%d'", C->log()->elem("assert_null reason='checkcast source' klass='%d'",
C->log()->identify(tp->klass())); C->log()->identify(klass));
} }
} }
null_assert(obj); null_assert(obj);
@ -194,7 +195,9 @@ void Parse::array_store_check() {
// (If no MDO at all, hope for the best, until a trap actually occurs.) // (If no MDO at all, hope for the best, until a trap actually occurs.)
// Make a constant out of the inexact array klass // Make a constant out of the inexact array klass
const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr(); const TypeKlassPtr *extak = tak->cast_to_exactness(true);
if (extak->exact_klass(true) != NULL) {
Node* con = makecon(extak); Node* con = makecon(extak);
Node* cmp = _gvn.transform(new CmpPNode( array_klass, con )); Node* cmp = _gvn.transform(new CmpPNode( array_klass, con ));
Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq )); Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq ));
@ -202,7 +205,7 @@ void Parse::array_store_check() {
{ BuildCutout unless(this, bol, PROB_MAX); { BuildCutout unless(this, bol, PROB_MAX);
uncommon_trap(Deoptimization::Reason_array_check, uncommon_trap(Deoptimization::Reason_array_check,
Deoptimization::Action_maybe_recompile, Deoptimization::Action_maybe_recompile,
tak->klass()); extak->exact_klass());
} }
if (stopped()) { // MUST uncommon-trap? if (stopped()) { // MUST uncommon-trap?
set_control(ctrl); // Then Don't Do It, just fall into the normal checking set_control(ctrl); // Then Don't Do It, just fall into the normal checking
@ -212,11 +215,12 @@ void Parse::array_store_check() {
CompileLog* log = C->log(); CompileLog* log = C->log();
if (log != NULL) { if (log != NULL) {
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'", log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
log->identify(tak->klass())); log->identify(extak->exact_klass()));
} }
array_klass = con; // Use cast value moving forward array_klass = con; // Use cast value moving forward
} }
} }
}
// Come here for polymorphic array klasses // Come here for polymorphic array klasses
@ -298,4 +302,3 @@ void Parse::dump_map_adr_mem() const {
} }
#endif #endif

View file

@ -970,11 +970,12 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
} }
// See if it is 2 unrelated classes. // See if it is 2 unrelated classes.
const TypeOopPtr* oop_p0 = r0->isa_oopptr(); const TypeOopPtr* p0 = r0->isa_oopptr();
const TypeOopPtr* oop_p1 = r1->isa_oopptr(); const TypeOopPtr* p1 = r1->isa_oopptr();
bool both_oop_ptr = oop_p0 && oop_p1; const TypeKlassPtr* k0 = r0->isa_klassptr();
const TypeKlassPtr* k1 = r1->isa_klassptr();
if (both_oop_ptr) { if ((p0 && p1) || (k0 && k1)) {
if (p0 && p1) {
Node* in1 = in(1)->uncast(); Node* in1 = in(1)->uncast();
Node* in2 = in(2)->uncast(); Node* in2 = in(2)->uncast();
AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL); AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL);
@ -983,56 +984,23 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
return TypeInt::CC_GT; // different pointers return TypeInt::CC_GT; // different pointers
} }
} }
bool xklass0 = p0 ? p0->klass_is_exact() : k0->klass_is_exact();
const TypeKlassPtr* klass_p0 = r0->isa_klassptr(); bool xklass1 = p1 ? p1->klass_is_exact() : k1->klass_is_exact();
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; 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 if ((p0 && p0->is_same_java_type_as(p1)) ||
// to fail if at least one of the pointers is provably not null. (k0 && k0->is_same_java_type_as(k1))) {
if (klass0->equals(klass1)) { // if types are unequal but klasses are equal } else if ((p0 && !p1->maybe_java_subtype_of(p0) && !p0->maybe_java_subtype_of(p1)) ||
// Do nothing; we know nothing for imprecise types (k0 && !k1->maybe_java_subtype_of(k0) && !k0->maybe_java_subtype_of(k1))) {
} 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; 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) { if (unrelated_classes) {
// The oops classes are known to be unrelated. If the joined PTRs of // 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 // two oops is not Null and not Bottom, then we are sure that one
@ -1043,7 +1011,6 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
} }
} }
} }
}
// Known constants can be compared exactly // Known constants can be compared exactly
// Null can be distinguished from any NotNull pointers // Null can be distinguished from any NotNull pointers
@ -1070,7 +1037,7 @@ static inline Node* isa_java_mirror_load(PhaseGVN* phase, Node* n) {
if (n->Opcode() != Op_LoadP) return NULL; if (n->Opcode() != Op_LoadP) return NULL;
const TypeInstPtr* tp = phase->type(n)->isa_instptr(); 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); Node* adr = n->in(MemNode::Address);
// First load from OopHandle: ((OopHandle)mirror)->resolve(); may need barrier. // 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()) if (t2 == NULL || !t2->klass_is_exact())
return NULL; return NULL;
// Get the constant klass we are comparing to. // Get the constant klass we are comparing to.
ciKlass* superklass = t2->klass(); ciKlass* superklass = t2->exact_klass();
// Now check for LoadKlass on left. // Now check for LoadKlass on left.
Node* ldk1 = in(1); Node* ldk1 = in(1);

View file

@ -33,58 +33,19 @@
#include "opto/subtypenode.hpp" #include "opto/subtypenode.hpp"
const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const { const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const {
ciKlass* superk = super_t->is_klassptr()->klass(); const TypeKlassPtr* superk = super_t->isa_klassptr();
ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass(); const TypeKlassPtr* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr() : sub_t->is_oopptr()->as_klass_type();
bool xsubk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass_is_exact() : sub_t->is_oopptr()->klass_is_exact();
// Oop can't be a subtype of abstract type that has no subclass. // Oop can't be a subtype of abstract type that has no subclass.
if (sub_t->isa_oopptr() && superk->is_instance_klass() && if (sub_t->isa_oopptr() && superk->isa_instklassptr() && superk->klass_is_exact()) {
!superk->is_interface() && superk->is_abstract() && ciKlass* superklass = superk->exact_klass();
!superk->as_instance_klass()->has_subklass()) { if (!superklass->is_interface() && superklass->is_abstract() &&
Compile::current()->dependencies()->assert_leaf_type(superk); !superklass->as_instance_klass()->has_subklass()) {
return TypeInt::CC_GT; Compile::current()->dependencies()->assert_leaf_type(superklass);
}
// 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; return TypeInt::CC_GT;
} }
} }
}
if (super_t->singleton()) {
if (subk != NULL) { if (subk != NULL) {
switch (Compile::current()->static_subtype_check(superk, subk)) { switch (Compile::current()->static_subtype_check(superk, subk)) {
case Compile::SSC_always_false: case Compile::SSC_always_false:
@ -98,7 +59,6 @@ const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const
ShouldNotReachHere(); ShouldNotReachHere();
} }
} }
}
return bottom_type(); return bottom_type();
} }
@ -203,8 +163,8 @@ bool SubTypeCheckNode::verify(PhaseGVN* phase) {
const Type* sub_t = phase->type(obj_or_subklass); const Type* sub_t = phase->type(obj_or_subklass);
const Type* super_t = phase->type(superklass); 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[] const TypeKlassPtr* superk = super_t->isa_klassptr();
ciKlass* superk = super_t->is_klassptr()->klass(); const TypeKlassPtr* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr() : sub_t->is_oopptr()->as_klass_type();
if (super_t->singleton() && subk != NULL) { if (super_t->singleton() && subk != NULL) {
Node* subklass = NULL; Node* subklass = NULL;

View file

@ -791,8 +791,8 @@ bool Type::interface_vs_oop_helper(const Type *t) const {
const TypeInstPtr* this_inst = this_ptr->isa_instptr(); const TypeInstPtr* this_inst = this_ptr->isa_instptr();
const TypeInstPtr* t_inst = t_ptr->isa_instptr(); const TypeInstPtr* t_inst = t_ptr->isa_instptr();
if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) { if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
bool this_interface = this_inst->klass()->is_interface(); bool this_interface = this_inst->is_interface();
bool t_interface = t_inst->klass()->is_interface(); bool t_interface = t_inst->is_interface();
result = this_interface ^ t_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 * 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); 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------------------------------- //------------------------------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"); assert(_base == AnyPtr, "subclass must override cast_to_ptr_type");
if( ptr == _ptr ) return this; if( ptr == _ptr ) return this;
return make(_base, ptr, _offset, _speculative, _inline_depth); 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); 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--------------------------------------------- //------------------------------eq---------------------------------------------
// Structural equality check for Type representations // Structural equality check for Type representations
bool TypePtr::eq( const Type *t ) const { bool TypePtr::eq( const Type *t ) const {
@ -2704,7 +2708,7 @@ int TypePtr::hash(void) const {
/** /**
* Return same type without a speculative part * Return same type without a speculative part
*/ */
const Type* TypePtr::remove_speculative() const { const TypePtr* TypePtr::remove_speculative() const {
if (_speculative == NULL) { if (_speculative == NULL) {
return this; return this;
} }
@ -2839,6 +2843,13 @@ const TypePtr* TypePtr::add_offset_speculative(intptr_t offset) const {
return _speculative->add_offset(offset)->is_ptr(); 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 * return exact klass from the speculative type if there's one
*/ */
@ -3094,7 +3105,7 @@ const Type *TypeRawPtr::xdual() const {
} }
//------------------------------add_offset------------------------------------- //------------------------------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 == OffsetTop ) return BOTTOM; // Undefined offset-> undefined pointer
if( offset == OffsetBot ) return BOTTOM; // Unknown offset-> unknown pointer if( offset == OffsetBot ) return BOTTOM; // Unknown offset-> unknown pointer
if( offset == 0 ) return this; // No change 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------------------------------- //-----------------------------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. // There is no such thing as an exact general oop.
// Return self unchanged. // Return self unchanged.
return this; 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); 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 * Return same type without a speculative part
*/ */
const Type* TypeOopPtr::remove_speculative() const { const TypeOopPtr* TypeOopPtr::remove_speculative() const {
if (_speculative == NULL) { if (_speculative == NULL) {
return this; return this;
} }
@ -3653,11 +3668,14 @@ const TypeInstPtr *TypeInstPtr::MIRROR;
const TypeInstPtr *TypeInstPtr::MARK; const TypeInstPtr *TypeInstPtr::MARK;
const TypeInstPtr *TypeInstPtr::KLASS; const TypeInstPtr *TypeInstPtr::KLASS;
ciKlass* TypeInstPtr::exact_klass_helper() const {
return _klass;
}
//------------------------------TypeInstPtr------------------------------------- //------------------------------TypeInstPtr-------------------------------------
TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off,
int instance_id, const TypePtr* speculative, int inline_depth) int instance_id, const TypePtr* speculative, int inline_depth)
: TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth) {
_name(k->name()) {
assert(k != NULL && assert(k != NULL &&
(k->is_loaded() || o == NULL), (k->is_loaded() || o == NULL),
"cannot have constants with non-loaded klass"); "cannot have constants with non-loaded klass");
@ -3720,16 +3738,16 @@ const Type* TypeInstPtr::get_const_boxed_value() const {
} }
//------------------------------cast_to_ptr_type------------------------------- //------------------------------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; if( ptr == _ptr ) return this;
// Reconstruct _sig info here since not a problem with later lazy // Reconstruct _sig info here since not a problem with later lazy
// construction, _sig will show up on demand. // 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------------------------------- //-----------------------------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_exact == _klass_is_exact ) return this;
if (!_klass->is_loaded()) return this; if (!_klass->is_loaded()) return this;
ciInstanceKlass* ik = _klass->as_instance_klass(); 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---------------------------- //-----------------------------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; if( instance_id == _instance_id ) return this;
return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth); 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; 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------------------------------------------ //------------------------------dump2------------------------------------------
// Dump oop Type // Dump oop Type
#ifndef PRODUCT #ifndef PRODUCT
@ -4191,12 +4273,17 @@ void TypeInstPtr::dump2(Dict &d, uint depth, outputStream* st) const {
#endif #endif
//------------------------------add_offset------------------------------------- //------------------------------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), return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset),
_instance_id, add_offset_speculative(offset), _inline_depth); _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) { if (_speculative == NULL) {
return this; return this;
} }
@ -4267,19 +4354,19 @@ const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciK
//------------------------------cast_to_ptr_type------------------------------- //------------------------------cast_to_ptr_type-------------------------------
const TypeAryPtr* TypeAryPtr::cast_to_ptr_type(PTR ptr) const { const TypeAryPtr* TypeAryPtr::cast_to_ptr_type(PTR ptr) const {
if( ptr == _ptr ) return this; 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------------------------------- //-----------------------------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( klass_is_exact == _klass_is_exact ) return this;
if (_ary->ary_must_be_exact()) return this; // cannot clear xk 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); return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth);
} }
//-----------------------------cast_to_instance_id---------------------------- //-----------------------------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; if( instance_id == _instance_id ) return this;
return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); 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(); 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------------------------------------------- //------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object. // Compute the MEET of two types. It returns a new Type object.
const Type *TypeAryPtr::xmeet_helper(const Type *t) const { 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); 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) { if (_speculative == NULL) {
return this; return this;
} }
@ -4856,7 +5018,7 @@ const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) {
return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons(); 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()); 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) { : TypePtr(t, ptr, offset), _klass(klass) {
} }
ciKlass* TypeKlassPtr::exact_klass_helper() const {
return _klass;
}
//------------------------------eq--------------------------------------------- //------------------------------eq---------------------------------------------
// Structural equality check for Type representations // Structural equality check for Type representations
bool TypeKlassPtr::eq(const Type *t) const { bool TypeKlassPtr::eq(const Type *t) const {
@ -5178,7 +5344,9 @@ intptr_t TypeKlassPtr::get_con() const {
ShouldNotReachHere(); ShouldNotReachHere();
} }
return (intptr_t)klass()->constant_encoding(); ciKlass* k = exact_klass();
return (intptr_t)k->constant_encoding();
} }
//------------------------------dump2------------------------------------------ //------------------------------dump2------------------------------------------
@ -5249,12 +5417,12 @@ const TypePtr *TypeInstKlassPtr::add_offset( intptr_t offset ) const {
return make( _ptr, klass(), xadd_offset(offset) ); 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); return make(_ptr, klass(), offset);
} }
//------------------------------cast_to_ptr_type------------------------------- //------------------------------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"); assert(_base == InstKlassPtr, "subclass must override cast_to_ptr_type");
if( ptr == _ptr ) return this; if( ptr == _ptr ) return this;
return make(ptr, _klass, _offset); return make(ptr, _klass, _offset);
@ -5280,9 +5448,28 @@ const TypeKlassPtr* TypeInstKlassPtr::cast_to_exactness(bool klass_is_exact) con
//-----------------------------as_instance_type-------------------------------- //-----------------------------as_instance_type--------------------------------
// Corresponding type for an instance of the given class. // Corresponding type for an instance of the given class.
// It will be NotNull, and exact if and only if the klass type is exact. // 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(); 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); 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()); 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) { const TypeAryKlassPtr *TypeAryKlassPtr::make(PTR ptr, const Type* elem, ciKlass* k, int offset) {
return (TypeAryKlassPtr*)(new TypeAryKlassPtr(ptr, elem, k, offset))->hashcons(); 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::OOPS->klass() are not common enough to matter.
((TypeAryPtr*)this)->_klass = k_ary; ((TypeAryPtr*)this)->_klass = k_ary;
if (UseCompressedOops && k_ary != NULL && k_ary->is_obj_array_klass() && 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; ((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true;
} }
} }
return k_ary; 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------------------------------------- //------------------------------add_offset-------------------------------------
// Access internals of klass object // 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)); 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); return make(_ptr, elem(), klass(), offset);
} }
//------------------------------cast_to_ptr_type------------------------------- //------------------------------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"); assert(_base == AryKlassPtr, "subclass must override cast_to_ptr_type");
if (ptr == _ptr) return this; if (ptr == _ptr) return this;
return make(ptr, elem(), _klass, _offset); return make(ptr, elem(), _klass, _offset);
@ -5601,11 +5874,17 @@ const TypeKlassPtr *TypeAryKlassPtr::cast_to_exactness(bool klass_is_exact) cons
//-----------------------------as_instance_type-------------------------------- //-----------------------------as_instance_type--------------------------------
// Corresponding type for an instance of the given class. // Corresponding type for an instance of the given class.
// It will be exact if and only if the klass type is exact. // It will be NotNull, and exact if and only if the klass type is exact.
const TypeOopPtr* TypeAryKlassPtr::as_instance_type() const { const TypeOopPtr* TypeAryKlassPtr::as_instance_type(bool klass_change) const {
ciKlass* k = klass(); ciKlass* k = klass();
bool xk = klass_is_exact(); 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); 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 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------------------------------------------ //------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual // Dual: compute field-by-field dual
const Type *TypeAryKlassPtr::xdual() const { const Type *TypeAryKlassPtr::xdual() const {
@ -5744,6 +6089,19 @@ const Type *TypeAryKlassPtr::xdual() const {
} }
//------------------------------get_con---------------------------------------- //------------------------------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 { ciKlass* TypeAryKlassPtr::klass() const {
if (_klass != NULL) { if (_klass != NULL) {
return _klass; return _klass;

View file

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

View file

@ -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(); int n_fields = iklass->nof_nonstatic_fields();
assert(n_fields == 1, "sanity"); assert(n_fields == 1, "sanity");
@ -348,7 +348,7 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc,
GraphKit kit(jvms); GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn(); 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(); BasicType bt = vect_type->element_basic_type();
int num_elem = vect_type->length(); int num_elem = vect_type->length();
@ -420,7 +420,7 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
Node* obj = vec_unbox->obj(); Node* obj = vec_unbox->obj();
const TypeInstPtr* tinst = gvn.type(obj)->isa_instptr(); 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(); const TypeVect* vt = vec_unbox->bottom_type()->is_vect();
BasicType bt = vt->element_basic_type(); BasicType bt = vt->element_basic_type();
BasicType masktype = bt; BasicType masktype = bt;

View file

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

View file

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

View file

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