提交 6a0a927d 编写于 作者: R roland

8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed

Summary: type methods shouldn't always operate on speculative part
Reviewed-by: kvn, twisti
上级 de51fea1
......@@ -722,7 +722,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser)
Node* m = kit.map()->in(i);
Node* n = slow_map->in(i);
if (m != n) {
const Type* t = gvn.type(m)->meet(gvn.type(n));
const Type* t = gvn.type(m)->meet_speculative(gvn.type(n));
Node* phi = PhiNode::make(region, m, t);
phi->set_req(2, n);
kit.map()->set_req(i, gvn.transform(phi));
......@@ -975,7 +975,7 @@ JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_pa
Node* m = kit.map()->in(i);
Node* n = slow_map->in(i);
if (m != n) {
const Type* t = gvn.type(m)->meet(gvn.type(n));
const Type* t = gvn.type(m)->meet_speculative(gvn.type(n));
Node* phi = PhiNode::make(region, m, t);
phi->set_req(2, n);
kit.map()->set_req(i, gvn.transform(phi));
......
......@@ -951,7 +951,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
if (is_intf != ti_is_intf)
{ t = _type; break; }
}
t = t->meet(ti);
t = t->meet_speculative(ti);
}
}
......@@ -968,11 +968,11 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
//
// It is not possible to see Type::BOTTOM values as phi inputs,
// because the ciTypeFlow pre-pass produces verifier-quality types.
const Type* ft = t->filter(_type); // Worst case type
const Type* ft = t->filter_speculative(_type); // Worst case type
#ifdef ASSERT
// The following logic has been moved into TypeOopPtr::filter.
const Type* jt = t->join(_type);
const Type* jt = t->join_speculative(_type);
if( jt->empty() ) { // Emptied out???
// Check for evil case of 't' being a class and '_type' expecting an
......@@ -1757,7 +1757,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
break;
}
// Accumulate type for resulting Phi
type = type->meet(in(i)->in(AddPNode::Base)->bottom_type());
type = type->meet_speculative(in(i)->in(AddPNode::Base)->bottom_type());
}
Node* base = NULL;
if (doit) {
......
......@@ -3919,16 +3919,18 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) {
// which may optimize it out.
for (uint next = 0; next < worklist.size(); ++next) {
Node *n = worklist.at(next);
if (n->is_Type() && n->as_Type()->type()->isa_oopptr() != NULL &&
n->as_Type()->type()->is_oopptr()->speculative() != NULL) {
if (n->is_Type()) {
TypeNode* tn = n->as_Type();
const TypeOopPtr* t = tn->type()->is_oopptr();
bool in_hash = igvn.hash_delete(n);
assert(in_hash, "node should be in igvn hash table");
tn->set_type(t->remove_speculative());
igvn.hash_insert(n);
igvn._worklist.push(n); // give it a chance to go away
modified++;
const Type* t = tn->type();
const Type* t_no_spec = t->remove_speculative();
if (t_no_spec != t) {
bool in_hash = igvn.hash_delete(n);
assert(in_hash, "node should be in igvn hash table");
tn->set_type(t_no_spec);
igvn.hash_insert(n);
igvn._worklist.push(n); // give it a chance to go away
modified++;
}
}
uint max = n->len();
for( uint i = 0; i < max; ++i ) {
......@@ -3942,6 +3944,27 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) {
if (modified > 0) {
igvn.optimize();
}
#ifdef ASSERT
// Verify that after the IGVN is over no speculative type has resurfaced
worklist.clear();
worklist.push(root());
for (uint next = 0; next < worklist.size(); ++next) {
Node *n = worklist.at(next);
const Type* t = igvn.type(n);
assert(t == t->remove_speculative(), "no more speculative types");
if (n->is_Type()) {
t = n->as_Type()->type();
assert(t == t->remove_speculative(), "no more speculative types");
}
uint max = n->len();
for( uint i = 0; i < max; ++i ) {
Node *m = n->in(i);
if (not_a_node(m)) continue;
worklist.push(m);
}
}
igvn.check_no_speculative_types();
#endif
}
}
......
......@@ -188,7 +188,7 @@ Node *CMoveNode::Identity( PhaseTransform *phase ) {
const Type *CMoveNode::Value( PhaseTransform *phase ) const {
if( phase->type(in(Condition)) == Type::TOP )
return Type::TOP;
return phase->type(in(IfFalse))->meet(phase->type(in(IfTrue)));
return phase->type(in(IfFalse))->meet_speculative(phase->type(in(IfTrue)));
}
//------------------------------make-------------------------------------------
......@@ -392,14 +392,14 @@ Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//=============================================================================
// If input is already higher or equal to cast type, then this is an identity.
Node *ConstraintCastNode::Identity( PhaseTransform *phase ) {
return phase->type(in(1))->higher_equal(_type) ? in(1) : this;
return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this;
}
//------------------------------Value------------------------------------------
// Take 'join' of input and cast-up type
const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
const Type* ft = phase->type(in(1))->filter(_type);
const Type* ft = phase->type(in(1))->filter_speculative(_type);
#ifdef ASSERT
// Previous versions of this function had some special case logic,
......@@ -409,7 +409,7 @@ const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
{
const Type* t1 = phase->type(in(1));
if( t1 == Type::TOP ) assert(ft == Type::TOP, "special case #1");
const Type* rt = t1->join(_type);
const Type* rt = t1->join_speculative(_type);
if (rt->empty()) assert(ft == Type::TOP, "special case #2");
break;
}
......
......@@ -36,7 +36,7 @@ class MachNode;
// Simple constants
class ConNode : public TypeNode {
public:
ConNode( const Type *t ) : TypeNode(t,1) {
ConNode( const Type *t ) : TypeNode(t->remove_speculative(),1) {
init_req(0, (Node*)Compile::current()->root());
init_flags(Flag_is_Con);
}
......
......@@ -420,7 +420,7 @@ void GraphKit::combine_exception_states(SafePointNode* ex_map, SafePointNode* ph
}
const Type* srctype = _gvn.type(src);
if (phi->type() != srctype) {
const Type* dsttype = phi->type()->meet(srctype);
const Type* dsttype = phi->type()->meet_speculative(srctype);
if (phi->type() != dsttype) {
phi->set_type(dsttype);
_gvn.set_type(phi, dsttype);
......@@ -1223,7 +1223,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
// See if mixing in the NULL pointer changes type.
// If so, then the NULL pointer was not allowed in the original
// type. In other words, "value" was not-null.
if (t->meet(TypePtr::NULL_PTR) != t) {
if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) {
// same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ...
explicit_null_checks_elided++;
return value; // Elided null check quickly!
......@@ -1356,7 +1356,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
// Cast obj to not-null on this path
Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) {
const Type *t = _gvn.type(obj);
const Type *t_not_null = t->join(TypePtr::NOTNULL);
const Type *t_not_null = t->join_speculative(TypePtr::NOTNULL);
// Object is already not-null?
if( t == t_not_null ) return obj;
......@@ -3009,7 +3009,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
if (failure_control != NULL) // failure is now impossible
(*failure_control) = top();
// adjust the type of the phi to the exact klass:
phi->raise_bottom_type(_gvn.type(cast_obj)->meet(TypePtr::NULL_PTR));
phi->raise_bottom_type(_gvn.type(cast_obj)->meet_speculative(TypePtr::NULL_PTR));
}
}
......
......@@ -1115,8 +1115,8 @@ BoolNode *PhaseIdealLoop::clone_iff( PhiNode *phi, IdealLoopTree *loop ) {
Node *n2 = phi->in(i)->in(1)->in(2);
phi1->set_req( i, n1 );
phi2->set_req( i, n2 );
phi1->set_type( phi1->type()->meet(n1->bottom_type()) );
phi2->set_type( phi2->type()->meet(n2->bottom_type()) );
phi1->set_type( phi1->type()->meet_speculative(n1->bottom_type()));
phi2->set_type( phi2->type()->meet_speculative(n2->bottom_type()));
}
// See if these Phis have been made before.
// Register with optimizer
......@@ -1189,8 +1189,8 @@ CmpNode *PhaseIdealLoop::clone_bool( PhiNode *phi, IdealLoopTree *loop ) {
}
phi1->set_req( j, n1 );
phi2->set_req( j, n2 );
phi1->set_type( phi1->type()->meet(n1->bottom_type()) );
phi2->set_type( phi2->type()->meet(n2->bottom_type()) );
phi1->set_type(phi1->type()->meet_speculative(n1->bottom_type()));
phi2->set_type(phi2->type()->meet_speculative(n2->bottom_type()));
}
// See if these Phis have been made before.
......
......@@ -657,7 +657,7 @@ const TypePtr* MemNode::calculate_adr_type(const Type* t, const TypePtr* cross_c
// disregarding "null"-ness.
// (We make an exception for TypeRawPtr::BOTTOM, which is a bit bucket.)
const TypePtr* tp_notnull = tp->join(TypePtr::NOTNULL)->is_ptr();
assert(cross_check->meet(tp_notnull) == cross_check,
assert(cross_check->meet(tp_notnull) == cross_check->remove_speculative(),
"real address must not escape from expected memory type");
}
#endif
......@@ -1681,7 +1681,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
// t might actually be lower than _type, if _type is a unique
// concrete subclass of abstract class t.
if (off_beyond_header) { // is the offset beyond the header?
const Type* jt = t->join(_type);
const Type* jt = t->join_speculative(_type);
// In any case, do not allow the join, per se, to empty out the type.
if (jt->empty() && !t->empty()) {
// This can happen if a interface-typed array narrows to a class type.
......
......@@ -94,7 +94,7 @@ const Type* ProjNode::proj_type(const Type* t) const {
if ((_con == TypeFunc::Parms) &&
n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method()) {
// The result of autoboxing is always non-null on normal path.
t = t->join(TypePtr::NOTNULL);
t = t->join_speculative(TypePtr::NOTNULL);
}
return t;
}
......
......@@ -995,13 +995,13 @@ void Node::raise_bottom_type(const Type* new_type) {
if (is_Type()) {
TypeNode *n = this->as_Type();
if (VerifyAliases) {
assert(new_type->higher_equal(n->type()), "new type must refine old type");
assert(new_type->higher_equal_speculative(n->type()), "new type must refine old type");
}
n->set_type(new_type);
} else if (is_Load()) {
LoadNode *n = this->as_Load();
if (VerifyAliases) {
assert(new_type->higher_equal(n->type()), "new type must refine old type");
assert(new_type->higher_equal_speculative(n->type()), "new type must refine old type");
}
n->set_type(new_type);
}
......
......@@ -1649,7 +1649,7 @@ void Parse::merge_common(Parse::Block* target, int pnum) {
assert(bt1 != Type::BOTTOM, "should not be building conflict phis");
map()->set_req(j, _gvn.transform_no_reclaim(phi));
debug_only(const Type* bt2 = phi->bottom_type());
assert(bt2->higher_equal(bt1), "must be consistent with type-flow");
assert(bt2->higher_equal_speculative(bt1), "must be consistent with type-flow");
record_for_igvn(phi);
}
}
......@@ -2022,7 +2022,7 @@ void Parse::return_current(Node* value) {
!tp->klass()->is_interface()) {
// sharpen the type eagerly; this eases certain assert checking
if (tp->higher_equal(TypeInstPtr::NOTNULL))
tr = tr->join(TypeInstPtr::NOTNULL)->is_instptr();
tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr();
value = _gvn.transform(new (C) CheckCastPPNode(0,value,tr));
}
}
......
......@@ -88,7 +88,7 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) {
if (toop->klass()->as_instance_klass()->unique_concrete_subklass()) {
// If we load from "AbstractClass[]" we must see "ConcreteSubClass".
const Type* subklass = Type::get_const_type(toop->klass());
elemtype = subklass->join(el);
elemtype = subklass->join_speculative(el);
}
}
}
......@@ -1278,7 +1278,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
// Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq])
// or the narrowOop equivalent.
const Type* obj_type = _gvn.type(obj);
const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr();
const TypeOopPtr* tboth = obj_type->join_speculative(con_type)->isa_oopptr();
if (tboth != NULL && tboth->klass_is_exact() && tboth != obj_type &&
tboth->higher_equal(obj_type)) {
// obj has to be of the exact type Foo if the CmpP succeeds.
......@@ -1288,7 +1288,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
(jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) {
TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth);
const Type* tcc = ccast->as_Type()->type();
assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve");
assert(tcc != obj_type && tcc->higher_equal_speculative(obj_type), "must improve");
// Delay transform() call to allow recovery of pre-cast value
// at the control merge.
_gvn.set_type_bottom(ccast);
......@@ -1318,7 +1318,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
switch (btest) {
case BoolTest::eq: // Constant test?
{
const Type* tboth = tcon->join(tval);
const Type* tboth = tcon->join_speculative(tval);
if (tboth == tval) break; // Nothing to gain.
if (tcon->isa_int()) {
ccast = new (C) CastIINode(val, tboth);
......@@ -1352,7 +1352,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
if (ccast != NULL) {
const Type* tcc = ccast->as_Type()->type();
assert(tcc != tval && tcc->higher_equal(tval), "must improve");
assert(tcc != tval && tcc->higher_equal_speculative(tval), "must improve");
// Delay transform() call to allow recovery of pre-cast value
// at the control merge.
ccast->set_req(0, control());
......
......@@ -337,7 +337,7 @@ bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_au
// should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
// An oop is not scavengable if it is in the perm gen.
if (stable_type != NULL && con_type != NULL && con_type->isa_oopptr())
con_type = con_type->join(stable_type);
con_type = con_type->join_speculative(stable_type);
break;
case T_ILLEGAL:
......
......@@ -323,6 +323,23 @@ void NodeHash::remove_useless_nodes(VectorSet &useful) {
}
}
void NodeHash::check_no_speculative_types() {
#ifdef ASSERT
uint max = size();
Node *sentinel_node = sentinel();
for (uint i = 0; i < max; ++i) {
Node *n = at(i);
if(n != NULL && n != sentinel_node && n->is_Type()) {
TypeNode* tn = n->as_Type();
const Type* t = tn->type();
const Type* t_no_spec = t->remove_speculative();
assert(t == t_no_spec, "dead node in hash table or missed node during speculative cleanup");
}
}
#endif
}
#ifndef PRODUCT
//------------------------------dump-------------------------------------------
// Dump statistics for the hash table
......@@ -1392,11 +1409,11 @@ void PhaseIterGVN::remove_speculative_types() {
assert(UseTypeSpeculation, "speculation is off");
for (uint i = 0; i < _types.Size(); i++) {
const Type* t = _types.fast_lookup(i);
if (t != NULL && t->isa_oopptr()) {
const TypeOopPtr* to = t->is_oopptr();
_types.map(i, to->remove_speculative());
if (t != NULL) {
_types.map(i, t->remove_speculative());
}
}
_table.check_no_speculative_types();
}
//=============================================================================
......
......@@ -92,7 +92,8 @@ public:
}
void remove_useless_nodes(VectorSet &useful); // replace with sentinel
void replace_with(NodeHash* nh);
void replace_with(NodeHash* nh);
void check_no_speculative_types(); // Check no speculative part for type nodes in table
Node *sentinel() { return _sentinel; }
......@@ -501,6 +502,9 @@ public:
Deoptimization::DeoptReason reason);
void remove_speculative_types();
void check_no_speculative_types() {
_table.check_no_speculative_types();
}
#ifndef PRODUCT
protected:
......
......@@ -236,6 +236,13 @@ int Type::cmp( const Type *const t1, const Type *const t2 ) {
return !t1->eq(t2); // Return ZERO if equal
}
const Type* Type::maybe_remove_speculative(bool include_speculative) const {
if (!include_speculative) {
return remove_speculative();
}
return this;
}
//------------------------------hash-------------------------------------------
int Type::uhash( const Type *const t ) {
return t->hash();
......@@ -628,41 +635,44 @@ bool Type::interface_vs_oop(const Type *t) const {
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. NOT virtual. It enforces that meet is
// commutative and the lattice is symmetric.
const Type *Type::meet( const Type *t ) const {
const Type *Type::meet_helper(const Type *t, bool include_speculative) const {
if (isa_narrowoop() && t->isa_narrowoop()) {
const Type* result = make_ptr()->meet(t->make_ptr());
const Type* result = make_ptr()->meet_helper(t->make_ptr(), include_speculative);
return result->make_narrowoop();
}
if (isa_narrowklass() && t->isa_narrowklass()) {
const Type* result = make_ptr()->meet(t->make_ptr());
const Type* result = make_ptr()->meet_helper(t->make_ptr(), include_speculative);
return result->make_narrowklass();
}
const Type *mt = xmeet(t);
const Type *this_t = maybe_remove_speculative(include_speculative);
t = t->maybe_remove_speculative(include_speculative);
const Type *mt = this_t->xmeet(t);
if (isa_narrowoop() || t->isa_narrowoop()) return mt;
if (isa_narrowklass() || t->isa_narrowklass()) return mt;
#ifdef ASSERT
assert( mt == t->xmeet(this), "meet not commutative" );
assert(mt == t->xmeet(this_t), "meet not commutative");
const Type* dual_join = mt->_dual;
const Type *t2t = dual_join->xmeet(t->_dual);
const Type *t2this = dual_join->xmeet( _dual);
const Type *t2this = dual_join->xmeet(this_t->_dual);
// Interface meet Oop is Not Symmetric:
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
// Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != _dual) ) {
if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this_t->_dual) ) {
tty->print_cr("=== Meet Not Symmetric ===");
tty->print("t = "); t->dump(); tty->cr();
tty->print("this= "); dump(); tty->cr();
tty->print("mt=(t meet this)= "); mt->dump(); tty->cr();
tty->print("t = "); t->dump(); tty->cr();
tty->print("this= "); this_t->dump(); tty->cr();
tty->print("mt=(t meet this)= "); mt->dump(); tty->cr();
tty->print("t_dual= "); t->_dual->dump(); tty->cr();
tty->print("this_dual= "); _dual->dump(); tty->cr();
tty->print("mt_dual= "); mt->_dual->dump(); tty->cr();
tty->print("t_dual= "); t->_dual->dump(); tty->cr();
tty->print("this_dual= "); this_t->_dual->dump(); tty->cr();
tty->print("mt_dual= "); mt->_dual->dump(); tty->cr();
tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr();
tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr();
tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr();
tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr();
fatal("meet not symmetric" );
}
......@@ -754,8 +764,8 @@ const Type *Type::xmeet( const Type *t ) const {
}
//-----------------------------filter------------------------------------------
const Type *Type::filter( const Type *kills ) const {
const Type* ft = join(kills);
const Type *Type::filter_helper(const Type *kills, bool include_speculative) const {
const Type* ft = join_helper(kills, include_speculative);
if (ft->empty())
return Type::TOP; // Canonical empty value
return ft;
......@@ -1309,8 +1319,8 @@ const Type *TypeInt::narrow( const Type *old ) const {
}
//-----------------------------filter------------------------------------------
const Type *TypeInt::filter( const Type *kills ) const {
const TypeInt* ft = join(kills)->isa_int();
const Type *TypeInt::filter_helper(const Type *kills, bool include_speculative) const {
const TypeInt* ft = join_helper(kills, include_speculative)->isa_int();
if (ft == NULL || ft->empty())
return Type::TOP; // Canonical empty value
if (ft->_widen < this->_widen) {
......@@ -1570,8 +1580,8 @@ const Type *TypeLong::narrow( const Type *old ) const {
}
//-----------------------------filter------------------------------------------
const Type *TypeLong::filter( const Type *kills ) const {
const TypeLong* ft = join(kills)->isa_long();
const Type *TypeLong::filter_helper(const Type *kills, bool include_speculative) const {
const TypeLong* ft = join_helper(kills, include_speculative)->isa_long();
if (ft == NULL || ft->empty())
return Type::TOP; // Canonical empty value
if (ft->_widen < this->_widen) {
......@@ -1726,7 +1736,7 @@ const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig)
total_fields++;
field_array = fields(total_fields);
// Use get_const_type here because it respects UseUniqueSubclasses:
field_array[pos++] = get_const_type(recv)->join(TypePtr::NOTNULL);
field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL);
} else {
field_array = fields(total_fields);
}
......@@ -1916,7 +1926,7 @@ const Type *TypeAry::xmeet( const Type *t ) const {
case Array: { // Meeting 2 arrays?
const TypeAry *a = t->is_ary();
return TypeAry::make(_elem->meet(a->_elem),
return TypeAry::make(_elem->meet_speculative(a->_elem),
_size->xmeet(a->_size)->is_int(),
_stable & a->_stable);
}
......@@ -1949,6 +1959,13 @@ int TypeAry::hash(void) const {
return (intptr_t)_elem + (intptr_t)_size + (_stable ? 43 : 0);
}
/**
* Return same type without a speculative part in the element
*/
const Type* TypeAry::remove_speculative() const {
return make(_elem->remove_speculative(), _size, _stable);
}
//----------------------interface_vs_oop---------------------------------------
#ifdef ASSERT
bool TypeAry::interface_vs_oop(const Type *t) const {
......@@ -2560,14 +2577,14 @@ const Type *TypeOopPtr::xmeet(const Type *t) const {
return res;
}
if (res->isa_oopptr() != NULL) {
const TypeOopPtr* res_oopptr = res->is_oopptr();
if (res_oopptr->speculative() != NULL) {
// type->speculative() == NULL means that speculation is no better
// than type, i.e. type->speculative() == type. So there are 2
// ways to represent the fact that we have no useful speculative
// data and we should use a single one to be able to test for
// equality between types. Check whether type->speculative() ==
// type and set speculative to NULL if it is the case.
const TypeOopPtr* res_oopptr = res->is_oopptr();
if (res_oopptr->remove_speculative() == res_oopptr->speculative()) {
return res_oopptr->remove_speculative();
}
......@@ -2633,7 +2650,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
case OopPtr: { // Meeting to other OopPtrs
const TypeOopPtr *tp = t->is_oopptr();
int instance_id = meet_instance_id(tp->instance_id());
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative);
}
......@@ -2787,9 +2804,9 @@ intptr_t TypeOopPtr::get_con() const {
//-----------------------------filter------------------------------------------
// Do not allow interface-vs.-noninterface joins to collapse to top.
const Type *TypeOopPtr::filter(const Type *kills) const {
const Type *TypeOopPtr::filter_helper(const Type *kills, bool include_speculative) const {
const Type* ft = join(kills);
const Type* ft = join_helper(kills, include_speculative);
const TypeInstPtr* ftip = ft->isa_instptr();
const TypeInstPtr* ktip = kills->isa_instptr();
......@@ -2901,7 +2918,10 @@ const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const {
/**
* Return same type without a speculative part
*/
const TypeOopPtr* TypeOopPtr::remove_speculative() const {
const Type* TypeOopPtr::remove_speculative() const {
if (_speculative == NULL) {
return this;
}
return make(_ptr, _offset, _instance_id, NULL);
}
......@@ -2927,7 +2947,7 @@ int TypeOopPtr::dual_instance_id( ) const {
*
* @param other type to meet with
*/
const TypeOopPtr* TypeOopPtr::meet_speculative(const TypeOopPtr* other) const {
const TypeOopPtr* TypeOopPtr::xmeet_speculative(const TypeOopPtr* other) const {
bool this_has_spec = (_speculative != NULL);
bool other_has_spec = (other->speculative() != NULL);
......@@ -2952,7 +2972,7 @@ const TypeOopPtr* TypeOopPtr::meet_speculative(const TypeOopPtr* other) const {
other_spec = other;
}
return this_spec->meet(other_spec)->is_oopptr();
return this_spec->meet_speculative(other_spec)->is_oopptr();
}
/**
......@@ -3111,7 +3131,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const {
int off = meet_offset(tinst->offset());
PTR ptr = meet_ptr(tinst->ptr());
int instance_id = meet_instance_id(tinst->instance_id());
const TypeOopPtr* speculative = meet_speculative(tinst);
const TypeOopPtr* speculative = xmeet_speculative(tinst);
const TypeInstPtr *loaded = is_loaded() ? this : tinst;
const TypeInstPtr *unloaded = is_loaded() ? tinst : this;
......@@ -3188,7 +3208,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
int instance_id = meet_instance_id(tp->instance_id());
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
switch (ptr) {
case TopPTR:
case AnyNull: // Fall 'down' to dual of object klass
......@@ -3238,14 +3258,14 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
case TopPTR:
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
return make(ptr, klass(), klass_is_exact(),
(ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative);
}
case NotNull:
case BotPTR: {
int instance_id = meet_instance_id(tp->instance_id());
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
return TypeOopPtr::make(ptr, offset, instance_id, speculative);
}
default: typerr(t);
......@@ -3297,7 +3317,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
int off = meet_offset( tinst->offset() );
PTR ptr = meet_ptr( tinst->ptr() );
int instance_id = meet_instance_id(tinst->instance_id());
const TypeOopPtr* speculative = meet_speculative(tinst);
const TypeOopPtr* speculative = xmeet_speculative(tinst);
// Check for easy case; klasses are equal (and perhaps not loaded!)
// If we have constants, then we created oops so classes are loaded
......@@ -3546,7 +3566,10 @@ const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id, add_offset_speculative(offset));
}
const TypeOopPtr *TypeInstPtr::remove_speculative() const {
const Type *TypeInstPtr::remove_speculative() const {
if (_speculative == NULL) {
return this;
}
return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL);
}
......@@ -3748,14 +3771,14 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
case TopPTR:
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
return make(ptr, (ptr == Constant ? const_oop() : NULL),
_ary, _klass, _klass_is_exact, offset, instance_id, speculative);
}
case BotPTR:
case NotNull: {
int instance_id = meet_instance_id(tp->instance_id());
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
return TypeOopPtr::make(ptr, offset, instance_id, speculative);
}
default: ShouldNotReachHere();
......@@ -3793,10 +3816,10 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
case AryPtr: { // Meeting 2 references?
const TypeAryPtr *tap = t->is_aryptr();
int off = meet_offset(tap->offset());
const TypeAry *tary = _ary->meet(tap->_ary)->is_ary();
const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary();
PTR ptr = meet_ptr(tap->ptr());
int instance_id = meet_instance_id(tap->instance_id());
const TypeOopPtr* speculative = meet_speculative(tap);
const TypeOopPtr* speculative = xmeet_speculative(tap);
ciKlass* lazy_klass = NULL;
if (tary->_elem->isa_int()) {
// Integral array element types have irrelevant lattice relations.
......@@ -3876,7 +3899,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
int instance_id = meet_instance_id(tp->instance_id());
const TypeOopPtr* speculative = meet_speculative(tp);
const TypeOopPtr* speculative = xmeet_speculative(tp);
switch (ptr) {
case TopPTR:
case AnyNull: // Fall 'down' to dual of object klass
......@@ -3990,8 +4013,8 @@ const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const {
return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset));
}
const TypeOopPtr *TypeAryPtr::remove_speculative() const {
return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, _offset, _instance_id, NULL);
const Type *TypeAryPtr::remove_speculative() const {
return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL);
}
//=============================================================================
......@@ -4031,9 +4054,9 @@ const Type *TypeNarrowPtr::xdual() const { // Compute dual right now.
}
const Type *TypeNarrowPtr::filter( const Type *kills ) const {
const Type *TypeNarrowPtr::filter_helper(const Type *kills, bool include_speculative) const {
if (isa_same_narrowptr(kills)) {
const Type* ft =_ptrtype->filter(is_same_narrowptr(kills)->_ptrtype);
const Type* ft =_ptrtype->filter_helper(is_same_narrowptr(kills)->_ptrtype, include_speculative);
if (ft->empty())
return Type::TOP; // Canonical empty value
if (ft->isa_ptr()) {
......@@ -4041,7 +4064,7 @@ const Type *TypeNarrowPtr::filter( const Type *kills ) const {
}
return ft;
} else if (kills->isa_ptr()) {
const Type* ft = _ptrtype->join(kills);
const Type* ft = _ptrtype->join_helper(kills, include_speculative);
if (ft->empty())
return Type::TOP; // Canonical empty value
return ft;
......@@ -4171,8 +4194,8 @@ const TypePtr *TypeMetadataPtr::add_offset( intptr_t offset ) const {
//-----------------------------filter------------------------------------------
// Do not allow interface-vs.-noninterface joins to collapse to top.
const Type *TypeMetadataPtr::filter( const Type *kills ) const {
const TypeMetadataPtr* ft = join(kills)->isa_metadataptr();
const Type *TypeMetadataPtr::filter_helper(const Type *kills, bool include_speculative) const {
const TypeMetadataPtr* ft = join_helper(kills, include_speculative)->isa_metadataptr();
if (ft == NULL || ft->empty())
return Type::TOP; // Canonical empty value
return ft;
......@@ -4374,10 +4397,10 @@ bool TypeKlassPtr::singleton(void) const {
}
// Do not allow interface-vs.-noninterface joins to collapse to top.
const Type *TypeKlassPtr::filter(const Type *kills) const {
const Type *TypeKlassPtr::filter_helper(const Type *kills, bool include_speculative) const {
// logic here mirrors the one from TypeOopPtr::filter. See comments
// there.
const Type* ft = join(kills);
const Type* ft = join_helper(kills, include_speculative);
const TypeKlassPtr* ftkp = ft->isa_klassptr();
const TypeKlassPtr* ktkp = kills->isa_klassptr();
......
......@@ -164,6 +164,8 @@ private:
virtual bool interface_vs_oop_helper(const Type *t) const;
#endif
const Type *meet_helper(const Type *t, bool include_speculative) const;
protected:
// Each class of type is also identified by its base.
const TYPES _base; // Enum of Types type
......@@ -171,6 +173,10 @@ protected:
Type( TYPES t ) : _dual(NULL), _base(t) {} // Simple types
// ~Type(); // Use fast deallocation
const Type *hashcons(); // Hash-cons the type
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
const Type *join_helper(const Type *t, bool include_speculative) const {
return dual()->meet_helper(t->dual(), include_speculative)->dual();
}
public:
......@@ -202,10 +208,24 @@ public:
// Test for equivalence of types
static int cmp( const Type *const t1, const Type *const t2 );
// Test for higher or equal in lattice
int higher_equal( const Type *t ) const { return !cmp(meet(t),t); }
// Variant that drops the speculative part of the types
int higher_equal(const Type *t) const {
return !cmp(meet(t),t->remove_speculative());
}
// Variant that keeps the speculative part of the types
int higher_equal_speculative(const Type *t) const {
return !cmp(meet_speculative(t),t);
}
// MEET operation; lower in lattice.
const Type *meet( const Type *t ) const;
// Variant that drops the speculative part of the types
const Type *meet(const Type *t) const {
return meet_helper(t, false);
}
// Variant that keeps the speculative part of the types
const Type *meet_speculative(const Type *t) const {
return meet_helper(t, true);
}
// WIDEN: 'widens' for Ints and other range types
virtual const Type *widen( const Type *old, const Type* limit ) const { return this; }
// NARROW: complement for widen, used by pessimistic phases
......@@ -221,13 +241,26 @@ public:
// JOIN operation; higher in lattice. Done by finding the dual of the
// meet of the dual of the 2 inputs.
const Type *join( const Type *t ) const {
return dual()->meet(t->dual())->dual(); }
// Variant that drops the speculative part of the types
const Type *join(const Type *t) const {
return join_helper(t, false);
}
// Variant that keeps the speculative part of the types
const Type *join_speculative(const Type *t) const {
return join_helper(t, true);
}
// Modified version of JOIN adapted to the needs Node::Value.
// Normalizes all empty values to TOP. Does not kill _widen bits.
// Currently, it also works around limitations involving interface types.
virtual const Type *filter( const Type *kills ) const;
// Variant that drops the speculative part of the types
const Type *filter(const Type *kills) const {
return filter_helper(kills, false);
}
// Variant that keeps the speculative part of the types
const Type *filter_speculative(const Type *kills) const {
return filter_helper(kills, true);
}
#ifdef ASSERT
// One type is interface, the other is oop
......@@ -383,6 +416,8 @@ public:
// Speculative type. See TypeInstPtr
virtual ciKlass* speculative_type() const { return NULL; }
const Type* maybe_remove_speculative(bool include_speculative) const;
virtual const Type* remove_speculative() const { return this; }
private:
// support arrays
......@@ -450,12 +485,14 @@ public:
// upper bound, inclusive.
class TypeInt : public Type {
TypeInt( jint lo, jint hi, int w );
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
virtual bool empty(void) const; // TRUE if type is vacuous
public:
const jint _lo, _hi; // Lower bound, upper bound
const short _widen; // Limit on times we widen this sucker
......@@ -475,7 +512,6 @@ public:
virtual const Type *widen( const Type *t, const Type* limit_type ) const;
virtual const Type *narrow( const Type *t ) const;
// Do not kill _widen bits.
virtual const Type *filter( const Type *kills ) const;
// Convenience common pre-built types.
static const TypeInt *MINUS_1;
static const TypeInt *ZERO;
......@@ -506,6 +542,9 @@ public:
// an upper bound, inclusive.
class TypeLong : public Type {
TypeLong( jlong lo, jlong hi, int w );
protected:
// Do not kill _widen bits.
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
......@@ -530,8 +569,6 @@ public:
virtual const Type *xdual() const; // Compute dual right now.
virtual const Type *widen( const Type *t, const Type* limit_type ) const;
virtual const Type *narrow( const Type *t ) const;
// Do not kill _widen bits.
virtual const Type *filter( const Type *kills ) const;
// Convenience common pre-built types.
static const TypeLong *MINUS_1;
static const TypeLong *ZERO;
......@@ -622,6 +659,7 @@ public:
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const; // Compute dual right now.
bool ary_must_be_exact() const; // true if arrays of such are never generic
virtual const Type* remove_speculative() const;
#ifdef ASSERT
// One type is interface, the other is oop
virtual bool interface_vs_oop(const Type *t) const;
......@@ -832,7 +870,7 @@ protected:
// utility methods to work on the speculative part of the type
const TypeOopPtr* dual_speculative() const;
const TypeOopPtr* meet_speculative(const TypeOopPtr* other) const;
const TypeOopPtr* xmeet_speculative(const TypeOopPtr* other) const;
bool eq_speculative(const TypeOopPtr* other) const;
int hash_speculative() const;
const TypeOopPtr* add_offset_speculative(intptr_t offset) const;
......@@ -840,6 +878,9 @@ protected:
void dump_speculative(outputStream *st) const;
#endif
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
public:
// Creates a type given a klass. Correctly handles multi-dimensional arrays
// Respects UseUniqueSubclasses.
......@@ -895,16 +936,13 @@ public:
virtual const TypePtr *add_offset( intptr_t offset ) const;
// Return same type without a speculative part
virtual const TypeOopPtr* remove_speculative() const;
virtual const Type* remove_speculative() const;
virtual const Type *xmeet(const Type *t) const;
virtual const Type *xdual() const; // Compute dual right now.
// the core of the computation of the meet for TypeOopPtr and for its subclasses
virtual const Type *xmeet_helper(const Type *t) const;
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter( const Type *kills ) const;
// Convenience common pre-built type.
static const TypeOopPtr *BOTTOM;
#ifndef PRODUCT
......@@ -981,7 +1019,7 @@ class TypeInstPtr : public TypeOopPtr {
virtual const TypePtr *add_offset( intptr_t offset ) const;
// Return same type without a speculative part
virtual const TypeOopPtr* remove_speculative() const;
virtual const Type* remove_speculative() const;
// the core of the computation of the meet of 2 types
virtual const Type *xmeet_helper(const Type *t) const;
......@@ -1059,7 +1097,7 @@ public:
virtual bool empty(void) const; // TRUE if type is vacuous
virtual const TypePtr *add_offset( intptr_t offset ) const;
// Return same type without a speculative part
virtual const TypeOopPtr* remove_speculative() const;
virtual const Type* remove_speculative() const;
// the core of the computation of the meet of 2 types
virtual const Type *xmeet_helper(const Type *t) const;
......@@ -1100,6 +1138,8 @@ public:
class TypeMetadataPtr : public TypePtr {
protected:
TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset);
// Do not allow interface-vs.-noninterface joins to collapse to top.
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
......@@ -1125,9 +1165,6 @@ public:
virtual intptr_t get_con() const;
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter( const Type *kills ) const;
// Convenience common pre-built types.
static const TypeMetadataPtr *BOTTOM;
......@@ -1141,6 +1178,8 @@ public:
class TypeKlassPtr : public TypePtr {
TypeKlassPtr( PTR ptr, ciKlass* klass, int offset );
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
......@@ -1202,9 +1241,6 @@ public:
virtual intptr_t get_con() const;
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter( const Type *kills ) const;
// 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
......@@ -1228,6 +1264,8 @@ protected:
virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const = 0;
virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const = 0;
virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const = 0;
// Do not allow interface-vs.-noninterface joins to collapse to top.
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
......@@ -1238,9 +1276,6 @@ public:
virtual intptr_t get_con() const;
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter( const Type *kills ) const;
virtual bool empty(void) const; // TRUE if type is vacuous
// returns the equivalent ptr type for this compressed pointer
......@@ -1291,6 +1326,10 @@ public:
static const TypeNarrowOop *BOTTOM;
static const TypeNarrowOop *NULL_PTR;
virtual const Type* remove_speculative() const {
return make(_ptrtype->remove_speculative()->is_ptr());
}
#ifndef PRODUCT
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
#endif
......
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8027422
* @summary type methods shouldn't always operate on speculative part
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:TypeProfileLevel=222 -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:-BackgroundCompilation TestSpeculationFailedHigherEqual
*
*/
public class TestSpeculationFailedHigherEqual {
static class A {
void m() {}
int i;
}
static class C extends A {
}
static C c;
static A m1(A a, boolean cond) {
// speculative type for a is C not null
if (cond ) {
a = c;
}
// speculative type for a is C (may be null)
int i = a.i;
return a;
}
static public void main(String[] args) {
C c = new C();
TestSpeculationFailedHigherEqual.c = c;
for (int i = 0; i < 20000; i++) {
m1(c, i%2 == 0);
}
System.out.println("TEST PASSED");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册