8266550: C2: mirror TypeOopPtr/TypeInstPtr/TypeAryPtr with TypeKlassPtr/TypeInstKlassPtr/TypeAryKlassPtr

Reviewed-by: vlivanov, thartmann
This commit is contained in:
Roland Westrelin 2021-09-14 08:35:09 +00:00
parent a143372818
commit 1d2458db34
18 changed files with 992 additions and 457 deletions

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