8024070: C2 needs some form of type speculation
authorroland
Wed, 23 Oct 2013 12:40:23 +0200
changeset 21099 46e6bbecd9e5
parent 21098 1820670a3362
child 21101 02624d68a712
child 21102 1dd11ccfe9da
8024070: C2 needs some form of type speculation Summary: record unused type profile information with type system, propagate and use it. Reviewed-by: kvn, twisti
hotspot/src/share/vm/ci/ciMethod.cpp
hotspot/src/share/vm/ci/ciMethod.hpp
hotspot/src/share/vm/ci/ciMethodData.hpp
hotspot/src/share/vm/opto/c2_globals.hpp
hotspot/src/share/vm/opto/callGenerator.cpp
hotspot/src/share/vm/opto/callGenerator.hpp
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/compile.hpp
hotspot/src/share/vm/opto/doCall.cpp
hotspot/src/share/vm/opto/graphKit.cpp
hotspot/src/share/vm/opto/graphKit.hpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/parse.hpp
hotspot/src/share/vm/opto/parse1.cpp
hotspot/src/share/vm/opto/parse2.cpp
hotspot/src/share/vm/opto/parseHelper.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/src/share/vm/runtime/arguments.cpp
hotspot/test/compiler/types/TypeSpeculation.java
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -565,6 +565,116 @@
   if (_limit < MorphismLimit) _limit++;
 }
 
+
+void ciMethod::assert_virtual_call_type_ok(int bci) {
+  assert(java_code_at_bci(bci) == Bytecodes::_invokevirtual ||
+         java_code_at_bci(bci) == Bytecodes::_invokeinterface, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
+}
+
+void ciMethod::assert_call_type_ok(int bci) {
+  assert(java_code_at_bci(bci) == Bytecodes::_invokestatic ||
+         java_code_at_bci(bci) == Bytecodes::_invokespecial ||
+         java_code_at_bci(bci) == Bytecodes::_invokedynamic, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
+}
+
+/**
+ * Check whether profiling provides a type for the argument i to the
+ * call at bci bci
+ *
+ * @param bci  bci of the call
+ * @param i    argument number
+ * @return     profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::argument_profiled_type(int bci, int i) {
+  if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
+    ciProfileData* data = method_data()->bci_to_data(bci);
+    if (data != NULL) {
+      if (data->is_VirtualCallTypeData()) {
+        assert_virtual_call_type_ok(bci);
+        ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
+        if (i >= call->number_of_arguments()) {
+          return NULL;
+        }
+        ciKlass* type = call->valid_argument_type(i);
+        if (type != NULL && !call->argument_maybe_null(i)) {
+          return type;
+        }
+      } else if (data->is_CallTypeData()) {
+        assert_call_type_ok(bci);
+        ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
+        if (i >= call->number_of_arguments()) {
+          return NULL;
+        }
+        ciKlass* type = call->valid_argument_type(i);
+        if (type != NULL && !call->argument_maybe_null(i)) {
+          return type;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Check whether profiling provides a type for the return value from
+ * the call at bci bci
+ *
+ * @param bci  bci of the call
+ * @return     profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::return_profiled_type(int bci) {
+  if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) {
+    ciProfileData* data = method_data()->bci_to_data(bci);
+    if (data != NULL) {
+      if (data->is_VirtualCallTypeData()) {
+        assert_virtual_call_type_ok(bci);
+        ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
+        ciKlass* type = call->valid_return_type();
+        if (type != NULL && !call->return_maybe_null()) {
+          return type;
+        }
+      } else if (data->is_CallTypeData()) {
+        assert_call_type_ok(bci);
+        ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
+        ciKlass* type = call->valid_return_type();
+        if (type != NULL && !call->return_maybe_null()) {
+          return type;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Check whether profiling provides a type for the parameter i
+ *
+ * @param i    parameter number
+ * @return     profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::parameter_profiled_type(int i) {
+  if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
+    ciParametersTypeData* parameters = method_data()->parameters_type_data();
+    if (parameters != NULL && i < parameters->number_of_parameters()) {
+      ciKlass* type = parameters->valid_parameter_type(i);
+      if (type != NULL && !parameters->parameter_maybe_null(i)) {
+        return type;
+      }
+    }
+  }
+  return NULL;
+}
+
+
 // ------------------------------------------------------------------
 // ciMethod::find_monomorphic_target
 //
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -117,6 +117,10 @@
     *bcp = code;
   }
 
+  // Check bytecode and profile data collected are compatible
+  void assert_virtual_call_type_ok(int bci);
+  void assert_call_type_ok(int bci);
+
  public:
   // Basic method information.
   ciFlags flags() const                          { check_is_loaded(); return _flags; }
@@ -230,6 +234,11 @@
   ciCallProfile call_profile_at_bci(int bci);
   int           interpreter_call_site_count(int bci);
 
+  // Does type profiling provide a useful type at this point?
+  ciKlass*      argument_profiled_type(int bci, int i);
+  ciKlass*      parameter_profiled_type(int i);
+  ciKlass*      return_profiled_type(int bci);
+
   ciField*      get_field_at_bci( int bci, bool &will_link);
   ciMethod*     get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature);
 
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -100,6 +100,10 @@
     return valid_ciklass(type(i));
   }
 
+  bool maybe_null(int i) const {
+    return was_null_seen(type(i));
+  }
+
 #ifndef PRODUCT
   void print_data_on(outputStream* st) const;
 #endif
@@ -113,6 +117,10 @@
     return valid_ciklass(type());
   }
 
+  bool maybe_null() const {
+    return was_null_seen(type());
+  }
+
 #ifndef PRODUCT
   void print_data_on(outputStream* st) const;
 #endif
@@ -154,6 +162,14 @@
     return ret()->valid_type();
   }
 
+  bool argument_maybe_null(int i) const {
+    return args()->maybe_null(i);
+  }
+
+  bool return_maybe_null() const {
+    return ret()->maybe_null();
+  }
+
 #ifndef PRODUCT
   void print_data_on(outputStream* st) const;
 #endif
@@ -260,6 +276,14 @@
     return ret()->valid_type();
   }
 
+  bool argument_maybe_null(int i) const {
+    return args()->maybe_null(i);
+  }
+
+  bool return_maybe_null() const {
+    return ret()->maybe_null();
+  }
+
 #ifndef PRODUCT
   void print_data_on(outputStream* st) const;
 #endif
@@ -305,6 +329,10 @@
     return parameters()->valid_type(i);
   }
 
+  bool parameter_maybe_null(int i) const {
+    return parameters()->maybe_null(i);
+  }
+
 #ifndef PRODUCT
   void print_data_on(outputStream* st) const;
 #endif
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -641,7 +641,10 @@
           "Enables intrinsification of various java.lang.Math functions")   \
                                                                             \
   experimental(bool, ReplaceInParentMaps, false,                            \
-          "Propagate type improvements in callers of inlinee if possible")
+          "Propagate type improvements in callers of inlinee if possible")  \
+                                                                            \
+  experimental(bool, UseTypeSpeculation, false,                             \
+          "Speculatively propagate types from profiles")
 
 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
 
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -486,6 +486,8 @@
     JVMState* new_jvms =  DirectCallGenerator::generate(jvms, parent_parser);
     return new_jvms;
   }
+
+  virtual bool is_string_late_inline() const { return true; }
 };
 
 CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGenerator* inline_cg) {
@@ -773,7 +775,7 @@
         ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
         guarantee(!target->is_method_handle_intrinsic(), "should not happen");  // XXX remove
         const int vtable_index = Method::invalid_vtable_index;
-        CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, true, true);
+        CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true);
         assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
         if (cg != NULL && cg->is_inline())
           return cg;
@@ -829,6 +831,7 @@
         int  vtable_index       = Method::invalid_vtable_index;
         bool call_does_dispatch = false;
 
+        ciKlass* speculative_receiver_type = NULL;
         if (is_virtual_or_interface) {
           ciInstanceKlass* klass = target->holder();
           Node*             receiver_node = kit.argument(0);
@@ -837,9 +840,12 @@
           target = C->optimize_virtual_call(caller, jvms->bci(), klass, target, receiver_type,
                                             is_virtual,
                                             call_does_dispatch, vtable_index);  // out-parameters
+          // We lack profiling at this call but type speculation may
+          // provide us with a type
+          speculative_receiver_type = receiver_type->speculative_type();
         }
 
-        CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, true, true);
+        CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true);
         assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
         if (cg != NULL && cg->is_inline())
           return cg;
--- a/hotspot/src/share/vm/opto/callGenerator.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -74,6 +74,7 @@
   virtual bool      is_late_inline() const      { return false; }
   // same but for method handle calls
   virtual bool      is_mh_late_inline() const   { return false; }
+  virtual bool      is_string_late_inline() const{ return false; }
 
   // for method handle calls: have we tried inlinining the call already?
   virtual bool      already_attempted() const   { ShouldNotReachHere(); return false; }
--- a/hotspot/src/share/vm/opto/compile.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -1360,7 +1360,7 @@
     // During the 2nd round of IterGVN, NotNull castings are removed.
     // Make sure the Bottom and NotNull variants alias the same.
     // Also, make sure exact and non-exact variants alias the same.
-    if( ptr == TypePtr::NotNull || ta->klass_is_exact() ) {
+    if (ptr == TypePtr::NotNull || ta->klass_is_exact() || ta->speculative() != NULL) {
       tj = ta = TypeAryPtr::make(TypePtr::BotPTR,ta->ary(),ta->klass(),false,offset);
     }
   }
@@ -1385,6 +1385,9 @@
       // Also, make sure exact and non-exact variants alias the same.
       tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
     }
+    if (to->speculative() != NULL) {
+      tj = to = TypeInstPtr::make(to->ptr(),to->klass(),to->klass_is_exact(),to->const_oop(),to->offset(), to->instance_id());
+    }
     // Canonicalize the holder of this field
     if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) {
       // First handle header references such as a LoadKlassNode, even if the
@@ -2013,6 +2016,12 @@
     if (failing())  return;
   }
 
+  // Remove the speculative part of types and clean up the graph from
+  // the extra CastPP nodes whose only purpose is to carry them. Do
+  // that early so that optimizations are not disrupted by the extra
+  // CastPP nodes.
+  remove_speculative_types(igvn);
+
   // No more new expensive nodes will be added to the list from here
   // so keep only the actual candidates for optimizations.
   cleanup_expensive_nodes(igvn);
@@ -3799,6 +3808,45 @@
   }
 }
 
+/**
+ * Remove the speculative part of types and clean up the graph
+ */
+void Compile::remove_speculative_types(PhaseIterGVN &igvn) {
+  if (UseTypeSpeculation) {
+    Unique_Node_List worklist;
+    worklist.push(root());
+    int modified = 0;
+    // Go over all type nodes that carry a speculative type, drop the
+    // speculative part of the type and enqueue the node for an 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) {
+        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++;
+      }
+      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);
+      }
+    }
+    // Drop the speculative part of all types in the igvn's type table
+    igvn.remove_speculative_types();
+    if (modified > 0) {
+      igvn.optimize();
+    }
+  }
+}
+
 // Auxiliary method to support randomized stressing/fuzzing.
 //
 // This method can be called the arbitrary number of times, with current count
