Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8251966: [lworld] TestArrays.java fails with -XX:+ExpandSubTypeCheckAtParseTime #281

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -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;