Skip to content
Permalink
Browse files
8251966: [lworld] TestArrays.java fails with -XX:+ExpandSubTypeCheckA…
…tParseTime
  • Loading branch information
TobiHartmann committed Nov 26, 2020
1 parent 89dde2a commit c2b5f11cf2ce37f4dace345c962171a4de773dda
@@ -2931,7 +2931,7 @@ Node* GraphKit::gen_subtype_check(Node* obj_or_subklass, Node* superklass) {
MergeMemNode* mem = merged_memory();
Node* ctrl = control();
Node* subklass = obj_or_subklass;
if (!sub_t->isa_klassptr()) {
if (!sub_t->isa_klassptr() && !sub_t->isa_inlinetype()) {
subklass = load_object_klass(obj_or_subklass);
}
Node* n = Phase::gen_subtype_check(subklass, superklass, &ctrl, mem, _gvn);
@@ -2391,7 +2391,7 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const {
return TypeKlassPtr::make(ak);
}
}
return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0));
return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0), false, tary->is_not_flat(), tary->is_not_null_free());
} else if (ak->is_type_array_klass()) {
return TypeKlassPtr::make(ak); // These are always precise
}
@@ -219,20 +219,18 @@ Node* Parse::array_store_check() {
reason = Deoptimization::Reason_array_check;
}
if (extak != NULL) {
always_see_exact_class = true;
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(reason,
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.
Node* cmp = _gvn.transform(new CmpPNode(array_klass, con));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
// Only do it if the check does not always pass/fail
if (!bol->is_Con()) {
always_see_exact_class = true;
{ BuildCutout unless(this, bol, PROB_MAX);
uncommon_trap(reason,
Deoptimization::Action_maybe_recompile,
tak->klass());
}
// Cast array klass to exactness
replace_in_map(array_klass,con);
Node* cast = _gvn.transform(new CheckCastPPNode(control(), ary, extak->as_instance_type()));
replace_in_map(ary, cast);
@@ -242,7 +240,8 @@ Node* Parse::array_store_check() {
log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'",
log->identify(tak->klass()));
}
array_klass = con; // Use cast value moving forward
// Use cast value moving forward
array_klass = con;
}
}
}
@@ -977,6 +977,14 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
(r1->flatten_array() && (!r0->can_be_inline_type() || (klass0->is_inlinetype() && !klass0->flatten_array())))) {
// One type is flattened in arrays but the other type is not. Must be unrelated.
unrelated_classes = true;
} else if ((r0->is_not_flat() && klass1->is_flat_array_klass()) ||
(r1->is_not_flat() && klass0->is_flat_array_klass())) {
// One type is a non-flattened array and the other type is a flattened array. Must be unrelated.
unrelated_classes = true;
} else if ((r0->is_not_null_free() && klass1->is_obj_array_klass() && klass1->as_obj_array_klass()->element_klass()->is_inlinetype()) ||
(r1->is_not_null_free() && klass0->is_obj_array_klass() && klass0->as_obj_array_klass()->element_klass()->is_inlinetype())) {
// One type is a non-null-free array and the other type is a null-free array. Must be unrelated.
unrelated_classes = true;
}
}
if (unrelated_classes) {
@@ -5376,32 +5376,35 @@ const TypeKlassPtr *TypeKlassPtr::OBJECT;
const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL;

//------------------------------TypeKlassPtr-----------------------------------
TypeKlassPtr::TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array)
: TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant), _flatten_array(flatten_array) {
TypeKlassPtr::TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array, bool not_flat, bool not_null_free)
: TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant),
_flatten_array(flatten_array), _not_flat(not_flat), _not_null_free(not_null_free) {
assert(!klass->flatten_array() || flatten_array, "Should be flat in array");
assert(!flatten_array || can_be_inline_type(), "Only inline types can be flat in array");
}

//------------------------------make-------------------------------------------
// ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant
const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array) {
const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array, bool not_flat, bool not_null_free) {
assert(k == NULL || k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop");
// Check if this type is known to be flat in arrays
flatten_array = flatten_array || k->flatten_array();
return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, flatten_array))->hashcons();
return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, flatten_array, not_flat, not_null_free))->hashcons();
}