--- a/hotspot/src/share/vm/opto/compile.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -424,6 +424,8 @@
   static int cmp_expensive_nodes(Node** n1, Node** n2);
   // Expensive nodes list already sorted?
   bool expensive_nodes_sorted() const;
+  // Remove the speculative part of types and clean up the graph
+  void remove_speculative_types(PhaseIterGVN &igvn);
 
   // Are we within a PreserveJVMState block?
   int _preserve_jvm_state;
@@ -824,8 +826,8 @@
   // Decide how to build a call.
   // The profile factor is a discount to apply to this site's interp. profile.
   CallGenerator*    call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch,
-                                   JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true,
-                                   bool delayed_forbidden = false);
+                                   JVMState* jvms, bool allow_inline, float profile_factor, ciKlass* speculative_receiver_type = NULL,
+                                   bool allow_intrinsics = true, bool delayed_forbidden = false);
   bool should_delay_inlining(ciMethod* call_method, JVMState* jvms) {
     return should_delay_string_inlining(call_method, jvms) ||
            should_delay_boxing_inlining(call_method, jvms);
--- a/hotspot/src/share/vm/opto/doCall.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -63,7 +63,8 @@
 
 CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch,
                                        JVMState* jvms, bool allow_inline,
-                                       float prof_factor, bool allow_intrinsics, bool delayed_forbidden) {
+                                       float prof_factor, ciKlass* speculative_receiver_type,
+                                       bool allow_intrinsics, bool delayed_forbidden) {
   ciMethod*       caller   = jvms->method();
   int             bci      = jvms->bci();
   Bytecodes::Code bytecode = caller->java_code_at_bci(bci);
@@ -117,7 +118,7 @@
       if (cg->is_predicted()) {
         // Code without intrinsic but, hopefully, inlined.
         CallGenerator* inline_cg = this->call_generator(callee,
-              vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, false);
+              vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, speculative_receiver_type, false);
         if (inline_cg != NULL) {
           cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg);
         }
@@ -212,8 +213,24 @@
       // The major receiver's count >= TypeProfileMajorReceiverPercent of site_count.
       bool have_major_receiver = (100.*profile.receiver_prob(0) >= (float)TypeProfileMajorReceiverPercent);
       ciMethod* receiver_method = NULL;
-      if (have_major_receiver || profile.morphism() == 1 ||
-          (profile.morphism() == 2 && UseBimorphicInlining)) {
+
+      int morphism = profile.morphism();
+      if (speculative_receiver_type != NULL) {
+        // We have a speculative type, we should be able to resolve
+        // the call. We do that before looking at the profiling at
+        // this invoke because it may lead to bimorphic inlining which
+        // a speculative type should help us avoid.
+        receiver_method = callee->resolve_invoke(jvms->method()->holder(),
+                                                 speculative_receiver_type);
+        if (receiver_method == NULL) {
+          speculative_receiver_type = NULL;
+        } else {
+          morphism = 1;
+        }
+      }
+      if (receiver_method == NULL &&
+          (have_major_receiver || morphism == 1 ||
+           (morphism == 2 && UseBimorphicInlining))) {
         // receiver_method = profile.method();
         // Profiles do not suggest methods now.  Look it up in the major receiver.
         receiver_method = callee->resolve_invoke(jvms->method()->holder(),
@@ -227,7 +244,7 @@
           // Look up second receiver.
           CallGenerator* next_hit_cg = NULL;
           ciMethod* next_receiver_method = NULL;
-          if (profile.morphism() == 2 && UseBimorphicInlining) {
+          if (morphism == 2 && UseBimorphicInlining) {
             next_receiver_method = callee->resolve_invoke(jvms->method()->holder(),
                                                                profile.receiver(1));
             if (next_receiver_method != NULL) {
@@ -242,11 +259,10 @@
             }
           }
           CallGenerator* miss_cg;
-          Deoptimization::DeoptReason reason = (profile.morphism() == 2) ?
+          Deoptimization::DeoptReason reason = morphism == 2 ?
                                     Deoptimization::Reason_bimorphic :
                                     Deoptimization::Reason_class_check;
-          if (( profile.morphism() == 1 ||
-               (profile.morphism() == 2 && next_hit_cg != NULL) ) &&
+          if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
               !too_many_traps(jvms->method(), jvms->bci(), reason)
              ) {
             // Generate uncommon trap for class check failure path
@@ -260,6 +276,7 @@
           }
           if (miss_cg != NULL) {
             if (next_hit_cg != NULL) {
+              assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation");
               trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1));
               // We don't need to record dependency on a receiver here and below.
               // Whenever we inline, the dependency is added by Parse::Parse().
@@ -267,7 +284,9 @@
             }
             if (miss_cg != NULL) {
               trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count);
-              CallGenerator* cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0));
+              ciKlass* k = speculative_receiver_type != NULL ? speculative_receiver_type : profile.receiver(0);
+              float hit_prob = speculative_receiver_type != NULL ? 1.0 : profile.receiver_prob(0);
+              CallGenerator* cg = CallGenerator::for_predicted_call(k, miss_cg, hit_cg, hit_prob);
               if (cg != NULL)  return cg;
             }
           }
@@ -446,13 +465,16 @@
   int       vtable_index       = Method::invalid_vtable_index;
   bool      call_does_dispatch = false;
 
+  // Speculative type of the receiver if any
+  ciKlass* speculative_receiver_type = NULL;
   if (is_virtual_or_interface) {
-    Node*             receiver_node = stack(sp() - nargs);
+    Node* receiver_node             = stack(sp() - nargs);
     const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
     // call_does_dispatch and vtable_index are out-parameters.  They might be changed.
     callee = C->optimize_virtual_call(method(), bci(), klass, orig_callee, receiver_type,
                                       is_virtual,
                                       call_does_dispatch, vtable_index);  // out-parameters
+    speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL;
   }
 
   // Note:  It's OK to try to inline a virtual call.
@@ -468,7 +490,7 @@
   // Decide call tactic.
   // This call checks with CHA, the interpreter profile, intrinsics table, etc.
   // It decides whether inlining is desirable or not.
-  CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor());
+  CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type);
 
   // NOTE:  Don't use orig_callee and callee after this point!  Use cg->method() instead.
   orig_callee = callee = NULL;
@@ -477,6 +499,10 @@
   // Round double arguments before call
   round_double_arguments(cg->method());
 
+  // Feed profiling data for arguments to the type system so it can
+  // propagate it as speculative types
+  record_profiled_arguments_for_speculation(cg->method(), bc());
+
 #ifndef PRODUCT
   // bump global counters for calls
   count_compiled_calls(/*at_method_entry*/ false, cg->is_inline());
@@ -491,6 +517,13 @@
   // save across call, for a subsequent cast_not_null.
   Node* receiver = has_receiver ? argument(0) : NULL;
 
+  // The extra CheckCastPP for speculative types mess with PhaseStringOpts
+  if (receiver != NULL && !call_does_dispatch && !cg->is_string_late_inline()) {
+    // Feed profiling data for a single receiver to the type system so
+    // it can propagate it as a speculative type
+    receiver = record_profiled_receiver_for_speculation(receiver);
+  }
+
   // Bump method data counters (We profile *before* the call is made
   // because exceptions don't return to the call site.)
   profile_call(receiver);
@@ -508,7 +541,7 @@
     // the call site, perhaps because it did not match a pattern the
     // intrinsic was expecting to optimize. Should always be possible to
     // get a normal java call that may inline in that case
-    cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
+    cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false);
     if ((new_jvms = cg->generate(jvms, this)) == NULL) {
       guarantee(failing(), "call failed to generate:  calls should work");
       return;
@@ -607,6 +640,16 @@
       null_assert(peek());
       set_bci(iter().cur_bci()); // put it back
     }
+    BasicType ct = ctype->basic_type();
+    if (ct == T_OBJECT || ct == T_ARRAY) {
+      ciKlass* better_type = method()->return_profiled_type(bci());
+      if (UseTypeSpeculation && better_type != NULL) {
+        // If profiling reports a single type for the return value,
+        // feed it to the type system so it can propagate it as a
+        // speculative type
+        record_profile_for_speculation(stack(sp()-1), better_type);
+      }
+    }
   }
 
   // Restart record of parsing work after possible inlining of call
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -2098,6 +2098,104 @@
   }
 }
 
