8266550: C2: mirror TypeOopPtr/TypeInstPtr/TypeAryPtr with TypeKlassPtr/TypeInstKlassPtr/TypeAryKlassPtr
Reviewed-by: vlivanov, thartmann
This commit is contained in:
parent
a143372818
commit
1d2458db34
src/hotspot/share
oops
opto
callnode.cppcfgnode.cppcompile.cppdoCall.cppescape.cppgraphKit.cppidealGraphPrinter.cpplibrary_call.cppmemnode.cppmemnode.hppparseHelper.cppsubtypenode.cpptype.cpptype.hpp
utilities
test/hotspot/jtreg
@ -88,14 +88,14 @@ ArrayKlass::ArrayKlass(Symbol* name, KlassID id) :
|
||||
_dimension(1),
|
||||
_higher_dimension(NULL),
|
||||
_lower_dimension(NULL) {
|
||||
// Arrays don't add any new methods, so their vtable is the same size as
|
||||
// the vtable of klass Object.
|
||||
set_vtable_length(Universe::base_vtable_size());
|
||||
set_name(name);
|
||||
set_super(Universe::is_bootstrapping() ? NULL : vmClasses::Object_klass());
|
||||
set_layout_helper(Klass::_lh_neutral_value);
|
||||
set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5)
|
||||
JFR_ONLY(INIT_ID(this);)
|
||||
// Arrays don't add any new methods, so their vtable is the same size as
|
||||
// the vtable of klass Object.
|
||||
set_vtable_length(Universe::base_vtable_size());
|
||||
set_name(name);
|
||||
set_super(Universe::is_bootstrapping() ? NULL : vmClasses::Object_klass());
|
||||
set_layout_helper(Klass::_lh_neutral_value);
|
||||
set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5)
|
||||
JFR_ONLY(INIT_ID(this);)
|
||||
}
|
||||
|
||||
|
||||
|
@ -378,6 +378,8 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c
|
||||
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,p2i(t->isa_oopptr()->const_oop()));
|
||||
break;
|
||||
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()));
|
||||
break;
|
||||
case Type::MetadataPtr:
|
||||
|
@ -1140,7 +1140,7 @@ 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_klassptr() : NULL;
|
||||
const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_instklassptr() : NULL;
|
||||
bool is_intf = false;
|
||||
if (ttip != NULL) {
|
||||
ciKlass* k = ttip->klass();
|
||||
@ -1233,7 +1233,7 @@ 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_klassptr() : 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() ) {
|
||||
|
@ -1410,7 +1410,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
if ( offset == Type::OffsetBot || (offset >= 0 && (size_t)offset < sizeof(Klass)) ) {
|
||||
|
||||
tj = tk = TypeKlassPtr::make(TypePtr::NotNull,
|
||||
TypeKlassPtr::OBJECT->klass(),
|
||||
TypeInstKlassPtr::OBJECT->klass(),
|
||||
offset);
|
||||
}
|
||||
|
||||
@ -1457,7 +1457,9 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
|
||||
case Type::RawPtr: tj = TypeRawPtr::BOTTOM; break;
|
||||
case Type::AryPtr: // do not distinguish arrays at all
|
||||
case Type::InstPtr: tj = TypeInstPtr::BOTTOM; break;
|
||||
case Type::KlassPtr: tj = TypeKlassPtr::OBJECT; break;
|
||||
case Type::KlassPtr:
|
||||
case Type::AryKlassPtr:
|
||||
case Type::InstKlassPtr: tj = TypeInstKlassPtr::OBJECT; break;
|
||||
case Type::AnyPtr: tj = TypePtr::BOTTOM; break; // caller checks it
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
|
@ -916,7 +916,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||
Node* ex_klass_node = NULL;
|
||||
if (has_ex_handler() && !ex_type->klass_is_exact()) {
|
||||
Node* p = basic_plus_adr( ex_node, ex_node, oopDesc::klass_offset_in_bytes());
|
||||
ex_klass_node = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT));
|
||||
ex_klass_node = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT));
|
||||
|
||||
// Compute the exception klass a little more cleverly.
|
||||
// Obvious solution is to simple do a LoadKlass from the 'ex_node'.
|
||||
@ -925,7 +925,7 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||
// I'm loading the class from, I can replace the LoadKlass with the
|
||||
// klass constant for the exception oop.
|
||||
if (ex_node->is_Phi()) {
|
||||
ex_klass_node = new PhiNode(ex_node->in(0), TypeKlassPtr::OBJECT);
|
||||
ex_klass_node = new PhiNode(ex_node->in(0), TypeInstKlassPtr::OBJECT);
|
||||
for (uint i = 1; i < ex_node->req(); i++) {
|
||||
Node* ex_in = ex_node->in(i);
|
||||
if (ex_in == top() || ex_in == NULL) {
|
||||
@ -934,10 +934,10 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
|
||||
continue;
|
||||
}
|
||||
Node* p = basic_plus_adr(ex_in, ex_in, oopDesc::klass_offset_in_bytes());
|
||||
Node* k = _gvn.transform( LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT));
|
||||
Node* k = _gvn.transform( LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeInstKlassPtr::OBJECT));
|
||||
ex_klass_node->init_req( i, k );
|
||||
}
|
||||
_gvn.set_type(ex_klass_node, TypeKlassPtr::OBJECT);
|
||||
_gvn.set_type(ex_klass_node, TypeInstKlassPtr::OBJECT);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3117,7 +3117,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
// to the actual Array type.
|
||||
if (alloc->is_Allocate() && n->as_Type()->type() == TypeInstPtr::NOTNULL
|
||||
&& (alloc->is_AllocateArray() ||
|
||||
igvn->type(alloc->in(AllocateNode::KlassNode)) != TypeKlassPtr::OBJECT)) {
|
||||
igvn->type(alloc->in(AllocateNode::KlassNode)) != TypeInstKlassPtr::OBJECT)) {
|
||||
Node *cast2 = NULL;
|
||||
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
|
||||
Node *use = n->fast_out(i);
|
||||
|
@ -2867,7 +2867,7 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, No
|
||||
if (might_be_cache && mem != NULL) {
|
||||
kmem = mem->is_MergeMem() ? mem->as_MergeMem()->memory_at(C->get_alias_index(gvn.type(p2)->is_ptr())) : mem;
|
||||
}
|
||||
Node *nkls = gvn.transform(LoadKlassNode::make(gvn, NULL, kmem, p2, gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL));
|
||||
Node *nkls = gvn.transform(LoadKlassNode::make(gvn, NULL, kmem, p2, gvn.type(p2)->is_ptr(), TypeInstKlassPtr::OBJECT_OR_NULL));
|
||||
|
||||
// Compile speed common case: ARE a subtype and we canNOT fail
|
||||
if( superklass == nkls )
|
||||
@ -3798,7 +3798,7 @@ Node* GraphKit::new_instance(Node* klass_node,
|
||||
// (Actually, it need not be precise if this is a reflective allocation.)
|
||||
// It's what we cast the result to.
|
||||
const TypeKlassPtr* tklass = _gvn.type(klass_node)->isa_klassptr();
|
||||
if (!tklass) tklass = TypeKlassPtr::OBJECT;
|
||||
if (!tklass) tklass = TypeInstKlassPtr::OBJECT;
|
||||
const TypeOopPtr* oop_type = tklass->as_instance_type();
|
||||
|
||||
// Now generate allocation code
|
||||
|
@ -545,7 +545,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
|
||||
} else {
|
||||
print_prop(short_name, "L");
|
||||
}
|
||||
} else if (t->base() == Type::KlassPtr) {
|
||||
} else if (t->base() == Type::KlassPtr || t->base() == Type::InstKlassPtr || t->base() == Type::AryKlassPtr) {
|
||||
const TypeKlassPtr *typeKlass = t->is_klassptr();
|
||||
print_prop(short_name, "CP");
|
||||
} else if (t->base() == Type::Control) {
|
||||
|
@ -2838,7 +2838,7 @@ bool LibraryCallKit::inline_native_classID() {
|
||||
IdealVariable result(ideal); __ declarations_done();
|
||||
Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(),
|
||||
basic_plus_adr(cls, java_lang_Class::klass_offset()),
|
||||
TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL));
|
||||
TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));
|
||||
|
||||
|
||||
__ if_then(kls, BoolTest::ne, null()); {
|
||||
@ -2868,7 +2868,7 @@ bool LibraryCallKit::inline_native_classID() {
|
||||
} __ else_(); {
|
||||
Node* array_kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(),
|
||||
basic_plus_adr(cls, java_lang_Class::array_klass_offset()),
|
||||
TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL));
|
||||
TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));
|
||||
__ if_then(array_kls, BoolTest::ne, null()); {
|
||||
Node* array_kls_trace_id_addr = basic_plus_adr(array_kls, in_bytes(KLASS_TRACE_ID_OFFSET));
|
||||
Node* array_kls_trace_id_raw = ideal.load(ideal.ctrl(), array_kls_trace_id_addr, TypeLong::LONG, T_LONG, Compile::AliasIdxRaw);
|
||||
@ -2961,7 +2961,7 @@ Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror,
|
||||
int offset) {
|
||||
if (region == NULL) never_see_null = true;
|
||||
Node* p = basic_plus_adr(mirror, offset);
|
||||
const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL;
|
||||
const TypeKlassPtr* kls_type = TypeInstKlassPtr::OBJECT_OR_NULL;
|
||||
Node* kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type));
|
||||
Node* null_ctl = top();
|
||||
kls = null_check_oop(kls, &null_ctl, never_see_null);
|
||||
@ -3150,7 +3150,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
|
||||
phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror())));
|
||||
// If we fall through, it's a plain class. Get its _super.
|
||||
p = basic_plus_adr(kls, in_bytes(Klass::super_offset()));
|
||||
kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL));
|
||||
kls = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeInstKlassPtr::OBJECT_OR_NULL));
|
||||
null_ctl = top();
|
||||
kls = null_check_oop(kls, &null_ctl);
|
||||
if (null_ctl != top()) {
|
||||
@ -3292,7 +3292,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
|
||||
record_for_igvn(region);
|
||||
|
||||
const TypePtr* adr_type = TypeRawPtr::BOTTOM; // memory type of loads
|
||||
const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL;
|
||||
const TypeKlassPtr* kls_type = TypeInstKlassPtr::OBJECT_OR_NULL;
|
||||
int class_klass_offset = java_lang_Class::klass_offset();
|
||||
|
||||
// First null-check both mirrors and load each mirror's klass metaobject.
|
||||
@ -6004,7 +6004,7 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
|
||||
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type()->cast_to_ptr_type(TypePtr::NotNull);
|
||||
Node* aescrypt_object = new CheckCastPPNode(control(), embeddedCipherObj, xtype);
|
||||
aescrypt_object = _gvn.transform(aescrypt_object);
|
||||
|
||||
@ -6092,7 +6092,7 @@ bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) {
|
||||
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type()->cast_to_ptr_type(TypePtr::NotNull);
|
||||
Node* aescrypt_object = new CheckCastPPNode(control(), embeddedCipherObj, xtype);
|
||||
aescrypt_object = _gvn.transform(aescrypt_object);
|
||||
|
||||
@ -6163,7 +6163,7 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
|
||||
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);
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type()->cast_to_ptr_type(TypePtr::NotNull);
|
||||
Node* aescrypt_object = new CheckCastPPNode(control(), embeddedCipherObj, xtype);
|
||||
aescrypt_object = _gvn.transform(aescrypt_object);
|
||||
// we need to get the start of the aescrypt_object's expanded key array
|
||||
@ -6681,7 +6681,7 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(Node* digestBase_obj, ciIn
|
||||
const char* state_type, address stubAddr, const char *stubName,
|
||||
Node* src_start, Node* ofs, Node* limit) {
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_digestBase);
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type()->cast_to_ptr_type(TypePtr::NotNull);
|
||||
Node* digest_obj = new CheckCastPPNode(control(), digestBase_obj, xtype);
|
||||
digest_obj = _gvn.transform(digest_obj);
|
||||
|
||||
|
@ -1972,7 +1972,7 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
|
||||
return con_type;
|
||||
}
|
||||
}
|
||||
} else if (tp->base() == Type::KlassPtr) {
|
||||
} 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() ||
|
||||
|
@ -528,7 +528,7 @@ public:
|
||||
|
||||
// Polymorphic factory method:
|
||||
static Node* make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* at,
|
||||
const TypeKlassPtr* tk = TypeKlassPtr::OBJECT);
|
||||
const TypeKlassPtr* tk = TypeInstKlassPtr::OBJECT);
|
||||
};
|
||||
|
||||
//------------------------------LoadNKlassNode---------------------------------
|
||||
|
@ -168,7 +168,7 @@ void Parse::array_store_check() {
|
||||
if (MonomorphicArrayCheck
|
||||
&& !too_many_traps(Deoptimization::Reason_array_check)
|
||||
&& !tak->klass_is_exact()
|
||||
&& tak != TypeKlassPtr::OBJECT) {
|
||||
&& tak != TypeInstKlassPtr::OBJECT) {
|
||||
// Regarding the fourth condition in the if-statement from above:
|
||||
//
|
||||
// If the compiler has determined that the type of array 'ary' (represented
|
||||
|
@ -234,7 +234,7 @@ bool SubTypeCheckNode::verify(PhaseGVN* phase) {
|
||||
chk_off_X = phase->transform(new ConvI2LNode(chk_off_X));
|
||||
#endif
|
||||
Node* p2 = phase->transform(new AddPNode(subklass, subklass, chk_off_X));
|
||||
Node* nkls = phase->transform(LoadKlassNode::make(*phase, NULL, C->immutable_memory(), p2, phase->type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL));
|
||||
Node* nkls = phase->transform(LoadKlassNode::make(*phase, NULL, C->immutable_memory(), p2, phase->type(p2)->is_ptr(), TypeInstKlassPtr::OBJECT_OR_NULL));
|
||||
|
||||
return verify_helper(phase, nkls, cached_t);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -67,6 +67,8 @@ class TypeOopPtr;
|
||||
class TypeInstPtr;
|
||||
class TypeAryPtr;
|
||||
class TypeKlassPtr;
|
||||
class TypeInstKlassPtr;
|
||||
class TypeAryKlassPtr;
|
||||
class TypeMetadataPtr;
|
||||
|
||||
//------------------------------Type-------------------------------------------
|
||||
@ -108,6 +110,8 @@ public:
|
||||
|
||||
MetadataPtr, // Generic metadata
|
||||
KlassPtr, // Klass pointers
|
||||
InstKlassPtr,
|
||||
AryKlassPtr,
|
||||
|
||||
Function, // Function signature
|
||||
Abio, // Abstract I/O
|
||||
@ -321,6 +325,10 @@ public:
|
||||
const TypeMetadataPtr *is_metadataptr() const; // Java-style GC'd pointer
|
||||
const TypeKlassPtr *isa_klassptr() const; // Returns NULL if not KlassPtr
|
||||
const TypeKlassPtr *is_klassptr() const; // assert if not KlassPtr
|
||||
const TypeInstKlassPtr *isa_instklassptr() const; // Returns NULL if not IntKlassPtr
|
||||
const TypeInstKlassPtr *is_instklassptr() const; // assert if not IntKlassPtr
|
||||
const TypeAryKlassPtr *isa_aryklassptr() const; // Returns NULL if not AryKlassPtr
|
||||
const TypeAryKlassPtr *is_aryklassptr() const; // assert if not AryKlassPtr
|
||||
|
||||
virtual bool is_finite() const; // Has a finite value
|
||||
virtual bool is_nan() const; // Is not a number (NaN)
|
||||
@ -916,6 +924,24 @@ protected:
|
||||
void dump_inline_depth(outputStream *st) const;
|
||||
#endif
|
||||
|
||||
// TypeInstPtr (TypeAryPtr resp.) and TypeInstKlassPtr (TypeAryKlassPtr resp.) implement very similar meet logic.
|
||||
// The logic for meeting 2 instances (2 arrays resp.) is shared in the 2 utility methods below. However the logic for
|
||||
// the oop and klass versions can be slightly different and extra logic may have to be executed depending on what
|
||||
// exact case the meet falls into. The MeetResult struct is used by the utility methods to communicate what case was
|
||||
// encountered so the right logic specific to klasses or oops can be executed.,
|
||||
enum MeetResult {
|
||||
QUICK,
|
||||
UNLOADED,
|
||||
SUBTYPE,
|
||||
NOT_SUBTYPE,
|
||||
LCA
|
||||
};
|
||||
static MeetResult
|
||||
meet_instptr(PTR &ptr, ciKlass* this_klass, ciKlass* tinst_klass, bool this_xk, bool tinst_xk, PTR this_ptr,
|
||||
PTR tinst_ptr, ciKlass*&res_klass, bool &res_xk);
|
||||
static MeetResult
|
||||
meet_aryptr(PTR& ptr, const Type*& elem, ciKlass* this_klass, ciKlass* tap_klass, bool this_xk, bool tap_xk, PTR this_ptr, PTR tap_ptr, ciKlass*& res_klass, bool& res_xk);
|
||||
|
||||
public:
|
||||
const int _offset; // Offset into oop, with TOP & BOT
|
||||
const PTR _ptr; // Pointer equivalence class
|
||||
@ -998,7 +1024,7 @@ public:
|
||||
static const TypeRawPtr *make( address bits );
|
||||
|
||||
// Return a 'ptr' version of this type
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeRawPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual intptr_t get_con() const;
|
||||
|
||||
@ -1097,14 +1123,14 @@ public:
|
||||
|
||||
virtual intptr_t get_con() const;
|
||||
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeOopPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
|
||||
|
||||
// corresponding pointer to klass, for a given instance
|
||||
const TypeKlassPtr* as_klass_type() const;
|
||||
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
|
||||
@ -1181,7 +1207,7 @@ class TypeInstPtr : public TypeOopPtr {
|
||||
// be a TypeInstPtr, but may also be a TypeInt::INT for int.class, etc.
|
||||
ciType* java_mirror_type() const;
|
||||
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeInstPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
@ -1199,6 +1225,8 @@ class TypeInstPtr : public TypeOopPtr {
|
||||
virtual const TypeInstPtr *xmeet_unloaded( const TypeInstPtr *t ) const;
|
||||
virtual const Type *xdual() const; // Compute dual right now.
|
||||
|
||||
const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeInstPtr *NOTNULL;
|
||||
static const TypeInstPtr *BOTTOM;
|
||||
@ -1265,7 +1293,7 @@ public:
|
||||
int inline_depth = InlineDepthBottom, bool is_autobox_cache = false);
|
||||
|
||||
// Return a 'ptr' version of this type
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeAryPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
|
||||
@ -1292,6 +1320,7 @@ public:
|
||||
const TypeAryPtr* cast_to_autobox_cache() const;
|
||||
|
||||
static jint max_array_length(BasicType etype) ;
|
||||
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeAryPtr *RANGE;
|
||||
@ -1343,7 +1372,7 @@ public:
|
||||
|
||||
ciMetadata* metadata() const { return _metadata; }
|
||||
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
virtual const TypeMetadataPtr* cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||
|
||||
@ -1363,74 +1392,130 @@ public:
|
||||
//------------------------------TypeKlassPtr-----------------------------------
|
||||
// Class of Java Klass pointers
|
||||
class TypeKlassPtr : public TypePtr {
|
||||
TypeKlassPtr( PTR ptr, ciKlass* klass, int offset );
|
||||
protected:
|
||||
TypeKlassPtr(TYPES t, PTR ptr, ciKlass* klass, int offset);
|
||||
|
||||
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
|
||||
|
||||
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:
|
||||
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
|
||||
public:
|
||||
virtual bool eq( const Type *t ) const;
|
||||
virtual int hash() const; // Type specific hashing
|
||||
virtual bool singleton(void) const; // TRUE if type is a singleton
|
||||
private:
|
||||
|
||||
static const TypeKlassPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact);
|
||||
|
||||
ciKlass* _klass;
|
||||
|
||||
// Does the type exclude subclasses of the klass? (Inexact == polymorphic.)
|
||||
bool _klass_is_exact;
|
||||
|
||||
public:
|
||||
ciSymbol* name() const { return klass()->name(); }
|
||||
|
||||
ciKlass* klass() const { return _klass; }
|
||||
bool klass_is_exact() const { return _klass_is_exact; }
|
||||
|
||||
virtual ciKlass* klass() const { return _klass; }
|
||||
bool klass_is_exact() const { return _ptr == Constant; }
|
||||
bool is_loaded() const { return klass()->is_loaded(); }
|
||||
|
||||
// Creates a type given a klass. Correctly handles multi-dimensional arrays
|
||||
// Respects UseUniqueSubclasses.
|
||||
// If the klass is final, the resulting type will be exact.
|
||||
static const TypeKlassPtr* make_from_klass(ciKlass* klass) {
|
||||
return make_from_klass_common(klass, true, false);
|
||||
}
|
||||
// Same as before, but will produce an exact type, even if
|
||||
// the klass is not final, as long as it has exactly one implementation.
|
||||
static const TypeKlassPtr* make_from_klass_unique(ciKlass* klass) {
|
||||
return make_from_klass_common(klass, true, true);
|
||||
}
|
||||
// Same as before, but does not respects UseUniqueSubclasses.
|
||||
// Use this only for creating array element types.
|
||||
static const TypeKlassPtr* make_from_klass_raw(ciKlass* klass) {
|
||||
return make_from_klass_common(klass, false, false);
|
||||
}
|
||||
static const TypeKlassPtr* make(ciKlass* klass);
|
||||
static const TypeKlassPtr *make(PTR ptr, ciKlass* klass, int offset);
|
||||
|
||||
// Make a generic (unclassed) pointer to metadata.
|
||||
static const TypeKlassPtr* make(PTR ptr, int offset);
|
||||
|
||||
// ptr to klass 'k'
|
||||
static const TypeKlassPtr *make( ciKlass* k ) { return make( TypePtr::Constant, k, 0); }
|
||||
// ptr to klass 'k' with offset
|
||||
static const TypeKlassPtr *make( ciKlass* k, int offset ) { return make( TypePtr::Constant, k, offset); }
|
||||
// ptr to klass 'k' or sub-klass
|
||||
static const TypeKlassPtr *make( PTR ptr, ciKlass* k, int offset);
|
||||
virtual const TypePtr* cast_to_ptr_type(PTR ptr) const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||
|
||||
virtual const Type *cast_to_exactness(bool klass_is_exact) const;
|
||||
virtual const TypeKlassPtr *cast_to_exactness(bool klass_is_exact) const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
// corresponding pointer to instance, for a given class
|
||||
const TypeOopPtr* as_instance_type() const;
|
||||
virtual const TypeOopPtr* as_instance_type() const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
virtual const TypePtr *add_offset( intptr_t offset ) const { ShouldNotReachHere(); return NULL; }
|
||||
virtual const Type *xmeet( const Type *t ) const { ShouldNotReachHere(); return NULL; }
|
||||
virtual const Type *xdual() const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
virtual intptr_t get_con() const;
|
||||
|
||||
virtual const TypeKlassPtr* with_offset(intptr_t offset) const { ShouldNotReachHere(); return NULL; }
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
|
||||
#endif
|
||||
};
|
||||
|
||||
// Instance klass pointer, mirrors TypeInstPtr
|
||||
class TypeInstKlassPtr : public TypeKlassPtr {
|
||||
|
||||
TypeInstKlassPtr(PTR ptr, ciKlass* klass, int offset)
|
||||
: TypeKlassPtr(InstKlassPtr, ptr, klass, offset) {
|
||||
}
|
||||
|
||||
virtual bool must_be_exact() const;
|
||||
|
||||
public:
|
||||
// Instance klass ignoring any interface
|
||||
ciInstanceKlass* instance_klass() const { return klass()->as_instance_klass(); }
|
||||
|
||||
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 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 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;
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeInstKlassPtr* OBJECT; // Not-null object klass or below
|
||||
static const TypeInstKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same
|
||||
};
|
||||
|
||||
// Array klass pointer, mirrors TypeAryPtr
|
||||
class TypeAryKlassPtr : public TypeKlassPtr {
|
||||
const Type *_elem;
|
||||
|
||||
TypeAryKlassPtr(PTR ptr, const Type *elem, ciKlass* klass, int offset)
|
||||
: TypeKlassPtr(AryKlassPtr, ptr, klass, offset), _elem(elem) {
|
||||
}
|
||||
|
||||
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);
|
||||
static const TypeAryKlassPtr *make(PTR ptr, const Type *elem, ciKlass* k, int offset);
|
||||
static const TypeAryKlassPtr* make(ciKlass* klass);
|
||||
|
||||
const Type *elem() const { return _elem; }
|
||||
|
||||
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 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 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 intptr_t get_con() const;
|
||||
virtual const TypeKlassPtr* with_offset(intptr_t offset) const;
|
||||
|
||||
virtual bool empty(void) const {
|
||||
return TypeKlassPtr::empty() || _elem->empty();
|
||||
}
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeKlassPtr* OBJECT; // Not-null object klass or below
|
||||
static const TypeKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same
|
||||
#ifndef PRODUCT
|
||||
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
|
||||
#endif
|
||||
@ -1721,13 +1806,13 @@ inline const TypeVect *Type::isa_vect() const {
|
||||
|
||||
inline const TypePtr *Type::is_ptr() const {
|
||||
// AnyPtr is the first Ptr and KlassPtr the last, with no non-ptrs between.
|
||||
assert(_base >= AnyPtr && _base <= KlassPtr, "Not a pointer");
|
||||
assert(_base >= AnyPtr && _base <= AryKlassPtr, "Not a pointer");
|
||||
return (TypePtr*)this;
|
||||
}
|
||||
|
||||
inline const TypePtr *Type::isa_ptr() const {
|
||||
// AnyPtr is the first Ptr and KlassPtr the last, with no non-ptrs between.
|
||||
return (_base >= AnyPtr && _base <= KlassPtr) ? (TypePtr*)this : NULL;
|
||||
return (_base >= AnyPtr && _base <= AryKlassPtr) ? (TypePtr*)this : NULL;
|
||||
}
|
||||
|
||||
inline const TypeOopPtr *Type::is_oopptr() const {
|
||||
@ -1799,14 +1884,32 @@ inline const TypeMetadataPtr *Type::isa_metadataptr() const {
|
||||
}
|
||||
|
||||
inline const TypeKlassPtr *Type::isa_klassptr() const {
|
||||
return (_base == KlassPtr) ? (TypeKlassPtr*)this : NULL;
|
||||
return (_base >= KlassPtr && _base <= AryKlassPtr ) ? (TypeKlassPtr*)this : NULL;
|
||||
}
|
||||
|
||||
inline const TypeKlassPtr *Type::is_klassptr() const {
|
||||
assert( _base == KlassPtr, "Not a klass pointer" );
|
||||
assert(_base >= KlassPtr && _base <= AryKlassPtr, "Not a klass pointer");
|
||||
return (TypeKlassPtr*)this;
|
||||
}
|
||||
|
||||
inline const TypeInstKlassPtr *Type::isa_instklassptr() const {
|
||||
return (_base == InstKlassPtr) ? (TypeInstKlassPtr*)this : NULL;
|
||||
}
|
||||
|
||||
inline const TypeInstKlassPtr *Type::is_instklassptr() const {
|
||||
assert(_base == InstKlassPtr, "Not a klass pointer");
|
||||
return (TypeInstKlassPtr*)this;
|
||||
}
|
||||
|
||||
inline const TypeAryKlassPtr *Type::isa_aryklassptr() const {
|
||||
return (_base == AryKlassPtr) ? (TypeAryKlassPtr*)this : NULL;
|
||||
}
|
||||
|
||||
inline const TypeAryKlassPtr *Type::is_aryklassptr() const {
|
||||
assert(_base == AryKlassPtr, "Not a klass pointer");
|
||||
return (TypeAryKlassPtr*)this;
|
||||
}
|
||||
|
||||
inline const TypePtr* Type::make_ptr() const {
|
||||
return (_base == NarrowOop) ? is_narrowoop()->get_ptrtype() :
|
||||
((_base == NarrowKlass) ? is_narrowklass()->get_ptrtype() :
|
||||
|
@ -447,7 +447,7 @@ public:
|
||||
|
||||
// Binary search and insertion utility. Search array for element
|
||||
// matching key according to the static compare function. Insert
|
||||
// that element is not already in the list. Assumes the list is
|
||||
// that element if not already in the list. Assumes the list is
|
||||
// already sorted according to compare function.
|
||||
template <int compare(const E&, const E&)> E insert_sorted(const E& key) {
|
||||
bool found;
|
||||
|
@ -53,13 +53,13 @@ public class IRNode {
|
||||
private static final String STORE_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
|
||||
private static final String LOAD_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
|
||||
|
||||
public static final String ALLOC = "(.*precise klass .*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java" + END;
|
||||
public static final String ALLOC_OF = COMPOSITE_PREFIX + "(.*precise klass .*" + IS_REPLACED + ":.*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java" + END;
|
||||
public static final String ALLOC_ARRAY = "(.*precise klass \\[L.*\\R((.*(?i:mov|xor|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_array_Java" + END;
|
||||
public static final String ALLOC_ARRAY_OF = COMPOSITE_PREFIX + "(.*precise klass \\[L.*" + IS_REPLACED + ";:.*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_array_Java" + END;
|
||||
public static final String ALLOC = "(.*precise .*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java" + END;
|
||||
public static final String ALLOC_OF = COMPOSITE_PREFIX + "(.*precise .*" + IS_REPLACED + ":.*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java" + END;
|
||||
public static final String ALLOC_ARRAY = "(.*precise \\[.*\\R((.*(?i:mov|xor|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_array_Java" + END;
|
||||
public static final String ALLOC_ARRAY_OF = COMPOSITE_PREFIX + "(.*precise \\[.*" + IS_REPLACED + ":.*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_array_Java" + END;
|
||||
|
||||
public static final String CHECKCAST_ARRAY = "(((?i:cmp|CLFI|CLR).*precise klass \\[.*;:|.*(?i:mov|or).*precise klass \\[.*;:.*\\R.*(cmp|CMP|CLR))" + END;
|
||||
public static final String CHECKCAST_ARRAY_OF = COMPOSITE_PREFIX + "(((?i:cmp|CLFI|CLR).*precise klass \\[.*" + IS_REPLACED + ";:|.*(?i:mov|or).*precise klass \\[.*" + IS_REPLACED + ";:.*\\R.*(cmp|CMP|CLR))" + END;
|
||||
public static final String CHECKCAST_ARRAY = "(((?i:cmp|CLFI|CLR).*precise \\[.*:|.*(?i:mov|or).*precise \\[.*:.*\\R.*(cmp|CMP|CLR))" + END;
|
||||
public static final String CHECKCAST_ARRAY_OF = COMPOSITE_PREFIX + "(((?i:cmp|CLFI|CLR).*precise \\[.*" + IS_REPLACED + ":|.*(?i:mov|or).*precise klass \\[.*" + IS_REPLACED + ";:.*\\R.*(cmp|CMP|CLR))" + END;
|
||||
// Does not work on s390 (a rule containing this regex will be skipped on s390).
|
||||
public static final String CHECKCAST_ARRAYCOPY = "(.*((?i:call_leaf_nofp,runtime)|CALL,\\s?runtime leaf nofp|BCTRL.*.leaf call).*checkcast_arraycopy.*" + END;
|
||||
|
||||
|
@ -207,9 +207,9 @@ public class TestIRMatching {
|
||||
} else {
|
||||
cmp = "cmp";
|
||||
}
|
||||
runCheck(BadFailOnConstraint.create(CheckCastArray.class, "array()", 1, cmp, "precise klass"),
|
||||
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 1,cmp, "precise klass", "MyClass"),
|
||||
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 2,cmp, "precise klass", "ir_framework/tests/MyClass"),
|
||||
runCheck(BadFailOnConstraint.create(CheckCastArray.class, "array()", 1, cmp, "precise"),
|
||||
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 1,cmp, "precise", "MyClass"),
|
||||
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 2,cmp, "precise", "ir_framework/tests/MyClass"),
|
||||
GoodFailOnConstraint.create(CheckCastArray.class, "array()", 3),
|
||||
Platform.isS390x() ? // There is no checkcast_arraycopy stub for C2 on s390
|
||||
GoodFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user