8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
authorroland
Fri, 24 Jan 2014 09:31:53 +0100
changeset 22799 83e58bac7980
parent 22514 7f26d1aea7a4
child 22800 fbb2ab3f06ec
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
hotspot/src/share/vm/opto/callGenerator.cpp
hotspot/src/share/vm/opto/cfgnode.cpp
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/connode.cpp
hotspot/src/share/vm/opto/connode.hpp
hotspot/src/share/vm/opto/graphKit.cpp
hotspot/src/share/vm/opto/loopopts.cpp
hotspot/src/share/vm/opto/memnode.cpp
hotspot/src/share/vm/opto/multnode.cpp
hotspot/src/share/vm/opto/node.cpp
hotspot/src/share/vm/opto/parse1.cpp
hotspot/src/share/vm/opto/parse2.cpp
hotspot/src/share/vm/opto/parse3.cpp
hotspot/src/share/vm/opto/phaseX.cpp
hotspot/src/share/vm/opto/phaseX.hpp
hotspot/src/share/vm/opto/type.cpp
hotspot/src/share/vm/opto/type.hpp
hotspot/test/compiler/types/TestSpeculationFailedHigherEqual.java
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -722,7 +722,7 @@
     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 @@
     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));
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -951,7 +951,7 @@
         if (is_intf != ti_is_intf)
           { t = _type; break; }
       }
-      t = t->meet(ti);
+      t = t->meet_speculative(ti);
     }
   }
 
@@ -968,11 +968,11 @@
   //
   // 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 @@
           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) {
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/compile.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -3919,16 +3919,18 @@
     // 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 @@
     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
   }
 }
 
--- a/hotspot/src/share/vm/opto/connode.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/connode.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -188,7 +188,7 @@
 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 @@
 //=============================================================================
 // 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* 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;
     }
--- a/hotspot/src/share/vm/opto/connode.hpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/connode.hpp	Fri Jan 24 09:31:53 2014 +0100
@@ -36,7 +36,7 @@
 // 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);
   }
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -420,7 +420,7 @@
       }
       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 @@
         // 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 @@
 // 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 @@
       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));
     }
   }
 
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -1115,8 +1115,8 @@
     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 @@
     }
     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.
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -657,7 +657,7 @@
       // 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 @@
       // 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.
--- a/hotspot/src/share/vm/opto/multnode.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/multnode.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -94,7 +94,7 @@
   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;
 }
--- a/hotspot/src/share/vm/opto/node.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/node.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -995,13 +995,13 @@
   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);
   }
--- a/hotspot/src/share/vm/opto/parse1.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -1649,7 +1649,7 @@
           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 @@
           !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));
       }
     }
--- a/hotspot/src/share/vm/opto/parse2.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -88,7 +88,7 @@
       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 @@
        //   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 @@
               (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 @@
   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 @@
 
   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());
--- a/hotspot/src/share/vm/opto/parse3.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -337,7 +337,7 @@
     //   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:
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -323,6 +323,23 @@
   }
 }
 
+
+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 @@
   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();
 }
 
 //=============================================================================
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Fri Jan 24 09:31:53 2014 +0100
@@ -92,7 +92,8 @@
   }
 
   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 @@
                                         Deoptimization::DeoptReason reason);
 
   void remove_speculative_types();
+  void check_no_speculative_types() {
+    _table.check_no_speculative_types();
+  }
 
 #ifndef PRODUCT
 protected:
--- a/hotspot/src/share/vm/opto/type.cpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/type.cpp	Fri Jan 24 09:31:53 2014 +0100
@@ -236,6 +236,13 @@
   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 @@
 //------------------------------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_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("mt_dual meet t_dual=    "); t2t      ->dump(); tty->cr();
-    tty->print("mt_dual meet this_dual= "); t2this   ->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=              ");  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();
 
     fatal("meet not symmetric" );
   }
@@ -754,8 +764,8 @@
 }
 
 //-----------------------------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 @@
 }
 
 //-----------------------------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 @@
 }
 
 //-----------------------------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 @@
     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 @@
 
   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 @@
   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 @@
     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 @@
   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 @@
 
 //-----------------------------filter------------------------------------------
 // Do not allow interface-vs.-noninterface joins to collapse to top.
-const Type *TypeOopPtr::filter(const Type *kills) const {
-
-  const Type* ft = join(kills);
+const Type *TypeOopPtr::filter_helper(const Type *kills, bool include_speculative) const {
+
+  const Type* ft = join_helper(kills, include_speculative);
   const TypeInstPtr* ftip = ft->isa_instptr();
   const TypeInstPtr* ktip = kills->isa_instptr();
 
@@ -2901,7 +2918,10 @@
 /**
  * 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 @@
  *
  * @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 @@
     other_spec = other;
   }
 
-  return this_spec->meet(other_spec)->is_oopptr();
+  return this_spec->meet_speculative(other_spec)->is_oopptr();
 }
 
 /**
@@ -3111,7 +3131,7 @@
     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 @@
     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 @@
     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 @@
     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 @@
   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 @@
     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 @@
   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 @@
     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 @@
   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::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 @@
     }
     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 @@
 
 //-----------------------------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 @@
 }
 
 // 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();
 
--- a/hotspot/src/share/vm/opto/type.hpp	Thu Jan 23 01:23:23 2014 +0400
+++ b/hotspot/src/share/vm/opto/type.hpp	Fri Jan 24 09:31:53 2014 +0100
@@ -164,6 +164,8 @@
   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 @@
   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 @@
   // 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 @@
 
   // 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 @@
 
   // 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 @@
 // 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 @@
   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 @@
 // 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 @@
   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 @@
   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 @@
 
   // 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 @@
   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 @@
 
   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 @@
 
   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 @@
   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 @@
 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 @@
 
   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 @@
 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 @@
 
   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 @@
   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 @@
 
   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 @@
   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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/TestSpeculationFailedHigherEqual.java	Fri Jan 24 09:31:53 2014 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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");
+    }
+}