+/**
+ * Record profiling data exact_kls for Node n with the type system so
+ * that it can propagate it (speculation)
+ *
+ * @param n          node that the type applies to
+ * @param exact_kls  type from profiling
+ *
+ * @return           node with improved type
+ */
+Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) {
+  const TypeOopPtr* current_type = _gvn.type(n)->isa_oopptr();
+  assert(UseTypeSpeculation, "type speculation must be on");
+  if (exact_kls != NULL &&
+      // nothing to improve if type is already exact
+      (current_type == NULL ||
+       (!current_type->klass_is_exact() &&
+        (current_type->speculative() == NULL ||
+         !current_type->speculative()->klass_is_exact())))) {
+    const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls);
+    const TypeOopPtr* xtype = tklass->as_instance_type();
+    assert(xtype->klass_is_exact(), "Should be exact");
+
+    // Build a type with a speculative type (what we think we know
+    // about the type but will need a guard when we use it)
+    const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, xtype);
+    // We're changing the type, we need a new cast node to carry the
+    // new type. The new type depends on the control: what profiling
+    // tells us is only valid from here as far as we can tell.
+    Node* cast = new(C) CastPPNode(n, spec_type);
+    cast->init_req(0, control());
+    cast = _gvn.transform(cast);
+    replace_in_map(n, cast);
+    n = cast;
+  }
+  return n;
+}
+
+/**
+ * Record profiling data from receiver profiling at an invoke with the
+ * type system so that it can propagate it (speculation)
+ *
+ * @param n  receiver node
+ *
+ * @return           node with improved type
+ */
+Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) {
+  if (!UseTypeSpeculation) {
+    return n;
+  }
+  ciKlass* exact_kls = profile_has_unique_klass();
+  return record_profile_for_speculation(n, exact_kls);
+}
+
+/**
+ * Record profiling data from argument profiling at an invoke with the
+ * type system so that it can propagate it (speculation)
+ *
+ * @param dest_method  target method for the call
+ * @param bc           what invoke bytecode is this?
+ */
+void GraphKit::record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc) {
+  if (!UseTypeSpeculation) {
+    return;
+  }
+  const TypeFunc* tf    = TypeFunc::make(dest_method);
+  int             nargs = tf->_domain->_cnt - TypeFunc::Parms;
+  int skip = Bytecodes::has_receiver(bc) ? 1 : 0;
+  for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) {
+    const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms);
+    if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) {
+      ciKlass* better_type = method()->argument_profiled_type(bci(), i);
+      if (better_type != NULL) {
+        record_profile_for_speculation(argument(j), better_type);
+      }
+      i++;
+    }
+  }
+}
+
+/**
+ * Record profiling data from parameter profiling at an invoke with
+ * the type system so that it can propagate it (speculation)
+ */
+void GraphKit::record_profiled_parameters_for_speculation() {
+  if (!UseTypeSpeculation) {
+    return;
+  }
+  for (int i = 0, j = 0; i < method()->arg_size() ; i++) {
+    if (_gvn.type(local(i))->isa_oopptr()) {
+      ciKlass* better_type = method()->parameter_profiled_type(j);
+      if (better_type != NULL) {
+        record_profile_for_speculation(local(i), better_type);
+      }
+      j++;
+    }
+  }
+}
+
 void GraphKit::round_double_result(ciMethod* dest_method) {
   // A non-strict method may return a double value which has an extended
   // exponent, but this must not be visible in a caller which is 'strict'
@@ -2635,10 +2733,10 @@
 // If the profile has seen exactly one type, narrow to exactly that type.
 // Subsequent type checks will always fold up.
 Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
-                                             ciProfileData* data,
-                                             ciKlass* require_klass) {
+                                             ciKlass* require_klass,
+                                            ciKlass* spec_klass,
+                                             bool safe_for_replace) {
   if (!UseTypeProfile || !TypeProfileCasts) return NULL;
-  if (data == NULL)  return NULL;
 
   // Make sure we haven't already deoptimized from this tactic.
   if (too_many_traps(Deoptimization::Reason_class_check))
@@ -2646,15 +2744,15 @@
 
   // (No, this isn't a call, but it's enough like a virtual call
   // to use the same ciMethod accessor to get the profile info...)
-  ciCallProfile profile = method()->call_profile_at_bci(bci());
-  if (profile.count() >= 0 &&         // no cast failures here
-      profile.has_receiver(0) &&
-      profile.morphism() == 1) {
-    ciKlass* exact_kls = profile.receiver(0);
+  // If we have a speculative type use it instead of profiling (which
+  // may not help us)
+  ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass;
+  if (exact_kls != NULL) {// no cast failures here
     if (require_klass == NULL ||
         static_subtype_check(require_klass, exact_kls) == SSC_always_true) {
-      // If we narrow the type to match what the type profile sees,
-      // we can then remove the rest of the cast.
+      // If we narrow the type to match what the type profile sees or
+      // the speculative type, we can then remove the rest of the
+      // cast.
       // This is a win, even if the exact_kls is very specific,
       // because downstream operations, such as method calls,
       // will often benefit from the sharper type.
@@ -2666,7 +2764,9 @@
         uncommon_trap(Deoptimization::Reason_class_check,
                       Deoptimization::Action_maybe_recompile);
       }
-      replace_in_map(not_null_obj, exact_obj);
+      if (safe_for_replace) {
+        replace_in_map(not_null_obj, exact_obj);
+      }
       return exact_obj;
     }
     // assert(ssc == SSC_always_true)... except maybe the profile lied to us.
@@ -2675,11 +2775,59 @@
   return NULL;
 }
 
+/**
+ * Cast obj to type and emit guard unless we had too many traps here
+ * already
+ *
+ * @param obj       node being casted
+ * @param type      type to cast the node to
+ * @param not_null  true if we know node cannot be null
+ */
+Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
+                                        ciKlass* type,
+                                        bool not_null) {
+  // type == NULL if profiling tells us this object is always null
+  if (type != NULL) {
+    if (!too_many_traps(Deoptimization::Reason_null_check) &&
+        !too_many_traps(Deoptimization::Reason_class_check)) {
+      Node* not_null_obj = NULL;
+      // not_null is true if we know the object is not null and
+      // there's no need for a null check
+      if (!not_null) {
+        Node* null_ctl = top();
+        not_null_obj = null_check_oop(obj, &null_ctl, true, true);
+        assert(null_ctl->is_top(), "no null control here");
+      } else {
+        not_null_obj = obj;
+      }
+
+      Node* exact_obj = not_null_obj;
+      ciKlass* exact_kls = type;
+      Node* slow_ctl  = type_check_receiver(exact_obj, exact_kls, 1.0,
+                                            &exact_obj);
+      {
+        PreserveJVMState pjvms(this);
+        set_control(slow_ctl);
+        uncommon_trap(Deoptimization::Reason_class_check,
+                      Deoptimization::Action_maybe_recompile);
+      }
+      replace_in_map(not_null_obj, exact_obj);
+      obj = exact_obj;
+    }
+  } else {
+    if (!too_many_traps(Deoptimization::Reason_null_assert)) {
+      Node* exact_obj = null_assert(obj);
+      replace_in_map(obj, exact_obj);
+      obj = exact_obj;
+    }
+  }
+  return obj;
+}
 
 //-------------------------------gen_instanceof--------------------------------
 // Generate an instance-of idiom.  Used by both the instance-of bytecode
 // and the reflective instance-of call.