//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
bool TypeKlassPtr::eq( const Type *t ) const {
const TypeKlassPtr *p = t->is_klassptr();
return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array();
return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array() &&
is_not_flat() == p->is_not_flat() && is_not_null_free() == p->is_not_null_free();
}

//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeKlassPtr::hash(void) const {
return java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()), (jint)flatten_array());
return java_add(java_add(java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()),
(jint)flatten_array()), (jint)is_not_flat()), (jint)is_not_null_free());
}

//------------------------------singleton--------------------------------------
@@ -5535,21 +5538,21 @@ ciKlass* TypeAryPtr::klass() const {
//------------------------------add_offset-------------------------------------
// Access internals of klass object
const TypePtr *TypeKlassPtr::add_offset( intptr_t offset ) const {
return make(_ptr, klass(), xadd_offset(offset), flatten_array());
return make(_ptr, klass(), xadd_offset(offset), flatten_array(), is_not_flat(), is_not_null_free());
}

//------------------------------cast_to_ptr_type-------------------------------
const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const {
assert(_base == KlassPtr, "subclass must override cast_to_ptr_type");
if( ptr == _ptr ) return this;
return make(ptr, _klass, _offset, _flatten_array);
return make(ptr, _klass, _offset, _flatten_array, _not_flat, _not_null_free);
}


//-----------------------------cast_to_exactness-------------------------------
const Type *TypeKlassPtr::cast_to_exactness(bool klass_is_exact) const {
if( klass_is_exact == _klass_is_exact ) return this;
return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array);
return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array, _not_flat, _not_null_free);
}


@@ -5560,12 +5563,15 @@ const TypeOopPtr* TypeKlassPtr::as_instance_type() const {
ciKlass* k = klass();
assert(k != NULL, "klass should not be NULL");
bool xk = klass_is_exact();
//return TypeInstPtr::make(TypePtr::NotNull, k, xk, NULL, 0);
const TypeOopPtr* toop = TypeOopPtr::make_from_klass_raw(k);
guarantee(toop != NULL, "need type for given klass");
toop = toop->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr();
if (flatten_array() && !klass()->is_inlinetype()) {
toop = toop->is_instptr()->cast_to_flatten_array();
} else if (is_not_null_free()) {
toop = toop->is_aryptr()->cast_to_not_null_free();
} else if (is_not_flat()) {
toop = toop->is_aryptr()->cast_to_not_flat();
}
return toop->cast_to_exactness(xk)->is_oopptr();
}
@@ -5609,7 +5615,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
case Null:
if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
case AnyNull:
return make(ptr, klass(), offset, flatten_array());
return make(ptr, klass(), offset, flatten_array(), is_not_flat(), is_not_null_free());
case BotPTR:
case NotNull:
return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
@@ -5657,18 +5663,18 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
// If we have constants, then we created oops so classes are loaded
// and we can handle the constants further down. This case handles
// not-loaded classes
if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array()) {
return make(ptr, klass(), off, flatten_array());
if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array() && is_not_flat() == tkls->is_not_flat() && is_not_null_free() && tkls->is_not_null_free()) {
return make(ptr, klass(), off, flatten_array(), is_not_flat(), is_not_null_free());
}

// Classes require inspection in the Java klass hierarchy. Must be loaded.
ciKlass* tkls_klass = tkls->klass();
ciKlass* this_klass = this->klass();
assert( tkls_klass->is_loaded(), "This class should have been loaded.");
assert( this_klass->is_loaded(), "This class should have been loaded.");
bool tkls_flatten_array = tkls->flatten_array();
bool this_flatten_array = this->flatten_array();
bool flatten_array = below_centerline(ptr) ? (this_flatten_array && tkls_flatten_array) : (this_flatten_array || tkls_flatten_array);
bool flatten_array = below_centerline(ptr) ? (this->flatten_array() && tkls->flatten_array()) : (this->flatten_array() || tkls->flatten_array());
bool is_not_flat = this->is_not_flat() && tkls->is_not_flat();
bool is_not_null_free = this->is_not_null_free() && tkls->is_not_null_free();

