8275201: C2: hide klass() accessor from TypeOopPtr and typeKlassPtr subclasses
Reviewed-by: vlivanov, iveresov
This commit is contained in:
parent
6586e5ae37
commit
aa7ccdf445
src/hotspot/share
ci
gc
g1/c2
shared/c2
shenandoah/c2
opto
arraycopynode.cppcallnode.cppcfgnode.cppcompile.cppcompile.hppdoCall.cppescape.cppgraphKit.cppgraphKit.hppidealGraphPrinter.cpplibrary_call.cppmacro.cppmacroArrayCopy.cppmemnode.cppnode.cppoutput.cppparse1.cppparse2.cppparseHelper.cppsubnode.cppsubtypenode.cpptype.cpptype.hppvector.cppvectorIntrinsics.cppvectornode.cpp
utilities
@ -167,6 +167,14 @@ ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass) {
|
||||
GUARDED_VM_ENTRY(return make_impl(element_klass);)
|
||||
}
|
||||
|
||||
ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass, int dims) {
|
||||
ciKlass* klass = element_klass;
|
||||
for (int i = 0; i < dims; i++) {
|
||||
klass = ciObjArrayKlass::make(klass);
|
||||
}
|
||||
return klass->as_obj_array_klass();
|
||||
}
|
||||
|
||||
ciKlass* ciObjArrayKlass::exact_klass() {
|
||||
ciType* base = base_element_type();
|
||||
if (base->is_instance_klass()) {
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
bool is_obj_array_klass() const { return true; }
|
||||
|
||||
static ciObjArrayKlass* make(ciKlass* element_klass);
|
||||
static ciObjArrayKlass* make(ciKlass* element_klass, int dims);
|
||||
|
||||
virtual ciKlass* exact_klass();
|
||||
};
|
||||
|
@ -528,8 +528,8 @@ void G1BarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, Node* off
|
||||
if (itype != NULL) {
|
||||
// Can the klass of base_oop be statically determined to be
|
||||
// _not_ a sub-class of Reference and _not_ Object?
|
||||
ciKlass* klass = itype->klass();
|
||||
if ( klass->is_loaded() &&
|
||||
ciKlass* klass = itype->instance_klass();
|
||||
if (klass->is_loaded() &&
|
||||
!klass->is_subtype_of(kit->env()->Reference_klass()) &&
|
||||
!kit->env()->Object_klass()->is_subtype_of(klass)) {
|
||||
return;
|
||||
|
@ -372,7 +372,7 @@ void C2Access::fixup_decorators() {
|
||||
intptr_t offset = Type::OffsetBot;
|
||||
AddPNode::Ideal_base_and_offset(adr, &gvn(), offset);
|
||||
if (offset >= 0) {
|
||||
int s = Klass::layout_helper_size_in_bytes(adr_type->isa_instptr()->klass()->layout_helper());
|
||||
int s = Klass::layout_helper_size_in_bytes(adr_type->isa_instptr()->instance_klass()->layout_helper());
|
||||
if (offset < s) {
|
||||
// Guaranteed to be a valid access, no need to pin it
|
||||
_decorators ^= C2_CONTROL_DEPENDENT_LOAD;
|
||||
|
@ -389,8 +389,8 @@ void ShenandoahBarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, N
|
||||
if (itype != NULL) {
|
||||
// Can the klass of base_oop be statically determined to be
|
||||
// _not_ a sub-class of Reference and _not_ Object?
|
||||
ciKlass* klass = itype->klass();
|
||||
if ( klass->is_loaded() &&
|
||||
ciKlass* klass = itype->instance_klass();
|
||||
if (klass->is_loaded() &&
|
||||
!klass->is_subtype_of(kit->env()->Reference_klass()) &&
|
||||
!kit->env()->Object_klass()->is_subtype_of(klass)) {
|
||||
return;
|
||||
@ -783,8 +783,8 @@ bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_couple
|
||||
bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
|
||||
const TypeOopPtr* src_type = gvn.type(src)->is_oopptr();
|
||||
if (src_type->isa_instptr() != NULL) {
|
||||
ciInstanceKlass* ik = src_type->klass()->as_instance_klass();
|
||||
if ((src_type->klass_is_exact() || (!ik->is_interface() && !ik->has_subklass())) && !ik->has_injected_fields()) {
|
||||
ciInstanceKlass* ik = src_type->is_instptr()->instance_klass();
|
||||
if ((src_type->klass_is_exact() || !ik->has_subklass()) && !ik->has_injected_fields()) {
|
||||
if (ik->has_object_fields()) {
|
||||
return true;
|
||||
} else {
|
||||
@ -796,8 +796,8 @@ bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
|
||||
return true;
|
||||
}
|
||||
} else if (src_type->isa_aryptr()) {
|
||||
BasicType src_elem = src_type->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (is_reference_type(src_elem)) {
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(src_elem, true)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -298,7 +298,7 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) {
|
||||
if (adr_type->isa_oopptr() && adr_type->is_oopptr()->offset() == oopDesc::mark_offset_in_bytes()) {
|
||||
if (trace) {tty->print_cr("Mark load");}
|
||||
} else if (adr_type->isa_instptr() &&
|
||||
adr_type->is_instptr()->klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&
|
||||
adr_type->is_instptr()->instance_klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&
|
||||
adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset()) {
|
||||
if (trace) {tty->print_cr("Reference.get()");}
|
||||
} else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
|
||||
|
@ -120,7 +120,7 @@ int ArrayCopyNode::get_count(PhaseGVN *phase) const {
|
||||
if (is_clonebasic()) {
|
||||
if (src_type->isa_instptr()) {
|
||||
const TypeInstPtr* inst_src = src_type->is_instptr();
|
||||
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = inst_src->instance_klass();
|
||||
// ciInstanceKlass::nof_nonstatic_fields() doesn't take injected
|
||||
// fields into account. They are rare anyway so easier to simply
|
||||
// skip instances with injected fields.
|
||||
@ -193,8 +193,10 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c
|
||||
phase->is_IterGVN()->_worklist.push(mem);
|
||||
}
|
||||
|
||||
|
||||
ciInstanceKlass* ik = inst_src->instance_klass();
|
||||
|
||||
if (!inst_src->klass_is_exact()) {
|
||||
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
|
||||
assert(!ik->is_interface(), "inconsistent klass hierarchy");
|
||||
if (ik->has_subklass()) {
|
||||
// Concurrent class loading.
|
||||
@ -205,7 +207,6 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c
|
||||
}
|
||||
}
|
||||
|
||||
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
|
||||
assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields");
|
||||
|
||||
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||
@ -263,17 +264,16 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
|
||||
|
||||
// newly allocated object is guaranteed to not overlap with source object
|
||||
disjoint_bases = is_alloc_tightly_coupled();
|
||||
|
||||
if (ary_src == NULL || ary_src->klass() == NULL ||
|
||||
ary_dest == NULL || ary_dest->klass() == NULL) {
|
||||
if (ary_src == NULL || ary_src->elem() == Type::BOTTOM ||
|
||||
ary_dest == NULL || ary_dest->elem() == Type::BOTTOM) {
|
||||
// We don't know if arguments are arrays
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType src_elem = ary_src->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType dest_elem = ary_dest->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (is_reference_type(src_elem)) src_elem = T_OBJECT;
|
||||
if (is_reference_type(dest_elem)) dest_elem = T_OBJECT;
|
||||
BasicType src_elem = ary_src->elem()->array_element_basic_type();
|
||||
BasicType dest_elem = ary_dest->elem()->array_element_basic_type();
|
||||
if (is_reference_type(src_elem, true)) src_elem = T_OBJECT;
|
||||
if (is_reference_type(dest_elem, true)) dest_elem = T_OBJECT;
|
||||
|
||||
if (src_elem != dest_elem || dest_elem == T_VOID) {
|
||||
// We don't know if arguments are arrays of the same type
|
||||
@ -323,8 +323,8 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
|
||||
|
||||
disjoint_bases = true;
|
||||
|
||||
BasicType elem = ary_src->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (is_reference_type(elem)) {
|
||||
BasicType elem = ary_src->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(elem, true)) {
|
||||
elem = T_OBJECT;
|
||||
}
|
||||
|
||||
@ -734,7 +734,9 @@ bool ArrayCopyNode::modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransf
|
||||
return !must_modify;
|
||||
}
|
||||
|
||||
BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType ary_elem = ary_t->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(ary_elem, true)) ary_elem = T_OBJECT;
|
||||
|
||||
uint header = arrayOopDesc::base_offset_in_bytes(ary_elem);
|
||||
uint elemsize = type2aelembytes(ary_elem);
|
||||
|
||||
|
@ -380,7 +380,7 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c
|
||||
case Type::KlassPtr:
|
||||
case Type::AryKlassPtr:
|
||||
case Type::InstKlassPtr:
|
||||
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_klassptr()->klass()));
|
||||
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_klassptr()->exact_klass()));
|
||||
break;
|
||||
case Type::MetadataPtr:
|
||||
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->make_ptr()->isa_metadataptr()->metadata()));
|
||||
@ -471,7 +471,7 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st)
|
||||
st->cr();
|
||||
st->print(" # ScObj" INT32_FORMAT " ", i);
|
||||
SafePointScalarObjectNode* spobj = scobjs.at(i);
|
||||
ciKlass* cik = spobj->bottom_type()->is_oopptr()->klass();
|
||||
ciKlass* cik = spobj->bottom_type()->is_oopptr()->exact_klass();
|
||||
assert(cik->is_instance_klass() ||
|
||||
cik->is_array_klass(), "Not supported allocation.");
|
||||
ciInstanceKlass *iklass = NULL;
|
||||
@ -807,11 +807,11 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
return false;
|
||||
}
|
||||
if (t_oop->is_ptr_to_boxed_value()) {
|
||||
ciKlass* boxing_klass = t_oop->klass();
|
||||
ciKlass* boxing_klass = t_oop->is_instptr()->instance_klass();
|
||||
if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) {
|
||||
// Skip unrelated boxing methods.
|
||||
Node* proj = proj_out_or_null(TypeFunc::Parms);
|
||||
if ((proj == NULL) || (phase->type(proj)->is_instptr()->klass() != boxing_klass)) {
|
||||
if ((proj == NULL) || (phase->type(proj)->is_instptr()->instance_klass() != boxing_klass)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -826,7 +826,7 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
if (proj != NULL) {
|
||||
const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr();
|
||||
if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
|
||||
(inst_t->klass() == boxing_klass))) {
|
||||
(inst_t->instance_klass() == boxing_klass))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -834,7 +834,7 @@ bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
|
||||
const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr();
|
||||
if ((inst_t != NULL) && (!inst_t->klass_is_exact() ||
|
||||
(inst_t->klass() == boxing_klass))) {
|
||||
(inst_t->instance_klass() == boxing_klass))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2309,7 +2309,7 @@ bool CallNode::may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeO
|
||||
return dest_t->instance_id() == t_oop->instance_id();
|
||||
}
|
||||
|
||||
if (dest_t->isa_instptr() && !dest_t->klass()->equals(phase->C->env()->Object_klass())) {
|
||||
if (dest_t->isa_instptr() && !dest_t->is_instptr()->instance_klass()->equals(phase->C->env()->Object_klass())) {
|
||||
// clone
|
||||
if (t_oop->isa_aryptr()) {
|
||||
return false;
|
||||
@ -2317,7 +2317,7 @@ bool CallNode::may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeO
|
||||
if (!t_oop->isa_instptr()) {
|
||||
return true;
|
||||
}
|
||||
if (dest_t->klass()->is_subtype_of(t_oop->klass()) || t_oop->klass()->is_subtype_of(dest_t->klass())) {
|
||||
if (dest_t->maybe_java_subtype_of(t_oop) || t_oop->maybe_java_subtype_of(dest_t)) {
|
||||
return true;
|
||||
}
|
||||
// unrelated
|
||||
|
@ -1177,16 +1177,14 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
|
||||
// convert the one to the other.
|
||||
const TypePtr* ttp = _type->make_ptr();
|
||||
const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL;
|
||||
const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_instklassptr() : NULL;
|
||||
const TypeInstKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_instklassptr() : NULL;
|
||||
bool is_intf = false;
|
||||
if (ttip != NULL) {
|
||||
ciKlass* k = ttip->klass();
|
||||
if (k->is_loaded() && k->is_interface())
|
||||
if (ttip->is_interface())
|
||||
is_intf = true;
|
||||
}
|
||||
if (ttkp != NULL) {
|
||||
ciKlass* k = ttkp->klass();
|
||||
if (k->is_loaded() && k->is_interface())
|
||||
if (ttkp->is_interface())
|
||||
is_intf = true;
|
||||
}
|
||||
|
||||
@ -1205,8 +1203,7 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
|
||||
const TypeInstPtr* tiip = (tip != NULL) ? tip->isa_instptr() : NULL;
|
||||
if (tiip) {
|
||||
bool ti_is_intf = false;
|
||||
ciKlass* k = tiip->klass();
|
||||
if (k->is_loaded() && k->is_interface())
|
||||
if (tiip->is_interface())
|
||||
ti_is_intf = true;
|
||||
if (is_intf != ti_is_intf)
|
||||
{ t = _type; break; }
|
||||
@ -1244,14 +1241,14 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
|
||||
// be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows
|
||||
// into a Phi which "knows" it's an Interface type we'll have to
|
||||
// uplift the type.
|
||||
if (!t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface()) {
|
||||
if (!t->empty() && ttip && ttip->is_interface()) {
|
||||
assert(ft == _type, ""); // Uplift to interface
|
||||
} else if (!t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
|
||||
} else if (!t->empty() && ttkp && ttkp->is_interface()) {
|
||||
assert(ft == _type, ""); // Uplift to interface
|
||||
} else {
|
||||
// We also have to handle 'evil cases' of interface- vs. class-arrays
|
||||
Type::get_arrays_base_elements(jt, _type, NULL, &ttip);
|
||||
if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
|
||||
if (!t->empty() && ttip != NULL && ttip->is_interface()) {
|
||||
assert(ft == _type, ""); // Uplift to array of interface
|
||||
} else {
|
||||
// Otherwise it's something stupid like non-overlapping int ranges
|
||||
@ -1270,19 +1267,19 @@ const Type* PhiNode::Value(PhaseGVN* phase) const {
|
||||
// because the type system doesn't interact well with interfaces.
|
||||
const TypePtr *jtp = jt->make_ptr();
|
||||
const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL;
|
||||
const TypeKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_instklassptr() : NULL;
|
||||
if( jtip && ttip ) {
|
||||
if( jtip->is_loaded() && jtip->klass()->is_interface() &&
|
||||
ttip->is_loaded() && !ttip->klass()->is_interface() ) {
|
||||
const TypeInstKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_instklassptr() : NULL;
|
||||
if (jtip && ttip) {
|
||||
if (jtip->is_interface() &&
|
||||
!ttip->is_interface()) {
|
||||
assert(ft == ttip->cast_to_ptr_type(jtip->ptr()) ||
|
||||
ft->isa_narrowoop() && ft->make_ptr() == ttip->cast_to_ptr_type(jtip->ptr()), "");
|
||||
jt = ft;
|
||||
}
|
||||
}
|
||||
if( jtkp && ttkp ) {
|
||||
if( jtkp->is_loaded() && jtkp->klass()->is_interface() &&
|
||||
if (jtkp && ttkp) {
|
||||
if (jtkp->is_interface() &&
|
||||
!jtkp->klass_is_exact() && // Keep exact interface klass (6894807)
|
||||
ttkp->is_loaded() && !ttkp->klass()->is_interface() ) {
|
||||
ttkp->is_loaded() && !ttkp->is_interface()) {
|
||||
assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) ||
|
||||
ft->isa_narrowklass() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), "");
|
||||
jt = ft;
|
||||
|
@ -1303,7 +1303,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
}
|
||||
|
||||
// Array pointers need some flattening
|
||||
const TypeAryPtr *ta = tj->isa_aryptr();
|
||||
const TypeAryPtr* ta = tj->isa_aryptr();
|
||||
if (ta && ta->is_stable()) {
|
||||
// Erase stability property for alias analysis.
|
||||
tj = ta = ta->cast_to_stable(false);
|
||||
@ -1312,7 +1312,10 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
if ( offset != Type::OffsetBot &&
|
||||
offset > arrayOopDesc::length_offset_in_bytes() ) {
|
||||
offset = Type::OffsetBot; // Flatten constant access into array body only
|
||||
tj = ta = TypeAryPtr::make(ptr, ta->ary(), ta->klass(), true, offset, ta->instance_id());
|
||||
tj = ta = ta->
|
||||
remove_speculative()->
|
||||
cast_to_ptr_type(ptr)->
|
||||
with_offset(offset);
|
||||
}
|
||||
} else if( ta && _AliasLevel >= 2 ) {
|
||||
// For arrays indexed by constant indices, we flatten the alias
|
||||
@ -1321,7 +1324,11 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
if( offset != Type::OffsetBot ) {
|
||||
if( ta->const_oop() ) { // MethodData* or Method*
|
||||
offset = Type::OffsetBot; // Flatten constant access into array body
|
||||
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,offset);
|
||||
tj = ta = ta->
|
||||
remove_speculative()->
|
||||
cast_to_ptr_type(ptr)->
|
||||
cast_to_exactness(false)->
|
||||
with_offset(offset);
|
||||
} else if( offset == arrayOopDesc::length_offset_in_bytes() ) {
|
||||
// range is OK as-is.
|
||||
tj = ta = TypeAryPtr::RANGE;
|
||||
@ -1335,13 +1342,21 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
ptr = TypePtr::BotPTR;
|
||||
} else { // Random constant offset into array body
|
||||
offset = Type::OffsetBot; // Flatten constant access into array body
|
||||
tj = ta = TypeAryPtr::make(ptr,ta->ary(),ta->klass(),false,offset);
|
||||
tj = ta = ta->
|
||||
remove_speculative()->
|
||||
cast_to_ptr_type(ptr)->
|
||||
cast_to_exactness(false)->
|
||||
with_offset(offset);
|
||||
}
|
||||
}
|
||||
// Arrays of fixed size alias with arrays of unknown size.
|
||||
if (ta->size() != TypeInt::POS) {
|
||||
const TypeAry *tary = TypeAry::make(ta->elem(), TypeInt::POS);
|
||||
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset);
|
||||
tj = ta = ta->
|
||||
remove_speculative()->
|
||||
cast_to_ptr_type(ptr)->
|
||||
with_ary(tary)->
|
||||
cast_to_exactness(false);
|
||||
}
|
||||
// Arrays of known objects become arrays of unknown objects.
|
||||
if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) {
|
||||
@ -1363,21 +1378,29 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
// Make sure the Bottom and NotNull variants alias the same.
|
||||
// Also, make sure exact and non-exact variants alias the same.
|
||||
if (ptr == TypePtr::NotNull || ta->klass_is_exact() || ta->speculative() != NULL) {
|
||||
tj = ta = TypeAryPtr::make(TypePtr::BotPTR,ta->ary(),ta->klass(),false,offset);
|
||||
tj = ta = ta->
|
||||
remove_speculative()->
|
||||
cast_to_ptr_type(TypePtr::BotPTR)->
|
||||
cast_to_exactness(false)->
|
||||
with_offset(offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Oop pointers need some flattening
|
||||
const TypeInstPtr *to = tj->isa_instptr();
|
||||
if( to && _AliasLevel >= 2 && to != TypeOopPtr::BOTTOM ) {
|
||||
ciInstanceKlass *k = to->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = to->instance_klass();
|
||||
if( ptr == TypePtr::Constant ) {
|
||||
if (to->klass() != ciEnv::current()->Class_klass() ||
|
||||
offset < k->layout_helper_size_in_bytes()) {
|
||||
if (ik != ciEnv::current()->Class_klass() ||
|
||||
offset < ik->layout_helper_size_in_bytes()) {
|
||||
// No constant oop pointers (such as Strings); they alias with
|
||||
// unknown strings.
|
||||
assert(!is_known_inst, "not scalarizable allocation");
|
||||
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
|
||||
tj = to = to->
|
||||
cast_to_instance_id(TypeOopPtr::InstanceBot)->
|
||||
remove_speculative()->
|
||||
cast_to_ptr_type(TypePtr::BotPTR)->
|
||||
cast_to_exactness(false);
|
||||
}
|
||||
} else if( is_known_inst ) {
|
||||
tj = to; // Keep NotNull and klass_is_exact for instance type
|
||||
@ -1385,10 +1408,14 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
// During the 2nd round of IterGVN, NotNull castings are removed.
|
||||
// Make sure the Bottom and NotNull variants alias the same.
|
||||
// Also, make sure exact and non-exact variants alias the same.
|
||||
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
|
||||
tj = to = to->
|
||||
remove_speculative()->
|
||||
cast_to_instance_id(TypeOopPtr::InstanceBot)->
|
||||
cast_to_ptr_type(TypePtr::BotPTR)->
|
||||
cast_to_exactness(false);
|
||||
}
|
||||
if (to->speculative() != NULL) {
|
||||
tj = to = TypeInstPtr::make(to->ptr(),to->klass(),to->klass_is_exact(),to->const_oop(),to->offset(), to->instance_id());
|
||||
tj = to = to->remove_speculative();
|
||||
}
|
||||
// Canonicalize the holder of this field
|
||||
if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) {
|
||||
@ -1397,18 +1424,18 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
if (!is_known_inst) { // Do it only for non-instance types
|
||||
tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset);
|
||||
}
|
||||
} else if (offset < 0 || offset >= k->layout_helper_size_in_bytes()) {
|
||||
} else if (offset < 0 || offset >= ik->layout_helper_size_in_bytes()) {
|
||||
// Static fields are in the space above the normal instance
|
||||
// fields in the java.lang.Class instance.
|
||||
if (to->klass() != ciEnv::current()->Class_klass()) {
|
||||
if (ik != ciEnv::current()->Class_klass()) {
|
||||
to = NULL;
|
||||
tj = TypeOopPtr::BOTTOM;
|
||||
offset = tj->offset();
|
||||
}
|
||||
} else {
|
||||
ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset);
|
||||
ciInstanceKlass *canonical_holder = ik->get_canonical_holder(offset);
|
||||
assert(offset < canonical_holder->layout_helper_size_in_bytes(), "");
|
||||
if (!k->equals(canonical_holder) || tj->offset() != offset) {
|
||||
if (!ik->equals(canonical_holder) || tj->offset() != offset) {
|
||||
if( is_known_inst ) {
|
||||
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, NULL, offset, to->instance_id());
|
||||
} else {
|
||||
@ -1426,18 +1453,18 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
// inexact types must flatten to the same alias class so
|
||||
// use NotNull as the PTR.
|
||||
if ( offset == Type::OffsetBot || (offset >= 0 && (size_t)offset < sizeof(Klass)) ) {
|
||||
|
||||
tj = tk = TypeKlassPtr::make(TypePtr::NotNull,
|
||||
TypeInstKlassPtr::OBJECT->klass(),
|
||||
offset);
|
||||
tj = tk = TypeInstKlassPtr::make(TypePtr::NotNull,
|
||||
env()->Object_klass(),
|
||||
offset);
|
||||
}
|
||||
|
||||
ciKlass* klass = tk->klass();
|
||||
if( klass->is_obj_array_klass() ) {
|
||||
ciKlass* k = TypeAryPtr::OOPS->klass();
|
||||
if( !k || !k->is_loaded() ) // Only fails for some -Xcomp runs
|
||||
k = TypeInstPtr::BOTTOM->klass();
|
||||
tj = tk = TypeKlassPtr::make( TypePtr::NotNull, k, offset );
|
||||
if (tk->isa_aryklassptr() && tk->is_aryklassptr()->elem()->isa_klassptr()) {
|
||||
ciKlass* k = ciObjArrayKlass::make(env()->Object_klass());
|
||||
if (!k || !k->is_loaded()) { // Only fails for some -Xcomp runs
|
||||
tj = tk = TypeInstKlassPtr::make(TypePtr::NotNull, env()->Object_klass(), offset);
|
||||
} else {
|
||||
tj = tk = TypeAryKlassPtr::make(TypePtr::NotNull, tk->is_aryklassptr()->elem(), k, offset);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for precise loads from the primary supertype array and force them
|
||||
@ -1453,7 +1480,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
offset < (int)(primary_supers_offset + Klass::primary_super_limit() * wordSize)) ||
|
||||
offset == (int)in_bytes(Klass::secondary_super_cache_offset())) {
|
||||
offset = in_bytes(Klass::secondary_super_cache_offset());
|
||||
tj = tk = TypeKlassPtr::make( TypePtr::NotNull, tk->klass(), offset );
|
||||
tj = tk = tk->with_offset(offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1552,7 +1579,7 @@ void Compile::AliasType::print_on(outputStream* st) {
|
||||
adr_type()->dump_on(st);
|
||||
const TypeOopPtr* tjp = adr_type()->isa_oopptr();
|
||||
if (field() != NULL && tjp) {
|
||||
if (tjp->klass() != field()->holder() ||
|
||||
if (tjp->is_instptr()->instance_klass() != field()->holder() ||
|
||||
tjp->offset() != field()->offset_in_bytes()) {
|
||||
st->print(" != ");
|
||||
field()->print();
|
||||
@ -1647,7 +1674,7 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
|
||||
if (flat == TypeAryPtr::RANGE) alias_type(idx)->set_rewritable(false);
|
||||
if (flat->isa_instptr()) {
|
||||
if (flat->offset() == java_lang_Class::klass_offset()
|
||||
&& flat->is_instptr()->klass() == env()->Class_klass())
|
||||
&& flat->is_instptr()->instance_klass() == env()->Class_klass())
|
||||
alias_type(idx)->set_rewritable(false);
|
||||
}
|
||||
if (flat->isa_aryptr()) {
|
||||
@ -1681,13 +1708,13 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
|
||||
if (tinst && tinst->offset() >= instanceOopDesc::base_offset_in_bytes()) {
|
||||
ciField* field;
|
||||
if (tinst->const_oop() != NULL &&
|
||||
tinst->klass() == ciEnv::current()->Class_klass() &&
|
||||
tinst->offset() >= (tinst->klass()->as_instance_klass()->layout_helper_size_in_bytes())) {
|
||||
tinst->instance_klass() == ciEnv::current()->Class_klass() &&
|
||||
tinst->offset() >= (tinst->instance_klass()->layout_helper_size_in_bytes())) {
|
||||
// static field
|
||||
ciInstanceKlass* k = tinst->const_oop()->as_instance()->java_lang_Class_klass()->as_instance_klass();
|
||||
field = k->get_field_by_offset(tinst->offset(), true);
|
||||
} else {
|
||||
ciInstanceKlass *k = tinst->klass()->as_instance_klass();
|
||||
ciInstanceKlass *k = tinst->instance_klass();
|
||||
field = k->get_field_by_offset(tinst->offset(), false);
|
||||
}
|
||||
assert(field == NULL ||
|
||||
@ -4238,46 +4265,35 @@ Compile::TracePhase::~TracePhase() {
|
||||
// (1) subklass is already limited to a subtype of superklass => always ok
|
||||
// (2) subklass does not overlap with superklass => always fail
|
||||
// (3) superklass has NO subtypes and we can check with a simple compare.
|
||||
int Compile::static_subtype_check(ciKlass* superk, ciKlass* subk) {
|
||||
Compile::SubTypeCheckResult Compile::static_subtype_check(const TypeKlassPtr* superk, const TypeKlassPtr* subk) {
|
||||
if (StressReflectiveCode) {
|
||||
return SSC_full_test; // Let caller generate the general case.
|
||||
}
|
||||
|
||||
if (superk == env()->Object_klass()) {
|
||||
return SSC_always_true; // (0) this test cannot fail
|
||||
if (subk->is_java_subtype_of(superk)) {
|
||||
return SSC_always_true; // (0) and (1) this test cannot fail
|
||||
}
|
||||
|
||||
ciType* superelem = superk;
|
||||
ciType* subelem = subk;
|
||||
if (superelem->is_array_klass()) {
|
||||
superelem = superelem->as_array_klass()->base_element_type();
|
||||
}
|
||||
if (subelem->is_array_klass()) {
|
||||
subelem = subelem->as_array_klass()->base_element_type();
|
||||
if (!subk->maybe_java_subtype_of(superk)) {
|
||||
return SSC_always_false; // (2) true path dead; no dynamic test needed
|
||||
}
|
||||
|
||||
if (!subk->is_interface()) { // cannot trust static interface types yet
|
||||
if (subk->is_subtype_of(superk)) {
|
||||
return SSC_always_true; // (1) false path dead; no dynamic test needed
|
||||
}
|
||||
if (!(superelem->is_klass() && superelem->as_klass()->is_interface()) &&
|
||||
!(subelem->is_klass() && subelem->as_klass()->is_interface()) &&
|
||||
!superk->is_subtype_of(subk)) {
|
||||
return SSC_always_false; // (2) true path dead; no dynamic test needed
|
||||
}
|
||||
const Type* superelem = superk;
|
||||
if (superk->isa_aryklassptr()) {
|
||||
int ignored;
|
||||
superelem = superk->is_aryklassptr()->base_element_type(ignored);
|
||||
}
|
||||
|
||||
// If casting to an instance klass, it must have no subtypes
|
||||
if (superk->is_interface()) {
|
||||
// Cannot trust interfaces yet.
|
||||
// %%% S.B. superk->nof_implementors() == 1
|
||||
} else if (superelem->is_instance_klass()) {
|
||||
ciInstanceKlass* ik = superelem->as_instance_klass();
|
||||
if (!ik->has_subklass() && !ik->is_interface()) {
|
||||
if (superelem->isa_instklassptr()) {
|
||||
ciInstanceKlass* ik = superelem->is_instklassptr()->instance_klass();
|
||||
if (!ik->has_subklass()) {
|
||||
if (!ik->is_final()) {
|
||||
// Add a dependency if there is a chance of a later subclass.
|
||||
dependencies()->assert_leaf_type(ik);
|
||||
}
|
||||
if (!superk->maybe_java_subtype_of(subk)) {
|
||||
return SSC_always_false;
|
||||
}
|
||||
return SSC_easy_test; // (3) caller can do a simple ptr comparison
|
||||
}
|
||||
} else {
|
||||
|
@ -84,6 +84,7 @@ class Type;
|
||||
class TypeData;
|
||||
class TypeInt;
|
||||
class TypeInteger;
|
||||
class TypeKlassPtr;
|
||||
class TypePtr;
|
||||
class TypeOopPtr;
|
||||
class TypeFunc;
|
||||
@ -1172,8 +1173,8 @@ class Compile : public Phase {
|
||||
static void pd_compiler2_init();
|
||||
|
||||
// Static parse-time type checking logic for gen_subtype_check:
|
||||
enum { SSC_always_false, SSC_always_true, SSC_easy_test, SSC_full_test };
|
||||
int static_subtype_check(ciKlass* superk, ciKlass* subk);
|
||||
enum SubTypeCheckResult { SSC_always_false, SSC_always_true, SSC_easy_test, SSC_full_test };
|
||||
SubTypeCheckResult static_subtype_check(const TypeKlassPtr* superk, const TypeKlassPtr* subk);
|
||||
|
||||
static Node* conv_I2X_index(PhaseGVN* phase, Node* offset, const TypeInt* sizetype,
|
||||
// Optional control dependency (for example, on range check)
|
||||
|
@ -859,7 +859,7 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
|
||||
method()->print_name(); tty->cr();
|
||||
} else if (PrintOpto && (Verbose || WizardMode)) {
|
||||
tty->print("Bailing out on unloaded exception type ");
|
||||
extype->klass()->print_name();
|
||||
extype->instance_klass()->print_name();
|
||||
tty->print(" at bci:%d in ", bci());
|
||||
method()->print_name(); tty->cr();
|
||||
}
|
||||
@ -869,7 +869,7 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
|
||||
push_ex_oop(ex_oop);
|
||||
uncommon_trap(Deoptimization::Reason_unloaded,
|
||||
Deoptimization::Action_reinterpret,
|
||||
extype->klass(), "!loaded exception");
|
||||
extype->instance_klass(), "!loaded exception");
|
||||
set_bci(iter().cur_bci()); // put it back
|
||||
continue;
|
||||
}
|
||||
@ -916,7 +916,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||
|
||||
// determine potential exception handlers
|
||||
ciExceptionHandlerStream handlers(method(), bci(),
|
||||
ex_type->klass()->as_instance_klass(),
|
||||
ex_type->instance_klass(),
|
||||
ex_type->klass_is_exact());
|
||||
|
||||
// Start executing from the given throw state. (Keep its stack, for now.)
|
||||
@ -1138,7 +1138,7 @@ ciMethod* Compile::optimize_inlining(ciMethod* caller, ciInstanceKlass* klass, c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ciInstanceKlass* receiver_klass = receiver_type->klass()->as_instance_klass();
|
||||
ciInstanceKlass* receiver_klass = receiver_type->is_instptr()->instance_klass();
|
||||
if (receiver_klass->is_loaded() && receiver_klass->is_initialized() && !receiver_klass->is_interface() &&
|
||||
(receiver_klass == actual_receiver || receiver_klass->is_subtype_of(actual_receiver))) {
|
||||
// ikl is a same or better type than the original actual_receiver,
|
||||
|
@ -941,12 +941,11 @@ void ConnectionGraph::add_call_node(CallNode* call) {
|
||||
Node* k = call->in(AllocateNode::KlassNode);
|
||||
const TypeKlassPtr* kt = k->bottom_type()->isa_klassptr();
|
||||
assert(kt != NULL, "TypeKlassPtr required.");
|
||||
ciKlass* cik = kt->klass();
|
||||
PointsToNode::EscapeState es = PointsToNode::NoEscape;
|
||||
bool scalar_replaceable = true;
|
||||
NOT_PRODUCT(const char* nsr_reason = "");
|
||||
if (call->is_AllocateArray()) {
|
||||
if (!cik->is_array_klass()) { // StressReflectiveCode
|
||||
if (!kt->isa_aryklassptr()) { // StressReflectiveCode
|
||||
es = PointsToNode::GlobalEscape;
|
||||
} else {
|
||||
int length = call->in(AllocateNode::ALength)->find_int_con(-1);
|
||||
@ -961,18 +960,23 @@ void ConnectionGraph::add_call_node(CallNode* call) {
|
||||
}
|
||||
}
|
||||
} else { // Allocate instance
|
||||
if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
|
||||
cik->is_subclass_of(_compile->env()->Reference_klass()) ||
|
||||
!cik->is_instance_klass() || // StressReflectiveCode
|
||||
!cik->as_instance_klass()->can_be_instantiated() ||
|
||||
cik->as_instance_klass()->has_finalizer()) {
|
||||
if (!kt->isa_instklassptr()) { // StressReflectiveCode
|
||||
es = PointsToNode::GlobalEscape;
|
||||
} else {
|
||||
int nfields = cik->as_instance_klass()->nof_nonstatic_fields();
|
||||
if (nfields > EliminateAllocationFieldsLimit) {
|
||||
// Not scalar replaceable if there are too many fields.
|
||||
scalar_replaceable = false;
|
||||
NOT_PRODUCT(nsr_reason = "has too many fields");
|
||||
const TypeInstKlassPtr* ikt = kt->is_instklassptr();
|
||||
ciInstanceKlass* ik = ikt->klass_is_exact() ? ikt->exact_klass()->as_instance_klass() : ikt->instance_klass();
|
||||
if (ik->is_subclass_of(_compile->env()->Thread_klass()) ||
|
||||
ik->is_subclass_of(_compile->env()->Reference_klass()) ||
|
||||
!ik->can_be_instantiated() ||
|
||||
ik->has_finalizer()) {
|
||||
es = PointsToNode::GlobalEscape;
|
||||
} else {
|
||||
int nfields = ik->as_instance_klass()->nof_nonstatic_fields();
|
||||
if (nfields > EliminateAllocationFieldsLimit) {
|
||||
// Not scalar replaceable if there are too many fields.
|
||||
scalar_replaceable = false;
|
||||
NOT_PRODUCT(nsr_reason = "has too many fields");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1113,8 +1117,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
|
||||
assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
|
||||
aat->isa_ptr() != NULL, "expecting an Ptr");
|
||||
bool arg_has_oops = aat->isa_oopptr() &&
|
||||
(aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
|
||||
(aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
|
||||
(aat->isa_instptr() ||
|
||||
(aat->isa_aryptr() && (aat->isa_aryptr()->elem() == Type::BOTTOM || aat->isa_aryptr()->elem()->make_oopptr() != NULL)));
|
||||
if (i == TypeFunc::Parms) {
|
||||
src_has_oops = arg_has_oops;
|
||||
}
|
||||
@ -2236,8 +2240,8 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
|
||||
if (offset == Type::OffsetBot) {
|
||||
// Check only oop fields.
|
||||
if (!adr_type->isa_aryptr() ||
|
||||
(adr_type->isa_aryptr()->klass() == NULL) ||
|
||||
adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
|
||||
adr_type->isa_aryptr()->elem() == Type::BOTTOM ||
|
||||
adr_type->isa_aryptr()->elem()->make_oopptr() != NULL) {
|
||||
// OffsetBot is used to reference array's element. Ignore first AddP.
|
||||
if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
|
||||
bt = T_OBJECT;
|
||||
@ -2628,7 +2632,7 @@ bool ConnectionGraph::split_AddP(Node *addp, Node *base) {
|
||||
// this code branch will go away.
|
||||
//
|
||||
if (!t->is_known_instance() &&
|
||||
!base_t->klass()->is_subtype_of(t->klass())) {
|
||||
!t->maybe_java_subtype_of(base_t)) {
|
||||
return false; // bail out
|
||||
}
|
||||
const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr();
|
||||
@ -2794,8 +2798,8 @@ Node* ConnectionGraph::step_through_mergemem(MergeMemNode *mmem, int alias_idx,
|
||||
// means an array I have not precisely typed yet. Do not do any
|
||||
// alias stuff with it any time soon.
|
||||
if (toop->base() != Type::AnyPtr &&
|
||||
!(toop->klass() != NULL &&
|
||||
toop->klass()->is_java_lang_Object() &&
|
||||
!(toop->isa_instptr() &&
|
||||
toop->is_instptr()->instance_klass()->is_java_lang_Object() &&
|
||||
toop->offset() == Type::OffsetBot)) {
|
||||
mem = mmem->memory_at(alias_idx);
|
||||
// Update input if it is progress over what we have now
|
||||
@ -3312,7 +3316,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
} else {
|
||||
tn_t = tn_type->isa_oopptr();
|
||||
}
|
||||
if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) {
|
||||
if (tn_t != NULL && tn_t->maybe_java_subtype_of(tinst)) {
|
||||
if (tn_type->isa_narrowoop()) {
|
||||
tn_type = tinst->make_narrowoop();
|
||||
} else {
|
||||
@ -3325,7 +3329,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
record_for_optimizer(n);
|
||||
} else {
|
||||
assert(tn_type == TypePtr::NULL_PTR ||
|
||||
tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()),
|
||||
tn_t != NULL && !tinst->is_java_subtype_of(tn_t),
|
||||
"unexpected type");
|
||||
continue; // Skip dead path with different type
|
||||
}
|
||||
|
@ -1242,7 +1242,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
|
||||
const Type *t = _gvn.type( value );
|
||||
|
||||
const TypeOopPtr* tp = t->isa_oopptr();
|
||||
if (tp != NULL && tp->klass() != NULL && !tp->klass()->is_loaded()
|
||||
if (tp != NULL && !tp->is_loaded()
|
||||
// Only for do_null_check, not any of its siblings:
|
||||
&& !assert_null && null_control == NULL) {
|
||||
// Usually, any field access or invocation on an unloaded oop type
|
||||
@ -1256,12 +1256,13 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
|
||||
// Our access to the unloaded class will only be correct
|
||||
// after it has been loaded and initialized, which requires
|
||||
// a trip through the interpreter.
|
||||
ciKlass* klass = tp->unloaded_klass();
|
||||
#ifndef PRODUCT
|
||||
if (WizardMode) { tty->print("Null check of unloaded "); tp->klass()->print(); tty->cr(); }
|
||||
if (WizardMode) { tty->print("Null check of unloaded "); klass->print(); tty->cr(); }
|
||||
#endif
|
||||
uncommon_trap(Deoptimization::Reason_unloaded,
|
||||
Deoptimization::Action_reinterpret,
|
||||
tp->klass(), "!loaded");
|
||||
klass, "!loaded");
|
||||
return top();
|
||||
}
|
||||
|
||||
@ -2778,8 +2779,8 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, No
|
||||
return C->top(); // false path is dead; no test needed.
|
||||
|
||||
if (gvn.type(superklass)->singleton()) {
|
||||
ciKlass* superk = gvn.type(superklass)->is_klassptr()->klass();
|
||||
ciKlass* subk = gvn.type(subklass)->is_klassptr()->klass();
|
||||
const TypeKlassPtr* superk = gvn.type(superklass)->is_klassptr();
|
||||
const TypeKlassPtr* subk = gvn.type(subklass)->is_klassptr();
|
||||
|
||||
// In the common case of an exact superklass, try to fold up the
|
||||
// test before generating code. You may ask, why not just generate
|
||||
@ -3091,7 +3092,7 @@ void GraphKit::clinit_barrier(ciInstanceKlass* ik, ciMethod* context) {
|
||||
// If the profile has seen exactly one type, narrow to exactly that type.
|
||||
// Subsequent type checks will always fold up.
|
||||
Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
|
||||
ciKlass* require_klass,
|
||||
const TypeKlassPtr* require_klass,
|
||||
ciKlass* spec_klass,
|
||||
bool safe_for_replace) {
|
||||
if (!UseTypeProfile || !TypeProfileCasts) return NULL;
|
||||
@ -3109,7 +3110,7 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
|
||||
ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass;
|
||||
if (exact_kls != NULL) {// no cast failures here
|
||||
if (require_klass == NULL ||
|
||||
C->static_subtype_check(require_klass, exact_kls) == Compile::SSC_always_true) {
|
||||
C->static_subtype_check(require_klass, TypeKlassPtr::make(exact_kls)) == Compile::SSC_always_true) {
|
||||
// If we narrow the type to match what the type profile sees or
|
||||
// the speculative type, we can then remove the rest of the
|
||||
// cast.
|
||||
@ -3234,9 +3235,9 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac
|
||||
// Do we know the type check always succeed?
|
||||
bool known_statically = false;
|
||||
if (_gvn.type(superklass)->singleton()) {
|
||||
ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass();
|
||||
ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass();
|
||||
if (subk != NULL && subk->is_loaded()) {
|
||||
const TypeKlassPtr* superk = _gvn.type(superklass)->is_klassptr();
|
||||
const TypeKlassPtr* subk = _gvn.type(obj)->is_oopptr()->as_klass_type();
|
||||
if (subk->is_loaded()) {
|
||||
int static_res = C->static_subtype_check(superk, subk);
|
||||
known_statically = (static_res == Compile::SSC_always_true || static_res == Compile::SSC_always_false);
|
||||
}
|
||||
@ -3296,7 +3297,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
|
||||
Node* *failure_control) {
|
||||
kill_dead_locals(); // Benefit all the uncommon traps
|
||||
const TypeKlassPtr *tk = _gvn.type(superklass)->is_klassptr();
|
||||
const Type *toop = TypeOopPtr::make_from_klass(tk->klass());
|
||||
const Type *toop = tk->cast_to_exactness(false)->as_instance_type();
|
||||
|
||||
// Fast cutout: Check the case that the cast is vacuously true.
|
||||
// This detects the common cases where the test will short-circuit
|
||||
@ -3306,8 +3307,8 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
|
||||
// for example, in some objArray manipulations, such as a[i]=a[j].)
|
||||
if (tk->singleton()) {
|
||||
const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr();
|
||||
if (objtp != NULL && objtp->klass() != NULL) {
|
||||
switch (C->static_subtype_check(tk->klass(), objtp->klass())) {
|
||||
if (objtp != NULL) {
|
||||
switch (C->static_subtype_check(tk, objtp->as_klass_type())) {
|
||||
case Compile::SSC_always_true:
|
||||
// If we know the type check always succeed then we don't use
|
||||
// the profiling data at this bytecode. Don't lose it, feed it
|
||||
@ -3326,6 +3327,8 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
|
||||
return null_assert(obj);
|
||||
}
|
||||
break; // Fall through to full check
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3381,7 +3384,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
|
||||
// a speculative type use it to perform an exact cast.
|
||||
ciKlass* spec_obj_type = obj_type->speculative_type();
|
||||
if (spec_obj_type != NULL || data != NULL) {
|
||||
cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk->klass(), spec_obj_type, safe_for_replace);
|
||||
cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk, spec_obj_type, safe_for_replace);
|
||||
if (cast_obj != NULL) {
|
||||
if (failure_control != NULL) // failure is now impossible
|
||||
(*failure_control) = top();
|
||||
@ -3607,10 +3610,18 @@ void GraphKit::shared_unlock(Node* box, Node* obj) {
|
||||
Node* GraphKit::get_layout_helper(Node* klass_node, jint& constant_value) {
|
||||
const TypeKlassPtr* inst_klass = _gvn.type(klass_node)->isa_klassptr();
|
||||
if (!StressReflectiveCode && inst_klass != NULL) {
|
||||
ciKlass* klass = inst_klass->klass();
|
||||
bool xklass = inst_klass->klass_is_exact();
|
||||
if (xklass || klass->is_array_klass()) {
|
||||
jint lhelper = klass->layout_helper();
|
||||
if (xklass || inst_klass->isa_aryklassptr()) {
|
||||
jint lhelper;
|
||||
if (inst_klass->isa_aryklassptr()) {
|
||||
BasicType elem = inst_klass->as_instance_type()->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(elem, true)) {
|
||||
elem = T_OBJECT;
|
||||
}
|
||||
lhelper = Klass::array_layout_helper(elem);
|
||||
} else {
|
||||
lhelper = inst_klass->is_instklassptr()->exact_klass()->layout_helper();
|
||||
}
|
||||
if (lhelper != Klass::_lh_neutral_value) {
|
||||
constant_value = lhelper;
|
||||
return (Node*) NULL;
|
||||
@ -3682,7 +3693,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
||||
int elemidx = C->get_alias_index(telemref);
|
||||
hook_memory_on_init(*this, elemidx, minit_in, minit_out);
|
||||
} else if (oop_type->isa_instptr()) {
|
||||
ciInstanceKlass* ik = oop_type->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = oop_type->is_instptr()->instance_klass();
|
||||
for (int i = 0, len = ik->nof_nonstatic_fields(); i < len; i++) {
|
||||
ciField* field = ik->nonstatic_field_at(i);
|
||||
if (field->offset() >= TrackedInitializationLimit * HeapWordSize)
|
||||
@ -3959,8 +3970,8 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||
|
||||
const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
|
||||
Node* valid_length_test = _gvn.intcon(1);
|
||||
if (ary_type->klass()->is_array_klass()) {
|
||||
BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (ary_type->isa_aryptr()) {
|
||||
BasicType bt = ary_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
jint max = TypeAryPtr::max_array_length(bt);
|
||||
Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max)));
|
||||
valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le));
|
||||
|
@ -420,7 +420,7 @@ class GraphKit : public Phase {
|
||||
|
||||
// Use the type profile to narrow an object type.
|
||||
Node* maybe_cast_profiled_receiver(Node* not_null_obj,
|
||||
ciKlass* require_klass,
|
||||
const TypeKlassPtr* require_klass,
|
||||
ciKlass* spec,
|
||||
bool safe_for_replace);
|
||||
|
||||
|
@ -491,15 +491,14 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
|
||||
stringStream s2(buffer, sizeof(buffer) - 1);
|
||||
|
||||
node->dump_spec(&s2);
|
||||
if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) {
|
||||
if (t != NULL && (t->isa_instptr() || t->isa_instklassptr())) {
|
||||
const TypeInstPtr *toop = t->isa_instptr();
|
||||
const TypeKlassPtr *tkls = t->isa_klassptr();
|
||||
ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL );
|
||||
if( klass && klass->is_loaded() && klass->is_interface() ) {
|
||||
const TypeInstKlassPtr *tkls = t->isa_instklassptr();
|
||||
if ((toop != NULL && toop->is_interface()) || (tkls != NULL && tkls->is_interface())) {
|
||||
s2.print(" Interface:");
|
||||
} else if( toop ) {
|
||||
} else if (toop) {
|
||||
s2.print(" Oop:");
|
||||
} else if( tkls ) {
|
||||
} else if (tkls) {
|
||||
s2.print(" Klass:");
|
||||
}
|
||||
t->dump_on(&s2);
|
||||
|
@ -1341,8 +1341,8 @@ bool LibraryCallKit::inline_string_copy(bool compress) {
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const Type* dst_type = dst->Value(&_gvn);
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType dst_elem = dst_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
assert((compress && dst_elem == T_BYTE && (src_elem == T_BYTE || src_elem == T_CHAR)) ||
|
||||
(!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)),
|
||||
"Unsupported array types for inline_string_copy");
|
||||
@ -2282,31 +2282,33 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
|
||||
}
|
||||
}
|
||||
|
||||
const TypeOopPtr* result = NULL;
|
||||
// See if it is a narrow oop array.
|
||||
if (adr_type->isa_aryptr()) {
|
||||
if (adr_type->offset() >= objArrayOopDesc::base_offset_in_bytes()) {
|
||||
const TypeOopPtr* elem_type = adr_type->is_aryptr()->elem()->make_oopptr();
|
||||
if (elem_type != NULL) {
|
||||
sharpened_klass = elem_type->klass();
|
||||
if (elem_type != NULL && elem_type->is_loaded()) {
|
||||
// Sharpen the value type.
|
||||
result = elem_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The sharpened class might be unloaded if there is no class loader
|
||||
// constraint in place.
|
||||
if (sharpened_klass != NULL && sharpened_klass->is_loaded()) {
|
||||
const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass);
|
||||
|
||||
// contraint in place.
|
||||
if (result == NULL && sharpened_klass != NULL && sharpened_klass->is_loaded()) {
|
||||
// Sharpen the value type.
|
||||
result = TypeOopPtr::make_from_klass(sharpened_klass);
|
||||
}
|
||||
if (result != NULL) {
|
||||
#ifndef PRODUCT
|
||||
if (C->print_intrinsics() || C->print_inlining()) {
|
||||
tty->print(" from base type: "); adr_type->dump(); tty->cr();
|
||||
tty->print(" sharpened value: "); tjp->dump(); tty->cr();
|
||||
tty->print(" sharpened value: "); result->dump(); tty->cr();
|
||||
}
|
||||
#endif
|
||||
// Sharpen the value type.
|
||||
return tjp;
|
||||
}
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
DecoratorSet LibraryCallKit::mo_decorator_for_access_kind(AccessKind kind) {
|
||||
@ -2441,7 +2443,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
|
||||
// Use address type to get the element type.
|
||||
bt = adr_type->is_aryptr()->elem()->array_element_basic_type();
|
||||
}
|
||||
if (bt == T_ARRAY || bt == T_NARROWOOP) {
|
||||
if (is_reference_type(bt, true)) {
|
||||
// accessing an array field with getReference is not a mismatch
|
||||
bt = T_OBJECT;
|
||||
}
|
||||
@ -2821,11 +2823,11 @@ bool LibraryCallKit::klass_needs_init_guard(Node* kls) {
|
||||
if (!kls->is_Con()) {
|
||||
return true;
|
||||
}
|
||||
const TypeKlassPtr* klsptr = kls->bottom_type()->isa_klassptr();
|
||||
const TypeInstKlassPtr* klsptr = kls->bottom_type()->isa_instklassptr();
|
||||
if (klsptr == NULL) {
|
||||
return true;
|
||||
}
|
||||
ciInstanceKlass* ik = klsptr->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = klsptr->instance_klass();
|
||||
// don't need a guard for a klass that is already initialized
|
||||
return !ik->is_initialized();
|
||||
}
|
||||
@ -3762,12 +3764,12 @@ bool LibraryCallKit::inline_Class_cast() {
|
||||
// java_mirror_type() returns non-null for compile-time Class constants.
|
||||
ciType* tm = mirror_con->java_mirror_type();
|
||||
if (tm != NULL && tm->is_klass() &&
|
||||
tp != NULL && tp->klass() != NULL) {
|
||||
if (!tp->klass()->is_loaded()) {
|
||||
tp != NULL) {
|
||||
if (!tp->is_loaded()) {
|
||||
// Don't use intrinsic when class is not loaded.
|
||||
return false;
|
||||
} else {
|
||||
int static_res = C->static_subtype_check(tm->as_klass(), tp->klass());
|
||||
int static_res = C->static_subtype_check(TypeKlassPtr::make(tm->as_klass()), tp->as_klass_type());
|
||||
if (static_res == Compile::SSC_always_true) {
|
||||
// isInstance() is true - fold the code.
|
||||
set_result(obj);
|
||||
@ -4176,8 +4178,8 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) {
|
||||
// check can be optimized if we know something on the type of
|
||||
// the input array from type speculation.
|
||||
if (_gvn.type(klass_node)->singleton()) {
|
||||
ciKlass* subk = _gvn.type(load_object_klass(original))->is_klassptr()->klass();
|
||||
ciKlass* superk = _gvn.type(klass_node)->is_klassptr()->klass();
|
||||
const TypeKlassPtr* subk = _gvn.type(load_object_klass(original))->is_klassptr();
|
||||
const TypeKlassPtr* superk = _gvn.type(klass_node)->is_klassptr();
|
||||
|
||||
int test = C->static_subtype_check(superk, subk);
|
||||
if (test != Compile::SSC_always_true && test != Compile::SSC_always_false) {
|
||||
@ -4798,10 +4800,8 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||
ciInstanceKlass* spec_ik = obj_type->speculative_type()->as_instance_klass();
|
||||
if (spec_ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem &&
|
||||
!spec_ik->has_injected_fields()) {
|
||||
ciKlass* k = obj_type->klass();
|
||||
if (!k->is_instance_klass() ||
|
||||
k->as_instance_klass()->is_interface() ||
|
||||
k->as_instance_klass()->has_subklass()) {
|
||||
if (!obj_type->isa_instptr() ||
|
||||
obj_type->is_instptr()->instance_klass()->has_subklass()) {
|
||||
obj = maybe_cast_profiled_obj(obj, obj_type->speculative_type(), false);
|
||||
}
|
||||
}
|
||||
@ -5176,9 +5176,9 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
|
||||
|
||||
// Do we have the type of src?
|
||||
bool has_src = (top_src != NULL && top_src->klass() != NULL);
|
||||
bool has_src = (top_src != NULL && top_src->elem() != Type::BOTTOM);
|
||||
// Do we have the type of dest?
|
||||
bool has_dest = (top_dest != NULL && top_dest->klass() != NULL);
|
||||
bool has_dest = (top_dest != NULL && top_dest->elem() != Type::BOTTOM);
|
||||
// Is the type for src from speculation?
|
||||
bool src_spec = false;
|
||||
// Is the type for dest from speculation?
|
||||
@ -5216,24 +5216,24 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||
src = maybe_cast_profiled_obj(src, src_k, true);
|
||||
src_type = _gvn.type(src);
|
||||
top_src = src_type->isa_aryptr();
|
||||
has_src = (top_src != NULL && top_src->klass() != NULL);
|
||||
has_src = (top_src != NULL && top_src->elem() != Type::BOTTOM);
|
||||
src_spec = true;
|
||||
}
|
||||
if (!has_dest) {
|
||||
dest = maybe_cast_profiled_obj(dest, dest_k, true);
|
||||
dest_type = _gvn.type(dest);
|
||||
top_dest = dest_type->isa_aryptr();
|
||||
has_dest = (top_dest != NULL && top_dest->klass() != NULL);
|
||||
has_dest = (top_dest != NULL && top_dest->elem() != Type::BOTTOM);
|
||||
dest_spec = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_src && has_dest && can_emit_guards) {
|
||||
BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (is_reference_type(src_elem)) src_elem = T_OBJECT;
|
||||
if (is_reference_type(dest_elem)) dest_elem = T_OBJECT;
|
||||
BasicType src_elem = top_src->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType dest_elem = top_dest->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(src_elem, true)) src_elem = T_OBJECT;
|
||||
if (is_reference_type(dest_elem, true)) dest_elem = T_OBJECT;
|
||||
|
||||
if (src_elem == dest_elem && src_elem == T_OBJECT) {
|
||||
// If both arrays are object arrays then having the exact types
|
||||
@ -5244,8 +5244,8 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||
bool could_have_src = src_spec;
|
||||
// Do we have the exact type of dest?
|
||||
bool could_have_dest = dest_spec;
|
||||
ciKlass* src_k = top_src->klass();
|
||||
ciKlass* dest_k = top_dest->klass();
|
||||
ciKlass* src_k = NULL;
|
||||
ciKlass* dest_k = NULL;
|
||||
if (!src_spec) {
|
||||
src_k = src_type->speculative_type_not_null();
|
||||
if (src_k != NULL && src_k->is_array_klass()) {
|
||||
@ -5342,7 +5342,7 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||
}
|
||||
|
||||
const TypeKlassPtr* dest_klass_t = _gvn.type(dest_klass)->is_klassptr();
|
||||
const Type *toop = TypeOopPtr::make_from_klass(dest_klass_t->klass());
|
||||
const Type *toop = dest_klass_t->cast_to_exactness(false)->as_instance_type();
|
||||
src = _gvn.transform(new CheckCastPPNode(control(), src, toop));
|
||||
}
|
||||
|
||||
@ -5462,15 +5462,15 @@ bool LibraryCallKit::inline_encodeISOArray(bool ascii) {
|
||||
const Type* dst_type = dst->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
const TypeAryPtr* top_dest = dst_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL ||
|
||||
top_dest == NULL || top_dest->klass() == NULL) {
|
||||
if (top_src == NULL || top_src->elem() == Type::BOTTOM ||
|
||||
top_dest == NULL || top_dest->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType dst_elem = dst_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (!((src_elem == T_CHAR) || (src_elem== T_BYTE)) || dst_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
@ -5517,14 +5517,14 @@ bool LibraryCallKit::inline_multiplyToLen() {
|
||||
const Type* y_type = y->Value(&_gvn);
|
||||
const TypeAryPtr* top_x = x_type->isa_aryptr();
|
||||
const TypeAryPtr* top_y = y_type->isa_aryptr();
|
||||
if (top_x == NULL || top_x->klass() == NULL ||
|
||||
top_y == NULL || top_y->klass() == NULL) {
|
||||
if (top_x == NULL || top_x->elem() == Type::BOTTOM ||
|
||||
top_y == NULL || top_y->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType y_elem = y_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType x_elem = x_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType y_elem = y_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (x_elem != T_INT || y_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
@ -5625,14 +5625,14 @@ bool LibraryCallKit::inline_squareToLen() {
|
||||
const Type* z_type = z->Value(&_gvn);
|
||||
const TypeAryPtr* top_x = x_type->isa_aryptr();
|
||||
const TypeAryPtr* top_z = z_type->isa_aryptr();
|
||||
if (top_x == NULL || top_x->klass() == NULL ||
|
||||
top_z == NULL || top_z->klass() == NULL) {
|
||||
if (top_x == NULL || top_x->elem() == Type::BOTTOM ||
|
||||
top_z == NULL || top_z->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType z_elem = z_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType x_elem = x_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType z_elem = z_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (x_elem != T_INT || z_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
@ -5674,14 +5674,14 @@ bool LibraryCallKit::inline_mulAdd() {
|
||||
const Type* in_type = in->Value(&_gvn);
|
||||
const TypeAryPtr* top_out = out_type->isa_aryptr();
|
||||
const TypeAryPtr* top_in = in_type->isa_aryptr();
|
||||
if (top_out == NULL || top_out->klass() == NULL ||
|
||||
top_in == NULL || top_in->klass() == NULL) {
|
||||
if (top_out == NULL || top_out->elem() == Type::BOTTOM ||
|
||||
top_in == NULL || top_in->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType out_elem = out_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType in_elem = in_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (out_elem != T_INT || in_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
@ -5727,18 +5727,18 @@ bool LibraryCallKit::inline_montgomeryMultiply() {
|
||||
const TypeAryPtr* top_n = n_type->isa_aryptr();
|
||||
const Type* m_type = a->Value(&_gvn);
|
||||
const TypeAryPtr* top_m = m_type->isa_aryptr();
|
||||
if (top_a == NULL || top_a->klass() == NULL ||
|
||||
top_b == NULL || top_b->klass() == NULL ||
|
||||
top_n == NULL || top_n->klass() == NULL ||
|
||||
top_m == NULL || top_m->klass() == NULL) {
|
||||
if (top_a == NULL || top_a->elem() == Type::BOTTOM ||
|
||||
top_b == NULL || top_b->elem() == Type::BOTTOM ||
|
||||
top_n == NULL || top_n->elem() == Type::BOTTOM ||
|
||||
top_m == NULL || top_m->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType b_elem = b_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType a_elem = a_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType b_elem = b_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType n_elem = n_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType m_elem = m_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (a_elem != T_INT || b_elem != T_INT || n_elem != T_INT || m_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
@ -5784,16 +5784,16 @@ bool LibraryCallKit::inline_montgomerySquare() {
|
||||
const TypeAryPtr* top_n = n_type->isa_aryptr();
|
||||
const Type* m_type = a->Value(&_gvn);
|
||||
const TypeAryPtr* top_m = m_type->isa_aryptr();
|
||||
if (top_a == NULL || top_a->klass() == NULL ||
|
||||
top_n == NULL || top_n->klass() == NULL ||
|
||||
top_m == NULL || top_m->klass() == NULL) {
|
||||
if (top_a == NULL || top_a->elem() == Type::BOTTOM ||
|
||||
top_n == NULL || top_n->elem() == Type::BOTTOM ||
|
||||
top_m == NULL || top_m->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType a_elem = a_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType n_elem = n_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType m_elem = m_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (a_elem != T_INT || n_elem != T_INT || m_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
@ -5838,13 +5838,13 @@ bool LibraryCallKit::inline_bigIntegerShift(bool isRightShift) {
|
||||
const TypeAryPtr* top_newArr = newArr_type->isa_aryptr();
|
||||
const Type* oldArr_type = oldArr->Value(&_gvn);
|
||||
const TypeAryPtr* top_oldArr = oldArr_type->isa_aryptr();
|
||||
if (top_newArr == NULL || top_newArr->klass() == NULL || top_oldArr == NULL
|
||||
|| top_oldArr->klass() == NULL) {
|
||||
if (top_newArr == NULL || top_newArr->elem() == Type::BOTTOM || top_oldArr == NULL
|
||||
|| top_oldArr->elem() == Type::BOTTOM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType newArr_elem = newArr_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType oldArr_elem = oldArr_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType newArr_elem = newArr_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
BasicType oldArr_elem = oldArr_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (newArr_elem != T_INT || oldArr_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
@ -5883,8 +5883,8 @@ bool LibraryCallKit::inline_vectorizedMismatch() {
|
||||
|
||||
const TypeAryPtr* obja_t = _gvn.type(obja)->isa_aryptr();
|
||||
const TypeAryPtr* objb_t = _gvn.type(objb)->isa_aryptr();
|
||||
if (obja_t == NULL || obja_t->klass() == NULL ||
|
||||
objb_t == NULL || objb_t->klass() == NULL ||
|
||||
if (obja_t == NULL || obja_t->elem() == Type::BOTTOM ||
|
||||
objb_t == NULL || objb_t->elem() == Type::BOTTOM ||
|
||||
scale == top()) {
|
||||
return false; // failed input validation
|
||||
}
|
||||
@ -6051,13 +6051,13 @@ bool LibraryCallKit::inline_updateBytesCRC32() {
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
@ -6140,13 +6140,13 @@ bool LibraryCallKit::inline_updateBytesCRC32C() {
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
@ -6233,13 +6233,13 @@ bool LibraryCallKit::inline_updateBytesAdler32() {
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
@ -6366,8 +6366,8 @@ Node* LibraryCallKit::load_field_from_object(Node* fromObj, const char* fieldNam
|
||||
if (fromKls == NULL) {
|
||||
const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
|
||||
assert(tinst != NULL, "obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "obj is not loaded");
|
||||
fromKls = tinst->klass()->as_instance_klass();
|
||||
assert(tinst->is_loaded(), "obj is not loaded");
|
||||
fromKls = tinst->instance_klass();
|
||||
} else {
|
||||
assert(is_static, "only for static field access");
|
||||
}
|
||||
@ -6415,9 +6415,9 @@ Node * LibraryCallKit::field_address_from_object(Node * fromObj, const char * fi
|
||||
if (fromKls == NULL) {
|
||||
const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
|
||||
assert(tinst != NULL, "obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "obj is not loaded");
|
||||
assert(tinst->is_loaded(), "obj is not loaded");
|
||||
assert(!is_exact || tinst->klass_is_exact(), "klass not exact");
|
||||
fromKls = tinst->klass()->as_instance_klass();
|
||||
fromKls = tinst->instance_klass();
|
||||
}
|
||||
else {
|
||||
assert(is_static, "only for static field access");
|
||||
@ -6477,7 +6477,7 @@ bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) {
|
||||
const Type* dest_type = dest->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
|
||||
assert (top_src != NULL && top_src->klass() != NULL && top_dest != NULL && top_dest->klass() != NULL, "args are strange");
|
||||
assert (top_src != NULL && top_src->elem() != Type::BOTTOM && top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
|
||||
|
||||
// for the quick and dirty code we will skip all the checks.
|
||||
// we are just trying to get the call to be generated.
|
||||
@ -6538,8 +6538,8 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
|
||||
const Type* dest_type = dest->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
|
||||
assert (top_src != NULL && top_src->klass() != NULL
|
||||
&& top_dest != NULL && top_dest->klass() != NULL, "args are strange");
|
||||
assert (top_src != NULL && top_src->elem() != Type::BOTTOM
|
||||
&& top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
|
||||
|
||||
// checks are the responsibility of the caller
|
||||
Node* src_start = src;
|
||||
@ -6561,8 +6561,8 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
|
||||
// cast it to what we know it will be at runtime
|
||||
const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr();
|
||||
assert(tinst != NULL, "CBC obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "CBC obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(tinst->is_loaded(), "CBC obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
|
||||
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
@ -6626,8 +6626,8 @@ bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) {
|
||||
const Type* dest_type = dest->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
|
||||
assert(top_src != NULL && top_src->klass() != NULL
|
||||
&& top_dest != NULL && top_dest->klass() != NULL, "args are strange");
|
||||
assert(top_src != NULL && top_src->elem() != Type::BOTTOM
|
||||
&& top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
|
||||
|
||||
// checks are the responsibility of the caller
|
||||
Node* src_start = src;
|
||||
@ -6649,8 +6649,8 @@ bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) {
|
||||
// cast it to what we know it will be at runtime
|
||||
const TypeInstPtr* tinst = _gvn.type(electronicCodeBook_object)->isa_instptr();
|
||||
assert(tinst != NULL, "ECB obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "ECB obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(tinst->is_loaded(), "ECB obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
|
||||
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
@ -6700,8 +6700,8 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
|
||||
const Type* dest_type = dest->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
|
||||
assert(top_src != NULL && top_src->klass() != NULL &&
|
||||
top_dest != NULL && top_dest->klass() != NULL, "args are strange");
|
||||
assert(top_src != NULL && top_src->elem() != Type::BOTTOM &&
|
||||
top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange");
|
||||
|
||||
// checks are the responsibility of the caller
|
||||
Node* src_start = src;
|
||||
@ -6721,8 +6721,8 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
|
||||
// cast it to what we know it will be at runtime
|
||||
const TypeInstPtr* tinst = _gvn.type(counterMode_object)->isa_instptr();
|
||||
assert(tinst != NULL, "CTR obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "CTR obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(tinst->is_loaded(), "CTR obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
||||
@ -6802,10 +6802,10 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
|
||||
// will have same classloader as CipherBlockChaining object
|
||||
const TypeInstPtr* tinst = _gvn.type(objCBC)->isa_instptr();
|
||||
assert(tinst != NULL, "CBCobj is null");
|
||||
assert(tinst->klass()->is_loaded(), "CBCobj is not loaded");
|
||||
assert(tinst->is_loaded(), "CBCobj is not loaded");
|
||||
|
||||
// we want to do an instanceof comparison against the AESCrypt class
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
if (!klass_AESCrypt->is_loaded()) {
|
||||
// if AESCrypt is not even loaded, we never take the intrinsic fast path
|
||||
Node* ctrl = control();
|
||||
@ -6865,10 +6865,10 @@ Node* LibraryCallKit::inline_electronicCodeBook_AESCrypt_predicate(bool decrypti
|
||||
// will have same classloader as ElectronicCodeBook object
|
||||
const TypeInstPtr* tinst = _gvn.type(objECB)->isa_instptr();
|
||||
assert(tinst != NULL, "ECBobj is null");
|
||||
assert(tinst->klass()->is_loaded(), "ECBobj is not loaded");
|
||||
assert(tinst->is_loaded(), "ECBobj is not loaded");
|
||||
|
||||
// we want to do an instanceof comparison against the AESCrypt class
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
if (!klass_AESCrypt->is_loaded()) {
|
||||
// if AESCrypt is not even loaded, we never take the intrinsic fast path
|
||||
Node* ctrl = control();
|
||||
@ -6925,10 +6925,10 @@ Node* LibraryCallKit::inline_counterMode_AESCrypt_predicate() {
|
||||
// will have same classloader as CipherBlockChaining object
|
||||
const TypeInstPtr* tinst = _gvn.type(objCTR)->isa_instptr();
|
||||
assert(tinst != NULL, "CTRobj is null");
|
||||
assert(tinst->klass()->is_loaded(), "CTRobj is not loaded");
|
||||
assert(tinst->is_loaded(), "CTRobj is not loaded");
|
||||
|
||||
// we want to do an instanceof comparison against the AESCrypt class
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
if (!klass_AESCrypt->is_loaded()) {
|
||||
// if AESCrypt is not even loaded, we never take the intrinsic fast path
|
||||
Node* ctrl = control();
|
||||
@ -7071,12 +7071,12 @@ bool LibraryCallKit::inline_digestBase_implCompress(vmIntrinsics::ID id) {
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
@ -7163,12 +7163,12 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
if (top_src == NULL || top_src->elem() == Type::BOTTOM) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
@ -7229,9 +7229,9 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
|
||||
// get DigestBase klass to lookup for SHA klass
|
||||
const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr();
|
||||
assert(tinst != NULL, "digestBase_obj is not instance???");
|
||||
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
|
||||
assert(tinst->is_loaded(), "DigestBase is not loaded");
|
||||
|
||||
ciKlass* klass_digestBase = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_digestBase_name));
|
||||
ciKlass* klass_digestBase = tinst->instance_klass()->find_klass(ciSymbol::make(klass_digestBase_name));
|
||||
assert(klass_digestBase->is_loaded(), "predicate checks that this class is loaded");
|
||||
ciInstanceKlass* instklass_digestBase = klass_digestBase->as_instance_klass();
|
||||
return inline_digestBase_implCompressMB(digestBase_obj, instklass_digestBase, elem_type, stub_addr, stub_name, src_start, ofs, limit);
|
||||
@ -7305,9 +7305,9 @@ bool LibraryCallKit::inline_galoisCounterMode_AESCrypt() {
|
||||
const TypeAryPtr* top_in = in_type->isa_aryptr();
|
||||
const TypeAryPtr* top_ct = ct_type->isa_aryptr();
|
||||
const TypeAryPtr* top_out = out_type->isa_aryptr();
|
||||
assert(top_in != NULL && top_in->klass() != NULL &&
|
||||
top_ct != NULL && top_ct->klass() != NULL &&
|
||||
top_out != NULL && top_out->klass() != NULL, "args are strange");
|
||||
assert(top_in != NULL && top_in->elem() != Type::BOTTOM &&
|
||||
top_ct != NULL && top_ct->elem() != Type::BOTTOM &&
|
||||
top_out != NULL && top_out->elem() != Type::BOTTOM, "args are strange");
|
||||
|
||||
// checks are the responsibility of the caller
|
||||
Node* in_start = in;
|
||||
@ -7335,8 +7335,8 @@ bool LibraryCallKit::inline_galoisCounterMode_AESCrypt() {
|
||||
// cast it to what we know it will be at runtime
|
||||
const TypeInstPtr* tinst = _gvn.type(gctr_object)->isa_instptr();
|
||||
assert(tinst != NULL, "GCTR obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "GCTR obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(tinst->is_loaded(), "GCTR obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
||||
@ -7387,10 +7387,10 @@ Node* LibraryCallKit::inline_galoisCounterMode_AESCrypt_predicate() {
|
||||
// will have same classloader as CipherBlockChaining object
|
||||
const TypeInstPtr* tinst = _gvn.type(objGCTR)->isa_instptr();
|
||||
assert(tinst != NULL, "GCTR obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "GCTR obj is not loaded");
|
||||
assert(tinst->is_loaded(), "GCTR obj is not loaded");
|
||||
|
||||
// we want to do an instanceof comparison against the AESCrypt class
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
if (!klass_AESCrypt->is_loaded()) {
|
||||
// if AESCrypt is not even loaded, we never take the intrinsic fast path
|
||||
Node* ctrl = control();
|
||||
@ -7448,7 +7448,7 @@ Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate)
|
||||
// get DigestBase klass for instanceOf check
|
||||
const TypeInstPtr* tinst = _gvn.type(digestBaseObj)->isa_instptr();
|
||||
assert(tinst != NULL, "digestBaseObj is null");
|
||||
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
|
||||
assert(tinst->is_loaded(), "DigestBase is not loaded");
|
||||
|
||||
const char* klass_name = NULL;
|
||||
switch (predicate) {
|
||||
@ -7488,7 +7488,7 @@ Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate)
|
||||
|
||||
ciKlass* klass = NULL;
|
||||
if (klass_name != NULL) {
|
||||
klass = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_name));
|
||||
klass = tinst->instance_klass()->find_klass(ciSymbol::make(klass_name));
|
||||
}
|
||||
if ((klass == NULL) || !klass->is_loaded()) {
|
||||
// if none of MD5/SHA/SHA2/SHA5 is loaded, we never take the intrinsic fast path
|
||||
|
@ -678,13 +678,12 @@ bool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArr
|
||||
bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) {
|
||||
GrowableArray <SafePointNode *> safepoints_done;
|
||||
|
||||
ciKlass* klass = NULL;
|
||||
ciInstanceKlass* iklass = NULL;
|
||||
int nfields = 0;
|
||||
int array_base = 0;
|
||||
int element_size = 0;
|
||||
BasicType basic_elem_type = T_ILLEGAL;
|
||||
ciType* elem_type = NULL;
|
||||
const Type* field_type = NULL;
|
||||
|
||||
Node* res = alloc->result_cast();
|
||||
assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result");
|
||||
@ -694,20 +693,18 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <Sa
|
||||
}
|
||||
|
||||
if (res != NULL) {
|
||||
klass = res_type->klass();
|
||||
if (res_type->isa_instptr()) {
|
||||
// find the fields of the class which will be needed for safepoint debug information
|
||||
assert(klass->is_instance_klass(), "must be an instance klass.");
|
||||
iklass = klass->as_instance_klass();
|
||||
iklass = res_type->is_instptr()->instance_klass();
|
||||
nfields = iklass->nof_nonstatic_fields();
|
||||
} else {
|
||||
// find the array's elements which will be needed for safepoint debug information
|
||||
nfields = alloc->in(AllocateNode::ALength)->find_int_con(-1);
|
||||
assert(klass->is_array_klass() && nfields >= 0, "must be an array klass.");
|
||||
elem_type = klass->as_array_klass()->element_type();
|
||||
basic_elem_type = elem_type->basic_type();
|
||||
assert(nfields >= 0, "must be an array klass.");
|
||||
basic_elem_type = res_type->is_aryptr()->elem()->array_element_basic_type();
|
||||
array_base = arrayOopDesc::base_offset_in_bytes(basic_elem_type);
|
||||
element_size = type2aelembytes(basic_elem_type);
|
||||
field_type = res_type->is_aryptr()->elem();
|
||||
}
|
||||
}
|
||||
//
|
||||
@ -737,35 +734,33 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <Sa
|
||||
if (iklass != NULL) {
|
||||
field = iklass->nonstatic_field_at(j);
|
||||
offset = field->offset();
|
||||
elem_type = field->type();
|
||||
ciType* elem_type = field->type();
|
||||
basic_elem_type = field->layout_type();
|
||||
|
||||
// The next code is taken from Parse::do_get_xxx().
|
||||
if (is_reference_type(basic_elem_type)) {
|
||||
if (!elem_type->is_loaded()) {
|
||||
field_type = TypeInstPtr::BOTTOM;
|
||||
} else if (field != NULL && field->is_static_constant()) {
|
||||
ciObject* con = field->constant_value().as_object();
|
||||
// Do not "join" in the previous type; it doesn't add value,
|
||||
// and may yield a vacuous result if the field is of interface type.
|
||||
field_type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
|
||||
assert(field_type != NULL, "field singleton type must be consistent");
|
||||
} else {
|
||||
field_type = TypeOopPtr::make_from_klass(elem_type->as_klass());
|
||||
}
|
||||
if (UseCompressedOops) {
|
||||
field_type = field_type->make_narrowoop();
|
||||
basic_elem_type = T_NARROWOOP;
|
||||
}
|
||||
} else {
|
||||
field_type = Type::get_const_basic_type(basic_elem_type);
|
||||
}
|
||||
} else {
|
||||
offset = array_base + j * (intptr_t)element_size;
|
||||
}
|
||||
|
||||
const Type *field_type;
|
||||
// The next code is taken from Parse::do_get_xxx().
|
||||
if (is_reference_type(basic_elem_type)) {
|
||||
if (!elem_type->is_loaded()) {
|
||||
field_type = TypeInstPtr::BOTTOM;
|
||||
} else if (field != NULL && field->is_static_constant()) {
|
||||
// This can happen if the constant oop is non-perm.
|
||||
ciObject* con = field->constant_value().as_object();
|
||||
// Do not "join" in the previous type; it doesn't add value,
|
||||
// and may yield a vacuous result if the field is of interface type.
|
||||
field_type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
|
||||
assert(field_type != NULL, "field singleton type must be consistent");
|
||||
} else {
|
||||
field_type = TypeOopPtr::make_from_klass(elem_type->as_klass());
|
||||
}
|
||||
if (UseCompressedOops) {
|
||||
field_type = field_type->make_narrowoop();
|
||||
basic_elem_type = T_NARROWOOP;
|
||||
}
|
||||
} else {
|
||||
field_type = Type::get_const_basic_type(basic_elem_type);
|
||||
}
|
||||
|
||||
const TypeOopPtr *field_addr_type = res_type->add_offset(offset)->isa_oopptr();
|
||||
|
||||
Node *field_val = value_from_mem(mem, ctl, basic_elem_type, field_type, field_addr_type, alloc);
|
||||
@ -1024,8 +1019,8 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
|
||||
// Eliminate boxing allocations which are not used
|
||||
// regardless scalar replaceable status.
|
||||
bool boxing_alloc = C->eliminate_boxing() &&
|
||||
tklass->klass()->is_instance_klass() &&
|
||||
tklass->klass()->as_instance_klass()->is_box_klass();
|
||||
tklass->isa_instklassptr() &&
|
||||
tklass->is_instklassptr()->instance_klass()->is_box_klass();
|
||||
if (!alloc->_is_scalar_replaceable && (!boxing_alloc || (res != NULL))) {
|
||||
return false;
|
||||
}
|
||||
@ -1054,7 +1049,7 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
|
||||
CompileLog* log = C->log();
|
||||
if (log != NULL) {
|
||||
log->head("eliminate_allocation type='%d'",
|
||||
log->identify(tklass->klass()));
|
||||
log->identify(tklass->exact_klass()));
|
||||
JVMState* p = alloc->jvms();
|
||||
while (p != NULL) {
|
||||
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
|
||||
@ -1095,7 +1090,7 @@ bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) {
|
||||
CompileLog* log = C->log();
|
||||
if (log != NULL) {
|
||||
log->head("eliminate_boxing type='%d'",
|
||||
log->identify(t->klass()));
|
||||
log->identify(t->instance_klass()));
|
||||
JVMState* p = boxing->jvms();
|
||||
while (p != NULL) {
|
||||
log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
|
||||
@ -1689,9 +1684,13 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc,
|
||||
rawmem = make_store(control, rawmem, object, arrayOopDesc::length_offset_in_bytes(), length, T_INT);
|
||||
// conservatively small header size:
|
||||
header_size = arrayOopDesc::base_offset_in_bytes(T_BYTE);
|
||||
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass();
|
||||
if (k->is_array_klass()) // we know the exact header size in most cases:
|
||||
header_size = Klass::layout_helper_header_size(k->layout_helper());
|
||||
if (_igvn.type(klass_node)->isa_aryklassptr()) { // we know the exact header size in most cases:
|
||||
BasicType elem = _igvn.type(klass_node)->is_klassptr()->as_instance_type()->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(elem, true)) {
|
||||
elem = T_OBJECT;
|
||||
}
|
||||
header_size = Klass::layout_helper_header_size(Klass::array_layout_helper(elem));
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the object body, if necessary.
|
||||
@ -1891,10 +1890,10 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
|
||||
Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest);
|
||||
InitializeNode* init = alloc->initialization();
|
||||
Node* klass_node = alloc->in(AllocateNode::KlassNode);
|
||||
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass();
|
||||
const TypeAryKlassPtr* ary_klass_t = _igvn.type(klass_node)->isa_aryklassptr();
|
||||
address slow_call_address; // Address of slow call
|
||||
if (init != NULL && init->is_complete_with_arraycopy() &&
|
||||
k->is_type_array_klass()) {
|
||||
ary_klass_t && ary_klass_t->elem()->isa_klassptr() == NULL) {
|
||||
// Don't zero type array during slow allocation in VM since
|
||||
// it will be initialized later by arraycopy in compiled code.
|
||||
slow_call_address = OptoRuntime::new_array_nozero_Java();
|
||||
|
@ -1292,14 +1292,14 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
|
||||
BasicType src_elem = T_CONFLICT;
|
||||
BasicType dest_elem = T_CONFLICT;
|
||||
|
||||
if (top_dest != NULL && top_dest->klass() != NULL) {
|
||||
dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (top_src != NULL && top_src->elem() != Type::BOTTOM) {
|
||||
src_elem = top_src->elem()->array_element_basic_type();
|
||||
}
|
||||
if (top_src != NULL && top_src->klass() != NULL) {
|
||||
src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (top_dest != NULL && top_dest->elem() != Type::BOTTOM) {
|
||||
dest_elem = top_dest->elem()->array_element_basic_type();
|
||||
}
|
||||
if (is_reference_type(src_elem)) src_elem = T_OBJECT;
|
||||
if (is_reference_type(dest_elem)) dest_elem = T_OBJECT;
|
||||
if (is_reference_type(src_elem, true)) src_elem = T_OBJECT;
|
||||
if (is_reference_type(dest_elem, true)) dest_elem = T_OBJECT;
|
||||
|
||||
if (ac->is_arraycopy_validated() &&
|
||||
dest_elem != T_CONFLICT &&
|
||||
|
@ -177,7 +177,7 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oo
|
||||
} else if (is_boxed_value_load) {
|
||||
Node* klass = alloc->in(AllocateNode::KlassNode);
|
||||
const TypeKlassPtr* tklass = phase->type(klass)->is_klassptr();
|
||||
if (tklass->klass_is_exact() && !tklass->klass()->equals(t_oop->klass())) {
|
||||
if (tklass->klass_is_exact() && !tklass->exact_klass()->equals(t_oop->is_instptr()->exact_klass())) {
|
||||
result = proj_in->in(TypeFunc::Memory); // not related allocation
|
||||
}
|
||||
}
|
||||
@ -265,11 +265,11 @@ static Node *step_through_mergemem(PhaseGVN *phase, MergeMemNode *mmem, const T
|
||||
// means an array I have not precisely typed yet. Do not do any
|
||||
// alias stuff with it any time soon.
|
||||
const TypeOopPtr *toop = tp->isa_oopptr();
|
||||
if( tp->base() != Type::AnyPtr &&
|
||||
if (tp->base() != Type::AnyPtr &&
|
||||
!(toop &&
|
||||
toop->klass() != NULL &&
|
||||
toop->klass()->is_java_lang_Object() &&
|
||||
toop->offset() == Type::OffsetBot) ) {
|
||||
toop->isa_instptr() &&
|
||||
toop->is_instptr()->instance_klass()->is_java_lang_Object() &&
|
||||
toop->offset() == Type::OffsetBot)) {
|
||||
// compress paths and change unreachable cycles to TOP
|
||||
// If not, we can update the input infinitely along a MergeMem cycle
|
||||
// Equivalent code in PhiNode::Ideal
|
||||
@ -550,7 +550,7 @@ Node* LoadNode::find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, N
|
||||
// is known to be within bounds. This is checked below.
|
||||
if (ary_t != NULL && ld_addp->is_AddP()) {
|
||||
Node* ld_offs = ld_addp->in(AddPNode::Offset);
|
||||
BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType ary_elem = ary_t->elem()->array_element_basic_type();
|
||||
jlong header = arrayOopDesc::base_offset_in_bytes(ary_elem);
|
||||
jlong elemsize = type2aelembytes(ary_elem);
|
||||
|
||||
@ -992,7 +992,9 @@ Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const {
|
||||
addp->set_req(AddPNode::Address, src);
|
||||
|
||||
const TypeAryPtr* ary_t = phase->type(in(MemNode::Address))->isa_aryptr();
|
||||
BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType ary_elem = ary_t->isa_aryptr()->elem()->array_element_basic_type();
|
||||
if (is_reference_type(ary_elem, true)) ary_elem = T_OBJECT;
|
||||
|
||||
uint header = arrayOopDesc::base_offset_in_bytes(ary_elem);
|
||||
uint shift = exact_log2(type2aelembytes(ary_elem));
|
||||
|
||||
@ -1942,7 +1944,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
} else if (tp->base() == Type::InstPtr) {
|
||||
assert( off != Type::OffsetBot ||
|
||||
// arrays can be cast to Objects
|
||||
tp->is_oopptr()->klass()->is_java_lang_Object() ||
|
||||
!tp->isa_instptr() ||
|
||||
tp->is_instptr()->instance_klass()->is_java_lang_Object() ||
|
||||
// unsafe field access may not have a constant offset
|
||||
C->has_unsafe_access(),
|
||||
"Field accesses must be precise" );
|
||||
@ -1958,13 +1961,14 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
}
|
||||
}
|
||||
} else if (tp->base() == Type::KlassPtr || tp->base() == Type::InstKlassPtr || tp->base() == Type::AryKlassPtr) {
|
||||
assert( off != Type::OffsetBot ||
|
||||
// arrays can be cast to Objects
|
||||
tp->is_klassptr()->klass()->is_java_lang_Object() ||
|
||||
// also allow array-loading from the primary supertype
|
||||
// array during subtype checks
|
||||
Opcode() == Op_LoadKlass,
|
||||
"Field accesses must be precise" );
|
||||
assert(off != Type::OffsetBot ||
|
||||
!tp->isa_instklassptr() ||
|
||||
// arrays can be cast to Objects
|
||||
tp->isa_instklassptr()->instance_klass()->is_java_lang_Object() ||
|
||||
// also allow array-loading from the primary supertype
|
||||
// array during subtype checks
|
||||
Opcode() == Op_LoadKlass,
|
||||
"Field accesses must be precise");
|
||||
// For klass/static loads, we expect the _type to be precise
|
||||
} else if (tp->base() == Type::RawPtr && adr->is_Load() && off == 0) {
|
||||
/* With mirrors being an indirect in the Klass*
|
||||
@ -1976,8 +1980,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
Node* adr2 = adr->in(MemNode::Address);
|
||||
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
|
||||
if (tkls != NULL && !StressReflectiveCode) {
|
||||
ciKlass* klass = tkls->klass();
|
||||
if (klass->is_loaded() && tkls->klass_is_exact() && tkls->offset() == in_bytes(Klass::java_mirror_offset())) {
|
||||
if (tkls->is_loaded() && tkls->klass_is_exact() && tkls->offset() == in_bytes(Klass::java_mirror_offset())) {
|
||||
ciKlass* klass = tkls->exact_klass();
|
||||
assert(adr->Opcode() == Op_LoadP, "must load an oop from _java_mirror");
|
||||
assert(Opcode() == Op_LoadP, "must load an oop from _java_mirror");
|
||||
return TypeInstPtr::make(klass->java_mirror());
|
||||
@ -1987,8 +1991,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
|
||||
const TypeKlassPtr *tkls = tp->isa_klassptr();
|
||||
if (tkls != NULL && !StressReflectiveCode) {
|
||||
ciKlass* klass = tkls->klass();
|
||||
if (klass->is_loaded() && tkls->klass_is_exact()) {
|
||||
if (tkls->is_loaded() && tkls->klass_is_exact()) {
|
||||
ciKlass* klass = tkls->exact_klass();
|
||||
// We are loading a field from a Klass metaobject whose identity
|
||||
// is known at compile time (the type is "exact" or "precise").
|
||||
// Check for fields we know are maintained as constants by the VM.
|
||||
@ -2015,17 +2019,24 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
// We can still check if we are loading from the primary_supers array at a
|
||||
// shallow enough depth. Even though the klass is not exact, entries less
|
||||
// than or equal to its super depth are correct.
|
||||
if (klass->is_loaded() ) {
|
||||
ciType *inner = klass;
|
||||
while( inner->is_obj_array_klass() )
|
||||
inner = inner->as_obj_array_klass()->base_element_type();
|
||||
if( inner->is_instance_klass() &&
|
||||
!inner->as_instance_klass()->flags().is_interface() ) {
|
||||
if (tkls->is_loaded()) {
|
||||
ciKlass* klass = NULL;
|
||||
if (tkls->isa_instklassptr()) {
|
||||
klass = tkls->is_instklassptr()->instance_klass();
|
||||
} else {
|
||||
int dims;
|
||||
const Type* inner = tkls->is_aryklassptr()->base_element_type(dims);
|
||||
if (inner->isa_instklassptr()) {
|
||||
klass = inner->is_instklassptr()->instance_klass();
|
||||
klass = ciObjArrayKlass::make(klass, dims);
|
||||
}
|
||||
}
|
||||
if (klass != NULL) {
|
||||
// Compute index into primary_supers array
|
||||
juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*);
|
||||
// Check for overflowing; use unsigned compare to handle the negative case.
|
||||
if( depth < ciKlass::primary_super_limit() &&
|
||||
depth <= klass->super_depth() ) { // allow self-depth checks to handle self-check case
|
||||
if (depth < ciKlass::primary_super_limit() &&
|
||||
depth <= klass->super_depth()) { // allow self-depth checks to handle self-check case
|
||||
// The field is an element of Klass::_primary_supers. Return its (constant) value.
|
||||
// (Folds up type checking code.)
|
||||
assert(Opcode() == Op_LoadKlass, "must load a klass from _primary_supers");
|
||||
@ -2038,10 +2049,9 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
// If the type is enough to determine that the thing is not an array,
|
||||
// we can give the layout_helper a positive interval type.
|
||||
// This will help short-circuit some reflective code.
|
||||
if (tkls->offset() == in_bytes(Klass::layout_helper_offset())
|
||||
&& !klass->is_array_klass() // not directly typed as an array
|
||||
&& !klass->is_interface() // specifically not Serializable & Cloneable
|
||||
&& !klass->is_java_lang_Object() // not the supertype of all T[]
|
||||
if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) &&
|
||||
tkls->isa_instklassptr() && // not directly typed as an array
|
||||
!tkls->is_instklassptr()->instance_klass()->is_java_lang_Object() // not the supertype of all T[] and specifically not Serializable & Cloneable
|
||||
) {
|
||||
// Note: When interfaces are reliable, we can narrow the interface
|
||||
// test to (klass != Serializable && klass != Cloneable).
|
||||
@ -2274,7 +2284,7 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
|
||||
// Return a more precise klass, if possible
|
||||
const TypeInstPtr *tinst = tp->isa_instptr();
|
||||
if (tinst != NULL) {
|
||||
ciInstanceKlass* ik = tinst->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = tinst->instance_klass();
|
||||
int offset = tinst->offset();
|
||||
if (ik == phase->C->env()->Class_klass()
|
||||
&& (offset == java_lang_Class::klass_offset() ||
|
||||
@ -2302,84 +2312,38 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
|
||||
}
|
||||
// non-constant mirror, so we can't tell what's going on
|
||||
}
|
||||
if( !ik->is_loaded() )
|
||||
if (!tinst->is_loaded())
|
||||
return _type; // Bail out if not loaded
|
||||
if (offset == oopDesc::klass_offset_in_bytes()) {
|
||||
if (tinst->klass_is_exact()) {
|
||||
return TypeKlassPtr::make(ik);
|
||||
}
|
||||
// See if we can become precise: no subklasses and no interface
|
||||
// (Note: We need to support verified interfaces.)
|
||||
if (!ik->is_interface() && !ik->has_subklass()) {
|
||||
// Add a dependence; if any subclass added we need to recompile
|
||||
if (!ik->is_final()) {
|
||||
// %%% should use stronger assert_unique_concrete_subtype instead
|
||||
phase->C->dependencies()->assert_leaf_type(ik);
|
||||
}
|
||||
// Return precise klass
|
||||
return TypeKlassPtr::make(ik);
|
||||
}
|
||||
|
||||
// Return root of possible klass
|
||||
return TypeKlassPtr::make(TypePtr::NotNull, ik, 0/*offset*/);
|
||||
return tinst->as_klass_type(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for loading klass from an array
|
||||
const TypeAryPtr *tary = tp->isa_aryptr();
|
||||
if( tary != NULL ) {
|
||||
ciKlass *tary_klass = tary->klass();
|
||||
if (tary_klass != NULL // can be NULL when at BOTTOM or TOP
|
||||
&& tary->offset() == oopDesc::klass_offset_in_bytes()) {
|
||||
if (tary->klass_is_exact()) {
|
||||
return TypeKlassPtr::make(tary_klass);
|
||||
}
|
||||
ciArrayKlass *ak = tary->klass()->as_array_klass();
|
||||
// If the klass is an object array, we defer the question to the
|
||||
// array component klass.
|
||||
if( ak->is_obj_array_klass() ) {
|
||||
assert( ak->is_loaded(), "" );
|
||||
ciKlass *base_k = ak->as_obj_array_klass()->base_element_klass();
|
||||
if( base_k->is_loaded() && base_k->is_instance_klass() ) {
|
||||
ciInstanceKlass* ik = base_k->as_instance_klass();
|
||||
// See if we can become precise: no subklasses and no interface
|
||||
if (!ik->is_interface() && !ik->has_subklass()) {
|
||||
// Add a dependence; if any subclass added we need to recompile
|
||||
if (!ik->is_final()) {
|
||||
phase->C->dependencies()->assert_leaf_type(ik);
|
||||
}
|
||||
// Return precise array klass
|
||||
return TypeKlassPtr::make(ak);
|
||||
}
|
||||
}
|
||||
return TypeKlassPtr::make(TypePtr::NotNull, ak, 0/*offset*/);
|
||||
} else { // Found a type-array?
|
||||
assert( ak->is_type_array_klass(), "" );
|
||||
return TypeKlassPtr::make(ak); // These are always precise
|
||||
}
|
||||
}
|
||||
if (tary != NULL && tary->elem() != Type::BOTTOM &&
|
||||
tary->offset() == oopDesc::klass_offset_in_bytes()) {
|
||||
return tary->as_klass_type(true);
|
||||
}
|
||||
|
||||
// Check for loading klass from an array klass
|
||||
const TypeKlassPtr *tkls = tp->isa_klassptr();
|
||||
if (tkls != NULL && !StressReflectiveCode) {
|
||||
ciKlass* klass = tkls->klass();
|
||||
if( !klass->is_loaded() )
|
||||
return _type; // Bail out if not loaded
|
||||
if( klass->is_obj_array_klass() &&
|
||||
if (!tkls->is_loaded())
|
||||
return _type; // Bail out if not loaded
|
||||
if (tkls->isa_aryklassptr() && tkls->is_aryklassptr()->elem()->isa_klassptr() &&
|
||||
tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) {
|
||||
ciKlass* elem = klass->as_obj_array_klass()->element_klass();
|
||||
// // Always returning precise element type is incorrect,
|
||||
// // e.g., element type could be object and array may contain strings
|
||||
// return TypeKlassPtr::make(TypePtr::Constant, elem, 0);
|
||||
|
||||
// The array's TypeKlassPtr was declared 'precise' or 'not precise'
|
||||
// according to the element type's subclassing.
|
||||
return TypeKlassPtr::make(tkls->ptr(), elem, 0/*offset*/);
|
||||
return tkls->is_aryklassptr()->elem();
|
||||
}
|
||||
if( klass->is_instance_klass() && tkls->klass_is_exact() &&
|
||||
if (tkls->isa_instklassptr() != NULL && tkls->klass_is_exact() &&
|
||||
tkls->offset() == in_bytes(Klass::super_offset())) {
|
||||
ciKlass* sup = klass->as_instance_klass()->super();
|
||||
ciKlass* sup = tkls->is_instklassptr()->instance_klass()->super();
|
||||
// The field is Klass::_super. Return its (constant) value.
|
||||
// (Folds up the 2nd indirection in aClassConstant.getSuperClass().)
|
||||
return sup ? TypeKlassPtr::make(sup) : TypePtr::NULL_PTR;
|
||||
@ -2434,7 +2398,7 @@ Node* LoadNode::klass_identity_common(PhaseGVN* phase) {
|
||||
// mirrors may appear in debug info, but we could clean them out by
|
||||
// introducing a new debug info operator for Klass.java_mirror).
|
||||
|
||||
if (toop->isa_instptr() && toop->klass() == phase->C->env()->Class_klass()
|
||||
if (toop->isa_instptr() && toop->is_instptr()->instance_klass() == phase->C->env()->Class_klass()
|
||||
&& offset == java_lang_Class::klass_offset()) {
|
||||
if (base->is_Load()) {
|
||||
Node* base2 = base->in(MemNode::Address);
|
||||
@ -2442,8 +2406,7 @@ Node* LoadNode::klass_identity_common(PhaseGVN* phase) {
|
||||
Node* adr2 = base2->in(MemNode::Address);
|
||||
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
|
||||
if (tkls != NULL && !tkls->empty()
|
||||
&& (tkls->klass()->is_instance_klass() ||
|
||||
tkls->klass()->is_array_klass())
|
||||
&& (tkls->isa_instklassptr() || tkls->isa_aryklassptr())
|
||||
&& adr2->is_AddP()
|
||||
) {
|
||||
int mirror_field = in_bytes(Klass::java_mirror_offset());
|
||||
@ -4497,7 +4460,7 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr,
|
||||
assert(alloc != NULL, "must be present");
|
||||
if (alloc != NULL && alloc->Opcode() == Op_Allocate) {
|
||||
Node* klass_node = alloc->in(AllocateNode::KlassNode);
|
||||
ciKlass* k = phase->type(klass_node)->is_klassptr()->klass();
|
||||
ciKlass* k = phase->type(klass_node)->is_instklassptr()->instance_klass();
|
||||
if (zeroes_done == k->layout_helper())
|
||||
zeroes_done = size_limit;
|
||||
}
|
||||
|
@ -1807,11 +1807,11 @@ void Node::dump(const char* suffix, bool mark, outputStream *st) const {
|
||||
|
||||
const Type *t = bottom_type();
|
||||
|
||||
if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) {
|
||||
if (t != NULL && (t->isa_instptr() || t->isa_instklassptr())) {
|
||||
const TypeInstPtr *toop = t->isa_instptr();
|
||||
const TypeKlassPtr *tkls = t->isa_klassptr();
|
||||
ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL );
|
||||
if (klass && klass->is_loaded() && klass->is_interface()) {
|
||||
const TypeInstKlassPtr *tkls = t->isa_instklassptr();
|
||||
ciKlass* klass = toop ? toop->instance_klass() : (tkls ? tkls->instance_klass() : NULL );
|
||||
if (klass && klass->is_loaded() && ((toop && toop->is_interface()) || (tkls && tkls->is_interface()))) {
|
||||
st->print(" Interface:");
|
||||
} else if (toop) {
|
||||
st->print(" Oop:");
|
||||
|
@ -816,7 +816,7 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
|
||||
|
||||
ObjectValue* sv = sv_for_node_id(objs, spobj->_idx);
|
||||
if (sv == NULL) {
|
||||
ciKlass* cik = t->is_oopptr()->klass();
|
||||
ciKlass* cik = t->is_oopptr()->exact_klass();
|
||||
assert(cik->is_instance_klass() ||
|
||||
cik->is_array_klass(), "Not supported allocation.");
|
||||
sv = new ObjectValue(spobj->_idx,
|
||||
@ -1089,7 +1089,7 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
|
||||
scval = PhaseOutput::sv_for_node_id(objs, spobj->_idx);
|
||||
if (scval == NULL) {
|
||||
const Type *t = spobj->bottom_type();
|
||||
ciKlass* cik = t->is_oopptr()->klass();
|
||||
ciKlass* cik = t->is_oopptr()->exact_klass();
|
||||
assert(cik->is_instance_klass() ||
|
||||
cik->is_array_klass(), "Not supported allocation.");
|
||||
ObjectValue* sv = new ObjectValue(spobj->_idx,
|
||||
|
@ -153,7 +153,7 @@ Node* Parse::check_interpreter_type(Node* l, const Type* type,
|
||||
|
||||
// TypeFlow may assert null-ness if a type appears unloaded.
|
||||
if (type == TypePtr::NULL_PTR ||
|
||||
(tp != NULL && !tp->klass()->is_loaded())) {
|
||||
(tp != NULL && !tp->is_loaded())) {
|
||||
// Value must be null, not a real oop.
|
||||
Node* chk = _gvn.transform( new CmpPNode(l, null()) );
|
||||
Node* tst = _gvn.transform( new BoolNode(chk, BoolTest::eq) );
|
||||
@ -169,10 +169,10 @@ Node* Parse::check_interpreter_type(Node* l, const Type* type,
|
||||
// When paths are cut off, values at later merge points can rise
|
||||
// toward more specific classes. Make sure these specific classes
|
||||
// are still in effect.
|
||||
if (tp != NULL && tp->klass() != C->env()->Object_klass()) {
|
||||
if (tp != NULL && !tp->is_same_java_type_as(TypeInstPtr::BOTTOM)) {
|
||||
// TypeFlow asserted a specific object type. Value must have that type.
|
||||
Node* bad_type_ctrl = NULL;
|
||||
l = gen_checkcast(l, makecon(TypeKlassPtr::make(tp->klass())), &bad_type_ctrl);
|
||||
l = gen_checkcast(l, makecon(tp->as_klass_type()->cast_to_exactness(true)), &bad_type_ctrl);
|
||||
bad_type_exit->control()->add_req(bad_type_ctrl);
|
||||
}
|
||||
|
||||
@ -798,7 +798,7 @@ void Parse::build_exits() {
|
||||
// becomes loaded during the subsequent parsing, the loaded and unloaded
|
||||
// types will not join when we transform and push in do_exits().
|
||||
const TypeOopPtr* ret_oop_type = ret_type->isa_oopptr();
|
||||
if (ret_oop_type && !ret_oop_type->klass()->is_loaded()) {
|
||||
if (ret_oop_type && !ret_oop_type->is_loaded()) {
|
||||
ret_type = TypeOopPtr::BOTTOM;
|
||||
}
|
||||
int ret_size = type2size[ret_type->basic_type()];
|
||||
@ -2080,9 +2080,9 @@ void Parse::call_register_finalizer() {
|
||||
"must have non-null instance type");
|
||||
|
||||
const TypeInstPtr *tinst = receiver->bottom_type()->isa_instptr();
|
||||
if (tinst != NULL && tinst->klass()->is_loaded() && !tinst->klass_is_exact()) {
|
||||
if (tinst != NULL && tinst->is_loaded() && !tinst->klass_is_exact()) {
|
||||
// The type isn't known exactly so see if CHA tells us anything.
|
||||
ciInstanceKlass* ik = tinst->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = tinst->instance_klass();
|
||||
if (!Dependencies::has_finalizable_subclass(ik)) {
|
||||
// No finalizable subclasses so skip the dynamic check.
|
||||
C->dependencies()->assert_has_no_finalizable_subclasses(ik);
|
||||
@ -2255,11 +2255,11 @@ void Parse::return_current(Node* value) {
|
||||
// here.
|
||||
Node* phi = _exits.argument(0);
|
||||
const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
|
||||
if (tr && tr->klass()->is_loaded() &&
|
||||
tr->klass()->is_interface()) {
|
||||
if (tr && tr->is_loaded() &&
|
||||
tr->is_interface()) {
|
||||
const TypeInstPtr *tp = value->bottom_type()->isa_instptr();
|
||||
if (tp && tp->klass()->is_loaded() &&
|
||||
!tp->klass()->is_interface()) {
|
||||
if (tp && tp->is_loaded() &&
|
||||
!tp->is_interface()) {
|
||||
// sharpen the type eagerly; this eases certain assert checking
|
||||
if (tp->higher_equal(TypeInstPtr::NOTNULL))
|
||||
tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr();
|
||||
@ -2270,8 +2270,8 @@ void Parse::return_current(Node* value) {
|
||||
const TypeInstPtr* phi_tip;
|
||||
const TypeInstPtr* val_tip;
|
||||
Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tip, &val_tip);
|
||||
if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->klass()->is_interface() &&
|
||||
val_tip != NULL && val_tip->is_loaded() && !val_tip->klass()->is_interface()) {
|
||||
if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->is_interface() &&
|
||||
val_tip != NULL && val_tip->is_loaded() && !val_tip->is_interface()) {
|
||||
value = _gvn.transform(new CheckCastPPNode(0, value, phi->bottom_type()));
|
||||
}
|
||||
}
|
||||
|
@ -124,9 +124,9 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) {
|
||||
const Type* el = elemtype->make_ptr();
|
||||
if (el && el->isa_instptr()) {
|
||||
const TypeInstPtr* toop = el->is_instptr();
|
||||
if (toop->klass()->as_instance_klass()->unique_concrete_subklass()) {
|
||||
if (toop->instance_klass()->unique_concrete_subklass()) {
|
||||
// If we load from "AbstractClass[]" we must see "ConcreteSubClass".
|
||||
const Type* subklass = Type::get_const_type(toop->klass());
|
||||
const Type* subklass = Type::get_const_type(toop->instance_klass());
|
||||
elemtype = subklass->join_speculative(el);
|
||||
}
|
||||
}
|
||||
@ -143,13 +143,14 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type*& elemtype) {
|
||||
if (C->log() != NULL) C->log()->elem("observe that='!need_range_check'");
|
||||
}
|
||||
|
||||
ciKlass * arytype_klass = arytype->klass();
|
||||
if ((arytype_klass != NULL) && (!arytype_klass->is_loaded())) {
|
||||
if (!arytype->is_loaded()) {
|
||||
// Only fails for some -Xcomp runs
|
||||
// The class is unloaded. We have to run this bytecode in the interpreter.
|
||||
ciKlass* klass = arytype->unloaded_klass();
|
||||
|
||||
uncommon_trap(Deoptimization::Reason_unloaded,
|
||||
Deoptimization::Action_reinterpret,
|
||||
arytype->klass(), "!loaded array");
|
||||
klass, "!loaded array");
|
||||
return top();
|
||||
}
|
||||
|
||||
|
@ -72,16 +72,17 @@ void Parse::do_checkcast() {
|
||||
// _from_ is not loaded, and value is not null. If the value _is_ NULL,
|
||||
// then the checkcast does nothing.
|
||||
const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr();
|
||||
if (!will_link || (tp && tp->klass() && !tp->klass()->is_loaded())) {
|
||||
if (!will_link || (tp && !tp->is_loaded())) {
|
||||
if (C->log() != NULL) {
|
||||
if (!will_link) {
|
||||
C->log()->elem("assert_null reason='checkcast' klass='%d'",
|
||||
C->log()->identify(klass));
|
||||
}
|
||||
if (tp && tp->klass() && !tp->klass()->is_loaded()) {
|
||||
if (tp && !tp->is_loaded()) {
|
||||
// %%% Cannot happen?
|
||||
ciKlass* klass = tp->unloaded_klass();
|
||||
C->log()->elem("assert_null reason='checkcast source' klass='%d'",
|
||||
C->log()->identify(tp->klass()));
|
||||
C->log()->identify(klass));
|
||||
}
|
||||
}
|
||||
null_assert(obj);
|
||||
@ -194,27 +195,30 @@ void Parse::array_store_check() {
|
||||
// (If no MDO at all, hope for the best, until a trap actually occurs.)
|
||||
|
||||
// Make a constant out of the inexact array klass
|
||||
const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr();
|
||||
Node* con = makecon(extak);
|
||||
Node* cmp = _gvn.transform(new CmpPNode( array_klass, con ));
|
||||
Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq ));
|
||||
Node* ctrl= control();
|
||||
{ BuildCutout unless(this, bol, PROB_MAX);
|
||||
uncommon_trap(Deoptimization::Reason_array_check,
|
||||
Deoptimization::Action_maybe_recompile,
|
||||
tak->klass());
|
||||
}
|
||||
if (stopped()) { // MUST uncommon-trap?
|
||||
set_control(ctrl); // Then Don't Do It, just fall into the normal checking
|
||||
} else { // Cast array klass to exactness:
|
||||
// Use the exact constant value we know it is.
|
||||
replace_in_map(array_klass,con);
|
||||
CompileLog* log = C->log();
|
||||
if (log != NULL) {
|
||||
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
|
||||
log->identify(tak->klass()));
|
||||
const TypeKlassPtr *extak = tak->cast_to_exactness(true);
|
||||
|
||||
if (extak->exact_klass(true) != NULL) {
|
||||
Node* con = makecon(extak);
|
||||
Node* cmp = _gvn.transform(new CmpPNode( array_klass, con ));
|
||||
Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq ));
|
||||
Node* ctrl= control();
|
||||
{ BuildCutout unless(this, bol, PROB_MAX);
|
||||
uncommon_trap(Deoptimization::Reason_array_check,
|
||||
Deoptimization::Action_maybe_recompile,
|
||||
extak->exact_klass());
|
||||
}
|
||||
if (stopped()) { // MUST uncommon-trap?
|
||||
set_control(ctrl); // Then Don't Do It, just fall into the normal checking
|
||||
} else { // Cast array klass to exactness:
|
||||
// Use the exact constant value we know it is.
|
||||
replace_in_map(array_klass,con);
|
||||
CompileLog* log = C->log();
|
||||
if (log != NULL) {
|
||||
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
|
||||
log->identify(extak->exact_klass()));
|
||||
}
|
||||
array_klass = con; // Use cast value moving forward
|
||||
}
|
||||
array_klass = con; // Use cast value moving forward
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,4 +302,3 @@ void Parse::dump_map_adr_mem() const {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -970,77 +970,44 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
|
||||
}
|
||||
|
||||
// See if it is 2 unrelated classes.
|
||||
const TypeOopPtr* oop_p0 = r0->isa_oopptr();
|
||||
const TypeOopPtr* oop_p1 = r1->isa_oopptr();
|
||||
bool both_oop_ptr = oop_p0 && oop_p1;
|
||||
|
||||
if (both_oop_ptr) {
|
||||
Node* in1 = in(1)->uncast();
|
||||
Node* in2 = in(2)->uncast();
|
||||
AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL);
|
||||
AllocateNode* alloc2 = AllocateNode::Ideal_allocation(in2, NULL);
|
||||
if (MemNode::detect_ptr_independence(in1, alloc1, in2, alloc2, NULL)) {
|
||||
return TypeInt::CC_GT; // different pointers
|
||||
}
|
||||
}
|
||||
|
||||
const TypeKlassPtr* klass_p0 = r0->isa_klassptr();
|
||||
const TypeKlassPtr* klass_p1 = r1->isa_klassptr();
|
||||
|
||||
if (both_oop_ptr || (klass_p0 && klass_p1)) { // both or neither are klass pointers
|
||||
ciKlass* klass0 = NULL;
|
||||
bool xklass0 = false;
|
||||
ciKlass* klass1 = NULL;
|
||||
bool xklass1 = false;
|
||||
|
||||
if (oop_p0) {
|
||||
klass0 = oop_p0->klass();
|
||||
xklass0 = oop_p0->klass_is_exact();
|
||||
} else {
|
||||
assert(klass_p0, "must be non-null if oop_p0 is null");
|
||||
klass0 = klass_p0->klass();
|
||||
xklass0 = klass_p0->klass_is_exact();
|
||||
}
|
||||
|
||||
if (oop_p1) {
|
||||
klass1 = oop_p1->klass();
|
||||
xklass1 = oop_p1->klass_is_exact();
|
||||
} else {
|
||||
assert(klass_p1, "must be non-null if oop_p1 is null");
|
||||
klass1 = klass_p1->klass();
|
||||
xklass1 = klass_p1->klass_is_exact();
|
||||
}
|
||||
|
||||
if (klass0 && klass1 &&
|
||||
klass0->is_loaded() && !klass0->is_interface() && // do not trust interfaces
|
||||
klass1->is_loaded() && !klass1->is_interface() &&
|
||||
(!klass0->is_obj_array_klass() ||
|
||||
!klass0->as_obj_array_klass()->base_element_klass()->is_interface()) &&
|
||||
(!klass1->is_obj_array_klass() ||
|
||||
!klass1->as_obj_array_klass()->base_element_klass()->is_interface())) {
|
||||
bool unrelated_classes = false;
|
||||
// See if neither subclasses the other, or if the class on top
|
||||
// is precise. In either of these cases, the compare is known
|
||||
// to fail if at least one of the pointers is provably not null.
|
||||
if (klass0->equals(klass1)) { // if types are unequal but klasses are equal
|
||||
// Do nothing; we know nothing for imprecise types
|
||||
} else if (klass0->is_subtype_of(klass1)) {
|
||||
// If klass1's type is PRECISE, then classes are unrelated.
|
||||
unrelated_classes = xklass1;
|
||||
} else if (klass1->is_subtype_of(klass0)) {
|
||||
// If klass0's type is PRECISE, then classes are unrelated.
|
||||
unrelated_classes = xklass0;
|
||||
} else { // Neither subtypes the other
|
||||
unrelated_classes = true;
|
||||
const TypeOopPtr* p0 = r0->isa_oopptr();
|
||||
const TypeOopPtr* p1 = r1->isa_oopptr();
|
||||
const TypeKlassPtr* k0 = r0->isa_klassptr();
|
||||
const TypeKlassPtr* k1 = r1->isa_klassptr();
|
||||
if ((p0 && p1) || (k0 && k1)) {
|
||||
if (p0 && p1) {
|
||||
Node* in1 = in(1)->uncast();
|
||||
Node* in2 = in(2)->uncast();
|
||||
AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL);
|
||||
AllocateNode* alloc2 = AllocateNode::Ideal_allocation(in2, NULL);
|
||||
if (MemNode::detect_ptr_independence(in1, alloc1, in2, alloc2, NULL)) {
|
||||
return TypeInt::CC_GT; // different pointers
|
||||
}
|
||||
if (unrelated_classes) {
|
||||
// The oops classes are known to be unrelated. If the joined PTRs of
|
||||
// two oops is not Null and not Bottom, then we are sure that one
|
||||
// of the two oops is non-null, and the comparison will always fail.
|
||||
TypePtr::PTR jp = r0->join_ptr(r1->_ptr);
|
||||
if (jp != TypePtr::Null && jp != TypePtr::BotPTR) {
|
||||
return TypeInt::CC_GT;
|
||||
}
|
||||
}
|
||||
bool xklass0 = p0 ? p0->klass_is_exact() : k0->klass_is_exact();
|
||||
bool xklass1 = p1 ? p1->klass_is_exact() : k1->klass_is_exact();
|
||||
bool unrelated_classes = false;
|
||||
|
||||
if ((p0 && p0->is_same_java_type_as(p1)) ||
|
||||
(k0 && k0->is_same_java_type_as(k1))) {
|
||||
} else if ((p0 && !p1->maybe_java_subtype_of(p0) && !p0->maybe_java_subtype_of(p1)) ||
|
||||
(k0 && !k1->maybe_java_subtype_of(k0) && !k0->maybe_java_subtype_of(k1))) {
|
||||
unrelated_classes = true;
|
||||
} else if ((p0 && !p1->maybe_java_subtype_of(p0)) ||
|
||||
(k0 && !k1->maybe_java_subtype_of(k0))) {
|
||||
unrelated_classes = xklass1;
|
||||
} else if ((p0 && !p0->maybe_java_subtype_of(p1)) ||
|
||||
(k0 && !k0->maybe_java_subtype_of(k1))) {
|
||||
unrelated_classes = xklass0;
|
||||
}
|
||||
|
||||
if (unrelated_classes) {
|
||||
// The oops classes are known to be unrelated. If the joined PTRs of
|
||||
// two oops is not Null and not Bottom, then we are sure that one
|
||||
// of the two oops is non-null, and the comparison will always fail.
|
||||
TypePtr::PTR jp = r0->join_ptr(r1->_ptr);
|
||||
if (jp != TypePtr::Null && jp != TypePtr::BotPTR) {
|
||||
return TypeInt::CC_GT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1070,7 +1037,7 @@ static inline Node* isa_java_mirror_load(PhaseGVN* phase, Node* n) {
|
||||
if (n->Opcode() != Op_LoadP) return NULL;
|
||||
|
||||
const TypeInstPtr* tp = phase->type(n)->isa_instptr();
|
||||
if (!tp || tp->klass() != phase->C->env()->Class_klass()) return NULL;
|
||||
if (!tp || tp->instance_klass() != phase->C->env()->Class_klass()) return NULL;
|
||||
|
||||
Node* adr = n->in(MemNode::Address);
|
||||
// First load from OopHandle: ((OopHandle)mirror)->resolve(); may need barrier.
|
||||
@ -1150,7 +1117,7 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
|
||||
if (t2 == NULL || !t2->klass_is_exact())
|
||||
return NULL;
|
||||
// Get the constant klass we are comparing to.
|
||||
ciKlass* superklass = t2->klass();
|
||||
ciKlass* superklass = t2->exact_klass();
|
||||
|
||||
// Now check for LoadKlass on left.
|
||||
Node* ldk1 = in(1);
|
||||
|
@ -33,60 +33,21 @@
|
||||
#include "opto/subtypenode.hpp"
|
||||
|
||||
const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const {
|
||||
ciKlass* superk = super_t->is_klassptr()->klass();
|
||||
ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass();
|
||||
|
||||
bool xsubk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass_is_exact() : sub_t->is_oopptr()->klass_is_exact();
|
||||
|
||||
const TypeKlassPtr* superk = super_t->isa_klassptr();
|
||||
const TypeKlassPtr* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr() : sub_t->is_oopptr()->as_klass_type();
|
||||
|
||||
// Oop can't be a subtype of abstract type that has no subclass.
|
||||
if (sub_t->isa_oopptr() && superk->is_instance_klass() &&
|
||||
!superk->is_interface() && superk->is_abstract() &&
|
||||
!superk->as_instance_klass()->has_subklass()) {
|
||||
Compile::current()->dependencies()->assert_leaf_type(superk);
|
||||
return TypeInt::CC_GT;
|
||||
}
|
||||
|
||||
// Similar to logic in CmpPNode::sub()
|
||||
|
||||
// Interfaces can't be trusted unless the subclass is an exact
|
||||
// interface (it can then only be a constant) or the subclass is an
|
||||
// exact array of interfaces (a newly allocated array of interfaces
|
||||
// for instance)
|
||||
if (superk && subk &&
|
||||
superk->is_loaded() && !superk->is_interface() &&
|
||||
subk->is_loaded() && (!subk->is_interface() || xsubk) &&
|
||||
(!superk->is_obj_array_klass() ||
|
||||
!superk->as_obj_array_klass()->base_element_klass()->is_interface()) &&
|
||||
(!subk->is_obj_array_klass() ||
|
||||
!subk->as_obj_array_klass()->base_element_klass()->is_interface() ||
|
||||
xsubk)) {
|
||||
bool unrelated_classes = false;
|
||||
if (superk->equals(subk)) {
|
||||
// skip
|
||||
} else if (superk->is_subtype_of(subk)) {
|
||||
// If the subclass is exact then the superclass is a subtype of
|
||||
// the subclass. Given they're no equals, that subtype check can
|
||||
// only fail.
|
||||
unrelated_classes = xsubk;
|
||||
} else if (subk->is_subtype_of(superk)) {
|
||||
// skip
|
||||
} else {
|
||||
// Neither class subtypes the other: they are unrelated and this
|
||||
// type check is known to fail.
|
||||
unrelated_classes = true;
|
||||
}
|
||||
if (unrelated_classes) {
|
||||
TypePtr::PTR jp = sub_t->is_ptr()->join_ptr(super_t->is_ptr()->_ptr);
|
||||
if (jp != TypePtr::Null && jp != TypePtr::BotPTR) {
|
||||
return TypeInt::CC_GT;
|
||||
}
|
||||
if (sub_t->isa_oopptr() && superk->isa_instklassptr() && superk->klass_is_exact()) {
|
||||
ciKlass* superklass = superk->exact_klass();
|
||||
if (!superklass->is_interface() && superklass->is_abstract() &&
|
||||
!superklass->as_instance_klass()->has_subklass()) {
|
||||
Compile::current()->dependencies()->assert_leaf_type(superklass);
|
||||
return TypeInt::CC_GT;
|
||||
}
|
||||
}
|
||||
|
||||
if (super_t->singleton()) {
|
||||
if (subk != NULL) {
|
||||
switch (Compile::current()->static_subtype_check(superk, subk)) {
|
||||
if (subk != NULL) {
|
||||
switch (Compile::current()->static_subtype_check(superk, subk)) {
|
||||
case Compile::SSC_always_false:
|
||||
return TypeInt::CC_GT;
|
||||
case Compile::SSC_always_true:
|
||||
@ -96,7 +57,6 @@ const Type* SubTypeCheckNode::sub(const Type* sub_t, const Type* super_t) const
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,8 +163,8 @@ bool SubTypeCheckNode::verify(PhaseGVN* phase) {
|
||||
const Type* sub_t = phase->type(obj_or_subklass);
|
||||
const Type* super_t = phase->type(superklass);
|
||||
|
||||
ciKlass* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr()->klass() : sub_t->is_oopptr()->klass(); // can be NULL for bottom[]
|
||||
ciKlass* superk = super_t->is_klassptr()->klass();
|
||||
const TypeKlassPtr* superk = super_t->isa_klassptr();
|
||||
const TypeKlassPtr* subk = sub_t->isa_klassptr() ? sub_t->is_klassptr() : sub_t->is_oopptr()->as_klass_type();
|
||||
|
||||
if (super_t->singleton() && subk != NULL) {
|
||||
Node* subklass = NULL;
|
||||
|
@ -791,8 +791,8 @@ bool Type::interface_vs_oop_helper(const Type *t) const {
|
||||
const TypeInstPtr* this_inst = this_ptr->isa_instptr();
|
||||
const TypeInstPtr* t_inst = t_ptr->isa_instptr();
|
||||
if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
|
||||
bool this_interface = this_inst->klass()->is_interface();
|
||||
bool t_interface = t_inst->klass()->is_interface();
|
||||
bool this_interface = this_inst->is_interface();
|
||||
bool t_interface = t_inst->is_interface();
|
||||
result = this_interface ^ t_interface;
|
||||
}
|
||||
|
||||
@ -2276,7 +2276,7 @@ int TypeAry::hash(void) const {
|
||||
/**
|
||||
* Return same type without a speculative part in the element
|
||||
*/
|
||||
const Type* TypeAry::remove_speculative() const {
|
||||
const TypeAry* TypeAry::remove_speculative() const {
|
||||
return make(_elem->remove_speculative(), _size, _stable);
|
||||
}
|
||||
|
||||
@ -2561,7 +2561,7 @@ const TypePtr *TypePtr::make(TYPES t, enum PTR ptr, int offset, const TypePtr* s
|
||||
}
|
||||
|
||||
//------------------------------cast_to_ptr_type-------------------------------
|
||||
const Type *TypePtr::cast_to_ptr_type(PTR ptr) const {
|
||||
const TypePtr* TypePtr::cast_to_ptr_type(PTR ptr) const {
|
||||
assert(_base == AnyPtr, "subclass must override cast_to_ptr_type");
|
||||
if( ptr == _ptr ) return this;
|
||||
return make(_base, ptr, _offset, _speculative, _inline_depth);
|
||||
@ -2687,6 +2687,10 @@ const TypePtr *TypePtr::add_offset( intptr_t offset ) const {
|
||||
return make(AnyPtr, _ptr, xadd_offset(offset), _speculative, _inline_depth);
|
||||
}
|
||||
|
||||
const TypePtr *TypePtr::with_offset(intptr_t offset) const {
|
||||
return make(AnyPtr, _ptr, offset, _speculative, _inline_depth);
|
||||
}
|
||||
|
||||
//------------------------------eq---------------------------------------------
|
||||
// Structural equality check for Type representations
|
||||
bool TypePtr::eq( const Type *t ) const {
|
||||
@ -2704,7 +2708,7 @@ int TypePtr::hash(void) const {
|
||||
/**
|
||||
* Return same type without a speculative part
|
||||
*/
|
||||
const Type* TypePtr::remove_speculative() const {
|
||||
const TypePtr* TypePtr::remove_speculative() const {
|
||||
if (_speculative == NULL) {
|
||||
return this;
|
||||
}
|
||||
@ -2839,6 +2843,13 @@ const TypePtr* TypePtr::add_offset_speculative(intptr_t offset) const {
|
||||
return _speculative->add_offset(offset)->is_ptr();
|
||||
}
|
||||
|
||||
const TypePtr* TypePtr::with_offset_speculative(intptr_t offset) const {
|
||||
if (_speculative == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return _speculative->with_offset(offset)->is_ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
* return exact klass from the speculative type if there's one
|
||||
*/
|
||||
@ -3094,7 +3105,7 @@ const Type *TypeRawPtr::xdual() const {
|
||||
}
|
||||
|
||||
//------------------------------add_offset-------------------------------------
|
||||
const TypePtr *TypeRawPtr::add_offset( intptr_t offset ) const {
|
||||
const TypePtr* TypeRawPtr::add_offset(intptr_t offset) const {
|
||||
if( offset == OffsetTop ) return BOTTOM; // Undefined offset-> undefined pointer
|
||||
if( offset == OffsetBot ) return BOTTOM; // Unknown offset-> unknown pointer
|
||||
if( offset == 0 ) return this; // No change
|
||||
@ -3245,7 +3256,7 @@ const TypeOopPtr *TypeOopPtr::cast_to_instance_id(int instance_id) const {
|
||||
}
|
||||
|
||||
//-----------------------------cast_to_exactness-------------------------------
|
||||
const Type *TypeOopPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
const TypeOopPtr* TypeOopPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
// There is no such thing as an exact general oop.
|
||||
// Return self unchanged.
|
||||
return this;
|
||||
@ -3570,10 +3581,14 @@ const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const {
|
||||
return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth);
|
||||
}
|
||||
|
||||
const TypeOopPtr* TypeOopPtr::with_offset(intptr_t offset) const {
|
||||
return make(_ptr, offset, _instance_id, with_offset_speculative(offset), _inline_depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return same type without a speculative part
|
||||
*/
|
||||
const Type* TypeOopPtr::remove_speculative() const {
|
||||
const TypeOopPtr* TypeOopPtr::remove_speculative() const {
|
||||
if (_speculative == NULL) {
|
||||
return this;
|
||||
}
|
||||
@ -3653,11 +3668,14 @@ const TypeInstPtr *TypeInstPtr::MIRROR;
|
||||
const TypeInstPtr *TypeInstPtr::MARK;
|
||||
const TypeInstPtr *TypeInstPtr::KLASS;
|
||||
|
||||
ciKlass* TypeInstPtr::exact_klass_helper() const {
|
||||
return _klass;
|
||||
}
|
||||
|
||||
//------------------------------TypeInstPtr-------------------------------------
|
||||
TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off,
|
||||
int instance_id, const TypePtr* speculative, int inline_depth)
|
||||
: TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth),
|
||||
_name(k->name()) {
|
||||
: TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth) {
|
||||
assert(k != NULL &&
|
||||
(k->is_loaded() || o == NULL),
|
||||
"cannot have constants with non-loaded klass");
|
||||
@ -3720,16 +3738,16 @@ const Type* TypeInstPtr::get_const_boxed_value() const {
|
||||
}
|
||||
|
||||
//------------------------------cast_to_ptr_type-------------------------------
|
||||
const TypeInstPtr *TypeInstPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
const TypeInstPtr* TypeInstPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
if( ptr == _ptr ) return this;
|
||||
// Reconstruct _sig info here since not a problem with later lazy
|
||||
// construction, _sig will show up on demand.
|
||||
return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, _inline_depth);
|
||||
return make(ptr, klass(), klass_is_exact(), ptr == Constant ? const_oop() : NULL, _offset, _instance_id, _speculative, _inline_depth);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------cast_to_exactness-------------------------------
|
||||
const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
const TypeInstPtr* TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
if( klass_is_exact == _klass_is_exact ) return this;
|
||||
if (!_klass->is_loaded()) return this;
|
||||
ciInstanceKlass* ik = _klass->as_instance_klass();
|
||||
@ -3739,7 +3757,7 @@ const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
}
|
||||
|
||||
//-----------------------------cast_to_instance_id----------------------------
|
||||
const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const {
|
||||
const TypeInstPtr* TypeInstPtr::cast_to_instance_id(int instance_id) const {
|
||||
if( instance_id == _instance_id ) return this;
|
||||
return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth);
|
||||
}
|
||||
@ -4137,6 +4155,70 @@ int TypeInstPtr::hash(void) const {
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool TypeInstPtr::is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (!is_loaded() || !other->is_loaded()) {
|
||||
return false;
|
||||
}
|
||||
if (!other->isa_instptr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!other_exact) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other->klass()->equals(ciEnv::current()->Object_klass())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this_exact && klass()->is_interface()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _klass->is_subtype_of(other->klass());
|
||||
}
|
||||
|
||||
bool TypeInstPtr::is_same_java_type_as(const TypeOopPtr* other) const {
|
||||
if (!is_loaded() || !other->is_loaded()) {
|
||||
return false;
|
||||
}
|
||||
if (!other->isa_instptr()) {
|
||||
return false;
|
||||
}
|
||||
return _klass->equals(other->_klass);
|
||||
}
|
||||
|
||||
bool TypeInstPtr::maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (!is_loaded() || !other->is_loaded()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (other->isa_aryptr()) {
|
||||
return !this_exact && (_klass->equals(ciEnv::current()->Object_klass()) || _klass->is_interface());
|
||||
}
|
||||
|
||||
if ((_klass->is_interface() && !this_exact) || (other->klass()->is_interface() /*&& !other_exact*/)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(other->isa_instptr(), "unsupported");
|
||||
|
||||
if (this_exact && other_exact) {
|
||||
return is_java_subtype_of(other);
|
||||
}
|
||||
|
||||
if (!_klass->is_subtype_of(other->_klass) && !other->_klass->is_subtype_of(_klass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this_exact) {
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------dump2------------------------------------------
|
||||
// Dump oop Type
|
||||
#ifndef PRODUCT
|
||||
@ -4191,12 +4273,17 @@ void TypeInstPtr::dump2(Dict &d, uint depth, outputStream* st) const {
|
||||
#endif
|
||||
|
||||
//------------------------------add_offset-------------------------------------
|
||||
const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
|
||||
const TypePtr* TypeInstPtr::add_offset(intptr_t offset) const {
|
||||
return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset),
|
||||
_instance_id, add_offset_speculative(offset), _inline_depth);
|
||||
}
|
||||
|
||||
const Type *TypeInstPtr::remove_speculative() const {
|
||||
const TypeInstPtr* TypeInstPtr::with_offset(intptr_t offset) const {
|
||||
return make(_ptr, klass(), klass_is_exact(), const_oop(), offset,
|
||||
_instance_id, with_offset_speculative(offset), _inline_depth);
|
||||
}
|
||||
|
||||
const TypeInstPtr* TypeInstPtr::remove_speculative() const {
|
||||
if (_speculative == NULL) {
|
||||
return this;
|
||||
}
|
||||
@ -4267,19 +4354,19 @@ const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciK
|
||||
//------------------------------cast_to_ptr_type-------------------------------
|
||||
const TypeAryPtr* TypeAryPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
if( ptr == _ptr ) return this;
|
||||
return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth);
|
||||
return make(ptr, ptr == Constant ? const_oop() : NULL, _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------cast_to_exactness-------------------------------
|
||||
const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
const TypeAryPtr* TypeAryPtr::cast_to_exactness(bool klass_is_exact) const {
|
||||
if( klass_is_exact == _klass_is_exact ) return this;
|
||||
if (_ary->ary_must_be_exact()) return this; // cannot clear xk
|
||||
return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth);
|
||||
}
|
||||
|
||||
//-----------------------------cast_to_instance_id----------------------------
|
||||
const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const {
|
||||
const TypeAryPtr* TypeAryPtr::cast_to_instance_id(int instance_id) const {
|
||||
if( instance_id == _instance_id ) return this;
|
||||
return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth);
|
||||
}
|
||||
@ -4395,6 +4482,73 @@ int TypeAryPtr::hash(void) const {
|
||||
return (intptr_t)_ary + TypeOopPtr::hash();
|
||||
}
|
||||
|
||||
bool TypeAryPtr::is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (other->klass() == ciEnv::current()->Object_klass() && other_exact) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_loaded() || !other->is_loaded() || other->klass() == NULL || klass() == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (other->isa_instptr()) {
|
||||
return _klass->is_subtype_of(other->_klass) && other_exact;
|
||||
}
|
||||
if (klass() == NULL) {
|
||||
return false;
|
||||
}
|
||||
assert(other->isa_aryptr(), "");
|
||||
const TypeAryPtr* other_ary = other->isa_aryptr();
|
||||
if (other_ary->elem()->make_oopptr() && elem()->make_oopptr()) {
|
||||
return elem()->make_oopptr()->is_java_subtype_of_helper(other_ary->elem()->make_oopptr(), this_exact, other_exact);
|
||||
}
|
||||
if (!other_ary->elem()->make_oopptr() && !elem()->make_oopptr()) {
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeAryPtr::is_same_java_type_as(const TypeOopPtr* other) const {
|
||||
if (!other->isa_aryptr() ||
|
||||
!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
|
||||
return false;
|
||||
}
|
||||
const TypeAryPtr* other_ary = other->isa_aryptr();
|
||||
if (other_ary->elem()->make_oopptr() && elem()->make_oopptr()) {
|
||||
return elem()->make_oopptr()->is_same_java_type_as(other_ary->elem()->make_oopptr());
|
||||
}
|
||||
if (!other_ary->elem()->make_oopptr() && !elem()->make_oopptr()) {
|
||||
return _klass->equals(other->_klass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeAryPtr::maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (other->klass() == ciEnv::current()->Object_klass()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
|
||||
return true;
|
||||
}
|
||||
if (other->isa_instptr()) {
|
||||
return (!other_exact && other->_klass->is_interface()) || _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
assert(other->isa_aryptr(), "");
|
||||
|
||||
if (this_exact && other_exact) {
|
||||
return is_java_subtype_of(other);
|
||||
}
|
||||
|
||||
const TypeAryPtr* other_ary = other->isa_aryptr();
|
||||
if (other_ary->elem()->make_oopptr() && elem()->make_oopptr()) {
|
||||
return elem()->make_oopptr()->maybe_java_subtype_of_helper(other_ary->elem()->make_oopptr(), this_exact,
|
||||
other_exact);
|
||||
}
|
||||
if (!other_ary->elem()->make_oopptr() && !elem()->make_oopptr()) {
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//------------------------------meet-------------------------------------------
|
||||
// Compute the MEET of two types. It returns a new Type object.
|
||||
const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
|
||||
@ -4716,7 +4870,15 @@ const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const {
|
||||
return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth);
|
||||
}
|
||||
|
||||
const Type *TypeAryPtr::remove_speculative() const {
|
||||
const TypeAryPtr* TypeAryPtr::with_offset(intptr_t offset) const {
|
||||
return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, offset, _instance_id, with_offset_speculative(offset), _inline_depth);
|
||||
}
|
||||
|
||||
const TypeAryPtr* TypeAryPtr::with_ary(const TypeAry* ary) const {
|
||||
return make(_ptr, _const_oop, ary, _klass, _klass_is_exact, _offset, _instance_id, _speculative, _inline_depth);
|
||||
}
|
||||
|
||||
const TypeAryPtr* TypeAryPtr::remove_speculative() const {
|
||||
if (_speculative == NULL) {
|
||||
return this;
|
||||
}
|
||||
@ -4856,7 +5018,7 @@ const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) {
|
||||
return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons();
|
||||
}
|
||||
|
||||
const Type* TypeNarrowOop::remove_speculative() const {
|
||||
const TypeNarrowOop* TypeNarrowOop::remove_speculative() const {
|
||||
return make(_ptrtype->remove_speculative()->is_ptr());
|
||||
}
|
||||
|
||||
@ -5111,6 +5273,10 @@ TypeKlassPtr::TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, int offset)
|
||||
: TypePtr(t, ptr, offset), _klass(klass) {
|
||||
}
|
||||
|
||||
ciKlass* TypeKlassPtr::exact_klass_helper() const {
|
||||
return _klass;
|
||||
}
|
||||
|
||||
//------------------------------eq---------------------------------------------
|
||||
// Structural equality check for Type representations
|
||||
bool TypeKlassPtr::eq(const Type *t) const {
|
||||
@ -5178,7 +5344,9 @@ intptr_t TypeKlassPtr::get_con() const {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
return (intptr_t)klass()->constant_encoding();
|
||||
ciKlass* k = exact_klass();
|
||||
|
||||
return (intptr_t)k->constant_encoding();
|
||||
}
|
||||
|
||||
//------------------------------dump2------------------------------------------
|
||||
@ -5249,12 +5417,12 @@ const TypePtr *TypeInstKlassPtr::add_offset( intptr_t offset ) const {
|
||||
return make( _ptr, klass(), xadd_offset(offset) );
|
||||
}
|
||||
|
||||
const TypeKlassPtr *TypeInstKlassPtr::with_offset(intptr_t offset) const {
|
||||
const TypeInstKlassPtr* TypeInstKlassPtr::with_offset(intptr_t offset) const {
|
||||
return make(_ptr, klass(), offset);
|
||||
}
|
||||
|
||||
//------------------------------cast_to_ptr_type-------------------------------
|
||||
const TypePtr* TypeInstKlassPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
const TypeInstKlassPtr* TypeInstKlassPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
assert(_base == InstKlassPtr, "subclass must override cast_to_ptr_type");
|
||||
if( ptr == _ptr ) return this;
|
||||
return make(ptr, _klass, _offset);
|
||||
@ -5280,9 +5448,28 @@ const TypeKlassPtr* TypeInstKlassPtr::cast_to_exactness(bool klass_is_exact) con
|
||||
//-----------------------------as_instance_type--------------------------------
|
||||
// Corresponding type for an instance of the given class.
|
||||
// It will be NotNull, and exact if and only if the klass type is exact.
|
||||
const TypeOopPtr* TypeInstKlassPtr::as_instance_type() const {
|
||||
const TypeOopPtr* TypeInstKlassPtr::as_instance_type(bool klass_change) const {
|
||||
ciKlass* k = klass();
|
||||
bool xk = klass_is_exact();
|
||||
bool xk = klass_is_exact();
|
||||
Compile* C = Compile::current();
|
||||
Dependencies* deps = C->dependencies();
|
||||
assert((deps != NULL) == (C->method() != NULL && C->method()->code_size() > 0), "sanity");
|
||||
// Element is an instance
|
||||
bool klass_is_exact = false;
|
||||
if (k->is_loaded()) {
|
||||
// Try to set klass_is_exact.
|
||||
ciInstanceKlass* ik = k->as_instance_klass();
|
||||
klass_is_exact = ik->is_final();
|
||||
if (!klass_is_exact && klass_change
|
||||
&& deps != NULL && UseUniqueSubclasses) {
|
||||
ciInstanceKlass* sub = ik->unique_concrete_subklass();
|
||||
if (sub != NULL) {
|
||||
deps->assert_abstract_with_unique_concrete_subtype(ik, sub);
|
||||
k = ik = sub;
|
||||
xk = sub->is_final();
|
||||
}
|
||||
}
|
||||
}
|
||||
return TypeInstPtr::make(TypePtr::BotPTR, k, xk, NULL, 0);
|
||||
}
|
||||
|
||||
@ -5434,6 +5621,69 @@ const Type *TypeInstKlassPtr::xdual() const {
|
||||
return new TypeInstKlassPtr(dual_ptr(), klass(), dual_offset());
|
||||
}
|
||||
|
||||
bool TypeInstKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (!is_loaded() || !other->is_loaded()) {
|
||||
return false;
|
||||
}
|
||||
if (!other->isa_instklassptr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!other_exact) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other->_klass->equals(ciEnv::current()->Object_klass())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this_exact && klass()->is_interface()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
|
||||
bool TypeInstKlassPtr::is_same_java_type_as(const TypeKlassPtr* other) const {
|
||||
if (!is_loaded() || !other->is_loaded()) {
|
||||
return false;
|
||||
}
|
||||
if (!other->isa_instklassptr()) {
|
||||
return false;
|
||||
}
|
||||
return _klass->equals(other->_klass);
|
||||
}
|
||||
|
||||
bool TypeInstKlassPtr::maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (!is_loaded() || !other->is_loaded()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (other->isa_aryklassptr()) {
|
||||
return !this_exact && (_klass->equals(ciEnv::current()->Object_klass()) || _klass->is_interface());
|
||||
}
|
||||
|
||||
if ((_klass->is_interface() && !this_exact) || (other->klass()->is_interface() /*&& !other_exact*/)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(other->isa_instklassptr(), "unsupported");
|
||||
|
||||
if (this_exact && other_exact) {
|
||||
return is_java_subtype_of(other);
|
||||
}
|
||||
|
||||
if (!_klass->is_subtype_of(other->_klass) && !other->_klass->is_subtype_of(_klass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this_exact) {
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const TypeAryKlassPtr *TypeAryKlassPtr::make(PTR ptr, const Type* elem, ciKlass* k, int offset) {
|
||||
return (TypeAryKlassPtr*)(new TypeAryKlassPtr(ptr, elem, k, offset))->hashcons();
|
||||
}
|
||||
@ -5553,13 +5803,36 @@ ciKlass* TypeAryPtr::klass() const {
|
||||
// TypeAryPtr::OOPS->klass() are not common enough to matter.
|
||||
((TypeAryPtr*)this)->_klass = k_ary;
|
||||
if (UseCompressedOops && k_ary != NULL && k_ary->is_obj_array_klass() &&
|
||||
_offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes()) {
|
||||
_offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes() &&
|
||||
_offset != arrayOopDesc::klass_offset_in_bytes()) {
|
||||
((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true;
|
||||
}
|
||||
}
|
||||
return k_ary;
|
||||
}
|
||||
|
||||
ciKlass* TypeAryPtr::exact_klass_helper() const {
|
||||
if (_ary->_elem->make_ptr() && _ary->_elem->make_ptr()->isa_oopptr()) {
|
||||
ciKlass* k = _ary->_elem->make_ptr()->is_oopptr()->exact_klass_helper();
|
||||
if (k == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
k = ciObjArrayKlass::make(k);
|
||||
return k;
|
||||
}
|
||||
|
||||
return klass();
|
||||
}
|
||||
|
||||
const Type* TypeAryPtr::base_element_type(int& dims) const {
|
||||
const Type* elem = this->elem();
|
||||
dims = 1;
|
||||
while (elem->make_ptr() && elem->make_ptr()->isa_aryptr()) {
|
||||
elem = elem->make_ptr()->is_aryptr()->elem();
|
||||
dims++;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
//------------------------------add_offset-------------------------------------
|
||||
// Access internals of klass object
|
||||
@ -5567,12 +5840,12 @@ const TypePtr *TypeAryKlassPtr::add_offset(intptr_t offset) const {
|
||||
return make(_ptr, elem(), klass(), xadd_offset(offset));
|
||||
}
|
||||
|
||||
const TypeKlassPtr *TypeAryKlassPtr::with_offset(intptr_t offset) const {
|
||||
const TypeAryKlassPtr* TypeAryKlassPtr::with_offset(intptr_t offset) const {
|
||||
return make(_ptr, elem(), klass(), offset);
|
||||
}
|
||||
|
||||
//------------------------------cast_to_ptr_type-------------------------------
|
||||
const TypePtr* TypeAryKlassPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
const TypeAryKlassPtr* TypeAryKlassPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
assert(_base == AryKlassPtr, "subclass must override cast_to_ptr_type");
|
||||
if (ptr == _ptr) return this;
|
||||
return make(ptr, elem(), _klass, _offset);
|
||||
@ -5601,11 +5874,17 @@ const TypeKlassPtr *TypeAryKlassPtr::cast_to_exactness(bool klass_is_exact) cons
|
||||
|
||||
//-----------------------------as_instance_type--------------------------------
|
||||
// Corresponding type for an instance of the given class.
|
||||
// It will be exact if and only if the klass type is exact.
|
||||
const TypeOopPtr* TypeAryKlassPtr::as_instance_type() const {
|
||||
// It will be NotNull, and exact if and only if the klass type is exact.
|
||||
const TypeOopPtr* TypeAryKlassPtr::as_instance_type(bool klass_change) const {
|
||||
ciKlass* k = klass();
|
||||
bool xk = klass_is_exact();
|
||||
const Type* el = elem()->isa_klassptr() ? elem()->is_klassptr()->as_instance_type()->is_oopptr()->cast_to_exactness(false) : elem();
|
||||
const Type* el = NULL;
|
||||
if (elem()->isa_klassptr()) {
|
||||
el = elem()->is_klassptr()->as_instance_type(false)->cast_to_exactness(false);
|
||||
k = NULL;
|
||||
} else {
|
||||
el = elem();
|
||||
}
|
||||
return TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(el, TypeInt::POS), k, xk, 0);
|
||||
}
|
||||
|
||||
@ -5737,6 +6016,72 @@ const Type *TypeAryKlassPtr::xmeet( const Type *t ) const {
|
||||
return this; // Return the double constant
|
||||
}
|
||||
|
||||
bool TypeAryKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (other->klass() == ciEnv::current()->Object_klass() && other_exact) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_loaded() || !other->is_loaded() || other->klass() == NULL || klass() == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (other->isa_instklassptr()) {
|
||||
return _klass->is_subtype_of(other->_klass) && other_exact;
|
||||
}
|
||||
if (klass() == NULL) {
|
||||
return false;
|
||||
}
|
||||
assert(other->isa_aryklassptr(), "");
|
||||
const TypeAryKlassPtr* other_ary = other->isa_aryklassptr();
|
||||
if (other_ary->_elem->isa_klassptr() && _elem->isa_klassptr()) {
|
||||
return _elem->is_klassptr()->is_java_subtype_of_helper(other_ary->_elem->is_klassptr(), this_exact, other_exact);
|
||||
}
|
||||
if (!other_ary->_elem->isa_klassptr() && !_elem->isa_klassptr()) {
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeAryKlassPtr::is_same_java_type_as(const TypeKlassPtr* other) const {
|
||||
if (!other->isa_aryklassptr() ||
|
||||
!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
|
||||
return false;
|
||||
}
|
||||
const TypeAryKlassPtr* other_ary = other->isa_aryklassptr();
|
||||
if (other_ary->_elem->isa_klassptr() && _elem->isa_klassptr()) {
|
||||
return _elem->is_klassptr()->is_same_java_type_as(other_ary->_elem->is_klassptr());
|
||||
}
|
||||
if (!other_ary->_elem->isa_klassptr() && !_elem->isa_klassptr()) {
|
||||
return _klass->equals(other->_klass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeAryKlassPtr::maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const {
|
||||
if (other->klass() == ciEnv::current()->Object_klass()) {
|
||||
return true;
|
||||
}
|
||||
if (!is_loaded() || !other->is_loaded() || klass() == NULL || other->klass() == NULL) {
|
||||
return true;
|
||||
}
|
||||
if (other->isa_instklassptr()) {
|
||||
return (!other_exact && other->_klass->is_interface()) || _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
assert(other->isa_aryklassptr(), "");
|
||||
|
||||
if (this_exact && other_exact) {
|
||||
return is_java_subtype_of(other);
|
||||
}
|
||||
|
||||
const TypeAryKlassPtr* other_ary = other->isa_aryklassptr();
|
||||
if (other_ary->_elem->isa_klassptr() && _elem->isa_klassptr()) {
|
||||
return _elem->is_klassptr()->maybe_java_subtype_of_helper(other_ary->_elem->is_klassptr(), this_exact, other_exact);
|
||||
}
|
||||
if (!other_ary->_elem->isa_klassptr() && !_elem->isa_klassptr()) {
|
||||
return _klass->is_subtype_of(other->_klass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------xdual------------------------------------------
|
||||
// Dual: compute field-by-field dual
|
||||
const Type *TypeAryKlassPtr::xdual() const {
|
||||
@ -5744,6 +6089,19 @@ const Type *TypeAryKlassPtr::xdual() const {
|
||||
}
|
||||
|
||||
//------------------------------get_con----------------------------------------
|
||||
ciKlass* TypeAryKlassPtr::exact_klass_helper() const {
|
||||
if (elem()->isa_klassptr()) {
|
||||
ciKlass* k = elem()->is_klassptr()->exact_klass_helper();
|
||||
if (k == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
k = ciObjArrayKlass::make(k);
|
||||
return k;
|
||||
}
|
||||
|
||||
return klass();
|
||||
}
|
||||
|
||||
ciKlass* TypeAryKlassPtr::klass() const {
|
||||
if (_klass != NULL) {
|
||||
return _klass;
|
||||
|
@ -774,7 +774,7 @@ public:
|
||||
virtual const Type *xmeet( const Type *t ) const;
|
||||
virtual const Type *xdual() const; // Compute dual right now.
|
||||
bool ary_must_be_exact() const; // true if arrays of such are never generic
|
||||
virtual const Type* remove_speculative() const;
|
||||
virtual const TypeAry* remove_speculative() const;
|
||||
virtual const Type* cleanup_speculative() const;
|
||||
#ifdef ASSERT
|
||||
// One type is interface, the other is oop
|
||||
@ -919,6 +919,7 @@ protected:
|
||||
bool eq_speculative(const TypePtr* other) const;
|
||||
int hash_speculative() const;
|
||||
const TypePtr* add_offset_speculative(intptr_t offset) const;
|
||||
const TypePtr* with_offset_speculative(intptr_t offset) const;
|
||||
#ifndef PRODUCT
|
||||
void dump_speculative(outputStream *st) const;
|
||||
#endif
|
||||
@ -960,12 +961,13 @@ public:
|
||||
int inline_depth = InlineDepthBottom);
|
||||
|
||||
// Return a 'ptr' version of this type
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual intptr_t get_con() const;
|
||||
|
||||
int xadd_offset( intptr_t offset ) const;
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const TypePtr* add_offset(intptr_t offset) const;
|
||||
virtual const TypePtr* with_offset(intptr_t offset) const;
|
||||
virtual bool eq(const Type *t) const;
|
||||
virtual int hash() const; // Type specific hashing
|
||||
|
||||
@ -994,7 +996,7 @@ public:
|
||||
virtual ciKlass* speculative_type_not_null() const;
|
||||
virtual bool speculative_maybe_null() const;
|
||||
virtual bool speculative_always_null() const;
|
||||
virtual const Type* remove_speculative() const;
|
||||
virtual const TypePtr* remove_speculative() const;
|
||||
virtual const Type* cleanup_speculative() const;
|
||||
virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
|
||||
virtual bool would_improve_ptr(ProfilePtrKind maybe_null) const;
|
||||
@ -1034,7 +1036,8 @@ public:
|
||||
|
||||
virtual intptr_t get_con() const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const TypePtr* add_offset(intptr_t offset) const;
|
||||
virtual const TypeRawPtr* with_offset(intptr_t offset) const { ShouldNotReachHere(); return NULL;}
|
||||
|
||||
virtual const Type *xmeet( const Type *t ) const;
|
||||
virtual const Type *xdual() const; // Compute dual right now.
|
||||
@ -1049,6 +1052,10 @@ public:
|
||||
//------------------------------TypeOopPtr-------------------------------------
|
||||
// Some kind of oop (Java pointer), either instance or array.
|
||||
class TypeOopPtr : public TypePtr {
|
||||
friend class TypeAry;
|
||||
friend class TypePtr;
|
||||
friend class TypeInstPtr;
|
||||
friend class TypeAryPtr;
|
||||
protected:
|
||||
TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id,
|
||||
const TypePtr* speculative, int inline_depth);
|
||||
@ -1085,7 +1092,22 @@ protected:
|
||||
// Do not allow interface-vs.-noninterface joins to collapse to top.
|
||||
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
|
||||
|
||||
virtual ciKlass* exact_klass_helper() const { return NULL; }
|
||||
virtual ciKlass* klass() const { return _klass; }
|
||||
|
||||
public:
|
||||
|
||||
bool is_java_subtype_of(const TypeOopPtr* other) const {
|
||||
return is_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
|
||||
}
|
||||
virtual bool is_same_java_type_as(const TypeOopPtr* other) const { ShouldNotReachHere(); return false; }
|
||||
bool maybe_java_subtype_of(const TypeOopPtr* other) const {
|
||||
return maybe_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
|
||||
}
|
||||
virtual bool is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
|
||||
virtual bool maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
|
||||
|
||||
|
||||
// Creates a type given a klass. Correctly handles multi-dimensional arrays
|
||||
// Respects UseUniqueSubclasses.
|
||||
// If the klass is final, the resulting type will be exact.
|
||||
@ -1115,7 +1137,11 @@ public:
|
||||
int inline_depth = InlineDepthBottom);
|
||||
|
||||
ciObject* const_oop() const { return _const_oop; }
|
||||
virtual ciKlass* klass() const { return _klass; }
|
||||
// Exact klass, possibly an interface or an array of interface
|
||||
ciKlass* exact_klass(bool maybe_null = false) const { assert(klass_is_exact(), ""); ciKlass* k = exact_klass_helper(); assert(k != NULL || maybe_null, ""); return k; }
|
||||
ciKlass* unloaded_klass() const { assert(!is_loaded(), "only for unloaded types"); return klass(); }
|
||||
|
||||
virtual bool is_loaded() const { return klass()->is_loaded(); }
|
||||
bool klass_is_exact() const { return _klass_is_exact; }
|
||||
|
||||
// Returns true if this pointer points at memory which contains a
|
||||
@ -1131,17 +1157,18 @@ public:
|
||||
|
||||
virtual const TypeOopPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
virtual const TypeOopPtr* cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
|
||||
|
||||
// corresponding pointer to klass, for a given instance
|
||||
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const TypeOopPtr* with_offset(intptr_t offset) const;
|
||||
virtual const TypePtr* add_offset(intptr_t offset) const;
|
||||
|
||||
// Speculative type helper methods.
|
||||
virtual const Type* remove_speculative() const;
|
||||
virtual const TypeOopPtr* remove_speculative() const;
|
||||
virtual const Type* cleanup_speculative() const;
|
||||
virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const;
|
||||
virtual const TypePtr* with_inline_depth(int depth) const;
|
||||
@ -1168,12 +1195,21 @@ class TypeInstPtr : public TypeOopPtr {
|
||||
virtual bool eq( const Type *t ) const;
|
||||
virtual int hash() const; // Type specific hashing
|
||||
|
||||
ciSymbol* _name; // class name
|
||||
ciKlass* exact_klass_helper() const;
|
||||
|
||||
public:
|
||||
ciSymbol* name() const { return _name; }
|
||||
public:
|
||||
|
||||
bool is_loaded() const { return _klass->is_loaded(); }
|
||||
// Instance klass, ignoring any interface
|
||||
ciInstanceKlass* instance_klass() const {
|
||||
if (klass()->is_loaded() && klass()->is_interface()) {
|
||||
return Compile::current()->env()->Object_klass();
|
||||
}
|
||||
return klass()->as_instance_klass();
|
||||
}
|
||||
|
||||
bool is_same_java_type_as(const TypeOopPtr* other) const;
|
||||
bool is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
|
||||
bool maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
|
||||
|
||||
// Make a pointer to a constant oop.
|
||||
static const TypeInstPtr *make(ciObject* o) {
|
||||
@ -1215,14 +1251,15 @@ class TypeInstPtr : public TypeOopPtr {
|
||||
|
||||
virtual const TypeInstPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
virtual const TypeInstPtr* cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
|
||||
virtual const TypeInstPtr* cast_to_instance_id(int instance_id) const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const TypePtr* add_offset(intptr_t offset) const;
|
||||
virtual const TypeInstPtr* with_offset(intptr_t offset) const;
|
||||
|
||||
// Speculative type helper methods.
|
||||
virtual const Type* remove_speculative() const;
|
||||
virtual const TypeInstPtr* remove_speculative() const;
|
||||
virtual const TypePtr* with_inline_depth(int depth) const;
|
||||
virtual const TypePtr* with_instance_id(int instance_id) const;
|
||||
|
||||
@ -1233,6 +1270,8 @@ class TypeInstPtr : public TypeOopPtr {
|
||||
|
||||
const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
|
||||
|
||||
bool is_interface() const { return is_loaded() && klass()->is_interface(); }
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeInstPtr *NOTNULL;
|
||||
static const TypeInstPtr *BOTTOM;
|
||||
@ -1278,9 +1317,21 @@ class TypeAryPtr : public TypeOopPtr {
|
||||
|
||||
ciKlass* compute_klass(DEBUG_ONLY(bool verify = false)) const;
|
||||
|
||||
public:
|
||||
// Accessors
|
||||
ciKlass* exact_klass_helper() const;
|
||||
ciKlass* klass() const;
|
||||
|
||||
public:
|
||||
|
||||
bool is_same_java_type_as(const TypeOopPtr* other) const;
|
||||
bool is_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
|
||||
bool maybe_java_subtype_of_helper(const TypeOopPtr* other, bool this_exact, bool other_exact) const;
|
||||
|
||||
// returns base element type, an instance klass (and not interface) for object arrays
|
||||
const Type* base_element_type(int& dims) const;
|
||||
|
||||
// Accessors
|
||||
bool is_loaded() const { return (_ary->_elem->make_oopptr() ? _ary->_elem->make_oopptr()->is_loaded() : true); }
|
||||
|
||||
const TypeAry* ary() const { return _ary; }
|
||||
const Type* elem() const { return _ary->_elem; }
|
||||
const TypeInt* size() const { return _ary->_size; }
|
||||
@ -1301,18 +1352,20 @@ public:
|
||||
// Return a 'ptr' version of this type
|
||||
virtual const TypeAryPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
virtual const TypeAryPtr* cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
|
||||
virtual const TypeAryPtr* cast_to_instance_id(int instance_id) const;
|
||||
|
||||
virtual const TypeAryPtr* cast_to_size(const TypeInt* size) const;
|
||||
virtual const TypeInt* narrow_size_type(const TypeInt* size) const;
|
||||
|
||||
virtual bool empty(void) const; // TRUE if type is vacuous
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const TypeAryPtr *with_offset( intptr_t offset ) const;
|
||||
const TypeAryPtr* with_ary(const TypeAry* ary) const;
|
||||
|
||||
// Speculative type helper methods.
|
||||
virtual const Type* remove_speculative() const;
|
||||
virtual const TypeAryPtr* remove_speculative() const;
|
||||
virtual const TypePtr* with_inline_depth(int depth) const;
|
||||
virtual const TypePtr* with_instance_id(int instance_id) const;
|
||||
|
||||
@ -1398,6 +1451,8 @@ public:
|
||||
//------------------------------TypeKlassPtr-----------------------------------
|
||||
// Class of Java Klass pointers
|
||||
class TypeKlassPtr : public TypePtr {
|
||||
friend class TypeInstKlassPtr;
|
||||
friend class TypeAryKlassPtr;
|
||||
protected:
|
||||
TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, int offset);
|
||||
|
||||
@ -1407,28 +1462,43 @@ public:
|
||||
virtual bool eq( const Type *t ) const;
|
||||
virtual int hash() const;
|
||||
virtual bool singleton(void) const; // TRUE if type is a singleton
|
||||
virtual bool must_be_exact() const { ShouldNotReachHere(); return false; }
|
||||
|
||||
protected:
|
||||
|
||||
ciKlass* _klass;
|
||||
|
||||
virtual bool must_be_exact() const { ShouldNotReachHere(); return false; }
|
||||
virtual ciKlass* exact_klass_helper() const;
|
||||
virtual ciKlass* klass() const { return _klass; }
|
||||
|
||||
public:
|
||||
|
||||
virtual ciKlass* klass() const { return _klass; }
|
||||
bool is_java_subtype_of(const TypeKlassPtr* other) const {
|
||||
return is_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
|
||||
}
|
||||
bool maybe_java_subtype_of(const TypeKlassPtr* other) const {
|
||||
return maybe_java_subtype_of_helper(other, klass_is_exact(), other->klass_is_exact());
|
||||
}
|
||||
virtual bool is_same_java_type_as(const TypeKlassPtr* other) const { ShouldNotReachHere(); return false; }
|
||||
virtual bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
|
||||
virtual bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { ShouldNotReachHere(); return false; }
|
||||
|
||||
// Exact klass, possibly an interface or an array of interface
|
||||
ciKlass* exact_klass(bool maybe_null = false) const { assert(klass_is_exact(), ""); ciKlass* k = exact_klass_helper(); assert(k != NULL || maybe_null, ""); return k; }
|
||||
|
||||
bool klass_is_exact() const { return _ptr == Constant; }
|
||||
bool is_loaded() const { return klass()->is_loaded(); }
|
||||
|
||||
static const TypeKlassPtr* make(ciKlass* klass);
|
||||
static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, int offset);
|
||||
|
||||
virtual bool is_loaded() const { return _klass->is_loaded(); }
|
||||
|
||||
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
|
||||
virtual const TypeKlassPtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
// corresponding pointer to instance, for a given class
|
||||
virtual const TypeOopPtr* as_instance_type() const { ShouldNotReachHere(); return NULL; }
|
||||
virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const { ShouldNotReachHere(); return NULL; }
|
||||
virtual const Type *xmeet( const Type *t ) const { ShouldNotReachHere(); return NULL; }
|
||||
@ -1454,26 +1524,37 @@ class TypeInstKlassPtr : public TypeKlassPtr {
|
||||
|
||||
public:
|
||||
// Instance klass ignoring any interface
|
||||
ciInstanceKlass* instance_klass() const { return klass()->as_instance_klass(); }
|
||||
ciInstanceKlass* instance_klass() const {
|
||||
if (klass()->is_interface()) {
|
||||
return Compile::current()->env()->Object_klass();
|
||||
}
|
||||
return klass()->as_instance_klass();
|
||||
}
|
||||
|
||||
bool is_same_java_type_as(const TypeKlassPtr* other) const;
|
||||
bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
|
||||
bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
|
||||
|
||||
static const TypeInstKlassPtr *make(ciKlass* k) {
|
||||
return make(TypePtr::Constant, k, 0);
|
||||
}
|
||||
static const TypeInstKlassPtr *make(PTR ptr, ciKlass* k, int offset);
|
||||
|
||||
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeInstKlassPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
// corresponding pointer to instance, for a given class
|
||||
virtual const TypeOopPtr* as_instance_type() const;
|
||||
virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const;
|
||||
virtual int hash() const;
|
||||
virtual bool eq(const Type *t) const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const Type *xmeet( const Type *t ) const;
|
||||
virtual const Type *xdual() const;
|
||||
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
|
||||
virtual const TypeInstKlassPtr* with_offset(intptr_t offset) const;
|
||||
|
||||
bool is_interface() const { return klass()->is_interface(); }
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeInstKlassPtr* OBJECT; // Not-null object klass or below
|
||||
@ -1482,21 +1563,31 @@ public:
|
||||
|
||||
// Array klass pointer, mirrors TypeAryPtr
|
||||
class TypeAryKlassPtr : public TypeKlassPtr {
|
||||
friend class TypeInstKlassPtr;
|
||||
const Type *_elem;
|
||||
|
||||
TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, int offset)
|
||||
: TypeKlassPtr(AryKlassPtr, ptr, klass, offset), _elem(elem) {
|
||||
}
|
||||
|
||||
virtual ciKlass* exact_klass_helper() const;
|
||||
virtual ciKlass* klass() const;
|
||||
|
||||
virtual bool must_be_exact() const;
|
||||
|
||||
public:
|
||||
virtual ciKlass* klass() const;
|
||||
|
||||
// returns base element type, an instance klass (and not interface) for object arrays
|
||||
const Type* base_element_type(int& dims) const;
|
||||
|
||||
static const TypeAryKlassPtr *make(PTR ptr, ciKlass* k, int offset);
|
||||
|
||||
bool is_same_java_type_as(const TypeKlassPtr* other) const;
|
||||
bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
|
||||
bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;
|
||||
|
||||
bool is_loaded() const { return (_elem->isa_klassptr() ? _elem->is_klassptr()->is_loaded() : true); }
|
||||
|
||||
static const TypeAryKlassPtr *make(PTR ptr, const Type *elem, ciKlass* k, int offset);
|
||||
static const TypeAryKlassPtr* make(ciKlass* klass);
|
||||
|
||||
@ -1505,18 +1596,18 @@ public:
|
||||
virtual bool eq(const Type *t) const;
|
||||
virtual int hash() const; // Type specific hashing
|
||||
|
||||
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeAryKlassPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
// corresponding pointer to instance, for a given class
|
||||
virtual const TypeOopPtr* as_instance_type() const;
|
||||
virtual const TypeOopPtr* as_instance_type(bool klass_change = true) const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
virtual const Type *xmeet( const Type *t ) const;
|
||||
virtual const Type *xdual() const; // Compute dual right now.
|
||||
|
||||
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
|
||||
virtual const TypeAryKlassPtr* with_offset(intptr_t offset) const;
|
||||
|
||||
virtual bool empty(void) const {
|
||||
return TypeKlassPtr::empty() || _elem->empty();
|
||||
@ -1608,7 +1699,7 @@ public:
|
||||
static const TypeNarrowOop *BOTTOM;
|
||||
static const TypeNarrowOop *NULL_PTR;
|
||||
|
||||
virtual const Type* remove_speculative() const;
|
||||
virtual const TypeNarrowOop* remove_speculative() const;
|
||||
virtual const Type* cleanup_speculative() const;
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -1946,8 +2037,7 @@ inline bool Type::is_floatingpoint() const {
|
||||
inline bool Type::is_ptr_to_boxing_obj() const {
|
||||
const TypeInstPtr* tp = isa_instptr();
|
||||
return (tp != NULL) && (tp->offset() == 0) &&
|
||||
tp->klass()->is_instance_klass() &&
|
||||
tp->klass()->as_instance_klass()->is_box_klass();
|
||||
tp->instance_klass()->is_box_klass();
|
||||
}
|
||||
|
||||
|
||||
|
@ -247,7 +247,7 @@ void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) {
|
||||
}
|
||||
}
|
||||
|
||||
ciInstanceKlass* iklass = vec_box->box_type()->klass()->as_instance_klass();
|
||||
ciInstanceKlass* iklass = vec_box->box_type()->instance_klass();
|
||||
int n_fields = iklass->nof_nonstatic_fields();
|
||||
assert(n_fields == 1, "sanity");
|
||||
|
||||
@ -348,7 +348,7 @@ Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc,
|
||||
GraphKit kit(jvms);
|
||||
PhaseGVN& gvn = kit.gvn();
|
||||
|
||||
ciInstanceKlass* box_klass = box_type->klass()->as_instance_klass();
|
||||
ciInstanceKlass* box_klass = box_type->instance_klass();
|
||||
BasicType bt = vect_type->element_basic_type();
|
||||
int num_elem = vect_type->length();
|
||||
|
||||
@ -420,7 +420,7 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {
|
||||
|
||||
Node* obj = vec_unbox->obj();
|
||||
const TypeInstPtr* tinst = gvn.type(obj)->isa_instptr();
|
||||
ciInstanceKlass* from_kls = tinst->klass()->as_instance_klass();
|
||||
ciInstanceKlass* from_kls = tinst->instance_klass();
|
||||
const TypeVect* vt = vec_unbox->bottom_type()->is_vect();
|
||||
BasicType bt = vt->element_basic_type();
|
||||
BasicType masktype = bt;
|
||||
|
@ -39,7 +39,7 @@ static bool is_vector(ciKlass* klass) {
|
||||
static bool check_vbox(const TypeInstPtr* vbox_type) {
|
||||
assert(vbox_type->klass_is_exact(), "");
|
||||
|
||||
ciInstanceKlass* ik = vbox_type->klass()->as_instance_klass();
|
||||
ciInstanceKlass* ik = vbox_type->instance_klass();
|
||||
assert(is_vector(ik), "not a vector");
|
||||
|
||||
ciField* fd1 = ik->get_field_by_name(ciSymbols::ETYPE_name(), ciSymbols::class_signature(), /* is_static */ true);
|
||||
@ -153,7 +153,7 @@ Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType
|
||||
Node* ret = gvn().transform(new ProjNode(alloc, TypeFunc::Parms));
|
||||
|
||||
assert(check_vbox(vbox_type), "");
|
||||
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->klass()));
|
||||
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->instance_klass()));
|
||||
VectorBoxNode* vbox = new VectorBoxNode(C, ret, vector, vbox_type, vt);
|
||||
return gvn().transform(vbox);
|
||||
}
|
||||
@ -161,14 +161,14 @@ Node* GraphKit::box_vector(Node* vector, const TypeInstPtr* vbox_type, BasicType
|
||||
Node* GraphKit::unbox_vector(Node* v, const TypeInstPtr* vbox_type, BasicType elem_bt, int num_elem, bool shuffle_to_vector) {
|
||||
assert(EnableVectorSupport, "");
|
||||
const TypeInstPtr* vbox_type_v = gvn().type(v)->is_instptr();
|
||||
if (vbox_type->klass() != vbox_type_v->klass()) {
|
||||
if (vbox_type->instance_klass() != vbox_type_v->instance_klass()) {
|
||||
return NULL; // arguments don't agree on vector shapes
|
||||
}
|
||||
if (vbox_type_v->maybe_null()) {
|
||||
return NULL; // no nulls are allowed
|
||||
}
|
||||
assert(check_vbox(vbox_type), "");
|
||||
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->klass()));
|
||||
const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_type->instance_klass()));
|
||||
Node* unbox = gvn().transform(new VectorUnboxNode(C, vt, v, merged_memory(), shuffle_to_vector));
|
||||
return unbox;
|
||||
}
|
||||
|
@ -1438,7 +1438,7 @@ Node* VectorUnboxNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
// Handled by VectorUnboxNode::Identity()
|
||||
} else {
|
||||
VectorBoxNode* vbox = static_cast<VectorBoxNode*>(n);
|
||||
ciKlass* vbox_klass = vbox->box_type()->klass();
|
||||
ciKlass* vbox_klass = vbox->box_type()->instance_klass();
|
||||
const TypeVect* in_vt = vbox->vec_type();
|
||||
const TypeVect* out_vt = type()->is_vect();
|
||||
|
||||
|
@ -713,8 +713,8 @@ inline bool is_double_word_type(BasicType t) {
|
||||
return (t == T_DOUBLE || t == T_LONG);
|
||||
}
|
||||
|
||||
inline bool is_reference_type(BasicType t) {
|
||||
return (t == T_OBJECT || t == T_ARRAY);
|
||||
inline bool is_reference_type(BasicType t, bool include_narrow_oop = false) {
|
||||
return (t == T_OBJECT || t == T_ARRAY || (include_narrow_oop && t == T_NARROWOOP));
|
||||
}
|
||||
|
||||
inline bool is_integral_type(BasicType t) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user