-Node* GraphKit::gen_instanceof(Node* obj, Node* superklass) {
+Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replace) {
   kill_dead_locals();           // Benefit all the uncommon traps
   assert( !stopped(), "dead parse path should be checked in callers" );
   assert(!TypePtr::NULL_PTR->higher_equal(_gvn.type(superklass)->is_klassptr()),
@@ -2692,10 +2840,8 @@
   C->set_has_split_ifs(true); // Has chance for split-if optimization
 
   ciProfileData* data = NULL;
-  bool safe_for_replace = false;
   if (java_bc() == Bytecodes::_instanceof) {  // Only for the bytecode
     data = method()->method_data()->bci_to_data(bci());
-    safe_for_replace = true;
   }
   bool never_see_null = (ProfileDynamicTypes  // aggressive use of profile
                          && seems_never_null(obj, data));
@@ -2719,14 +2865,37 @@
     phi   ->del_req(_null_path);
   }
 
-  if (ProfileDynamicTypes && data != NULL) {
-    Node* cast_obj = maybe_cast_profiled_receiver(not_null_obj, data, NULL);
-    if (stopped()) {            // Profile disagrees with this path.
-      set_control(null_ctl);    // Null is the only remaining possibility.
-      return intcon(0);
+  // Do we know the type check always succeed?
+  bool known_statically = false;
+  if (_gvn.type(superklass)->singleton()) {
+    ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass();
+    ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass();
+    if (subk != NULL && subk->is_loaded()) {
+      int static_res = static_subtype_check(superk, subk);
+      known_statically = (static_res == SSC_always_true || static_res == SSC_always_false);
     }
-    if (cast_obj != NULL)
-      not_null_obj = cast_obj;
+  }
+
+  if (known_statically && UseTypeSpeculation) {
+    // If we know the type check always succeed then we don't use the
+    // profiling data at this bytecode. Don't lose it, feed it to the
+    // type system as a speculative type.
+    not_null_obj = record_profiled_receiver_for_speculation(not_null_obj);
+  } else {
+    const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
+    // We may not have profiling here or it may not help us. If we
+    // have a speculative type use it to perform an exact cast.
+    ciKlass* spec_obj_type = obj_type->speculative_type();
+    if (spec_obj_type != NULL || (ProfileDynamicTypes && data != NULL)) {
+      Node* cast_obj = maybe_cast_profiled_receiver(not_null_obj, NULL, spec_obj_type, safe_for_replace);
+      if (stopped()) {            // Profile disagrees with this path.
+        set_control(null_ctl);    // Null is the only remaining possibility.
+        return intcon(0);
+      }
+      if (cast_obj != NULL) {
+        not_null_obj = cast_obj;
+      }
+    }
   }
 
   // Load the object's klass
@@ -2773,7 +2942,10 @@
     if (objtp != NULL && objtp->klass() != NULL) {
       switch (static_subtype_check(tk->klass(), objtp->klass())) {
       case SSC_always_true:
-        return obj;
+        // If we know the type check always succeed then we don't use
+        // the profiling data at this bytecode. Don't lose it, feed it
+        // to the type system as a speculative type.
+        return record_profiled_receiver_for_speculation(obj);
       case SSC_always_false:
         // It needs a null check because a null will *pass* the cast check.
         // A non-null value will always produce an exception.
@@ -2822,12 +2994,17 @@
   }
 
   Node* cast_obj = NULL;
-  if (data != NULL &&
-      // Counter has never been decremented (due to cast failure).
-      // ...This is a reasonable thing to expect.  It is true of
-      // all casts inserted by javac to implement generic types.
-      data->as_CounterData()->count() >= 0) {
-    cast_obj = maybe_cast_profiled_receiver(not_null_obj, data, tk->klass());
+  const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
+  // We may not have profiling here or it may not help us. If we have
+  // a speculative type use it to perform an exact cast.
+  ciKlass* spec_obj_type = obj_type->speculative_type();
+  if (spec_obj_type != NULL ||
+      (data != NULL &&
+       // Counter has never been decremented (due to cast failure).
+       // ...This is a reasonable thing to expect.  It is true of
+       // all casts inserted by javac to implement generic types.
+       data->as_CounterData()->count() >= 0)) {
+    cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk->klass(), spec_obj_type, safe_for_replace);
     if (cast_obj != NULL) {
       if (failure_control != NULL) // failure is now impossible
         (*failure_control) = top();
--- a/hotspot/src/share/vm/opto/graphKit.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -386,10 +386,33 @@
   // Check the null_seen bit.
   bool seems_never_null(Node* obj, ciProfileData* data);
 
+  // Check for unique class for receiver at call
+  ciKlass* profile_has_unique_klass() {
+    ciCallProfile profile = method()->call_profile_at_bci(bci());
+    if (profile.count() >= 0 &&         // no cast failures here
+        profile.has_receiver(0) &&
+        profile.morphism() == 1) {
+      return profile.receiver(0);
+    }
+    return NULL;
+  }
+
+  // record type from profiling with the type system
+  Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls);
+  Node* record_profiled_receiver_for_speculation(Node* n);
+  void record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc);
+  void record_profiled_parameters_for_speculation();
+
   // Use the type profile to narrow an object type.
   Node* maybe_cast_profiled_receiver(Node* not_null_obj,
-                                     ciProfileData* data,
-                                     ciKlass* require_klass);
+                                     ciKlass* require_klass,
+                                    ciKlass* spec,
+                                     bool safe_for_replace);
+
+  // Cast obj to type and emit guard unless we had too many traps here already
+  Node* maybe_cast_profiled_obj(Node* obj,
+                                ciKlass* type,
+                                bool not_null = false);
 
   // Cast obj to not-null on this path
   Node* cast_not_null(Node* obj, bool do_replace_in_map = true);
@@ -775,7 +798,7 @@
 
   // Generate an instance-of idiom.  Used by both the instance-of bytecode
   // and the reflective instance-of call.
-  Node* gen_instanceof( Node *subobj, Node* superkls );
+  Node* gen_instanceof(Node *subobj, Node* superkls, bool safe_for_replace = false);
 
   // Generate a check-cast idiom.  Used by both the check-cast bytecode
   // and the array-store bytecode
--- a/hotspot/src/share/vm/opto/library_call.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -3353,6 +3353,7 @@
   // If kls is null, we have a primitive mirror.
   phi->init_req(_prim_path, prim_return_value);
   if (stopped()) { set_result(region, phi); return true; }
+  bool safe_for_replace = (region->in(_prim_path) == top());
 
   Node* p;  // handy temp
   Node* null_ctl;
@@ -3363,7 +3364,7 @@
   switch (id) {
   case vmIntrinsics::_isInstance:
     // nothing is an instance of a primitive type
-    query_value = gen_instanceof(obj, kls);
+    query_value = gen_instanceof(obj, kls, safe_for_replace);
     break;
 
   case vmIntrinsics::_getModifiers:
@@ -4553,8 +4554,62 @@
   const Type* dest_type = dest->Value(&_gvn);
   const TypeAryPtr* top_src  = src_type->isa_aryptr();
   const TypeAryPtr* top_dest = dest_type->isa_aryptr();
-  if (top_src  == NULL || top_src->klass()  == NULL ||
-      top_dest == NULL || top_dest->klass() == NULL) {
+
+  // Do we have the type of src?
+  bool has_src = (top_src != NULL && top_src->klass() != NULL);
+  // Do we have the type of dest?
+  bool has_dest = (top_dest != NULL && top_dest->klass() != NULL);
+  // Is the type for src from speculation?
+  bool src_spec = false;
+  // Is the type for dest from speculation?
+  bool dest_spec = false;
+
+  if (!has_src || !has_dest) {
+    // We don't have sufficient type information, let's see if
+    // speculative types can help. We need to have types for both src
+    // and dest so that it pays off.
+
+    // Do we already have or could we have type information for src
+    bool could_have_src = has_src;
+    // Do we already have or could we have type information for dest
+    bool could_have_dest = has_dest;
+
+    ciKlass* src_k = NULL;
+    if (!has_src) {
+      src_k = src_type->speculative_type();
+      if (src_k != NULL && src_k->is_array_klass()) {
+        could_have_src = true;
+      }
+    }
+
+    ciKlass* dest_k = NULL;
+    if (!has_dest) {
+      dest_k = dest_type->speculative_type();
+      if (dest_k != NULL && dest_k->is_array_klass()) {
+        could_have_dest = true;
+      }
+    }
+
+    if (could_have_src && could_have_dest) {
+      // This is going to pay off so emit the required guards
+      if (!has_src) {
+        src = maybe_cast_profiled_obj(src, src_k);
+        src_type  = _gvn.type(src);
+        top_src  = src_type->isa_aryptr();
+        has_src = (top_src != NULL && top_src->klass() != NULL);
+        src_spec = true;
+      }
+      if (!has_dest) {
+        dest = maybe_cast_profiled_obj(dest, dest_k);
+        dest_type  = _gvn.type(dest);
+        top_dest  = dest_type->isa_aryptr();
+        has_dest = (top_dest != NULL && top_dest->klass() != NULL);
+        dest_spec = true;
+      }
+    }
+  }
+
+  if (!has_src || !has_dest) {
     // Conservatively insert a memory barrier on all memory slices.
     // Do not let writes into the source float below the arraycopy.
     insert_mem_bar(Op_MemBarCPUOrder);
@@ -4589,6 +4644,40 @@
     return true;
   }
 
+  if (src_elem == T_OBJECT) {
+    // If both arrays are object arrays then having the exact types
+    // for both will remove the need for a subtype check at runtime
+    // before the call and may make it possible to pick a faster copy
+    // routine (without a subtype check on every element)
+    // Do we have the exact type of src?
+    bool could_have_src = src_spec;
+    // Do we have the exact type of dest?
+    bool could_have_dest = dest_spec;
+    ciKlass* src_k = top_src->klass();
+    ciKlass* dest_k = top_dest->klass();
+    if (!src_spec) {
+      src_k = src_type->speculative_type();
+      if (src_k != NULL && src_k->is_array_klass()) {
+          could_have_src = true;
+      }
+    }
+    if (!dest_spec) {
+      dest_k = dest_type->speculative_type();
+      if (dest_k != NULL && dest_k->is_array_klass()) {
+        could_have_dest = true;
+      }
+    }
+    if (could_have_src && could_have_dest) {
+      // If we can have both exact types, emit the missing guards
+      if (could_have_src && !src_spec) {
+        src = maybe_cast_profiled_obj(src, src_k);
+      }
+      if (could_have_dest && !dest_spec) {
+        dest = maybe_cast_profiled_obj(dest, dest_k);
+      }
+    }
+  }
+
   //---------------------------------------------------------------------------
   // We will make a fast path for this call to arraycopy.
 
--- a/hotspot/src/share/vm/opto/parse.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/parse.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -607,6 +607,9 @@
   // Assumes that there is no applicable local handler.
   void throw_to_exit(SafePointNode* ex_map);
 
+  // Use speculative type to optimize CmpP node
+  Node* optimize_cmp_with_klass(Node* c);
+
  public:
 #ifndef PRODUCT
   // Handle PrintOpto, etc.
--- a/hotspot/src/share/vm/opto/parse1.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -1102,6 +1102,10 @@
     _synch_lock = shared_lock(lock_obj);
   }
 
+  // Feed profiling data for parameters to the type system so it can
+  // propagate it as speculative types
+  record_profiled_parameters_for_speculation();
+
   if (depth() == 1) {
     increment_and_test_invocation_counter(Tier2CompileThreshold);
   }
--- a/hotspot/src/share/vm/opto/parse2.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -1366,6 +1366,56 @@
   }
 }
 
+/**
+ * Use speculative type to optimize CmpP node: if comparison is
+ * against the low level class, cast the object to the speculative
+ * type if any. CmpP should then go away.
+ *
+ * @param c  expected CmpP node
+ * @return   result of CmpP on object casted to speculative type
+ *
+ */
+Node* Parse::optimize_cmp_with_klass(Node* c) {
+  // If this is transformed by the _gvn to a comparison with the low
+  // level klass then we may be able to use speculation
+  if (c->Opcode() == Op_CmpP &&
+      (c->in(1)->Opcode() == Op_LoadKlass || c->in(1)->Opcode() == Op_DecodeNKlass) &&
+      c->in(2)->is_Con()) {
+    Node* load_klass = NULL;
+    Node* decode = NULL;
+    if (c->in(1)->Opcode() == Op_DecodeNKlass) {
+      decode = c->in(1);
+      load_klass = c->in(1)->in(1);
+    } else {
+      load_klass = c->in(1);
+    }
+    if (load_klass->in(2)->is_AddP()) {
+      Node* addp = load_klass->in(2);
+      Node* obj = addp->in(AddPNode::Address);
+      const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
+      if (obj_type->speculative_type() != NULL) {
+        ciKlass* k = obj_type->speculative_type();
+        inc_sp(2);
+        obj = maybe_cast_profiled_obj(obj, k);
+        dec_sp(2);
+        // Make the CmpP use the casted obj
+        addp = basic_plus_adr(obj, addp->in(AddPNode::Offset));
+        load_klass = load_klass->clone();
+        load_klass->set_req(2, addp);
+        load_klass = _gvn.transform(load_klass);
+        if (decode != NULL) {
+          decode = decode->clone();
+          decode->set_req(1, load_klass);
+          load_klass = _gvn.transform(decode);
+        }
+        c = c->clone();
+        c->set_req(1, load_klass);
+        c = _gvn.transform(c);
+      }
+    }
+  }
+  return c;
+}
 
 //------------------------------do_one_bytecode--------------------------------
 // Parse this bytecode, and alter the Parsers JVM->Node mapping
@@ -2239,6 +2289,7 @@
     a = pop();
     b = pop();
     c = _gvn.transform( new (C) CmpPNode(b, a) );
+    c = optimize_cmp_with_klass(c);
     do_if(btest, c);
     break;
 
--- a/hotspot/src/share/vm/opto/parseHelper.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -128,7 +128,7 @@
   }
 
   // Push the bool result back on stack
-  Node* res = gen_instanceof(peek(), makecon(TypeKlassPtr::make(klass)));
+  Node* res = gen_instanceof(peek(), makecon(TypeKlassPtr::make(klass)), true);
 
   // Pop from stack AFTER gen_instanceof because it can uncommon trap.
   pop();
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -1385,6 +1385,20 @@
   }
 }
 
+/**
+ * Remove the speculative part of all types that we know of
+ */
+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());
+    }
+  }
+}
+
 //=============================================================================
 #ifndef PRODUCT
 uint PhaseCCP::_total_invokes   = 0;
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -500,6 +500,8 @@
   ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
                                         Deoptimization::DeoptReason reason);
 
+  void remove_speculative_types();
+
 #ifndef PRODUCT
 protected:
   // Sub-quadratic implementation of VerifyIterativeGVN.
--- a/hotspot/src/share/vm/opto/type.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/type.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -358,7 +358,7 @@
                                            false, 0, oopDesc::mark_offset_in_bytes());
   TypeInstPtr::KLASS   = TypeInstPtr::make(TypePtr::BotPTR,  current->env()->Object_klass(),
                                            false, 0, oopDesc::klass_offset_in_bytes());
-  TypeOopPtr::BOTTOM  = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot);
+  TypeOopPtr::BOTTOM  = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot, NULL);
 
   TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot);
 