// If 'this' type is above the centerline and is a superclass of the
// other, we can treat 'this' as having the same type as the other.
@@ -5696,7 +5702,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
else
ptr = NotNull;
}
return make(ptr, this_klass, off, flatten_array);
return make(ptr, this_klass, off, flatten_array, is_not_flat, is_not_null_free);
} // Else classes are not equal

// Since klasses are different, we require the LCA in the Java
@@ -5705,7 +5711,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
ptr = NotNull;
// Now we find the LCA of Java classes
ciKlass* k = this_klass->least_common_ancestor(tkls_klass);
return make(ptr, k, off);
return make(ptr, k, off, false, is_not_flat, is_not_null_free);
} // End of case KlassPtr

} // End of switch
@@ -5715,7 +5721,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type *TypeKlassPtr::xdual() const {
return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array());
return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array(), !is_not_flat(), !is_not_null_free());
}

//------------------------------get_con----------------------------------------
@@ -5763,6 +5769,11 @@ void TypeKlassPtr::dump2( Dict & d, uint depth, outputStream *st ) const {
default:
break;
}
if (Verbose) {
if (_flatten_array) st->print(":flatten array");
if (_not_flat) st->print(":not flat");
if (_not_null_free) st->print(":not null free");
}

_offset.dump2(st);

@@ -1017,6 +1017,8 @@ class TypePtr : public Type {

virtual bool can_be_inline_type() const { return false; }
virtual bool flatten_array() const { return false; }
virtual bool is_not_flat() const { return false; }
virtual bool is_not_null_free() const { return false; }

// Tests for relation to centerline of type lattice:
static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); }
@@ -1449,7 +1451,7 @@ class TypeMetadataPtr : public TypePtr {
//------------------------------TypeKlassPtr-----------------------------------
// Class of Java Klass pointers
class TypeKlassPtr : public TypePtr {
TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array);
TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array, bool not_flat, bool not_null_free);

protected:
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
@@ -1463,23 +1465,30 @@ class TypeKlassPtr : public TypePtr {

// Does the type exclude subclasses of the klass? (Inexact == polymorphic.)
bool _klass_is_exact;
bool _flatten_array; // Type is flat in arrays
const bool _flatten_array; // Type is flat in arrays
const bool _not_flat; // Array is never flattened
const bool _not_null_free; // Array is never null-free

public:
ciKlass* klass() const { return _klass; }
bool klass_is_exact() const { return _klass_is_exact; }

virtual bool can_be_inline_type() const { return EnableValhalla && (_klass == NULL || _klass->can_be_inline_klass(_klass_is_exact)); }
virtual bool flatten_array() const { return _flatten_array; }
virtual bool is_not_flat() const { return _not_flat; }
virtual bool is_not_null_free() const { return _not_null_free; }

bool is_loaded() const { return klass() != NULL && klass()->is_loaded(); }

// ptr to klass 'k'
static const TypeKlassPtr* make(ciKlass* k) { return make( TypePtr::Constant, k, Offset(0)); }
// ptr to klass 'k' with offset
static const TypeKlassPtr* make(ciKlass* k, Offset offset) { return make( TypePtr::Constant, k, offset); }
static const TypeKlassPtr* make(ciKlass* k) {
bool not_null_free = k->is_array_klass() && ( k->as_array_klass()->element_klass() == NULL ||
!k->as_array_klass()->element_klass()->can_be_inline_klass(true));
bool not_flat = k->is_array_klass() && !k->is_flat_array_klass();
return make( TypePtr::Constant, k, Offset(0), false, not_flat, not_null_free);
}
// ptr to klass 'k' or sub-klass
static const TypeKlassPtr* make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false);
static const TypeKlassPtr* make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false, bool not_flat = false, bool not_null_free = false);

virtual const Type *cast_to_ptr_type(PTR ptr) const;

0 comments on commit c2b5f11

Please sign in to comment.