@@ -577,7 +577,7 @@
 
 //----------------------interface_vs_oop---------------------------------------
 #ifdef ASSERT
-bool Type::interface_vs_oop(const Type *t) const {
+bool Type::interface_vs_oop_helper(const Type *t) const {
   bool result = false;
 
   const TypePtr* this_ptr = this->make_ptr(); // In case it is narrow_oop
@@ -595,6 +595,29 @@
 
   return result;
 }
+
+bool Type::interface_vs_oop(const Type *t) const {
+  if (interface_vs_oop_helper(t)) {
+    return true;
+  }
+  // Now check the speculative parts as well
+  const TypeOopPtr* this_spec = isa_oopptr() != NULL ? isa_oopptr()->speculative() : NULL;
+  const TypeOopPtr* t_spec = t->isa_oopptr() != NULL ? t->isa_oopptr()->speculative() : NULL;
+  if (this_spec != NULL && t_spec != NULL) {
+    if (this_spec->interface_vs_oop_helper(t_spec)) {
+      return true;
+    }
+    return false;
+  }
+  if (this_spec != NULL && this_spec->interface_vs_oop_helper(t)) {
+    return true;
+  }
+  if (t_spec != NULL && interface_vs_oop_helper(t_spec)) {
+    return true;
+  }
+  return false;
+}
+
 #endif
 
 //------------------------------meet-------------------------------------------
@@ -2407,14 +2430,15 @@
 const TypeOopPtr *TypeOopPtr::BOTTOM;
 
 //------------------------------TypeOopPtr-------------------------------------
-TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id )
+TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative)
   : TypePtr(t, ptr, offset),
     _const_oop(o), _klass(k),
     _klass_is_exact(xk),
     _is_ptr_to_narrowoop(false),
     _is_ptr_to_narrowklass(false),
     _is_ptr_to_boxed_value(false),
-    _instance_id(instance_id) {
+    _instance_id(instance_id),
+    _speculative(speculative) {
   if (Compile::current()->eliminate_boxing() && (t == InstPtr) &&
       (offset > 0) && xk && (k != 0) && k->is_instance_klass()) {
     _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset);
@@ -2481,12 +2505,12 @@
 
 //------------------------------make-------------------------------------------
 const TypeOopPtr *TypeOopPtr::make(PTR ptr,
-                                   int offset, int instance_id) {
+                                   int offset, int instance_id, const TypeOopPtr* speculative) {
   assert(ptr != Constant, "no constant generic pointers");
   ciKlass*  k = Compile::current()->env()->Object_klass();
   bool      xk = false;
   ciObject* o = NULL;
-  return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons();
+  return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative))->hashcons();
 }
 
 
@@ -2494,7 +2518,7 @@
 const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const {
   assert(_base == OopPtr, "subclass must override cast_to_ptr_type");
   if( ptr == _ptr ) return this;
-  return make(ptr, _offset, _instance_id);
+  return make(ptr, _offset, _instance_id, _speculative);
 }
 
 //-----------------------------cast_to_instance_id----------------------------
@@ -2524,10 +2548,31 @@
     return TypeKlassPtr::make(xk? Constant: NotNull, k, 0);
 }
 
+const Type *TypeOopPtr::xmeet(const Type *t) const {
+  const Type* res = xmeet_helper(t);
+  if (res->isa_oopptr() == NULL) {
+    return res;
+  }
+
+  if (res->isa_oopptr() != 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();
+    }
+  }
+
+  return res;
+}
 
 //------------------------------meet-------------------------------------------
 // Compute the MEET of two types.  It returns a new Type object.
-const Type *TypeOopPtr::xmeet( const Type *t ) const {
+const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
   // Perform a fast test for common case; meeting the same types together.
   if( this == t ) return this;  // Meeting same type-rep?
 
@@ -2569,7 +2614,8 @@
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      return make(ptr, offset, instance_id);
+      const TypeOopPtr* speculative = _speculative;
+      return make(ptr, offset, instance_id, speculative);
     }
     case BotPTR:
     case NotNull:
@@ -2581,7 +2627,8 @@
   case OopPtr: {                 // Meeting to other OopPtrs
     const TypeOopPtr *tp = t->is_oopptr();
     int instance_id = meet_instance_id(tp->instance_id());
-    return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id );
+    const TypeOopPtr* speculative = meet_speculative(tp);
+    return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative);
   }
 
   case InstPtr:                  // For these, flip the call around to cut down
@@ -2598,7 +2645,7 @@
 const Type *TypeOopPtr::xdual() const {
   assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here");
   assert(const_oop() == NULL,             "no constants here");
-  return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id()  );
+  return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative());
 }
 
 //--------------------------make_from_klass_common-----------------------------
@@ -2689,7 +2736,7 @@
     } else if (!o->should_be_constant()) {
       return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
     }
-    const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, is_autobox_cache);
+    const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, is_autobox_cache);
     return arr;
   } else if (klass->is_type_array_klass()) {
     // Element is an typeArray
@@ -2789,7 +2836,8 @@
 bool TypeOopPtr::eq( const Type *t ) const {
   const TypeOopPtr *a = (const TypeOopPtr*)t;
   if (_klass_is_exact != a->_klass_is_exact ||
-      _instance_id != a->_instance_id)  return false;
+      _instance_id != a->_instance_id ||
+      !eq_speculative(a))  return false;
   ciObject* one = const_oop();
   ciObject* two = a->const_oop();
   if (one == NULL || two == NULL) {
@@ -2806,6 +2854,7 @@
     (const_oop() ? const_oop()->hash() : 0) +
     _klass_is_exact +
     _instance_id +
+    hash_speculative() +
     TypePtr::hash();
 }
 
@@ -2825,6 +2874,19 @@
     st->print(",iid=top");
   else if (_instance_id != InstanceBot)
     st->print(",iid=%d",_instance_id);
+
+  dump_speculative(st);
+}
+
+/**
+ *dump the speculative part of the type
+ */
+void TypeOopPtr::dump_speculative(outputStream *st) const {
+  if (_speculative != NULL) {
+    st->print(" (speculative=");
+    _speculative->dump_on(st);
+    st->print(")");
+  }
 }
 #endif
 
@@ -2838,8 +2900,15 @@
 }
 
 //------------------------------add_offset-------------------------------------
-const TypePtr *TypeOopPtr::add_offset( intptr_t offset ) const {
-  return make( _ptr, xadd_offset(offset), _instance_id);
+const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const {
+  return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset));
+}
+
+/**
+ * Return same type without a speculative part
+ */
+const TypeOopPtr* TypeOopPtr::remove_speculative() const {
+  return make(_ptr, _offset, _instance_id, NULL);
 }
 
 //------------------------------meet_instance_id--------------------------------
@@ -2859,6 +2928,89 @@
   return _instance_id;              // Map everything else into self
 }
 
+/**
+ * meet of the speculative parts of 2 types
+ *
+ * @param other  type to meet with
+ */
+const TypeOopPtr* TypeOopPtr::meet_speculative(const TypeOopPtr* other) const {
+  bool this_has_spec = (_speculative != NULL);
+  bool other_has_spec = (other->speculative() != NULL);
+
+  if (!this_has_spec && !other_has_spec) {
+    return NULL;
+  }
+
+  // If we are at a point where control flow meets and one branch has
+  // a speculative type and the other has not, we meet the speculative
+  // type of one branch with the actual type of the other. If the
+  // actual type is exact and the speculative is as well, then the
+  // result is a speculative type which is exact and we can continue
+  // speculation further.
+  const TypeOopPtr* this_spec = _speculative;
+  const TypeOopPtr* other_spec = other->speculative();
+
+  if (!this_has_spec) {
+    this_spec = this;
+  }
+
+  if (!other_has_spec) {
+    other_spec = other;
+  }
+
+  return this_spec->meet(other_spec)->is_oopptr();
+}
+
+/**
+ * dual of the speculative part of the type
+ */
+const TypeOopPtr* TypeOopPtr::dual_speculative() const {
+  if (_speculative == NULL) {
+    return NULL;
+  }
+  return _speculative->dual()->is_oopptr();
+}
+
+/**
+ * add offset to the speculative part of the type
+ *
+ * @param offset  offset to add
+ */
+const TypeOopPtr* TypeOopPtr::add_offset_speculative(intptr_t offset) const {
+  if (_speculative == NULL) {
+    return NULL;
+  }
+  return _speculative->add_offset(offset)->is_oopptr();
+}
+
+/**
+ * Are the speculative parts of 2 types equal?
+ *
+ * @param other  type to compare this one to
+ */
+bool TypeOopPtr::eq_speculative(const TypeOopPtr* other) const {
+  if (_speculative == NULL || other->speculative() == NULL) {
+    return _speculative == other->speculative();
+  }
+
+  if (_speculative->base() != other->speculative()->base()) {
+    return false;
+  }
+
+  return _speculative->eq(other->speculative());
+}
+
+/**
+ * Hash of the speculative part of the type
+ */
+int TypeOopPtr::hash_speculative() const {
+  if (_speculative == NULL) {
+    return 0;
+  }
+
+  return _speculative->hash();
+}
+
 
 //=============================================================================
 // Convenience common pre-built types.
@@ -2869,8 +3021,8 @@
 const TypeInstPtr *TypeInstPtr::KLASS;
 
 //------------------------------TypeInstPtr-------------------------------------
-TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id)
- : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id), _name(k->name()) {
+TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative)
+  : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative), _name(k->name()) {
    assert(k != NULL &&
           (k->is_loaded() || o == NULL),
           "cannot have constants with non-loaded klass");
@@ -2882,7 +3034,8 @@
                                      bool xk,
                                      ciObject* o,
                                      int offset,
-                                     int instance_id) {
+                                     int instance_id,
+                                     const TypeOopPtr* speculative) {
   assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
   // Either const_oop() is NULL or else ptr is Constant
   assert( (!o && ptr != Constant) || (o && ptr == Constant),
@@ -2903,7 +3056,7 @@
 
   // Now hash this baby
   TypeInstPtr *result =
-    (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id))->hashcons();
+    (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative))->hashcons();
 
   return result;
 }
@@ -2936,7 +3089,7 @@
   if( ptr == _ptr ) return this;
   // Reconstruct _sig info here since not a problem with later lazy
   // construction, _sig will show up on demand.
-  return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id);
+  return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative);
 }
 
 
@@ -2948,13 +3101,13 @@
   ciInstanceKlass* ik = _klass->as_instance_klass();
   if( (ik->is_final() || _const_oop) )  return this;  // cannot clear xk
   if( ik->is_interface() )              return this;  // cannot set xk
-  return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id);
+  return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative);
 }
 
 //-----------------------------cast_to_instance_id----------------------------
 const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const {
   if( instance_id == _instance_id ) return this;
-  return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id);
+  return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative);
 }
 
 //------------------------------xmeet_unloaded---------------------------------
@@ -2964,6 +3117,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 TypeInstPtr *loaded    = is_loaded() ? this  : tinst;
     const TypeInstPtr *unloaded  = is_loaded() ? tinst : this;
@@ -2984,7 +3138,7 @@
       assert(loaded->ptr() != TypePtr::Null, "insanity check");
       //
       if(      loaded->ptr() == TypePtr::TopPTR ) { return unloaded; }
-      else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make( ptr, unloaded->klass(), false, NULL, off, instance_id ); }
+      else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative); }
       else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; }
       else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) {
         if (unloaded->ptr() == TypePtr::BotPTR  ) { return TypeInstPtr::BOTTOM;  }
@@ -3006,7 +3160,7 @@
 
 //------------------------------meet-------------------------------------------
 // Compute the MEET of two types.  It returns a new Type object.
-const Type *TypeInstPtr::xmeet( const Type *t ) const {
+const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
   // Perform a fast test for common case; meeting the same types together.
   if( this == t ) return this;  // Meeting same type-rep?
 
@@ -3040,16 +3194,20 @@
     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);
     switch (ptr) {
     case TopPTR:
     case AnyNull:                // Fall 'down' to dual of object klass
-      if (klass()->equals(ciEnv::current()->Object_klass())) {
-        return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id);
+      // For instances when a subclass meets a superclass we fall
+      // below the centerline when the superclass is exact. We need to
+      // do the same here.
+      if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) {
+        return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative);
       } else {
         // cannot subclass, so the meet has to fall badly below the centerline
         ptr = NotNull;
         instance_id = InstanceBot;
-        return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id);
+        return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative);
       }
     case Constant:
     case NotNull:
@@ -3058,10 +3216,13 @@
       if( above_centerline(_ptr) ) { // if( _ptr == TopPTR || _ptr == AnyNull )
         // If 'this' (InstPtr) is above the centerline and it is Object class
         // then we can subclass in the Java class hierarchy.
-        if (klass()->equals(ciEnv::current()->Object_klass())) {
+        // For instances when a subclass meets a superclass we fall
+        // below the centerline when the superclass is exact. We need
+        // to do the same here.
+        if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) {
           // that is, tp's array type is a subtype of my klass
           return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL),
-                                  tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id);
+                                  tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative);
         }
       }
       // The other case cannot happen, since I cannot be a subtype of an array.
@@ -3069,7 +3230,7 @@
       if( ptr == Constant )
          ptr = NotNull;
       instance_id = InstanceBot;
-      return make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id );
+      return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative);
     default: typerr(t);
     }
   }
@@ -3083,13 +3244,15 @@
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
+      const TypeOopPtr* speculative = meet_speculative(tp);
       return make(ptr, klass(), klass_is_exact(),
-                  (ptr == Constant ? const_oop() : NULL), offset, instance_id);
+                  (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative);
     }
     case NotNull:
     case BotPTR: {
       int instance_id = meet_instance_id(tp->instance_id());
-      return TypeOopPtr::make(ptr, offset, instance_id);
+      const TypeOopPtr* speculative = meet_speculative(tp);
+      return TypeOopPtr::make(ptr, offset, instance_id, speculative);
     }
     default: typerr(t);
     }
@@ -3102,17 +3265,18 @@
     PTR ptr = meet_ptr(tp->ptr());
     switch (tp->ptr()) {
     case Null:
-      if( ptr == Null ) return TypePtr::make( AnyPtr, ptr, offset );
+      if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset);
       // else fall through to AnyNull
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      return make( ptr, klass(), klass_is_exact(),
-                   (ptr == Constant ? const_oop() : NULL), offset, instance_id);
+      const TypeOopPtr* speculative = _speculative;
+      return make(ptr, klass(), klass_is_exact(),
+                  (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative);
     }
     case NotNull:
     case BotPTR:
-      return TypePtr::make( AnyPtr, ptr, offset );
+      return TypePtr::make(AnyPtr, ptr, offset);
     default: typerr(t);
     }
   }
@@ -3139,13 +3303,14 @@
     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);
 
     // Check for easy case; klasses are equal (and perhaps not loaded!)
     // If we have constants, then we created oops so classes are loaded
     // and we can handle the constants further down.  This case handles
     // both-not-loaded or both-loaded classes
     if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact()) {
-      return make( ptr, klass(), klass_is_exact(), NULL, off, instance_id );
+      return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative);
     }
 
     // Classes require inspection in the Java klass hierarchy.  Must be loaded.
@@ -3167,7 +3332,8 @@
     }
 
     // Handle mixing oops and interfaces first.
-    if( this_klass->is_interface() && !tinst_klass->is_interface() ) {
+    if( this_klass->is_interface() && !(tinst_klass->is_interface() ||
+                                        tinst_klass == ciEnv::current()->Object_klass())) {
       ciKlass *tmp = tinst_klass; // Swap interface around
       tinst_klass = this_klass;
       this_klass = tmp;
@@ -3208,7 +3374,7 @@
         // Find out which constant.
         o = (this_klass == klass()) ? const_oop() : tinst->const_oop();
       }
-      return make( ptr, k, xk, o, off, instance_id );
+      return make(ptr, k, xk, o, off, instance_id, speculative);
     }
 
     // Either oop vs oop or interface vs interface or interface vs Object
@@ -3285,7 +3451,7 @@
         else
           ptr = NotNull;
       }
-      return make( ptr, this_klass, this_xk, o, off, instance_id );
+      return make(ptr, this_klass, this_xk, o, off, instance_id, speculative);
     } // Else classes are not equal
 
     // Since klasses are different, we require a LCA in the Java
@@ -3296,7 +3462,7 @@
 
     // Now we find the LCA of Java classes
     ciKlass* k = this_klass->least_common_ancestor(tinst_klass);
-    return make( ptr, k, false, NULL, off, instance_id );
+    return make(ptr, k, false, NULL, off, instance_id, speculative);
   } // End of case InstPtr
 
   } // End of switch
@@ -3320,7 +3486,7 @@
 // Dual: do NOT dual on klasses.  This means I do NOT understand the Java
 // inheritance mechanism.
 const Type *TypeInstPtr::xdual() const {
-  return new TypeInstPtr( dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id()  );
+  return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative());
 }
 
 //------------------------------eq---------------------------------------------
@@ -3376,12 +3542,18 @@
     st->print(",iid=top");
   else if (_instance_id != InstanceBot)
     st->print(",iid=%d",_instance_id);
+
+  dump_speculative(st);
 }
 #endif
 
 //------------------------------add_offset-------------------------------------
-const TypePtr *TypeInstPtr::add_offset( intptr_t offset ) const {
-  return make( _ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id );
+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 {
+  return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL);
 }
 
 //=============================================================================
@@ -3398,30 +3570,30 @@
 const TypeAryPtr *TypeAryPtr::DOUBLES;
 
 //------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) {
+const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative) {
   assert(!(k == NULL && ary->_elem->isa_int()),
          "integral arrays must be pre-equipped with a class");
   if (!xk)  xk = ary->ary_must_be_exact();
   assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
   if (!UseExactTypes)  xk = (ptr == Constant);
-  return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false))->hashcons();
+  return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative))->hashcons();
 }
 
 //------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, bool is_autobox_cache) {
+const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, bool is_autobox_cache) {
   assert(!(k == NULL && ary->_elem->isa_int()),
          "integral arrays must be pre-equipped with a class");
   assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
   if (!xk)  xk = (o != NULL) || ary->ary_must_be_exact();
   assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
   if (!UseExactTypes)  xk = (ptr == Constant);
-  return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache))->hashcons();
+  return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative))->hashcons();
 }
 
 //------------------------------cast_to_ptr_type-------------------------------
 const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const {
   if( ptr == _ptr ) return this;
-  return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id);
+  return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative);
 }
 
 
@@ -3430,13 +3602,13 @@
   if( klass_is_exact == _klass_is_exact ) return this;
   if (!UseExactTypes)  return this;
   if (_ary->ary_must_be_exact())  return this;  // cannot clear xk
-  return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id);
+  return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative);
 }
 
 //-----------------------------cast_to_instance_id----------------------------
 const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const {
   if( instance_id == _instance_id ) return this;
-  return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id);
+  return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative);
 }
 
 //-----------------------------narrow_size_type-------------------------------
@@ -3499,7 +3671,7 @@
   new_size = narrow_size_type(new_size);
   if (new_size == size())  return this;
   const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable());
-  return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
+  return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative);
 }
 
 
@@ -3548,7 +3720,7 @@
 
 //------------------------------meet-------------------------------------------
 // Compute the MEET of two types.  It returns a new Type object.
-const Type *TypeAryPtr::xmeet( const Type *t ) const {
+const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
   // Perform a fast test for common case; meeting the same types together.
   if( this == t ) return this;  // Meeting same type-rep?
   // Current "this->_base" is Pointer
@@ -3582,13 +3754,15 @@
     case TopPTR:
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
+      const TypeOopPtr* speculative = meet_speculative(tp);
       return make(ptr, (ptr == Constant ? const_oop() : NULL),
-                  _ary, _klass, _klass_is_exact, offset, instance_id);
+                  _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
     }
     case BotPTR:
     case NotNull: {
       int instance_id = meet_instance_id(tp->instance_id());
-      return TypeOopPtr::make(ptr, offset, instance_id);
+      const TypeOopPtr* speculative = meet_speculative(tp);
+      return TypeOopPtr::make(ptr, offset, instance_id, speculative);
     }
     default: ShouldNotReachHere();
     }
@@ -3610,8 +3784,9 @@
       // else fall through to AnyNull
     case AnyNull: {
       int instance_id = meet_instance_id(InstanceTop);
-      return make( ptr, (ptr == Constant ? const_oop() : NULL),
-                  _ary, _klass, _klass_is_exact, offset, instance_id);
+      const TypeOopPtr* speculative = _speculative;
+      return make(ptr, (ptr == Constant ? const_oop() : NULL),
+                  _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
     }
     default: ShouldNotReachHere();
     }
@@ -3627,6 +3802,7 @@
     const TypeAry *tary = _ary->meet(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);
     ciKlass* lazy_klass = NULL;
     if (tary->_elem->isa_int()) {
       // Integral array element types have irrelevant lattice relations.
@@ -3654,7 +3830,7 @@
          // 'this' is exact and super or unrelated:
          (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
       tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
-      return make( NotNull, NULL, tary, lazy_klass, false, off, InstanceBot );
+      return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot);
     }
 
     bool xk = false;
@@ -3662,8 +3838,12 @@
     case AnyNull:
     case TopPTR:
       // Compute new klass on demand, do not use tap->_klass
-      xk = (tap->_klass_is_exact | this->_klass_is_exact);
-      return make( ptr, const_oop(), tary, lazy_klass, xk, off, instance_id );
+      if (below_centerline(this->_ptr)) {
+        xk = this->_klass_is_exact;
+      } else {
+        xk = (tap->_klass_is_exact | this->_klass_is_exact);
+      }
+      return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative);
     case Constant: {
       ciObject* o = const_oop();
       if( _ptr == Constant ) {
@@ -3675,25 +3855,23 @@
         } else {
           xk = true;
         }
-      } else if( above_centerline(_ptr) ) {
+      } else if(above_centerline(_ptr)) {
         o = tap->const_oop();
         xk = true;
       } else {
         // Only precise for identical arrays
         xk = this->_klass_is_exact && (klass() == tap->klass());
       }
-      return TypeAryPtr::make( ptr, o, tary, lazy_klass, xk, off, instance_id );
+      return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative);
     }
     case NotNull:
     case BotPTR:
       // Compute new klass on demand, do not use tap->_klass
       if (above_centerline(this->_ptr))
             xk = tap->_klass_is_exact;
-      else if (above_centerline(tap->_ptr))
-            xk = this->_klass_is_exact;
       else  xk = (tap->_klass_is_exact & this->_klass_is_exact) &&
               (klass() == tap->klass()); // Only precise for identical arrays
-      return TypeAryPtr::make( ptr, NULL, tary, lazy_klass, xk, off, instance_id );
+      return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative);
     default: ShouldNotReachHere();
     }
   }
@@ -3704,16 +3882,20 @@
     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);
     switch (ptr) {
     case TopPTR:
     case AnyNull:                // Fall 'down' to dual of object klass
-      if( tp->klass()->equals(ciEnv::current()->Object_klass()) ) {
-        return TypeAryPtr::make( ptr, _ary, _klass, _klass_is_exact, offset, instance_id );
+      // For instances when a subclass meets a superclass we fall
+      // below the centerline when the superclass is exact. We need to
+      // do the same here.
+      if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) {
+        return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
       } else {
         // cannot subclass, so the meet has to fall badly below the centerline
         ptr = NotNull;
         instance_id = InstanceBot;
-        return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id);
+        return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative);
       }
     case Constant:
     case NotNull:
@@ -3722,10 +3904,13 @@
       if (above_centerline(tp->ptr())) {
         // If 'tp'  is above the centerline and it is Object class
         // then we can subclass in the Java class hierarchy.
-        if( tp->klass()->equals(ciEnv::current()->Object_klass()) ) {
+        // For instances when a subclass meets a superclass we fall
+        // below the centerline when the superclass is exact. We need
+        // to do the same here.
+        if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) {
           // that is, my array type is a subtype of 'tp' klass
-          return make( ptr, (ptr == Constant ? const_oop() : NULL),
-                       _ary, _klass, _klass_is_exact, offset, instance_id );
+          return make(ptr, (ptr == Constant ? const_oop() : NULL),
+                      _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
         }
       }
       // The other case cannot happen, since t cannot be a subtype of an array.
@@ -3733,7 +3918,7 @@
       if( ptr == Constant )
          ptr = NotNull;
       instance_id = InstanceBot;
-      return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id);
+      return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative);
     default: typerr(t);
     }
   }
@@ -3744,7 +3929,7 @@
 //------------------------------xdual------------------------------------------
 // Dual: compute field-by-field dual
 const Type *TypeAryPtr::xdual() const {
-  return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache() );
+  return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative());
 }
 
 //----------------------interface_vs_oop---------------------------------------
@@ -3796,6 +3981,8 @@
     st->print(",iid=top");
   else if (_instance_id != InstanceBot)
     st->print(",iid=%d",_instance_id);
+
+  dump_speculative(st);
 }
 #endif
 
@@ -3805,10 +3992,13 @@
 }
 
 //------------------------------add_offset-------------------------------------
-const TypePtr *TypeAryPtr::add_offset( intptr_t offset ) const {
-  return make( _ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id );
-}
-
+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);
+}
 
 //=============================================================================
 
--- a/hotspot/src/share/vm/opto/type.hpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/opto/type.hpp	Wed Oct 23 12:40:23 2013 +0200
@@ -159,6 +159,11 @@
   // Table for efficient dualing of base types
   static const TYPES dual_type[lastype];
 
+#ifdef ASSERT
+  // One type is interface, the other is oop
+  virtual bool interface_vs_oop_helper(const Type *t) const;
+#endif
+
 protected:
   // Each class of type is also identified by its base.
   const TYPES _base;            // Enum of Types type
@@ -376,6 +381,9 @@
                                         bool require_constant = false,
                                         bool is_autobox_cache = false);
 
+  // Speculative type. See TypeInstPtr
+  virtual ciKlass* speculative_type() const { return NULL; }
+
 private:
   // support arrays
   static const BasicType _basic_type[];
@@ -784,7 +792,7 @@
 // Some kind of oop (Java pointer), either klass or instance or array.
 class TypeOopPtr : public TypePtr {
 protected:
-  TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id );
+  TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative);
 public:
   virtual bool eq( const Type *t ) const;
   virtual int  hash() const;             // Type specific hashing
@@ -810,11 +818,27 @@
   // This is the the node index of the allocation node creating this instance.
   int           _instance_id;
 
+  // Extra type information profiling gave us. We propagate it the
+  // same way the rest of the type info is propagated. If we want to
+  // use it, then we have to emit a guard: this part of the type is
+  // not something we know but something we speculate about the type.
+  const TypeOopPtr*   _speculative;
+
   static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact);
 
   int dual_instance_id() const;
   int meet_instance_id(int uid) const;
 
+  // utility methods to work on the speculative part of the type
+  const TypeOopPtr* dual_speculative() const;
+  const TypeOopPtr* meet_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;
+#ifndef PRODUCT
+  void dump_speculative(outputStream *st) const;
+#endif
+
 public:
   // Creates a type given a klass. Correctly handles multi-dimensional arrays
   // Respects UseUniqueSubclasses.
@@ -841,7 +865,7 @@
                                               bool not_null_elements = false);
 
   // Make a generic (unclassed) pointer to an oop.
-  static const TypeOopPtr* make(PTR ptr, int offset, int instance_id);
+  static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative);
 
   ciObject* const_oop()    const { return _const_oop; }
   virtual ciKlass* klass() const { return _klass;     }
@@ -855,6 +879,7 @@
   bool is_known_instance()       const { return _instance_id > 0; }
   int  instance_id()             const { return _instance_id; }
   bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; }
+  const TypeOopPtr* speculative() const { return _speculative; }
 
   virtual intptr_t get_con() const;
 
@@ -868,9 +893,13 @@
   const TypeKlassPtr* as_klass_type() const;
 
   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 *xmeet( const Type *t ) 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;
@@ -880,13 +909,24 @@
 #ifndef PRODUCT
   virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
 #endif
+
+  // Return the speculative type if any
+  ciKlass* speculative_type() const {
+    if (_speculative != NULL) {
+      const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr();
+      if (speculative->klass_is_exact()) {
+       return speculative->klass();
+      }
+    }
+    return NULL;
+  }
 };
 
 //------------------------------TypeInstPtr------------------------------------
 // Class of Java object pointers, pointing either to non-array Java instances
 // or to a Klass* (including array klasses).
 class TypeInstPtr : public TypeOopPtr {
-  TypeInstPtr( PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id );
+  TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative);
   virtual bool eq( const Type *t ) const;
   virtual int  hash() const;             // Type specific hashing
 
@@ -899,30 +939,30 @@
 
   // Make a pointer to a constant oop.
   static const TypeInstPtr *make(ciObject* o) {
-    return make(TypePtr::Constant, o->klass(), true, o, 0);
+    return make(TypePtr::Constant, o->klass(), true, o, 0, InstanceBot);
   }
   // Make a pointer to a constant oop with offset.
   static const TypeInstPtr *make(ciObject* o, int offset) {
-    return make(TypePtr::Constant, o->klass(), true, o, offset);
+    return make(TypePtr::Constant, o->klass(), true, o, offset, InstanceBot);
   }
 
   // Make a pointer to some value of type klass.
   static const TypeInstPtr *make(PTR ptr, ciKlass* klass) {
-    return make(ptr, klass, false, NULL, 0);
+    return make(ptr, klass, false, NULL, 0, InstanceBot);
   }
 
   // Make a pointer to some non-polymorphic value of exactly type klass.
   static const TypeInstPtr *make_exact(PTR ptr, ciKlass* klass) {
-    return make(ptr, klass, true, NULL, 0);
+    return make(ptr, klass, true, NULL, 0, InstanceBot);
   }
 
   // Make a pointer to some value of type klass with offset.
   static const TypeInstPtr *make(PTR ptr, ciKlass* klass, int offset) {
-    return make(ptr, klass, false, NULL, offset);
+    return make(ptr, klass, false, NULL, offset, InstanceBot);
   }
 
   // Make a pointer to an oop.
-  static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot );
+  static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL);
 
   /** Create constant type for a constant boxed value */
   const Type* get_const_boxed_value() const;
@@ -939,8 +979,11 @@
   virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
 
   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 *xmeet( const Type *t ) const;
+  // the core of the computation of the meet of 2 types
+  virtual const Type *xmeet_helper(const Type *t) const;
   virtual const TypeInstPtr *xmeet_unloaded( const TypeInstPtr *t ) const;
   virtual const Type *xdual() const;    // Compute dual right now.
 
@@ -959,8 +1002,8 @@
 // Class of Java array pointers
 class TypeAryPtr : public TypeOopPtr {
   TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk,
-              int offset, int instance_id, bool is_autobox_cache )
-  : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id),
+              int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative)
+    : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative),
     _ary(ary),
     _is_autobox_cache(is_autobox_cache)
  {
@@ -998,9 +1041,9 @@
 
   bool is_autobox_cache() const { return _is_autobox_cache; }
 
-  static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot);
+  static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL);
   // Constant pointer to array
-  static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, bool is_autobox_cache = false);
+  static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, bool is_autobox_cache = false);
 
   // Return a 'ptr' version of this type
   virtual const Type *cast_to_ptr_type(PTR ptr) const;
@@ -1014,8 +1057,11 @@
 
   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 *xmeet( const Type *t ) const;
+  // the core of the computation of the meet of 2 types
+  virtual const Type *xmeet_helper(const Type *t) const;
   virtual const Type *xdual() const;    // Compute dual right now.
 
   const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const;
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Oct 23 10:00:39 2013 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Oct 23 12:40:23 2013 +0200
@@ -3721,6 +3721,14 @@
     // incremental inlining: bump MaxNodeLimit
     FLAG_SET_DEFAULT(MaxNodeLimit, (intx)75000);
   }
+  if (!UseTypeSpeculation && FLAG_IS_DEFAULT(TypeProfileLevel)) {
+    // nothing to use the profiling, turn if off
+    FLAG_SET_DEFAULT(TypeProfileLevel, 0);
+  }
+  if (UseTypeSpeculation && FLAG_IS_DEFAULT(ReplaceInParentMaps)) {
+    // Doing the replace in parent maps helps speculation
+    FLAG_SET_DEFAULT(ReplaceInParentMaps, true);
+  }
 #endif
 
   if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/TypeSpeculation.java	Wed Oct 23 12:40:23 2013 +0200
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2013, 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 8024070
+ * @summary Test that type speculation doesn't cause incorrect execution
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=222 TypeSpeculation
+ *
+ */
+
+public class TypeSpeculation {
+
+    interface I {
+    }
+
+    static class A {
+        int m() {
+            return 1;
+        }
+    }
+
+    static class B extends A implements I {
+        int m() {
+            return 2;
+        }
+    }
+
+    static class C extends B {
+        int m() {
+            return 3;
+        }
+    }
+
+    static int test1_invokevirtual(A a) {
+        return a.m();
+    }
+
+    static int test1_1(A a) {
+        return test1_invokevirtual(a);
+    }
+
+    static boolean test1() {
+        A a = new A();
+        B b = new B();
+        C c = new C();
+
+        // pollute profile at test1_invokevirtual to make sure the
+        // compiler cannot rely on it
+        for (int i = 0; i < 5000; i++) {
+            test1_invokevirtual(a);
+            test1_invokevirtual(b);
+            test1_invokevirtual(c);
+        }
+
+        // profiling + speculation should make test1_invokevirtual
+        // inline A.m() with a guard
+        for (int i = 0; i < 20000; i++) {
+            int res = test1_1(b);
+            if (res != b.m()) {
+                System.out.println("test1 failed with class B");
+                return false;
+            }
+        }
+        // check that the guard works as expected by passing a
+        // different type
+        int res = test1_1(a);
+        if (res != a.m()) {
+            System.out.println("test1 failed with class A");
+            return false;
+        }
+        return true;
+    }
+
+    static int test2_invokevirtual(A a) {
+        return a.m();
+    }
+
+    static int test2_1(A a, boolean t) {
+        A aa;
+        if (t) {
+            aa = (B)a;
+        } else {
+            aa = a;
+        }
+        // if a of type B is passed to test2_1, the static type of aa
+        // here is no better than A but the profiled type is B so this
+        // should inline
+        return test2_invokevirtual(aa);
+    }
+
+    static boolean test2() {
+        A a = new A();
+        B b = new B();
+        C c = new C();
+
+        // pollute profile at test2_invokevirtual to make sure the
+        // compiler cannot rely on it
+        for (int i = 0; i < 5000; i++) {
+            test2_invokevirtual(a);
+            test2_invokevirtual(b);
+            test2_invokevirtual(c);
+        }
+
+        // profiling + speculation should make test2_invokevirtual
+        // inline A.m() with a guard
+        for (int i = 0; i < 20000; i++) {
+            int res = test2_1(b, (i % 2) == 0);
+            if (res != b.m()) {
+                System.out.println("test2 failed with class B");
+                return false;
+            }
+        }
+        // check that the guard works as expected by passing a
+        // different type
+        int res = test2_1(a, false);
+        if (res != a.m()) {
+            System.out.println("test2 failed with class A");
+            return false;
+        }
+        return true;
+    }
+
+    static int test3_invokevirtual(A a) {
+        return a.m();
+    }
+
+    static void test3_2(A a) {
+    }
+
+    static int test3_1(A a, int i) {
+        if (i == 0) {
+            return 0;
+        }
+        // If we come here and a is of type B but parameter profiling
+        // is polluted, both branches of the if below should have
+        // profiling that tell us and inlining of the virtual call
+        // should happen
+        if (i == 1) {
+            test3_2(a);
+        } else {
+            test3_2(a);
+        }
+        return test3_invokevirtual(a);
+    }
+
+    static boolean test3() {
+        A a = new A();
+        B b = new B();
+        C c = new C();
+
+        // pollute profile at test3_invokevirtual and test3_1 to make
+        // sure the compiler cannot rely on it
+        for (int i = 0; i < 3000; i++) {
+            test3_invokevirtual(a);
+            test3_invokevirtual(b);
+            test3_invokevirtual(c);
+            test3_1(a, 0);
+            test3_1(b, 0);
+        }
+
+        // profiling + speculation should make test3_invokevirtual
+        // inline A.m() with a guard
+        for (int i = 0; i < 20000; i++) {
+            int res = test3_1(b, (i % 2) + 1);
+            if (res != b.m()) {
+                System.out.println("test3 failed with class B");
+                return false;
+            }
+        }
+        // check that the guard works as expected by passing a
+        // different type
+        int res = test3_1(a, 1);
+        if (res != a.m()) {
+            System.out.println("test3 failed with class A");
+            return false;
+        }
+        return true;
+    }
+
+    // Mix 2 incompatible profiled types
+    static int test4_invokevirtual(A a) {
+        return a.m();
+    }
+
+    static void test4_2(A a) {
+    }
+
+    static int test4_1(A a, boolean b) {
+        if (b) {
+            test4_2(a);
+        } else {
+            test4_2(a);
+        }
+        // shouldn't inline
+        return test4_invokevirtual(a);
+    }
+
+    static boolean test4() {
+        A a = new A();
+        B b = new B();
+        C c = new C();
+
+        // pollute profile at test3_invokevirtual and test3_1 to make
+        // sure the compiler cannot rely on it
+        for (int i = 0; i < 3000; i++) {
+            test4_invokevirtual(a);
+            test4_invokevirtual(b);
+            test4_invokevirtual(c);
+        }
+
+        for (int i = 0; i < 20000; i++) {
+            if ((i % 2) == 0) {
+                int res = test4_1(a, true);
+                if (res != a.m()) {
+                    System.out.println("test4 failed with class A");
+                    return false;
+                }
+            } else {
+                int res = test4_1(b, false);
+                if (res != b.m()) {
+                    System.out.println("test4 failed with class B");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // Mix one profiled type with an incompatible type
+    static int test5_invokevirtual(A a) {
+        return a.m();
+    }
+
+    static void test5_2(A a) {
+    }
+
+    static int test5_1(A a, boolean b) {
+        if (b) {
+            test5_2(a);
+        } else {
+            A aa = (B)a;
+        }
+        // shouldn't inline
+        return test5_invokevirtual(a);
+    }
+
+    static boolean test5() {
+        A a = new A();
+        B b = new B();
+        C c = new C();
+
+        // pollute profile at test3_invokevirtual and test3_1 to make
+        // sure the compiler cannot rely on it
+        for (int i = 0; i < 3000; i++) {
+            test5_invokevirtual(a);
+            test5_invokevirtual(b);
+            test5_invokevirtual(c);
+        }
+
+        for (int i = 0; i < 20000; i++) {
+            if ((i % 2) == 0) {
+                int res = test5_1(a, true);
+                if (res != a.m()) {
+                    System.out.println("test5 failed with class A");
+                    return false;
+                }
+            } else {
+                int res = test5_1(b, false);
+                if (res != b.m()) {
+                    System.out.println("test5 failed with class B");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    // Mix incompatible profiled types
+    static void test6_2(Object o) {
+    }
+
+    static Object test6_1(Object o, boolean b) {
+        if (b) {
+            test6_2(o);
+        } else {
+            test6_2(o);
+        }
+        return o;
+    }
+
+    static boolean test6() {
+        A a = new A();
+        A[] aa = new A[10];
+
+        for (int i = 0; i < 20000; i++) {
+            if ((i % 2) == 0) {
+                test6_1(a, true);
+            } else {
+                test6_1(aa, false);
+            }
+        }
+        return true;
+    }
+
+    // Mix a profiled type with an incompatible type
+    static void test7_2(Object o) {
+    }
+
+    static Object test7_1(Object o, boolean b) {
+        if (b) {
+            test7_2(o);
+        } else {
+            Object oo = (A[])o;
+        }
+        return o;
+    }
+
+    static boolean test7() {
+        A a = new A();
+        A[] aa = new A[10];
+
+        for (int i = 0; i < 20000; i++) {
+            if ((i % 2) == 0) {
+                test7_1(a, true);
+            } else {
+                test7_1(aa, false);
+            }
+        }
+        return true;
+    }
+
+    // Mix a profiled type with an interface
+    static void test8_2(Object o) {
+    }
+
+    static I test8_1(Object o) {
+        test8_2(o);
+        return (I)o;
+    }
+
+    static boolean test8() {
+        A a = new A();
+        B b = new B();
+        C c = new C();
+
+        for (int i = 0; i < 20000; i++) {
+            test8_1(b);
+        }
+        return true;
+    }
+
+    // Mix a profiled type with a constant
+    static void test9_2(Object o) {
+    }
+
+    static Object test9_1(Object o, boolean b) {
+        Object oo;
+        if (b) {
+            test9_2(o);
+            oo = o;
+        } else {
+            oo = "some string";
+        }
+        return oo;
+    }
+
+    static boolean test9() {
+        A a = new A();
+
+        for (int i = 0; i < 20000; i++) {
+            if ((i % 2) == 0) {
+                test9_1(a, true);
+            } else {
+                test9_1(a, false);
+            }
+        }
+        return true;
+    }
+
+    static public void main(String[] args) {
+        boolean success = true;
+
+        success = test1() && success;
+
+        success = test2() && success;
+
+        success = test3() && success;
+
+        success = test4() && success;
+
+        success = test5() && success;
+
+        success = test6() && success;
+
+        success = test7() && success;
+
+        success = test8() && success;
+
+        success = test9() && success;
+
+        if (success) {
+            System.out.println("TEST PASSED");
+        } else {
+            throw new RuntimeException("TEST FAILED: erroneous bound check elimination");
+        }
+    }
+}