Merge
authoriveresov
Thu, 24 Oct 2013 16:14:28 -0700
changeset 21110 a2f5a6b65746
parent 21064 a5b00e232ca8 (current diff)
parent 21109 43d5f32a3421 (diff)
child 21111 c44e0cc2287b
Merge
hotspot/test/compiler/intrinsics/mathexact/CondTest.java
hotspot/test/compiler/intrinsics/mathexact/ConstantTest.java
hotspot/test/compiler/intrinsics/mathexact/LoadTest.java
hotspot/test/compiler/intrinsics/mathexact/LoopDependentTest.java
hotspot/test/compiler/intrinsics/mathexact/NonConstantTest.java
hotspot/test/compiler/intrinsics/mathexact/RepeatTest.java
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -53,6 +53,8 @@
       opr = as_long_opr(reg);
     } else if (type == T_OBJECT || type == T_ARRAY) {
       opr = as_oop_opr(reg);
+    } else if (type == T_METADATA) {
+      opr = as_metadata_opr(reg);
     } else {
       opr = as_opr(reg);
     }
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -2565,7 +2565,7 @@
     Address receiver_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) -
                           mdo_offset_bias);
     __ ld_ptr(receiver_addr, tmp1);
-    __ verify_oop(tmp1);
+    __ verify_klass_ptr(tmp1);
     __ cmp_and_brx_short(recv, tmp1, Assembler::notEqual, Assembler::pt, next_test);
     Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)) -
                       mdo_offset_bias);
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -404,7 +404,9 @@
           if (id == fast_new_instance_init_check_id) {
             // make sure the klass is initialized
             __ ldub(G5_klass, in_bytes(InstanceKlass::init_state_offset()), G3_t1);
-            __ cmp_and_br_short(G3_t1, InstanceKlass::fully_initialized, Assembler::notEqual, Assembler::pn, slow_path);
+            __ cmp(G3_t1, InstanceKlass::fully_initialized);
+            __ br(Assembler::notEqual, false, Assembler::pn, slow_path);
+            __ delayed()->nop();
           }
 #ifdef ASSERT
           // assert object can be fast path allocated
@@ -515,7 +517,9 @@
 
           // check that array length is small enough for fast path
           __ set(C1_MacroAssembler::max_array_allocation_length, G3_t1);
-          __ cmp_and_br_short(G4_length, G3_t1, Assembler::greaterUnsigned, Assembler::pn, slow_path);
+          __ cmp(G4_length, G3_t1);
+          __ br(Assembler::greaterUnsigned, false, Assembler::pn, slow_path);
+          __ delayed()->nop();
 
           // if we got here then the TLAB allocation failed, so try
           // refilling the TLAB or allocating directly from eden.
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -3333,7 +3333,8 @@
 
   if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) {
     // No allocation in the shared eden.
-    ba_short(slow_case);
+    ba(slow_case);
+    delayed()->nop();
   }
 
   ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), top);
@@ -3358,7 +3359,8 @@
     add(t2, 1, t2);
     stw(t2, G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset()));
   }
-  ba_short(try_eden);
+  ba(try_eden);
+  delayed()->nop();
 
   bind(discard_tlab);
   if (TLABStats) {
@@ -3420,7 +3422,8 @@
   sub(top, ThreadLocalAllocBuffer::alignment_reserve_in_bytes(), top);
   st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_end_offset()));
   verify_tlab();
-  ba_short(retry);
+  ba(retry);
+  delayed()->nop();
 }
 
 void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes,
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Thu Oct 24 16:14:28 2013 -0700
@@ -2022,6 +2022,10 @@
   return G1_REGI_mask();
 }
 
+const RegMask Matcher::mathExactL_result_proj_mask() {
+  return G1_REGL_mask();
+}
+
 const RegMask Matcher::mathExactI_flags_proj_mask() {
   return INT_FLAGS_mask();
 }
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1405,6 +1405,15 @@
   }
 }
 
+void Assembler::imull(Register dst, Address src) {
+  InstructionMark im(this);
+  prefix(src, dst);
+  emit_int8(0x0F);
+  emit_int8((unsigned char) 0xAF);
+  emit_operand(dst, src);
+}
+
+
 void Assembler::incl(Address dst) {
   // Don't use it directly. Use MacroAssembler::increment() instead.
   InstructionMark im(this);
@@ -5024,6 +5033,14 @@
   }
 }
 
+void Assembler::imulq(Register dst, Address src) {
+  InstructionMark im(this);
+  prefixq(src, dst);
+  emit_int8(0x0F);
+  emit_int8((unsigned char) 0xAF);
+  emit_operand(dst, src);
+}
+
 void Assembler::incl(Register dst) {
   // Don't use it directly. Use MacroAssembler::incrementl() instead.
   // Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1162,9 +1162,13 @@
 
   void imull(Register dst, Register src);
   void imull(Register dst, Register src, int value);
+  void imull(Register dst, Address src);
 
   void imulq(Register dst, Register src);
   void imulq(Register dst, Register src, int value);
+#ifdef _LP64
+  void imulq(Register dst, Address src);
+#endif
 
 
   // jcc is the generic conditional branch generator to run-
--- a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -40,11 +40,8 @@
 #include "runtime/synchronizer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
 #endif
 
 #ifdef CC_INTERP
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -52,6 +52,8 @@
 #endif // _LP64
     } else if (type == T_OBJECT || type == T_ARRAY) {
       opr = as_oop_opr(reg);
+    } else if (type == T_METADATA) {
+      opr = as_metadata_opr(reg);
     } else {
       opr = as_opr(reg);
     }
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -432,15 +432,16 @@
   int offset = code_offset();
 
   // Fetch the exception from TLS and clear out exception related thread state
-  __ get_thread(rsi);
-  __ movptr(rax, Address(rsi, JavaThread::exception_oop_offset()));
-  __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
-  __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
+  Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread);
+  NOT_LP64(__ get_thread(rsi));
+  __ movptr(rax, Address(thread, JavaThread::exception_oop_offset()));
+  __ movptr(Address(thread, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
+  __ movptr(Address(thread, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
 
   __ bind(_unwind_handler_entry);
   __ verify_not_null_oop(rax);
   if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
-    __ mov(rsi, rax);  // Preserve the exception
+    __ mov(rbx, rax);  // Preserve the exception (rbx is always callee-saved)
   }
 
   // Preform needed unlocking
@@ -448,19 +449,24 @@
   if (method()->is_synchronized()) {
     monitor_address(0, FrameMap::rax_opr);
     stub = new MonitorExitStub(FrameMap::rax_opr, true, 0);
-    __ unlock_object(rdi, rbx, rax, *stub->entry());
+    __ unlock_object(rdi, rsi, rax, *stub->entry());
     __ bind(*stub->continuation());
   }
 
   if (compilation()->env()->dtrace_method_probes()) {
+#ifdef _LP64
+    __ mov(rdi, r15_thread);
+    __ mov_metadata(rsi, method()->constant_encoding());
+#else
     __ get_thread(rax);
     __ movptr(Address(rsp, 0), rax);
     __ mov_metadata(Address(rsp, sizeof(void*)), method()->constant_encoding());
+#endif
     __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit)));
   }
 
   if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
-    __ mov(rax, rsi);  // Restore the exception
+    __ mov(rax, rbx);  // Restore the exception
   }
 
   // remove the activation and dispatch to the unwind handler
@@ -1206,6 +1212,10 @@
   LIR_Address* addr = src->as_address_ptr();
   Address from_addr = as_Address(addr);
 
+  if (addr->base()->type() == T_OBJECT) {
+    __ verify_oop(addr->base()->as_pointer_register());
+  }
+
   switch (type) {
     case T_BOOLEAN: // fall through
     case T_BYTE:    // fall through
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -79,7 +79,7 @@
 // GC Ergo Flags
 define_pd_global(uintx, CMSYoungGenPerWorker, 64*M);  // default max size of CMS young gen, per GC worker thread
 
-define_pd_global(uintx, TypeProfileLevel, 11);
+define_pd_global(uintx, TypeProfileLevel, 111);
 
 #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
                                                                             \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1997, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "interp_masm_x86.hpp"
+#include "interpreter/interpreter.hpp"
+#include "oops/methodData.hpp"
+
+#ifndef CC_INTERP
+void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
+  Label update, next, none;
+
+  verify_oop(obj);
+
+  testptr(obj, obj);
+  jccb(Assembler::notZero, update);
+  orptr(mdo_addr, TypeEntries::null_seen);
+  jmpb(next);
+
+  bind(update);
+  load_klass(obj, obj);
+
+  xorptr(obj, mdo_addr);
+  testptr(obj, TypeEntries::type_klass_mask);
+  jccb(Assembler::zero, next); // klass seen before, nothing to
+                               // do. The unknown bit may have been
+                               // set already but no need to check.
+
+  testptr(obj, TypeEntries::type_unknown);
+  jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
+
+  cmpptr(mdo_addr, 0);
+  jccb(Assembler::equal, none);
+  cmpptr(mdo_addr, TypeEntries::null_seen);
+  jccb(Assembler::equal, none);
+  // There is a chance that the checks above (re-reading profiling
+  // data from memory) fail if another thread has just set the
+  // profiling to this obj's klass
+  xorptr(obj, mdo_addr);
+  testptr(obj, TypeEntries::type_klass_mask);
+  jccb(Assembler::zero, next);
+
+  // different than before. Cannot keep accurate profile.
+  orptr(mdo_addr, TypeEntries::type_unknown);
+  jmpb(next);
+
+  bind(none);
+  // first time here. Set profile type.
+  movptr(mdo_addr, obj);
+
+  bind(next);
+}
+
+void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
+  if (!ProfileInterpreter) {
+    return;
+  }
+
+  if (MethodData::profile_arguments() || MethodData::profile_return()) {
+    Label profile_continue;
+
+    test_method_data_pointer(mdp, profile_continue);
+
+    int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
+
+    cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
+    jcc(Assembler::notEqual, profile_continue);
+
+    if (MethodData::profile_arguments()) {
+      Label done;
+      int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
+      addptr(mdp, off_to_args);
+
+      for (int i = 0; i < TypeProfileArgsLimit; i++) {
+        if (i > 0 || MethodData::profile_return()) {
+          // If return value type is profiled we may have no argument to profile
+          movptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
+          subl(tmp, i*TypeStackSlotEntries::per_arg_count());
+          cmpl(tmp, TypeStackSlotEntries::per_arg_count());
+          jcc(Assembler::less, done);
+        }
+        movptr(tmp, Address(callee, Method::const_offset()));
+        load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
+        // stack offset o (zero based) from the start of the argument
+        // list, for n arguments translates into offset n - o - 1 from
+        // the end of the argument list
+        subptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
+        subl(tmp, 1);
+        Address arg_addr = argument_address(tmp);
+        movptr(tmp, arg_addr);
+
+        Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
+        profile_obj_type(tmp, mdo_arg_addr);
+
+        int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
+        addptr(mdp, to_add);
+        off_to_args += to_add;
+      }
+
+      if (MethodData::profile_return()) {
+        movptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
+        subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
+      }
+
+      bind(done);
+
+      if (MethodData::profile_return()) {
+        // We're right after the type profile for the last
+        // argument. tmp is the number of cell left in the
+        // CallTypeData/VirtualCallTypeData to reach its end. Non null
+        // if there's a return to profile.
+        assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
+        shll(tmp, exact_log2(DataLayout::cell_size));
+        addptr(mdp, tmp);
+      }
+      movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
+    } else {
+      assert(MethodData::profile_return(), "either profile call args or call ret");
+      update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
+    }
+
+    // mdp points right after the end of the
+    // CallTypeData/VirtualCallTypeData, right after the cells for the
+    // return value type if there's one
+
+    bind(profile_continue);
+  }
+}
+
+void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
+  assert_different_registers(mdp, ret, tmp, _bcp_register);
+  if (ProfileInterpreter && MethodData::profile_return()) {
+    Label profile_continue, done;
+
+    test_method_data_pointer(mdp, profile_continue);
+
+    if (MethodData::profile_return_jsr292_only()) {
+      // If we don't profile all invoke bytecodes we must make sure
+      // it's a bytecode we indeed profile. We can't go back to the
+      // begining of the ProfileData we intend to update to check its
+      // type because we're right after it and we don't known its
+      // length
+      Label do_profile;
+      cmpb(Address(_bcp_register, 0), Bytecodes::_invokedynamic);
+      jcc(Assembler::equal, do_profile);
+      cmpb(Address(_bcp_register, 0), Bytecodes::_invokehandle);
+      jcc(Assembler::equal, do_profile);
+      get_method(tmp);
+      cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
+      jcc(Assembler::notEqual, profile_continue);
+
+      bind(do_profile);
+    }
+
+    Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
+    mov(tmp, ret);
+    profile_obj_type(tmp, mdo_ret_addr);
+
+    bind(profile_continue);
+  }
+}
+
+void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register tmp1, Register tmp2) {
+  if (ProfileInterpreter && MethodData::profile_parameters()) {
+    Label profile_continue, done;
+
+    test_method_data_pointer(mdp, profile_continue);
+
+    // Load the offset of the area within the MDO used for
+    // parameters. If it's negative we're not profiling any parameters
+    movl(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset())));
+    testl(tmp1, tmp1);
+    jcc(Assembler::negative, profile_continue);
+
+    // Compute a pointer to the area for parameters from the offset
+    // and move the pointer to the slot for the last
+    // parameters. Collect profiling from last parameter down.
+    // mdo start + parameters offset + array length - 1
+    addptr(mdp, tmp1);
+    movptr(tmp1, Address(mdp, in_bytes(ArrayData::array_len_offset())));
+    decrement(tmp1, TypeStackSlotEntries::per_arg_count());
+
+    Label loop;
+    bind(loop);
+
+    int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0));
+    int type_base = in_bytes(ParametersTypeData::type_offset(0));
+    Address::ScaleFactor per_arg_scale = Address::times(DataLayout::cell_size);
+    Address arg_off(mdp, tmp1, per_arg_scale, off_base);
+    Address arg_type(mdp, tmp1, per_arg_scale, type_base);
+
+    // load offset on the stack from the slot for this parameter
+    movptr(tmp2, arg_off);
+    negptr(tmp2);
+    // read the parameter from the local area
+    movptr(tmp2, Address(_locals_register, tmp2, Interpreter::stackElementScale()));
+
+    // profile the parameter
+    profile_obj_type(tmp2, arg_type);
+
+    // go to next parameter
+    decrement(tmp1, TypeStackSlotEntries::per_arg_count());
+    jcc(Assembler::positive, loop);
+
+    bind(profile_continue);
+  }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef CPU_X86_VM_INTERP_MASM_X86_HPP
+#define CPU_X86_VM_INTERP_MASM_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "interpreter/invocationCounter.hpp"
+#include "runtime/frame.hpp"
+
+// This file specializes the assember with interpreter-specific macros
+
+
+class InterpreterMacroAssembler: public MacroAssembler {
+
+#ifdef TARGET_ARCH_MODEL_x86_32
+# include "interp_masm_x86_32.hpp"
+#endif
+#ifdef TARGET_ARCH_MODEL_x86_64
+# include "interp_masm_x86_64.hpp"
+#endif
+
+ private:
+
+  Register _locals_register; // register that contains the pointer to the locals
+  Register _bcp_register; // register that contains the bcp
+
+ public:
+#ifndef CC_INTERP
+  void profile_obj_type(Register obj, const Address& mdo_addr);
+  void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual);
+  void profile_return_type(Register mdp, Register ret, Register tmp);
+  void profile_parameters_type(Register mdp, Register tmp1, Register tmp2);
+#endif /* !CC_INTERP */
+
+};
+
+#endif // CPU_X86_VM_INTERP_MASM_X86_HPP
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "interp_masm_x86_32.hpp"
+#include "interp_masm_x86.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "oops/arrayOop.hpp"
@@ -1046,159 +1046,6 @@
   }
 }
 
-void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
-  Label update, next, none;
-
-  verify_oop(obj);
-
-  testptr(obj, obj);
-  jccb(Assembler::notZero, update);
-  orptr(mdo_addr, TypeEntries::null_seen);
-  jmpb(next);
-
-  bind(update);
-  load_klass(obj, obj);
-
-  xorptr(obj, mdo_addr);
-  testptr(obj, TypeEntries::type_klass_mask);
-  jccb(Assembler::zero, next); // klass seen before, nothing to
-                               // do. The unknown bit may have been
-                               // set already but no need to check.
-
-  testptr(obj, TypeEntries::type_unknown);
-  jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
-
-  cmpptr(mdo_addr, 0);
-  jccb(Assembler::equal, none);
-  cmpptr(mdo_addr, TypeEntries::null_seen);
-  jccb(Assembler::equal, none);
-  // There is a chance that the checks above (re-reading profiling
-  // data from memory) fail if another thread has just set the
-  // profiling to this obj's klass
-  xorptr(obj, mdo_addr);
-  testptr(obj, TypeEntries::type_klass_mask);
-  jccb(Assembler::zero, next);
-
-  // different than before. Cannot keep accurate profile.
-  orptr(mdo_addr, TypeEntries::type_unknown);
-  jmpb(next);
-
-  bind(none);
-  // first time here. Set profile type.
-  movptr(mdo_addr, obj);
-
-  bind(next);
-}
-
-void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
-  if (!ProfileInterpreter) {
-    return;
-  }
-
-  if (MethodData::profile_arguments() || MethodData::profile_return()) {
-    Label profile_continue;
-
-    test_method_data_pointer(mdp, profile_continue);
-
-    int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
-
-    cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
-    jcc(Assembler::notEqual, profile_continue);
-
-    if (MethodData::profile_arguments()) {
-      Label done;
-      int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
-      addptr(mdp, off_to_args);
-
-      for (int i = 0; i < TypeProfileArgsLimit; i++) {
-        if (i > 0 || MethodData::profile_return()) {
-          // If return value type is profiled we may have no argument to profile
-          movl(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
-          subl(tmp, i*TypeStackSlotEntries::per_arg_count());
-          cmpl(tmp, TypeStackSlotEntries::per_arg_count());
-          jcc(Assembler::less, done);
-        }
-        movptr(tmp, Address(callee, Method::const_offset()));
-        load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
-        // stack offset o (zero based) from the start of the argument
-        // list, for n arguments translates into offset n - o - 1 from
-        // the end of the argument list
-        subl(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
-        subl(tmp, 1);
-        Address arg_addr = argument_address(tmp);
-        movptr(tmp, arg_addr);
-
-        Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
-        profile_obj_type(tmp, mdo_arg_addr);
-
-        int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
-        addptr(mdp, to_add);
-        off_to_args += to_add;
-      }
-
-      if (MethodData::profile_return()) {
-        movl(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
-        subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
-      }
-
-      bind(done);
-
-      if (MethodData::profile_return()) {
-        // We're right after the type profile for the last
-        // argument. tmp is the number of cell left in the
-        // CallTypeData/VirtualCallTypeData to reach its end. Non null
-        // if there's a return to profile.
-        assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
-        shll(tmp, exact_log2(DataLayout::cell_size));
-        addptr(mdp, tmp);
-      }
-      movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
-    } else {
-      assert(MethodData::profile_return(), "either profile call args or call ret");
-      update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
-    }
-
-    // mdp points right after the end of the
-    // CallTypeData/VirtualCallTypeData, right after the cells for the
-    // return value type if there's one
-
-    bind(profile_continue);
-  }
-}
-
-void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
-  assert_different_registers(mdp, ret, tmp, rsi);
-  if (ProfileInterpreter && MethodData::profile_return()) {
-    Label profile_continue, done;
-
-    test_method_data_pointer(mdp, profile_continue);
-
-    if (MethodData::profile_return_jsr292_only()) {
-      // If we don't profile all invoke bytecodes we must make sure
-      // it's a bytecode we indeed profile. We can't go back to the
-      // begining of the ProfileData we intend to update to check its
-      // type because we're right after it and we don't known its
-      // length
-      Label do_profile;
-      cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
-      jcc(Assembler::equal, do_profile);
-      cmpb(Address(rsi, 0), Bytecodes::_invokehandle);
-      jcc(Assembler::equal, do_profile);
-      get_method(tmp);
-      cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
-      jcc(Assembler::notEqual, profile_continue);
-
-      bind(do_profile);
-    }
-
-    Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
-    mov(tmp, ret);
-    profile_obj_type(tmp, mdo_ret_addr);
-
-    bind(profile_continue);
-  }
-}
-
 void InterpreterMacroAssembler::profile_call(Register mdp) {
   if (ProfileInterpreter) {
     Label profile_continue;
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -22,18 +22,6 @@
  *
  */
 
-#ifndef CPU_X86_VM_INTERP_MASM_X86_32_HPP
-#define CPU_X86_VM_INTERP_MASM_X86_32_HPP
-
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "interpreter/invocationCounter.hpp"
-#include "runtime/frame.hpp"
-
-// This file specializes the assember with interpreter-specific macros
-
-
-class InterpreterMacroAssembler: public MacroAssembler {
 #ifndef CC_INTERP
  protected:
   // Interpreter specific version of call_VM_base
@@ -59,7 +47,7 @@
 #endif /* CC_INTERP */
 
  public:
-  InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {}
+  InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(rdi), _bcp_register(rsi) {}
 
   void load_earlyret_value(TosState state);
 
@@ -215,9 +203,6 @@
 
   void profile_taken_branch(Register mdp, Register bumped_count);
   void profile_not_taken_branch(Register mdp);
-  void profile_obj_type(Register obj, const Address& mdo_addr);
-  void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual);
-  void profile_return_type(Register mdp, Register ret, Register tmp);
   void profile_call(Register mdp);
   void profile_final_call(Register mdp);
   void profile_virtual_call(Register receiver, Register mdp, Register scratch2,
@@ -236,7 +221,3 @@
   // support for jvmti
   void notify_method_entry();
   void notify_method_exit(TosState state, NotifyMethodExitMode mode);
-
-};
-
-#endif // CPU_X86_VM_INTERP_MASM_X86_32_HPP
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "interp_masm_x86_64.hpp"
+#include "interp_masm_x86.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "oops/arrayOop.hpp"
@@ -1067,160 +1067,6 @@
   }
 }
 
-void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
-  Label update, next, none;
-
-  verify_oop(obj);
-
-  testptr(obj, obj);
-  jccb(Assembler::notZero, update);
-  orptr(mdo_addr, TypeEntries::null_seen);
-  jmpb(next);
-
-  bind(update);
-  load_klass(obj, obj);
-
-  xorptr(obj, mdo_addr);
-  testptr(obj, TypeEntries::type_klass_mask);
-  jccb(Assembler::zero, next); // klass seen before, nothing to
-                               // do. The unknown bit may have been
-                               // set already but no need to check.
-
-  testptr(obj, TypeEntries::type_unknown);
-  jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
-
-  // There is a chance that by the time we do these checks (re-reading
-  // profiling data from memory) another thread has set the profling
-  // to this obj's klass and we set the profiling as unknow
-  // erroneously
-  cmpptr(mdo_addr, 0);
-  jccb(Assembler::equal, none);
-  cmpptr(mdo_addr, TypeEntries::null_seen);
-  jccb(Assembler::equal, none);
-  // There is a chance that the checks above (re-reading profiling
-  // data from memory) fail if another thread has just set the
-  // profiling to this obj's klass
-  xorptr(obj, mdo_addr);
-  testptr(obj, TypeEntries::type_klass_mask);
-  jccb(Assembler::zero, next);
-
-  // different than before. Cannot keep accurate profile.
-  orptr(mdo_addr, TypeEntries::type_unknown);
-  jmpb(next);
-
-  bind(none);
-  // first time here. Set profile type.
-  movptr(mdo_addr, obj);
-
-  bind(next);
-}
-
-void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
-  if (!ProfileInterpreter) {
-    return;
-  }
-
-  if (MethodData::profile_arguments() || MethodData::profile_return()) {
-    Label profile_continue;
-
-    test_method_data_pointer(mdp, profile_continue);
-
-    int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
-
-    cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
-    jcc(Assembler::notEqual, profile_continue);
-
-    if (MethodData::profile_arguments()) {
-      Label done;
-      int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
-      addptr(mdp, off_to_args);
-
-      for (int i = 0; i < TypeProfileArgsLimit; i++) {
-        if (i > 0 || MethodData::profile_return()) {
-          // If return value type is profiled we may have no argument to profile
-          movq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
-          subl(tmp, i*TypeStackSlotEntries::per_arg_count());
-          cmpl(tmp, TypeStackSlotEntries::per_arg_count());
-          jcc(Assembler::less, done);
-        }
-        movptr(tmp, Address(callee, Method::const_offset()));
-        load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
-        subq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
-        subl(tmp, 1);
-        Address arg_addr = argument_address(tmp);
-        movptr(tmp, arg_addr);
-
-        Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
-        profile_obj_type(tmp, mdo_arg_addr);
-
-        int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
-        addptr(mdp, to_add);
-        off_to_args += to_add;
-      }
-
-      if (MethodData::profile_return()) {
-        movq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
-        subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
-      }
-
-      bind(done);
-
-      if (MethodData::profile_return()) {
-        // We're right after the type profile for the last
-        // argument. tmp is the number of cell left in the
-        // CallTypeData/VirtualCallTypeData to reach its end. Non null
-        // if there's a return to profile.
-        assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
-        shll(tmp, exact_log2(DataLayout::cell_size));
-        addptr(mdp, tmp);
-      }
-      movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
-    } else {
-      assert(MethodData::profile_return(), "either profile call args or call ret");
-      update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
-    }
-
-    // mdp points right after the end of the
-    // CallTypeData/VirtualCallTypeData, right after the cells for the
-    // return value type if there's one
-
-    bind(profile_continue);
-  }
-}
-
-void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
-  assert_different_registers(mdp, ret, tmp, r13);
-  if (ProfileInterpreter && MethodData::profile_return()) {
-    Label profile_continue, done;
-
-    test_method_data_pointer(mdp, profile_continue);
-
-    if (MethodData::profile_return_jsr292_only()) {
-      // If we don't profile all invoke bytecodes we must make sure
-      // it's a bytecode we indeed profile. We can't go back to the
-      // begining of the ProfileData we intend to update to check its
-      // type because we're right after it and we don't known its
-      // length
-      Label do_profile;
-      cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
-      jcc(Assembler::equal, do_profile);
-      cmpb(Address(r13, 0), Bytecodes::_invokehandle);
-      jcc(Assembler::equal, do_profile);
-      get_method(tmp);
-      cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
-      jcc(Assembler::notEqual, profile_continue);
-
-      bind(do_profile);
-    }
-
-    Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
-    mov(tmp, ret);
-    profile_obj_type(tmp, mdo_ret_addr);
-
-    bind(profile_continue);
-  }
-}
-
 void InterpreterMacroAssembler::profile_call(Register mdp) {
   if (ProfileInterpreter) {
     Label profile_continue;
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -22,18 +22,6 @@
  *
  */
 
-#ifndef CPU_X86_VM_INTERP_MASM_X86_64_HPP
-#define CPU_X86_VM_INTERP_MASM_X86_64_HPP
-
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "interpreter/invocationCounter.hpp"
-#include "runtime/frame.hpp"
-
-// This file specializes the assember with interpreter-specific macros
-
-
-class InterpreterMacroAssembler: public MacroAssembler {
 #ifndef CC_INTERP
  protected:
   // Interpreter specific version of call_VM_base
@@ -55,7 +43,7 @@
 #endif // CC_INTERP
 
  public:
-  InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {}
+  InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(r14), _bcp_register(r13) {}
 
   void load_earlyret_value(TosState state);
 
@@ -224,9 +212,6 @@
 
   void profile_taken_branch(Register mdp, Register bumped_count);
   void profile_not_taken_branch(Register mdp);
-  void profile_obj_type(Register obj, const Address& mdo_addr);
-  void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual);
-  void profile_return_type(Register mdp, Register ret, Register tmp);
   void profile_call(Register mdp);
   void profile_final_call(Register mdp);
   void profile_virtual_call(Register receiver, Register mdp,
@@ -253,6 +238,3 @@
   // support for jvmti/dtrace
   void notify_method_entry();
   void notify_method_exit(TosState state, NotifyMethodExitMode mode);
-};
-
-#endif // CPU_X86_VM_INTERP_MASM_X86_64_HPP
--- a/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -26,11 +26,8 @@
 #include "asm/assembler.hpp"
 #include "asm/register.hpp"
 #include "register_x86.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
 #endif
 
 REGISTER_DEFINITION(Register, noreg);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -34,9 +34,9 @@
   // Run with +PrintInterpreter to get the VM to print out the size.
   // Max size with JVMTI
 #ifdef AMD64
-  const static int InterpreterCodeSize = 208 * 1024;
+  const static int InterpreterCodeSize = 256 * 1024;
 #else
-  const static int InterpreterCodeSize = 176 * 1024;
+  const static int InterpreterCodeSize = 224 * 1024;
 #endif // AMD64
 
 #endif // CPU_X86_VM_TEMPLATEINTERPRETER_X86_HPP
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1490,6 +1490,7 @@
         in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
   __ movbool(do_not_unlock_if_synchronized, true);
 
+  __ profile_parameters_type(rax, rcx, rdx);
   // increment invocation count & check for overflow
   Label invocation_counter_overflow;
   Label profile_method;
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1497,6 +1497,7 @@
         in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
   __ movbool(do_not_unlock_if_synchronized, true);
 
+  __ profile_parameters_type(rax, rcx, rdx);
   // increment invocation count & check for overflow
   Label invocation_counter_overflow;
   Label profile_method;
--- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
 #include "code/vtableStubs.hpp"
-#include "interp_masm_x86_32.hpp"
+#include "interp_masm_x86.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/klassVtable.hpp"
--- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
 #include "code/vtableStubs.hpp"
-#include "interp_masm_x86_64.hpp"
+#include "interp_masm_x86.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/klassVtable.hpp"
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Oct 24 16:14:28 2013 -0700
@@ -1538,6 +1538,11 @@
   return EAX_REG_mask();
 }
 
+const RegMask Matcher::mathExactL_result_proj_mask() {
+  ShouldNotReachHere();
+  return RegMask();
+}
+
 const RegMask Matcher::mathExactI_flags_proj_mask() {
   return INT_FLAGS_mask();
 }
@@ -7519,7 +7524,7 @@
 //----------Arithmetic Instructions--------------------------------------------
 //----------Addition Instructions----------------------------------------------
 
-instruct addExactI_rReg(eAXRegI dst, rRegI src, eFlagsReg cr)
+instruct addExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr)
 %{
   match(AddExactI dst src);
   effect(DEF cr);
@@ -7531,7 +7536,7 @@
   ins_pipe(ialu_reg_reg);
 %}
 
-instruct addExactI_rReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
+instruct addExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
 %{
   match(AddExactI dst src);
   effect(DEF cr);
@@ -7543,6 +7548,20 @@
   ins_pipe(ialu_reg_reg);
 %}
 
+instruct addExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr)
+%{
+  match(AddExactI dst (LoadI src));
+  effect(DEF cr);
+
+  ins_cost(125);
+  format %{ "ADD    $dst,$src\t# addExact int" %}
+  ins_encode %{
+    __ addl($dst$$Register, $src$$Address);
+  %}
+  ins_pipe( ialu_reg_mem );
+%}
+
+
 // Integer Addition Instructions
 instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
   match(Set dst (AddI dst src));
@@ -7851,6 +7870,44 @@
 %}
 
 //----------Subtraction Instructions-------------------------------------------
+
+instruct subExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr)
+%{
+  match(SubExactI dst src);
+  effect(DEF cr);
+
+  format %{ "SUB    $dst, $src\t# subExact int" %}
+  ins_encode %{
+    __ subl($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
+%{
+  match(SubExactI dst src);
+  effect(DEF cr);
+
+  format %{ "SUB    $dst, $src\t# subExact int" %}
+  ins_encode %{
+    __ subl($dst$$Register, $src$$constant);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr)
+%{
+  match(SubExactI dst (LoadI src));
+  effect(DEF cr);
+
+  ins_cost(125);
+  format %{ "SUB    $dst,$src\t# subExact int" %}
+  ins_encode %{
+    __ subl($dst$$Register, $src$$Address);
+  %}
+  ins_pipe( ialu_reg_mem );
+%}
+
 // Integer Subtraction Instructions
 instruct subI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
   match(Set dst (SubI dst src));
@@ -7919,6 +7976,16 @@
   ins_pipe( ialu_reg );
 %}
 
+instruct negExactI_eReg(eAXRegI dst, eFlagsReg cr) %{
+  match(NegExactI dst);
+  effect(DEF cr);
+
+  format %{ "NEG    $dst\t# negExact int"%}
+  ins_encode %{
+    __ negl($dst$$Register);
+  %}
+  ins_pipe(ialu_reg);
+%}
 
 //----------Multiplication/Division Instructions-------------------------------
 // Integer Multiplication Instructions
@@ -8131,6 +8198,46 @@
   ins_pipe( pipe_slow );
 %}
 
+instruct mulExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr)
+%{
+  match(MulExactI dst src);
+  effect(DEF cr);
+
+  ins_cost(300);
+  format %{ "IMUL   $dst, $src\t# mulExact int" %}
+  ins_encode %{
+    __ imull($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactI_eReg_imm(eAXRegI dst, rRegI src, immI imm, eFlagsReg cr)
+%{
+  match(MulExactI src imm);
+  effect(DEF cr);
+
+  ins_cost(300);
+  format %{ "IMUL   $dst, $src, $imm\t# mulExact int" %}
+  ins_encode %{
+    __ imull($dst$$Register, $src$$Register, $imm$$constant);
+  %}
+  ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr)
+%{
+  match(MulExactI dst (LoadI src));
+  effect(DEF cr);
+
+  ins_cost(350);
+  format %{ "IMUL   $dst, $src\t# mulExact int" %}
+  ins_encode %{
+    __ imull($dst$$Register, $src$$Address);
+  %}
+  ins_pipe(ialu_reg_mem_alu0);
+%}
+
+
 // Integer DIV with Register
 instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{
   match(Set rax (DivI rax div));
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Oct 24 16:14:28 2013 -0700
@@ -1653,6 +1653,10 @@
   return INT_RAX_REG_mask();
 }
 
+const RegMask Matcher::mathExactL_result_proj_mask() {
+  return LONG_RAX_REG_mask();
+}
+
 const RegMask Matcher::mathExactI_flags_proj_mask() {
   return INT_FLAGS_mask();
 }
@@ -6962,6 +6966,58 @@
   ins_pipe(ialu_reg_reg);
 %}
 
+instruct addExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+  match(AddExactI dst (LoadI src));
+  effect(DEF cr);
+
+  ins_cost(125); // XXX
+  format %{ "addl    $dst, $src\t# addExact int" %}
+  ins_encode %{
+    __ addl($dst$$Register, $src$$Address);
+  %}
+
+  ins_pipe(ialu_reg_mem);
+%}
+
+instruct addExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr)
+%{
+  match(AddExactL dst src);
+  effect(DEF cr);
+
+  format %{ "addq    $dst, $src\t# addExact long" %}
+  ins_encode %{
+    __ addq($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct addExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr)
+%{
+  match(AddExactL dst src);
+  effect(DEF cr);
+
+  format %{ "addq    $dst, $src\t# addExact long" %}
+  ins_encode %{
+    __ addq($dst$$Register, $src$$constant);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct addExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr)
+%{
+  match(AddExactL dst (LoadL src));
+  effect(DEF cr);
+
+  ins_cost(125); // XXX
+  format %{ "addq    $dst, $src\t# addExact long" %}
+  ins_encode %{
+    __ addq($dst$$Register, $src$$Address);
+  %}
+
+  ins_pipe(ialu_reg_mem);
+%}
+
 instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
 %{
   match(Set dst (AddI dst src));
@@ -7574,6 +7630,80 @@
   ins_pipe(ialu_mem_imm);
 %}
 
+instruct subExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr)
+%{
+  match(SubExactI dst src);
+  effect(DEF cr);
+
+  format %{ "subl    $dst, $src\t# subExact int" %}
+  ins_encode %{
+    __ subl($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr)
+%{
+  match(SubExactI dst src);
+  effect(DEF cr);
+
+  format %{ "subl    $dst, $src\t# subExact int" %}
+  ins_encode %{
+    __ subl($dst$$Register, $src$$constant);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+  match(SubExactI dst (LoadI src));
+  effect(DEF cr);
+
+  ins_cost(125);
+  format %{ "subl    $dst, $src\t# subExact int" %}
+  ins_encode %{
+    __ subl($dst$$Register, $src$$Address);
+  %}
+  ins_pipe(ialu_reg_mem);
+%}
+
+instruct subExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr)
+%{
+  match(SubExactL dst src);
+  effect(DEF cr);
+
+  format %{ "subq    $dst, $src\t# subExact long" %}
+  ins_encode %{
+    __ subq($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr)
+%{
+  match(SubExactL dst (LoadL src));
+  effect(DEF cr);
+
+  format %{ "subq    $dst, $src\t# subExact long" %}
+  ins_encode %{
+    __ subq($dst$$Register, $src$$constant);
+  %}
+  ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactL_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+  match(SubExactI dst src);
+  effect(DEF cr);
+
+  ins_cost(125);
+  format %{ "subq    $dst, $src\t# subExact long" %}
+  ins_encode %{
+    __ subq($dst$$Register, $src$$Address);
+  %}
+  ins_pipe(ialu_reg_mem);
+%}
+
 instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
 %{
   match(Set dst (SubL dst src));
@@ -7690,6 +7820,30 @@
   ins_pipe(ialu_reg);
 %}
 
+instruct negExactI_rReg(rax_RegI dst, rFlagsReg cr)
+%{
+  match(NegExactI dst);
+  effect(KILL cr);
+
+  format %{ "negl    $dst\t# negExact int" %}
+  ins_encode %{
+    __ negl($dst$$Register);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct negExactL_rReg(rax_RegL dst, rFlagsReg cr)
+%{
+  match(NegExactL dst);
+  effect(KILL cr);
+
+  format %{ "negq    $dst\t# negExact long" %}
+  ins_encode %{
+    __ negq($dst$$Register);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
 
 //----------Multiplication/Division Instructions-------------------------------
 // Integer Multiplication Instructions
@@ -7807,6 +7961,86 @@
   ins_pipe(ialu_reg_reg_alu0);
 %}
 
+
+instruct mulExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr)
+%{
+  match(MulExactI dst src);
+  effect(DEF cr);
+
+  ins_cost(300);
+  format %{ "imull   $dst, $src\t# mulExact int" %}
+  ins_encode %{
+    __ imull($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg_alu0);
+%}
+
+
+instruct mulExactI_rReg_imm(rax_RegI dst, rRegI src, immI imm, rFlagsReg cr)
+%{
+  match(MulExactI src imm);
+  effect(DEF cr);
+
+  ins_cost(300);
+  format %{ "imull   $dst, $src, $imm\t# mulExact int" %}
+  ins_encode %{
+    __ imull($dst$$Register, $src$$Register, $imm$$constant);
+  %}
+  ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+  match(MulExactI dst (LoadI src));
+  effect(DEF cr);
+
+  ins_cost(350);
+  format %{ "imull   $dst, $src\t# mulExact int" %}
+  ins_encode %{
+    __ imull($dst$$Register, $src$$Address);
+  %}
+  ins_pipe(ialu_reg_mem_alu0);
+%}
+
+instruct mulExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr)
+%{
+  match(MulExactL dst src);
+  effect(DEF cr);
+
+  ins_cost(300);
+  format %{ "imulq   $dst, $src\t# mulExact long" %}
+  ins_encode %{
+    __ imulq($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactL_rReg_imm(rax_RegL dst, rRegL src, immL32 imm, rFlagsReg cr)
+%{
+  match(MulExactL src imm);
+  effect(DEF cr);
+
+  ins_cost(300);
+  format %{ "imulq   $dst, $src, $imm\t# mulExact long" %}
+  ins_encode %{
+    __ imulq($dst$$Register, $src$$Register, $imm$$constant);
+  %}
+  ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr)
+%{
+  match(MulExactL dst (LoadL src));
+  effect(DEF cr);
+
+  ins_cost(350);
+  format %{ "imulq   $dst, $src\t# mulExact long" %}
+  ins_encode %{
+    __ imulq($dst$$Register, $src$$Address);
+  %}
+  ins_pipe(ialu_reg_mem_alu0);
+%}
+
 instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
                    rFlagsReg cr)
 %{
--- a/hotspot/src/share/vm/adlc/archDesc.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/adlc/archDesc.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1193,6 +1193,13 @@
          || strcmp(idealName,"FastLock") == 0
          || strcmp(idealName,"FastUnlock") == 0
          || strcmp(idealName,"AddExactI") == 0
+         || strcmp(idealName,"AddExactL") == 0
+         || strcmp(idealName,"SubExactI") == 0
+         || strcmp(idealName,"SubExactL") == 0
+         || strcmp(idealName,"MulExactI") == 0
+         || strcmp(idealName,"MulExactL") == 0
+         || strcmp(idealName,"NegExactI") == 0
+         || strcmp(idealName,"NegExactL") == 0
          || strcmp(idealName,"FlagsProj") == 0
          || strcmp(idealName,"Bool") == 0
          || strcmp(idealName,"Binary") == 0 ) {
--- a/hotspot/src/share/vm/adlc/formssel.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -536,12 +536,6 @@
   if( data_type != Form::none )
     rematerialize = true;
 
-  // Ugly: until a better fix is implemented, disable rematerialization for
-  // negD nodes because they are proved to be problematic.
-  if (is_ideal_negD()) {
-    return false;
-  }
-
   // Constants
   if( _components.count() == 1 && _components[0]->is(Component::USE_DEF) )
     rematerialize = true;
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -238,7 +238,18 @@
     return env()->comp_level() == CompLevel_full_profile &&
       C1UpdateMethodData && C1ProfileCheckcasts;
   }
-
+  bool profile_parameters() {
+    return env()->comp_level() == CompLevel_full_profile &&
+      C1UpdateMethodData && MethodData::profile_parameters();
+  }
+  bool profile_arguments() {
+    return env()->comp_level() == CompLevel_full_profile &&
+      C1UpdateMethodData && MethodData::profile_arguments();
+  }
+  bool profile_return() {
+    return env()->comp_level() == CompLevel_full_profile &&
+      C1UpdateMethodData && MethodData::profile_return();
+  }
   // will compilation make optimistic assumptions that might lead to
   // deoptimization and that the runtime will account for?
   bool is_optimistic() const                             {
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1470,7 +1470,7 @@
     set_state(state()->caller_state()->copy_for_parsing());
     if (x != NULL) {
       state()->push(x->type(), x);
-      if (profile_calls() && MethodData::profile_return() && x->type()->is_object_kind()) {
+      if (profile_return() && x->type()->is_object_kind()) {
         ciMethod* caller = state()->scope()->method();
         ciMethodData* md = caller->method_data_or_null();
         ciProfileData* data = md->bci_to_data(invoke_bci);
@@ -1672,15 +1672,23 @@
 }
 
 // How many arguments do we want to profile?
-Values* GraphBuilder::args_list_for_profiling(int& start, bool may_have_receiver) {
+Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver) {
   int n = 0;
-  assert(start == 0, "should be initialized");
-  if (MethodData::profile_arguments()) {
+  bool has_receiver = may_have_receiver && Bytecodes::has_receiver(method()->java_code_at_bci(bci()));
+  start = has_receiver ? 1 : 0;
+  if (profile_arguments()) {
     ciProfileData* data = method()->method_data()->bci_to_data(bci());
     if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
       n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments();
-      bool has_receiver = may_have_receiver && Bytecodes::has_receiver(method()->java_code_at_bci(bci()));
-      start = has_receiver ? 1 : 0;
+    }
+  }
+  // If we are inlining then we need to collect arguments to profile parameters for the target
+  if (profile_parameters() && target != NULL) {
+    if (target->method_data() != NULL && target->method_data()->parameters_type_data() != NULL) {
+      // The receiver is profiled on method entry so it's included in
+      // the number of parameters but here we're only interested in
+      // actual arguments.
+      n = MAX2(n, target->method_data()->parameters_type_data()->number_of_parameters() - start);
     }
   }
   if (n > 0) {
@@ -1690,9 +1698,9 @@
 }
 
 // Collect arguments that we want to profile in a list
-Values* GraphBuilder::collect_args_for_profiling(Values* args, bool may_have_receiver) {
+Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) {
   int start = 0;
-  Values* obj_args = args_list_for_profiling(start, may_have_receiver);
+  Values* obj_args = args_list_for_profiling(target, start, may_have_receiver);
   if (obj_args == NULL) {
     return NULL;
   }
@@ -2006,7 +2014,7 @@
       } else if (exact_target != NULL) {
         target_klass = exact_target->holder();
       }
-      profile_call(target, recv, target_klass, collect_args_for_profiling(args, false), false);
+      profile_call(target, recv, target_klass, collect_args_for_profiling(args, NULL, false), false);
     }
   }
 
@@ -2021,7 +2029,7 @@
       push(result_type, result);
     }
   }
-  if (profile_calls() && MethodData::profile_return() && result_type->is_object_kind()) {
+  if (profile_return() && result_type->is_object_kind()) {
     profile_return_type(result, target);
   }
 }
@@ -3561,7 +3569,7 @@
           recv = args->at(0);
           null_check(recv);
         }
-        profile_call(callee, recv, NULL, collect_args_for_profiling(args, true), true);
+        profile_call(callee, recv, NULL, collect_args_for_profiling(args, callee, true), true);
       }
     }
   }
@@ -3572,7 +3580,7 @@
   Value value = append_split(result);
   if (result_type != voidType) push(result_type, value);
 
-  if (callee != method() && profile_calls() && MethodData::profile_return() && result_type->is_object_kind()) {
+  if (callee != method() && profile_return() && result_type->is_object_kind()) {
     profile_return_type(result, callee);
   }
 
@@ -3760,6 +3768,7 @@
 
   // now perform tests that are based on flag settings
   if (callee->force_inline()) {
+    if (inline_level() > MaxForceInlineLevel) INLINE_BAILOUT("MaxForceInlineLevel");
     print_inlining(callee, "force inline by annotation");
   } else if (callee->should_inline()) {
     print_inlining(callee, "force inline by CompileOracle");
@@ -3820,7 +3829,7 @@
 
     if (profile_calls()) {
       int start = 0;
-      Values* obj_args = args_list_for_profiling(start, has_receiver);
+      Values* obj_args = args_list_for_profiling(callee, start, has_receiver);
       if (obj_args != NULL) {
         int s = obj_args->size();
         // if called through method handle invoke, some arguments may have been popped
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -386,9 +386,12 @@
   bool profile_calls()         { return _compilation->profile_calls();         }
   bool profile_inlined_calls() { return _compilation->profile_inlined_calls(); }
   bool profile_checkcasts()    { return _compilation->profile_checkcasts();    }
+  bool profile_parameters()    { return _compilation->profile_parameters();    }
+  bool profile_arguments()     { return _compilation->profile_arguments();     }
+  bool profile_return()        { return _compilation->profile_return();        }
 
-  Values* args_list_for_profiling(int& start, bool may_have_receiver);
-  Values* collect_args_for_profiling(Values* args, bool may_have_receiver);
+  Values* args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver);
+  Values* collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver);
 
  public:
   NOT_PRODUCT(void print_stats();)
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -183,10 +183,10 @@
     case T_LONG:
     case T_OBJECT:
     case T_ADDRESS:
-    case T_METADATA:
     case T_VOID:
       return ::type2char(t);
-
+    case T_METADATA:
+      return 'M';
     case T_ILLEGAL:
       return '?';
 
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1175,7 +1175,7 @@
   if (compilation()->env()->dtrace_method_probes()) {
     BasicTypeList signature;
     signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT));    // thread
-    signature.append(T_OBJECT); // Method*
+    signature.append(T_METADATA); // Method*
     LIR_OprList* args = new LIR_OprList();
     args->append(getThreadPointer());
     LIR_Opr meth = new_register(T_METADATA);
@@ -1265,6 +1265,7 @@
 
   LIRItem rcvr(x->argument_at(0), this);
   rcvr.load_item();
+  LIR_Opr temp = new_register(T_METADATA);
   LIR_Opr result = rlock_result(x);
 
   // need to perform the null check on the rcvr
@@ -1272,8 +1273,11 @@
   if (x->needs_null_check()) {
     info = state_for(x);
   }
-  __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), result, info);
-  __ move_wide(new LIR_Address(result, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
+
+  // FIXME T_ADDRESS should actually be T_METADATA but it can't because the
+  // meaning of these two is mixed up (see JDK-8026837).
+  __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), temp, info);
+  __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
 }
 
 
@@ -2643,6 +2647,39 @@
   return result;
 }
 
+// profile parameters on entry to the root of the compilation
+void LIRGenerator::profile_parameters(Base* x) {
+  if (compilation()->profile_parameters()) {
+    CallingConvention* args = compilation()->frame_map()->incoming_arguments();
+    ciMethodData* md = scope()->method()->method_data_or_null();
+    assert(md != NULL, "Sanity");
+
+    if (md->parameters_type_data() != NULL) {
+      ciParametersTypeData* parameters_type_data = md->parameters_type_data();
+      ciTypeStackSlotEntries* parameters =  parameters_type_data->parameters();
+      LIR_Opr mdp = LIR_OprFact::illegalOpr;
+      for (int java_index = 0, i = 0, j = 0; j < parameters_type_data->number_of_parameters(); i++) {
+        LIR_Opr src = args->at(i);
+        assert(!src->is_illegal(), "check");
+        BasicType t = src->type();
+        if (t == T_OBJECT || t == T_ARRAY) {
+          intptr_t profiled_k = parameters->type(j);
+          Local* local = x->state()->local_at(java_index)->as_Local();
+          ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
+                                            in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)),
+                                            profiled_k, local, mdp, false, local->declared_type()->as_klass());
+          // If the profile is known statically set it once for all and do not emit any code
+          if (exact != NULL) {
+            md->set_parameter_type(j, exact);
+          }
+          j++;
+        }
+        java_index += type2size[t];
+      }
+    }
+  }
+}
+
 void LIRGenerator::do_Base(Base* x) {
   __ std_entry(LIR_OprFact::illegalOpr);
   // Emit moves from physical registers / stack slots to virtual registers
@@ -2683,7 +2720,7 @@
   if (compilation()->env()->dtrace_method_probes()) {
     BasicTypeList signature;
     signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT));    // thread
-    signature.append(T_OBJECT); // Method*
+    signature.append(T_METADATA); // Method*
     LIR_OprList* args = new LIR_OprList();
     args->append(getThreadPointer());
     LIR_Opr meth = new_register(T_METADATA);
@@ -2718,6 +2755,7 @@
 
   // increment invocation counters if needed
   if (!method()->is_accessor()) { // Accessors do not have MDOs, so no counting.
+    profile_parameters(x);
     CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, false);
     increment_invocation_counter(info);
   }
@@ -3077,11 +3115,12 @@
 }
 
 void LIRGenerator::profile_arguments(ProfileCall* x) {
-  if (MethodData::profile_arguments()) {
+  if (compilation()->profile_arguments()) {
     int bci = x->bci_of_invoke();
     ciMethodData* md = x->method()->method_data_or_null();
     ciProfileData* data = md->bci_to_data(bci);
-    if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+    if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
+        (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
       ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
       int base_offset = md->byte_offset_of_slot(data, extra);
       LIR_Opr mdp = LIR_OprFact::illegalOpr;
@@ -3107,6 +3146,71 @@
           md->set_argument_type(bci, i, exact);
         }
       }
+    } else {
+#ifdef ASSERT
+      Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
+      int n = x->nb_profiled_args();
+      assert(MethodData::profile_parameters() && x->inlined() &&
+             ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)),
+             "only at JSR292 bytecodes");
+#endif
+    }
+  }
+}
+
+// profile parameters on entry to an inlined method
+void LIRGenerator::profile_parameters_at_call(ProfileCall* x) {
+  if (compilation()->profile_parameters() && x->inlined()) {
+    ciMethodData* md = x->callee()->method_data_or_null();
+    if (md != NULL) {
+      ciParametersTypeData* parameters_type_data = md->parameters_type_data();
+      if (parameters_type_data != NULL) {
+        ciTypeStackSlotEntries* parameters =  parameters_type_data->parameters();
+        LIR_Opr mdp = LIR_OprFact::illegalOpr;
+        bool has_receiver = !x->callee()->is_static();
+        ciSignature* sig = x->callee()->signature();
+        ciSignatureStream sig_stream(sig, has_receiver ? x->callee()->holder() : NULL);
+        int i = 0; // to iterate on the Instructions
+        Value arg = x->recv();
+        bool not_null = false;
+        int bci = x->bci_of_invoke();
+        Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
+        // The first parameter is the receiver so that's what we start
+        // with if it exists. On exception if method handle call to
+        // virtual method has receiver in the args list
+        if (arg == NULL || !Bytecodes::has_receiver(bc)) {
+          i = 1;
+          arg = x->profiled_arg_at(0);
+          not_null = !x->arg_needs_null_check(0);
+        }
+        int k = 0; // to iterate on the profile data
+        for (;;) {
+          intptr_t profiled_k = parameters->type(k);
+          ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
+                                            in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)),
+                                            profiled_k, arg, mdp, not_null, sig_stream.next_klass());
+          // If the profile is known statically set it once for all and do not emit any code
+          if (exact != NULL) {
+            md->set_parameter_type(k, exact);
+          }
+          k++;
+          if (k >= parameters_type_data->number_of_parameters()) {
+#ifdef ASSERT
+            int extra = 0;
+            if (MethodData::profile_arguments() && TypeProfileParmsLimit != -1 &&
+                x->nb_profiled_args() >= TypeProfileParmsLimit &&
+                x->recv() != NULL && Bytecodes::has_receiver(bc)) {
+              extra += 1;
+            }
+            assert(i == x->nb_profiled_args() - extra || (TypeProfileParmsLimit != -1 && TypeProfileArgsLimit > TypeProfileParmsLimit), "unused parameters?");
+#endif
+            break;
+          }
+          arg = x->profiled_arg_at(i);
+          not_null = !x->arg_needs_null_check(i);
+          i++;
+        }
+      }
     }
   }
 }
@@ -3122,6 +3226,11 @@
     profile_arguments(x);
   }
 
+  // profile parameters on inlined method entry including receiver
+  if (x->recv() != NULL || x->nb_profiled_args() > 0) {
+    profile_parameters_at_call(x);
+  }
+
   if (x->recv() != NULL) {
     LIRItem value(x->recv(), this);
     value.load_item();
@@ -3222,7 +3331,7 @@
   BasicTypeList* signature = new BasicTypeList(x->number_of_arguments());
 
   if (x->pass_thread()) {
-    signature->append(T_ADDRESS);
+    signature->append(LP64_ONLY(T_LONG) NOT_LP64(T_INT));    // thread
     args->append(getThreadPointer());
   }
 
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -436,6 +436,8 @@
 #endif
   ciKlass* profile_arg_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_k);
   void profile_arguments(ProfileCall* x);
+  void profile_parameters(Base* x);
+  void profile_parameters_at_call(ProfileCall* x);
 
  public:
   Compilation*  compilation() const              { return _compilation; }
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -75,9 +75,9 @@
 
 // Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
 #ifdef _LP64
-static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 1, -1};
+static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 2,  1, 2, 1, -1};
 #else
-static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1};
+static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1, 1, 1, -1};
 #endif
 
 
--- a/hotspot/src/share/vm/c1/c1_globals.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/c1/c1_globals.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -341,6 +341,8 @@
   diagnostic(bool, C1PatchInvokeDynamic, true,                              \
              "Patch invokedynamic appendix not known at compile time")      \
                                                                             \
+  develop(intx, MaxForceInlineLevel, 100,                                   \
+          "maximum number of nested @ForceInline calls that are inlined")   \
                                                                             \
 
 
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -53,6 +53,7 @@
   _hint_di = first_di();
   // Initialize the escape information (to "don't know.");
   _eflags = _arg_local = _arg_stack = _arg_returned = 0;
+  _parameters = NULL;
 }
 
 // ------------------------------------------------------------------
@@ -74,6 +75,7 @@
   _hint_di = first_di();
   // Initialize the escape information (to "don't know.");
   _eflags = _arg_local = _arg_stack = _arg_returned = 0;
+  _parameters = NULL;
 }
 
 void ciMethodData::load_data() {
@@ -108,6 +110,12 @@
     ci_data = next_data(ci_data);
     data = mdo->next_data(data);
   }
+  if (mdo->parameters_type_data() != NULL) {
+    _parameters = data_layout_at(mdo->parameters_type_data_di());
+    ciParametersTypeData* parameters = new ciParametersTypeData(_parameters);
+    parameters->translate_from(mdo->parameters_type_data());
+  }
+
   // Note:  Extra data are all BitData, and do not need translation.
   _current_mileage = MethodData::mileage_of(mdo->method());
   _invocation_counter = mdo->invocation_count();
@@ -182,6 +190,8 @@
     return new ciCallTypeData(data_layout);
   case DataLayout::virtual_call_type_data_tag:
     return new ciVirtualCallTypeData(data_layout);
+  case DataLayout::parameters_type_data_tag:
+    return new ciParametersTypeData(data_layout);
   };
 }
 
@@ -318,6 +328,14 @@
   }
 }
 
+void ciMethodData::set_parameter_type(int i, ciKlass* k) {
+  VM_ENTRY_MARK;
+  MethodData* mdo = get_MethodData();
+  if (mdo != NULL) {
+    mdo->parameters_type_data()->set_type(i, k->get_Klass());
+  }
+}
+
 void ciMethodData::set_return_type(int bci, ciKlass* k) {
   VM_ENTRY_MARK;
   MethodData* mdo = get_MethodData();
@@ -605,4 +623,9 @@
     ret()->print_data_on(st);
   }
 }
+
+void ciParametersTypeData::print_data_on(outputStream* st) const {
+  st->print_cr("Parametertypes");
+  parameters()->print_data_on(st);
+}
 #endif
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -43,6 +43,7 @@
 class ciArgInfoData;
 class ciCallTypeData;
 class ciVirtualCallTypeData;
+class ciParametersTypeData;
 
 typedef ProfileData ciProfileData;
 
@@ -99,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
@@ -112,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
@@ -124,7 +133,7 @@
   ciTypeStackSlotEntries* args() const { return (ciTypeStackSlotEntries*)CallTypeData::args(); }
   ciReturnTypeEntry* ret() const { return (ciReturnTypeEntry*)CallTypeData::ret(); }
 
-  void translate_type_data_from(const ProfileData* data) {
+  void translate_from(const ProfileData* data) {
     if (has_arguments()) {
       args()->translate_type_data_from(data->as_CallTypeData()->args());
     }
@@ -153,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
@@ -259,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
@@ -290,6 +315,29 @@
   ciArgInfoData(DataLayout* layout) : ArgInfoData(layout) {};
 };
 
+class ciParametersTypeData : public ParametersTypeData {
+public:
+  ciParametersTypeData(DataLayout* layout) : ParametersTypeData(layout) {}
+
+  virtual void translate_from(const ProfileData* data) {
+    parameters()->translate_type_data_from(data->as_ParametersTypeData()->parameters());
+  }
+
+  ciTypeStackSlotEntries* parameters() const { return (ciTypeStackSlotEntries*)ParametersTypeData::parameters(); }
+
+  ciKlass* valid_parameter_type(int i) const {
+    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
+};
+
 // ciMethodData
 //
 // This class represents a MethodData* in the HotSpot virtual
@@ -335,6 +383,10 @@
   // Coherent snapshot of original header.
   MethodData _orig;
 
+  // Dedicated area dedicated to parameters. Null if no parameter
+  // profiling for this method.
+  DataLayout* _parameters;
+
   ciMethodData(MethodData* md);
   ciMethodData();
 
@@ -403,6 +455,7 @@
   // If the compiler finds a profiled type that is known statically
   // for sure, set it in the MethodData
   void set_argument_type(int bci, int i, ciKlass* k);
+  void set_parameter_type(int i, ciKlass* k);
   void set_return_type(int bci, ciKlass* k);
 
   void load_data();
@@ -467,6 +520,10 @@
   bool is_arg_returned(int i) const;
   uint arg_modified(int arg) const;
 
+  ciParametersTypeData* parameters_type_data() const {
+    return _parameters != NULL ? new ciParametersTypeData(_parameters) : NULL;
+  }
+
   // Code generation helper
   ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data);
   int      byte_offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { return in_bytes(offset_of_slot(data, slot_offset_in_data)); }
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -2360,6 +2360,11 @@
   objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
   assert(appendix_box->obj_at(0) == NULL, "");
 
+  // This should not happen.  JDK code should take care of that.
+  if (accessing_klass.is_null() || method_type.is_null()) {
+    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokehandle", empty);
+  }
+
   // call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName
   JavaCallArguments args;
   args.push_oop(accessing_klass()->java_mirror());
@@ -2485,6 +2490,9 @@
   Handle type;
   if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
     type = find_method_handle_type(signature, caller, CHECK_(empty));
+  } else if (caller.is_null()) {
+    // This should not happen.  JDK code should take care of that.
+    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad MH constant", empty);
   } else {
     ResourceMark rm(THREAD);
     SignatureStream ss(signature, false);
@@ -2548,6 +2556,11 @@
   Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
   Handle method_type = find_method_handle_type(type, caller, CHECK_(empty));
 
+  // This should not happen.  JDK code should take care of that.
+  if (caller.is_null() || method_type.is_null()) {
+    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty);
+  }
+
   objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
   assert(appendix_box->obj_at(0) == NULL, "");
 
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -624,6 +624,7 @@
   do_class(java_lang_StrictMath,          "java/lang/StrictMath")                                                       \
   do_signature(double2_double_signature,  "(DD)D")                                                                      \
   do_signature(int2_int_signature,        "(II)I")                                                                      \
+  do_signature(long2_long_signature,      "(JJ)J")                                                                         \
                                                                                                                         \
   /* here are the math names, all together: */                                                                          \
   do_name(abs_name,"abs")       do_name(sin_name,"sin")         do_name(cos_name,"cos")                                 \
@@ -632,8 +633,11 @@
   do_name(exp_name,"exp")       do_name(min_name,"min")         do_name(max_name,"max")                                 \
                                                                                                                         \
   do_name(addExact_name,"addExact")                                                                                     \
+  do_name(decrementExact_name,"decrementExact")                                                                         \
+  do_name(incrementExact_name,"incrementExact")                                                                         \
+  do_name(multiplyExact_name,"multiplyExact")                                                                           \
+  do_name(negateExact_name,"negateExact")                                                                               \
   do_name(subtractExact_name,"subtractExact")                                                                           \
-  do_name(multiplyExact_name,"multiplyExact")                                                                           \
                                                                                                                         \
   do_intrinsic(_dabs,                     java_lang_Math,         abs_name,   double_double_signature,           F_S)   \
   do_intrinsic(_dsin,                     java_lang_Math,         sin_name,   double_double_signature,           F_S)   \
@@ -647,7 +651,18 @@
   do_intrinsic(_dexp,                     java_lang_Math,         exp_name,   double_double_signature,           F_S)   \
   do_intrinsic(_min,                      java_lang_Math,         min_name,   int2_int_signature,                F_S)   \
   do_intrinsic(_max,                      java_lang_Math,         max_name,   int2_int_signature,                F_S)   \
-  do_intrinsic(_addExact,                 java_lang_Math,         addExact_name, int2_int_signature,             F_S)   \
+  do_intrinsic(_addExactI,                java_lang_Math,         addExact_name, int2_int_signature,             F_S)   \
+  do_intrinsic(_addExactL,                java_lang_Math,         addExact_name, long2_long_signature,           F_S)   \
+  do_intrinsic(_decrementExactI,          java_lang_Math,         decrementExact_name, int_int_signature,        F_S)   \
+  do_intrinsic(_decrementExactL,          java_lang_Math,         decrementExact_name, long2_long_signature,     F_S)   \
+  do_intrinsic(_incrementExactI,          java_lang_Math,         incrementExact_name, int_int_signature,        F_S)   \
+  do_intrinsic(_incrementExactL,          java_lang_Math,         incrementExact_name, long2_long_signature,     F_S)   \
+  do_intrinsic(_multiplyExactI,           java_lang_Math,         multiplyExact_name, int2_int_signature,        F_S)   \
+  do_intrinsic(_multiplyExactL,           java_lang_Math,         multiplyExact_name, long2_long_signature,      F_S)   \
+  do_intrinsic(_negateExactI,             java_lang_Math,         negateExact_name, int_int_signature,           F_S)   \
+  do_intrinsic(_negateExactL,             java_lang_Math,         negateExact_name, long_long_signature,         F_S)   \
+  do_intrinsic(_subtractExactI,           java_lang_Math,         subtractExact_name, int2_int_signature,        F_S)   \
+  do_intrinsic(_subtractExactL,           java_lang_Math,         subtractExact_name, long2_long_signature,      F_S)   \
                                                                                                                         \
   do_intrinsic(_floatToRawIntBits,        java_lang_Float,        floatToRawIntBits_name,   float_int_signature, F_S)   \
    do_name(     floatToRawIntBits_name,                          "floatToRawIntBits")                                   \
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1297,13 +1297,6 @@
     method->jmethod_id();
   }
 
-  // If the compiler is shut off due to code cache getting full
-  // fail out now so blocking compiles dont hang the java thread
-  if (!should_compile_new_jobs()) {
-    CompilationPolicy::policy()->delay_compilation(method());
-    return NULL;
-  }
-
   // do the compilation
   if (method->is_native()) {
     if (!PreferInterpreterNativeStubs || method->is_method_handle_intrinsic()) {
@@ -1313,11 +1306,22 @@
         MutexLocker locker(MethodCompileQueue_lock, THREAD);
         compile_id = assign_compile_id(method, standard_entry_bci);
       }
+      // To properly handle the appendix argument for out-of-line calls we are using a small trampoline that
+      // pops off the appendix argument and jumps to the target (see gen_special_dispatch in SharedRuntime).
+      //
+      // Since normal compiled-to-compiled calls are not able to handle such a thing we MUST generate an adapter
+      // in this case.  If we can't generate one and use it we can not execute the out-of-line method handle calls.
       (void) AdapterHandlerLibrary::create_native_wrapper(method, compile_id);
     } else {
       return NULL;
     }
   } else {
+    // If the compiler is shut off due to code cache getting full
+    // fail out now so blocking compiles dont hang the java thread
+    if (!should_compile_new_jobs()) {
+      CompilationPolicy::policy()->delay_compilation(method());
+      return NULL;
+    }
     compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD);
   }
 
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -30,11 +30,8 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "utilities/top.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
 #endif
 #ifdef TARGET_ARCH_MODEL_sparc
 # include "interp_masm_sparc.hpp"
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -28,11 +28,8 @@
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/frame.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
 #endif
 #ifdef TARGET_ARCH_MODEL_sparc
 # include "interp_masm_sparc.hpp"
--- a/hotspot/src/share/vm/oops/methodData.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -41,7 +41,7 @@
 
 // Some types of data layouts need a length field.
 bool DataLayout::needs_array_len(u1 tag) {
-  return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag);
+  return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag);
 }
 
 // Perform generic initialization of the data.  More specific
@@ -156,10 +156,13 @@
 }
 #endif // !PRODUCT
 
-int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) {
+int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
+  // Parameter profiling include the receiver
+  int args_count = include_receiver ? 1 : 0;
   ResourceMark rm;
   SignatureStream ss(signature);
-  int args_count = MIN2(ss.reference_parameter_count(), max);
+  args_count += ss.reference_parameter_count();
+  args_count = MIN2(args_count, max);
   return args_count * per_arg_cell_count;
 }
 
@@ -169,7 +172,7 @@
   Bytecode_invoke inv(stream->method(), stream->bci());
   int args_cell = 0;
   if (arguments_profiling_enabled()) {
-    args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit);
+    args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), false, TypeProfileArgsLimit);
   }
   int ret_cell = 0;
   if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) {
@@ -212,12 +215,19 @@
   int off_at(int i) const { return _offsets.at(i); }
 };
 
-void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) {
+void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver, bool include_receiver) {
   ResourceMark rm;
-  ArgumentOffsetComputer aos(signature, _number_of_entries);
+  int start = 0;
+  // Parameter profiling include the receiver
+  if (include_receiver && has_receiver) {
+    set_stack_slot(0, 0);
+    set_type(0, type_none());
+    start += 1;
+  }
+  ArgumentOffsetComputer aos(signature, _number_of_entries-start);
   aos.total();
-  for (int i = 0; i < _number_of_entries; i++) {
-    set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0));
+  for (int i = start; i < _number_of_entries; i++) {
+    set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
     set_type(i, type_none());
   }
 }
@@ -234,7 +244,7 @@
     assert(count > 0, "room for args type but none found?");
     check_number_of_arguments(count);
 #endif
-    _args.post_initialize(inv.signature(), inv.has_receiver());
+    _args.post_initialize(inv.signature(), inv.has_receiver(), false);
   }
 
   if (has_return()) {
@@ -255,7 +265,7 @@
     assert(count > 0, "room for args type but none found?");
     check_number_of_arguments(count);
 #endif
-    _args.post_initialize(inv.signature(), inv.has_receiver());
+    _args.post_initialize(inv.signature(), inv.has_receiver(), false);
   }
 
   if (has_return()) {
@@ -579,6 +589,34 @@
 }
 
 #endif
+
+int ParametersTypeData::compute_cell_count(Method* m) {
+  if (!MethodData::profile_parameters_for_method(m)) {
+    return 0;
+  }
+  int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit;
+  int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max);
+  if (obj_args > 0) {
+    return obj_args + 1; // 1 cell for array len
+  }
+  return 0;
+}
+
+void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
+  _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true);
+}
+
+bool ParametersTypeData::profiling_enabled() {
+  return MethodData::profile_parameters();
+}
+
+#ifndef PRODUCT
+void ParametersTypeData::print_data_on(outputStream* st) const {
+  st->print("parameter types");
+  _parameters.print_data_on(st);
+}
+#endif
+
 // ==================================================================
 // MethodData*
 //
@@ -741,6 +779,12 @@
   int arg_size = method->size_of_parameters();
   object_size += DataLayout::compute_size_in_bytes(arg_size+1);
 
+  // Reserve room for an area of the MDO dedicated to profiling of
+  // parameters
+  int args_cell = ParametersTypeData::compute_cell_count(method());
+  if (args_cell > 0) {
+    object_size += DataLayout::compute_size_in_bytes(args_cell);
+  }
   return object_size;
 }
 
@@ -915,6 +959,8 @@
     return new CallTypeData(this);
   case DataLayout::virtual_call_type_data_tag:
     return new VirtualCallTypeData(this);
+  case DataLayout::parameters_type_data_tag:
+    return new ParametersTypeData(this);
   };
 }
 
@@ -936,6 +982,9 @@
     stream->next();
     data->post_initialize(stream, this);
   }
+  if (_parameters_type_data_di != -1) {
+    parameters_type_data()->post_initialize(NULL, this);
+  }
 }
 
 // Initialize the MethodData* corresponding to a given method.
@@ -975,7 +1024,23 @@
   int arg_size = method->size_of_parameters();
   dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
 
-  object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1);
+  int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
+  object_size += extra_size + arg_data_size;
+
+  int args_cell = ParametersTypeData::compute_cell_count(method());
+  // If we are profiling parameters, we reserver an area near the end
+  // of the MDO after the slots for bytecodes (because there's no bci
+  // for method entry so they don't fit with the framework for the
+  // profiling of bytecodes). We store the offset within the MDO of
+  // this area (or -1 if no parameter is profiled)
+  if (args_cell > 0) {
+    object_size += DataLayout::compute_size_in_bytes(args_cell);
+    _parameters_type_data_di = data_size + extra_size + arg_data_size;
+    DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
+    dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell);
+  } else {
+    _parameters_type_data_di = -1;
+  }
 
   // Set an initial hint. Don't use set_hint_di() because
   // first_di() may be out of bounds if data_size is 0.
@@ -1134,6 +1199,9 @@
 void MethodData::print_data_on(outputStream* st) const {
   ResourceMark rm;
   ProfileData* data = first_data();
+  if (_parameters_type_data_di != -1) {
+    parameters_type_data()->print_data_on(st);
+  }
   for ( ; is_valid(data); data = next_data(data)) {
     st->print("%d", dp_to_di(data->dp()));
     st->fill_to(6);
@@ -1222,7 +1290,7 @@
 }
 
 int MethodData::profile_return_flag() {
-  return TypeProfileLevel / 10;
+  return (TypeProfileLevel % 100) / 10;
 }
 
 bool MethodData::profile_return() {
@@ -1249,3 +1317,32 @@
   assert(profile_return_jsr292_only(), "inconsistent");
   return profile_jsr292(m, bci);
 }
+
+int MethodData::profile_parameters_flag() {
+  return TypeProfileLevel / 100;
+}
+
+bool MethodData::profile_parameters() {
+  return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all;
+}
+
+bool MethodData::profile_parameters_jsr292_only() {
+  return profile_parameters_flag() == type_profile_jsr292;
+}
+
+bool MethodData::profile_all_parameters() {
+  return profile_parameters_flag() == type_profile_all;
+}
+
+bool MethodData::profile_parameters_for_method(methodHandle m) {
+  if (!profile_parameters()) {
+    return false;
+  }
+
+  if (profile_all_parameters()) {
+    return true;
+  }
+
+  assert(profile_parameters_jsr292_only(), "inconsistent");
+  return m->is_compiled_lambda_form();
+}
--- a/hotspot/src/share/vm/oops/methodData.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -119,7 +119,8 @@
     multi_branch_data_tag,
     arg_info_data_tag,
     call_type_data_tag,
-    virtual_call_type_data_tag
+    virtual_call_type_data_tag,
+    parameters_type_data_tag
   };
 
   enum {
@@ -264,6 +265,7 @@
 class   ArrayData;
 class     MultiBranchData;
 class     ArgInfoData;
+class     ParametersTypeData;
 
 // ProfileData
 //
@@ -397,6 +399,7 @@
   virtual bool is_ArgInfoData()     const { return false; }
   virtual bool is_CallTypeData()    const { return false; }
   virtual bool is_VirtualCallTypeData()const { return false; }
+  virtual bool is_ParametersTypeData() const { return false; }
 
 
   BitData* as_BitData() const {
@@ -447,6 +450,10 @@
     assert(is_VirtualCallTypeData(), "wrong type");
     return is_VirtualCallTypeData() ? (VirtualCallTypeData*)this : NULL;
   }
+  ParametersTypeData* as_ParametersTypeData() const {
+    assert(is_ParametersTypeData(), "wrong type");
+    return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL;
+  }
 
 
   // Subclass specific initialization
@@ -767,9 +774,9 @@
   TypeStackSlotEntries(int base_off, int nb_entries)
     : TypeEntries(base_off), _number_of_entries(nb_entries) {}
 
-  static int compute_cell_count(Symbol* signature, int max);
+  static int compute_cell_count(Symbol* signature, bool include_receiver, int max);
 
-  void post_initialize(Symbol* signature, bool has_receiver);
+  void post_initialize(Symbol* signature, bool has_receiver, bool include_receiver);
 
   // offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries
   static int stack_slot_local_offset(int i) {
@@ -946,17 +953,6 @@
     assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
   }
 
-protected:
-  // An entry for a return value takes less space than an entry for an
-  // argument so if the number of cells exceeds the number of cells
-  // needed for an argument, this object contains type information for
-  // at least one argument.
-  bool has_arguments() const {
-    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
-    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
-    return res;
-  }
-
 public:
   CallTypeData(DataLayout* layout) :
     CounterData(layout),
@@ -1018,6 +1014,16 @@
   }
 
   // An entry for a return value takes less space than an entry for an
+  // argument so if the number of cells exceeds the number of cells
+  // needed for an argument, this object contains type information for
+  // at least one argument.
+  bool has_arguments() const {
+    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
+    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
+    return res;
+  }
+
+  // An entry for a return value takes less space than an entry for an
   // argument, so if the remainder of the number of cells divided by
   // the number of cells for an argument is not null, a return value
   // is profiled in this object.
@@ -1213,17 +1219,6 @@
     assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
   }
 
-protected:
-  // An entry for a return value takes less space than an entry for an
-  // argument so if the number of cells exceeds the number of cells
-  // needed for an argument, this object contains type information for
-  // at least one argument.
-  bool has_arguments() const {
-    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
-    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
-    return res;
-  }
-
 public:
   VirtualCallTypeData(DataLayout* layout) :
     VirtualCallData(layout),
@@ -1294,6 +1289,16 @@
     return res;
   }
 
+  // An entry for a return value takes less space than an entry for an
+  // argument so if the number of cells exceeds the number of cells
+  // needed for an argument, this object contains type information for
+  // at least one argument.
+  bool has_arguments() const {
+    bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
+    assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
+    return res;
+  }
+
   // Code generation support
   static ByteSize args_data_offset() {
     return cell_offset(VirtualCallData::static_cell_count()) + TypeEntriesAtCall::args_data_offset();
@@ -1662,6 +1667,75 @@
 #endif
 };
 
+// ParametersTypeData
+//
+// A ParametersTypeData is used to access profiling information about
+// types of parameters to a method
+class ParametersTypeData : public ArrayData {
+
+private:
+  TypeStackSlotEntries _parameters;
+
+  static int stack_slot_local_offset(int i) {
+    assert_profiling_enabled();
+    return array_start_off_set + TypeStackSlotEntries::stack_slot_local_offset(i);
+  }
+
+  static int type_local_offset(int i) {
+    assert_profiling_enabled();
+    return array_start_off_set + TypeStackSlotEntries::type_local_offset(i);
+  }
+
+  static bool profiling_enabled();
+  static void assert_profiling_enabled() {
+    assert(profiling_enabled(), "method parameters profiling should be on");
+  }
+
+public:
+  ParametersTypeData(DataLayout* layout) : ArrayData(layout), _parameters(1, number_of_parameters()) {
+    assert(layout->tag() == DataLayout::parameters_type_data_tag, "wrong type");
+    // Some compilers (VC++) don't want this passed in member initialization list
+    _parameters.set_profile_data(this);
+  }
+
+  static int compute_cell_count(Method* m);
+
+  virtual bool is_ParametersTypeData() const { return true; }
+
+  virtual void post_initialize(BytecodeStream* stream, MethodData* mdo);
+
+  int number_of_parameters() const {
+    return array_len() / TypeStackSlotEntries::per_arg_count();
+  }
+
+  const TypeStackSlotEntries* parameters() const { return &_parameters; }
+
+  uint stack_slot(int i) const {
+    return _parameters.stack_slot(i);
+  }
+
+  void set_type(int i, Klass* k) {
+    intptr_t current = _parameters.type(i);
+    _parameters.set_type(i, TypeEntries::with_status((intptr_t)k, current));
+  }
+
+  virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
+    _parameters.clean_weak_klass_links(is_alive_closure);
+  }
+
+#ifndef PRODUCT
+  virtual void print_data_on(outputStream* st) const;
+#endif
+
+  static ByteSize stack_slot_offset(int i) {
+    return cell_offset(stack_slot_local_offset(i));
+  }
+
+  static ByteSize type_offset(int i) {
+    return cell_offset(type_local_offset(i));
+  }
+};
+
 // MethodData*
 //
 // A MethodData* holds information which has been collected about
@@ -1773,6 +1847,10 @@
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
   int _data_size;
 
+  // data index for the area dedicated to parameters. -1 if no
+  // parameter profiling.
+  int _parameters_type_data_di;
+
   // Beginning of the data entries
   intptr_t _data[1];
 
@@ -1842,6 +1920,9 @@
   static int profile_return_flag();
   static bool profile_all_return();
   static bool profile_return_for_invoke(methodHandle m, int bci);
+  static int profile_parameters_flag();
+  static bool profile_parameters_jsr292_only();
+  static bool profile_all_parameters();
 
 public:
   static int header_size() {
@@ -2048,6 +2129,16 @@
     }
   }
 
+  // Return pointer to area dedicated to parameters in MDO
+  ParametersTypeData* parameters_type_data() const {
+    return _parameters_type_data_di != -1 ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
+  }
+
+  int parameters_type_data_di() const {
+    assert(_parameters_type_data_di != -1, "no args type data");
+    return _parameters_type_data_di;
+  }
+
   // Support for code generation
   static ByteSize data_offset() {
     return byte_offset_of(MethodData, _data[0]);
@@ -2060,6 +2151,10 @@
     return byte_offset_of(MethodData, _backedge_counter);
   }
 
+  static ByteSize parameters_type_data_di_offset() {
+    return byte_offset_of(MethodData, _parameters_type_data_di);
+  }
+
   // Deallocation support - no pointer fields to deallocate
   void deallocate_contents(ClassLoaderData* loader_data) {}
 
@@ -2083,8 +2178,10 @@
   void verify_on(outputStream* st);
   void verify_data_on(outputStream* st);
 
+  static bool profile_parameters_for_method(methodHandle m);
   static bool profile_arguments();
   static bool profile_return();
+  static bool profile_parameters();
   static bool profile_return_jsr292_only();
 };
 
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -638,7 +638,13 @@
           "Find best control for expensive operations")                     \
                                                                             \
   product(bool, UseMathExactIntrinsics, true,                               \
-          "Enables intrinsification of various java.lang.Math funcitons")
+          "Enables intrinsification of various java.lang.Math functions")   \
+                                                                            \
+  experimental(bool, ReplaceInParentMaps, false,                            \
+          "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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -63,12 +63,12 @@
   }
 
   virtual bool      is_parse() const           { return true; }
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
   int is_osr() { return _is_osr; }
 
 };
 
-JVMState* ParseGenerator::generate(JVMState* jvms) {
+JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   Compile* C = Compile::current();
 
   if (is_osr()) {
@@ -80,7 +80,7 @@
     return NULL;  // bailing out of the compile; do not try to parse
   }
 
-  Parse parser(jvms, method(), _expected_uses);
+  Parse parser(jvms, method(), _expected_uses, parent_parser);
   // Grab signature for matching/allocation
 #ifdef ASSERT
   if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
@@ -119,12 +119,12 @@
       _separate_io_proj(separate_io_proj)
   {
   }
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
 
   CallStaticJavaNode* call_node() const { return _call_node; }
 };
 
-JVMState* DirectCallGenerator::generate(JVMState* jvms) {
+JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
   bool is_static = method()->is_static();
   address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
@@ -171,10 +171,10 @@
            vtable_index >= 0, "either invalid or usable");
   }
   virtual bool      is_virtual() const          { return true; }
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
 };
 
-JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
+JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
   Node* receiver = kit.argument(0);
 
@@ -276,7 +276,7 @@
   // Convert the CallStaticJava into an inline
   virtual void do_late_inline();
 
-  virtual JVMState* generate(JVMState* jvms) {
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     Compile *C = Compile::current();
     C->print_inlining_skip(this);
 
@@ -290,7 +290,7 @@
     // that the late inlining logic can distinguish between fall
     // through and exceptional uses of the memory and io projections
     // as is done for allocations and macro expansion.
-    return DirectCallGenerator::generate(jvms);
+    return DirectCallGenerator::generate(jvms, parent_parser);
   }
 
   virtual void print_inlining_late(const char* msg) {
@@ -389,7 +389,7 @@
   }
 
   // Now perform the inling using the synthesized JVMState
-  JVMState* new_jvms = _inline_cg->generate(jvms);
+  JVMState* new_jvms = _inline_cg->generate(jvms, NULL);
   if (new_jvms == NULL)  return;  // no change
   if (C->failing())      return;
 
@@ -429,8 +429,8 @@
 
   virtual bool is_mh_late_inline() const { return true; }
 
-  virtual JVMState* generate(JVMState* jvms) {
-    JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
+    JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser);
     if (_input_not_const) {
       // inlining won't be possible so no need to enqueue right now.
       call_node()->set_generator(this);
@@ -477,15 +477,17 @@
   LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
     LateInlineCallGenerator(method, inline_cg) {}
 
-  virtual JVMState* generate(JVMState* jvms) {
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     Compile *C = Compile::current();
     C->print_inlining_skip(this);
 
     C->add_string_late_inline(this);
 
-    JVMState* new_jvms =  DirectCallGenerator::generate(jvms);
+    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) {
@@ -498,13 +500,13 @@
   LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
     LateInlineCallGenerator(method, inline_cg) {}
 
-  virtual JVMState* generate(JVMState* jvms) {
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     Compile *C = Compile::current();
     C->print_inlining_skip(this);
 
     C->add_boxing_late_inline(this);
 
-    JVMState* new_jvms =  DirectCallGenerator::generate(jvms);
+    JVMState* new_jvms =  DirectCallGenerator::generate(jvms, parent_parser);
     return new_jvms;
   }
 };
@@ -540,7 +542,7 @@
   virtual bool      is_virtual() const          { return _is_virtual; }
   virtual bool      is_deferred() const         { return true; }
 
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
 };
 
 
@@ -550,12 +552,12 @@
   return new WarmCallGenerator(ci, if_cold, if_hot);
 }
 
-JVMState* WarmCallGenerator::generate(JVMState* jvms) {
+JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   Compile* C = Compile::current();
   if (C->log() != NULL) {
     C->log()->elem("warm_call bci='%d'", jvms->bci());
   }
-  jvms = _if_cold->generate(jvms);
+  jvms = _if_cold->generate(jvms, parent_parser);
   if (jvms != NULL) {
     Node* m = jvms->map()->control();
     if (m->is_CatchProj()) m = m->in(0);  else m = C->top();
@@ -616,7 +618,7 @@
   virtual bool      is_inline()    const    { return _if_hit->is_inline(); }
   virtual bool      is_deferred()  const    { return _if_hit->is_deferred(); }
 
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
 };
 
 
@@ -628,7 +630,7 @@
 }
 
 
-JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
+JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
   PhaseGVN& gvn = kit.gvn();
   // We need an explicit receiver null_check before checking its type.
@@ -656,7 +658,7 @@
   { PreserveJVMState pjvms(&kit);
     kit.set_control(slow_ctl);
     if (!kit.stopped()) {
-      slow_jvms = _if_missed->generate(kit.sync_jvms());
+      slow_jvms = _if_missed->generate(kit.sync_jvms(), parent_parser);
       if (kit.failing())
         return NULL;  // might happen because of NodeCountInliningCutoff
       assert(slow_jvms != NULL, "must be");
@@ -677,12 +679,12 @@
   kit.replace_in_map(receiver, exact_receiver);
 
   // Make the hot call:
-  JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
+  JVMState* new_jvms = _if_hit->generate(kit.sync_jvms(), parent_parser);
   if (new_jvms == NULL) {
     // Inline failed, so make a direct call.
     assert(_if_hit->is_inline(), "must have been a failed inline");
     CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
-    new_jvms = cg->generate(kit.sync_jvms());
+    new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
   }
   kit.add_exception_states_from(new_jvms);
   kit.set_jvms(new_jvms);
@@ -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;
@@ -874,7 +880,7 @@
   virtual bool      is_inlined()   const    { return true; }
   virtual bool      is_intrinsic() const    { return true; }
 
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
 };
 
 
@@ -884,7 +890,7 @@
 }
 
 
-JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms) {
+JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
   PhaseGVN& gvn = kit.gvn();
 
@@ -904,7 +910,7 @@
     PreserveJVMState pjvms(&kit);
     kit.set_control(slow_ctl);
     if (!kit.stopped()) {
-      slow_jvms = _cg->generate(kit.sync_jvms());
+      slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
       if (kit.failing())
         return NULL;  // might happen because of NodeCountInliningCutoff
       assert(slow_jvms != NULL, "must be");
@@ -922,12 +928,12 @@
   }
 
   // Generate intrinsic code:
-  JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms());
+  JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
   if (new_jvms == NULL) {
     // Intrinsic failed, so use slow code or make a direct call.
     if (slow_map == NULL) {
       CallGenerator* cg = CallGenerator::for_direct_call(method());
-      new_jvms = cg->generate(kit.sync_jvms());
+      new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
     } else {
       kit.set_jvms(slow_jvms);
       return kit.transfer_exceptions_into_jvms();
@@ -997,7 +1003,7 @@
   virtual bool      is_virtual() const          { ShouldNotReachHere(); return false; }
   virtual bool      is_trap() const             { return true; }
 
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
 };
 
 
@@ -1009,7 +1015,7 @@
 }
 
 
-JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
+JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
   // Take the trap with arguments pushed on the stack.  (Cf. null_check_receiver).
   int nargs = method()->arg_size();
--- a/hotspot/src/share/vm/opto/callGenerator.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -31,6 +31,8 @@
 #include "opto/type.hpp"
 #include "runtime/deoptimization.hpp"
 
+class Parse;
+
 //---------------------------CallGenerator-------------------------------------
 // The subclasses of this class handle generation of ideal nodes for
 // call sites and method entry points.
@@ -72,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; }
@@ -108,7 +111,7 @@
   //
   // If the result is NULL, it means that this CallGenerator was unable
   // to handle the given call, and another CallGenerator should be consulted.
-  virtual JVMState* generate(JVMState* jvms) = 0;
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) = 0;
 
   // How to generate a call site that is inlined:
   static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
--- a/hotspot/src/share/vm/opto/classes.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/classes.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -30,6 +30,7 @@
 macro(AbsI)
 macro(AddD)
 macro(AddExactI)
+macro(AddExactL)
 macro(AddF)
 macro(AddI)
 macro(AddL)
@@ -170,6 +171,8 @@
 macro(Mach)
 macro(MachProj)
 macro(MathExact)
+macro(MathExactI)
+macro(MathExactL)
 macro(MaxI)
 macro(MemBarAcquire)
 macro(MemBarAcquireLock)
@@ -189,12 +192,16 @@
 macro(MoveL2D)
 macro(MoveD2L)
 macro(MulD)
+macro(MulExactI)
+macro(MulExactL)
 macro(MulF)
 macro(MulHiL)
 macro(MulI)
 macro(MulL)
 macro(Multi)
 macro(NegD)
+macro(NegExactI)
+macro(NegExactL)
 macro(NegF)
 macro(NeverBranch)
 macro(Opaque1)
@@ -244,6 +251,8 @@
 macro(StrEquals)
 macro(StrIndexOf)
 macro(SubD)
+macro(SubExactI)
+macro(SubExactL)
 macro(SubF)
 macro(SubI)
 macro(SubL)
--- a/hotspot/src/share/vm/opto/compile.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/compile.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -655,7 +655,8 @@
                   _inlining_progress(false),
                   _inlining_incrementally(false),
                   _print_inlining_list(NULL),
-                  _print_inlining_idx(0) {
+                  _print_inlining_idx(0),
+                  _preserve_jvm_state(0) {
   C = this;
 
   CompileWrapper cw(this);
@@ -763,7 +764,7 @@
       return;
     }
     JVMState* jvms = build_start_state(start(), tf());
-    if ((jvms = cg->generate(jvms)) == NULL) {
+    if ((jvms = cg->generate(jvms, NULL)) == NULL) {
       record_method_not_compilable("method parse failed");
       return;
     }
@@ -940,7 +941,8 @@
     _inlining_progress(false),
     _inlining_incrementally(false),
     _print_inlining_list(NULL),
-    _print_inlining_idx(0) {
+    _print_inlining_idx(0),
+    _preserve_jvm_state(0) {
   C = this;
 
 #ifndef PRODUCT
@@ -1358,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);
     }
   }
@@ -1383,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
@@ -2011,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);
@@ -3004,10 +3015,15 @@
       if (result != NULL) {
         for (DUIterator_Fast jmax, j = result->fast_outs(jmax); j < jmax; j++) {
           Node* out = result->fast_out(j);
-          if (out->in(0) == NULL) {
-            out->set_req(0, non_throwing);
-          } else if (out->in(0) == ctrl) {
-            out->set_req(0, non_throwing);
+          // Phi nodes shouldn't be moved. They would only match below if they
+          // had the same control as the MathExactNode. The only time that
+          // would happen is if the Phi is also an input to the MathExact
+          if (!out->is_Phi()) {
+            if (out->in(0) == NULL) {
+              out->set_req(0, non_throwing);
+            } else if (out->in(0) == ctrl) {
+              out->set_req(0, non_throwing);
+            }
           }
         }
       }
@@ -3792,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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/compile.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -424,6 +424,11 @@
   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;
 
  public:
 
@@ -820,7 +825,9 @@
 
   // 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);
+  CallGenerator*    call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch,
+                                   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);
@@ -1156,6 +1163,21 @@
 
   // Auxiliary method for randomized fuzzing/stressing
   static bool randomized_select(int count);
+
+  // enter a PreserveJVMState block
+  void inc_preserve_jvm_state() {
+    _preserve_jvm_state++;
+  }
+
+  // exit a PreserveJVMState block
+  void dec_preserve_jvm_state() {
+    _preserve_jvm_state--;
+    assert(_preserve_jvm_state >= 0, "_preserve_jvm_state shouldn't be negative");
+  }
+
+  bool has_preserve_jvm_state() const {
+    return _preserve_jvm_state > 0;
+  }
 };
 
 #endif // SHARE_VM_OPTO_COMPILE_HPP
--- a/hotspot/src/share/vm/opto/doCall.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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,11 +517,18 @@
   // 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);
 
-  JVMState* new_jvms = cg->generate(jvms);
+  JVMState* new_jvms = cg->generate(jvms, this);
   if (new_jvms == NULL) {
     // When inlining attempt fails (e.g., too many arguments),
     // it may contaminate the current compile state, making it
@@ -508,8 +541,8 @@
     // 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);
-    if ((new_jvms = cg->generate(jvms)) == NULL) {
+    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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -639,6 +639,7 @@
   _map    = kit->map();   // preserve the map
   _sp     = kit->sp();
   kit->set_map(clone_map ? kit->clone_map() : NULL);
+  Compile::current()->inc_preserve_jvm_state();
 #ifdef ASSERT
   _bci    = kit->bci();
   Parse* parser = kit->is_Parse();
@@ -656,6 +657,7 @@
 #endif
   kit->set_map(_map);
   kit->set_sp(_sp);
+  Compile::current()->dec_preserve_jvm_state();
 }
 
 
@@ -1373,17 +1375,70 @@
 
 //--------------------------replace_in_map-------------------------------------
 void GraphKit::replace_in_map(Node* old, Node* neww) {
-  this->map()->replace_edge(old, neww);
+  if (old == neww) {
+    return;
+  }
+
+  map()->replace_edge(old, neww);
 
   // Note: This operation potentially replaces any edge
   // on the map.  This includes locals, stack, and monitors
   // of the current (innermost) JVM state.
 
-  // We can consider replacing in caller maps.
-  // The idea would be that an inlined function's null checks
-  // can be shared with the entire inlining tree.
-  // The expense of doing this is that the PreserveJVMState class
-  // would have to preserve caller states too, with a deep copy.
+  if (!ReplaceInParentMaps) {
+    return;
+  }
+
+  // PreserveJVMState doesn't do a deep copy so we can't modify
+  // parents
+  if (Compile::current()->has_preserve_jvm_state()) {
+    return;
+  }
+
+  Parse* parser = is_Parse();
+  bool progress = true;
+  Node* ctrl = map()->in(0);
+  // Follow the chain of parsers and see whether the update can be
+  // done in the map of callers. We can do the replace for a caller if
+  // the current control post dominates the control of a caller.
+  while (parser != NULL && parser->caller() != NULL && progress) {
+    progress = false;
+    Node* parent_map = parser->caller()->map();
+    assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch");
+
+    Node* parent_ctrl = parent_map->in(0);
+
+    while (parent_ctrl->is_Region()) {
+      Node* n = parent_ctrl->as_Region()->is_copy();
+      if (n == NULL) {
+        break;
+      }
+      parent_ctrl = n;
+    }
+
+    for (;;) {
+      if (ctrl == parent_ctrl) {
+        // update the map of the exits which is the one that will be
+        // used when compilation resume after inlining
+        parser->exits().map()->replace_edge(old, neww);
+        progress = true;
+        break;
+      }
+      if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
+        ctrl = ctrl->in(0)->in(0);
+      } else if (ctrl->is_Region()) {
+        Node* n = ctrl->as_Region()->is_copy();
+        if (n == NULL) {
+          break;
+        }
+        ctrl = n;
+      } else {
+        break;
+      }
+    }
+
+    parser = parser->parent_parser();
+  }
 }
 
 
@@ -2043,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'
@@ -2580,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))
@@ -2591,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.
@@ -2611,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.
@@ -2620,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()),
@@ -2637,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));
@@ -2664,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
@@ -2718,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.
@@ -2767,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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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/ifnode.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/ifnode.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1019,7 +1019,7 @@
   // be skipped. For example, range check predicate has two checks
   // for lower and upper bounds.
   ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj();
-  if (PhaseIdealLoop::is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate))
+  if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
     prev_dom = idom;
 
   // Now walk the current IfNode's projections.
--- a/hotspot/src/share/vm/opto/library_call.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -63,7 +63,7 @@
   virtual bool is_virtual()   const { return _is_virtual; }
   virtual bool is_predicted()   const { return _is_predicted; }
   virtual bool does_virtual_dispatch()   const { return _does_virtual_dispatch; }
-  virtual JVMState* generate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
   virtual Node* generate_predicate(JVMState* jvms);
   vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
 };
@@ -203,8 +203,15 @@
   bool inline_math_native(vmIntrinsics::ID id);
   bool inline_trig(vmIntrinsics::ID id);
   bool inline_math(vmIntrinsics::ID id);
-  bool inline_math_mathExact(Node* math);
-  bool inline_math_addExact();
+  void inline_math_mathExact(Node* math);
+  bool inline_math_addExactI(bool is_increment);
+  bool inline_math_addExactL(bool is_increment);
+  bool inline_math_multiplyExactI();
+  bool inline_math_multiplyExactL();
+  bool inline_math_negateExactI();
+  bool inline_math_negateExactL();
+  bool inline_math_subtractExactI(bool is_decrement);
+  bool inline_math_subtractExactL(bool is_decrement);
   bool inline_exp();
   bool inline_pow();
   void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName);
@@ -507,13 +514,33 @@
     if (!UseCRC32Intrinsics) return NULL;
     break;
 
-  case vmIntrinsics::_addExact:
-    if (!Matcher::match_rule_supported(Op_AddExactI)) {
-      return NULL;
-    }
-    if (!UseMathExactIntrinsics) {
-      return NULL;
-    }
+  case vmIntrinsics::_incrementExactI:
+  case vmIntrinsics::_addExactI:
+    if (!Matcher::match_rule_supported(Op_AddExactI) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_incrementExactL:
+  case vmIntrinsics::_addExactL:
+    if (!Matcher::match_rule_supported(Op_AddExactL) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_decrementExactI:
+  case vmIntrinsics::_subtractExactI:
+    if (!Matcher::match_rule_supported(Op_SubExactI) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_decrementExactL:
+  case vmIntrinsics::_subtractExactL:
+    if (!Matcher::match_rule_supported(Op_SubExactL) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_negateExactI:
+    if (!Matcher::match_rule_supported(Op_NegExactI) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_negateExactL:
+    if (!Matcher::match_rule_supported(Op_NegExactL) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_multiplyExactI:
+    if (!Matcher::match_rule_supported(Op_MulExactI) || !UseMathExactIntrinsics) return NULL;
+    break;
+  case vmIntrinsics::_multiplyExactL:
+    if (!Matcher::match_rule_supported(Op_MulExactL) || !UseMathExactIntrinsics) return NULL;
     break;
 
  default:
@@ -556,7 +583,7 @@
   // Nothing to do here.
 }
 
-JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
+JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) {
   LibraryCallKit kit(jvms, this);
   Compile* C = kit.C;
   int nodes = C->unique();
@@ -686,7 +713,18 @@
   case vmIntrinsics::_min:
   case vmIntrinsics::_max:                      return inline_min_max(intrinsic_id());
 
-  case vmIntrinsics::_addExact:                 return inline_math_addExact();
+  case vmIntrinsics::_addExactI:                return inline_math_addExactI(false /* add */);
+  case vmIntrinsics::_addExactL:                return inline_math_addExactL(false /* add */);
+  case vmIntrinsics::_decrementExactI:          return inline_math_subtractExactI(true /* decrement */);
+  case vmIntrinsics::_decrementExactL:          return inline_math_subtractExactL(true /* decrement */);
+  case vmIntrinsics::_incrementExactI:          return inline_math_addExactI(true /* increment */);
+  case vmIntrinsics::_incrementExactL:          return inline_math_addExactL(true /* increment */);
+  case vmIntrinsics::_multiplyExactI:           return inline_math_multiplyExactI();
+  case vmIntrinsics::_multiplyExactL:           return inline_math_multiplyExactL();
+  case vmIntrinsics::_negateExactI:             return inline_math_negateExactI();
+  case vmIntrinsics::_negateExactL:             return inline_math_negateExactL();
+  case vmIntrinsics::_subtractExactI:           return inline_math_subtractExactI(false /* subtract */);
+  case vmIntrinsics::_subtractExactL:           return inline_math_subtractExactL(false /* subtract */);
 
   case vmIntrinsics::_arraycopy:                return inline_arraycopy();
 
@@ -1931,7 +1969,14 @@
   return true;
 }
 
-bool LibraryCallKit::inline_math_mathExact(Node* math) {
+void LibraryCallKit::inline_math_mathExact(Node* math) {
+  // If we didn't get the expected opcode it means we have optimized
+  // the node to something else and don't need the exception edge.
+  if (!math->is_MathExact()) {
+    set_result(math);
+    return;
+  }
+
   Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node));
   Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node));
 
@@ -1954,19 +1999,106 @@
 
   set_control(fast_path);
   set_result(result);
+}
+
+bool LibraryCallKit::inline_math_addExactI(bool is_increment) {
+  Node* arg1 = argument(0);
+  Node* arg2 = NULL;
+
+  if (is_increment) {
+      arg2 = intcon(1);
+  } else {
+      arg2 = argument(1);
+  }
+
+  Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) );
+  inline_math_mathExact(add);
+  return true;
+}
+
+bool LibraryCallKit::inline_math_addExactL(bool is_increment) {
+  Node* arg1 = argument(0); // type long
+  // argument(1) == TOP
+  Node* arg2 = NULL;
+
+  if (is_increment) {
+    arg2 = longcon(1);
+  } else {
+    arg2 = argument(2); // type long
+    // argument(3) == TOP
+  }
+
+  Node* add = _gvn.transform(new(C) AddExactLNode(NULL, arg1, arg2));
+  inline_math_mathExact(add);
   return true;
 }
 
-bool LibraryCallKit::inline_math_addExact() {
+bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) {
+  Node* arg1 = argument(0);
+  Node* arg2 = NULL;
+
+  if (is_decrement) {
+    arg2 = intcon(1);
+  } else {
+    arg2 = argument(1);
+  }
+
+  Node* sub = _gvn.transform(new(C) SubExactINode(NULL, arg1, arg2));
+  inline_math_mathExact(sub);
+  return true;
+}
+
+bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) {
+  Node* arg1 = argument(0); // type long
+  // argument(1) == TOP
+  Node* arg2 = NULL;
+
+  if (is_decrement) {
+    arg2 = longcon(1);
+  } else {
+    Node* arg2 = argument(2); // type long
+    // argument(3) == TOP
+  }
+
+  Node* sub = _gvn.transform(new(C) SubExactLNode(NULL, arg1, arg2));
+  inline_math_mathExact(sub);
+  return true;
+}
+
+bool LibraryCallKit::inline_math_negateExactI() {
+  Node* arg1 = argument(0);
+
+  Node* neg = _gvn.transform(new(C) NegExactINode(NULL, arg1));
+  inline_math_mathExact(neg);
+  return true;
+}
+
+bool LibraryCallKit::inline_math_negateExactL() {
+  Node* arg1 = argument(0);
+  // argument(1) == TOP
+
+  Node* neg = _gvn.transform(new(C) NegExactLNode(NULL, arg1));
+  inline_math_mathExact(neg);
+  return true;
+}
+
+bool LibraryCallKit::inline_math_multiplyExactI() {
   Node* arg1 = argument(0);
   Node* arg2 = argument(1);
 
-  Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) );
-  if (add->Opcode() == Op_AddExactI) {
-    return inline_math_mathExact(add);
-  } else {
-    set_result(add);
-  }
+  Node* mul = _gvn.transform(new(C) MulExactINode(NULL, arg1, arg2));
+  inline_math_mathExact(mul);
+  return true;
+}
+
+bool LibraryCallKit::inline_math_multiplyExactL() {
+  Node* arg1 = argument(0);
+  // argument(1) == TOP
+  Node* arg2 = argument(2);
+  // argument(3) == TOP
+
+  Node* mul = _gvn.transform(new(C) MulExactLNode(NULL, arg1, arg2));
+  inline_math_mathExact(mul);
   return true;
 }
 
@@ -3353,6 +3485,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 +3496,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 +4686,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 +4776,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/loopPredicate.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -41,63 +41,6 @@
  * checks (such as null checks).
 */
 
-//-------------------------------is_uncommon_trap_proj----------------------------
-// Return true if proj is the form of "proj->[region->..]call_uct"
-bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, Deoptimization::DeoptReason reason) {
-  int path_limit = 10;
-  assert(proj, "invalid argument");
-  Node* out = proj;
-  for (int ct = 0; ct < path_limit; ct++) {
-    out = out->unique_ctrl_out();
-    if (out == NULL)
-      return false;
-    if (out->is_CallStaticJava()) {
-      int req = out->as_CallStaticJava()->uncommon_trap_request();
-      if (req != 0) {
-        Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
-        if (trap_reason == reason || reason == Deoptimization::Reason_none) {
-           return true;
-        }
-      }
-      return false; // don't do further after call
-    }
-    if (out->Opcode() != Op_Region)
-      return false;
-  }
-  return false;
-}
-
-//-------------------------------is_uncommon_trap_if_pattern-------------------------
-// Return true  for "if(test)-> proj -> ...
-//                          |
-//                          V
-//                      other_proj->[region->..]call_uct"
-//
-// "must_reason_predicate" means the uct reason must be Reason_predicate
-bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, Deoptimization::DeoptReason reason) {
-  Node *in0 = proj->in(0);
-  if (!in0->is_If()) return false;
-  // Variation of a dead If node.
-  if (in0->outcnt() < 2)  return false;
-  IfNode* iff = in0->as_If();
-
-  // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate
-  if (reason != Deoptimization::Reason_none) {
-    if (iff->in(1)->Opcode() != Op_Conv2B ||
-       iff->in(1)->in(1)->Opcode() != Op_Opaque1) {
-      return false;
-    }
-  }
-
-  ProjNode* other_proj = iff->proj_out(1-proj->_con)->as_Proj();
-  if (is_uncommon_trap_proj(other_proj, reason)) {
-    assert(reason == Deoptimization::Reason_none ||
-           Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list");
-    return true;
-  }
-  return false;
-}
-
 //-------------------------------register_control-------------------------
 void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred) {
   assert(n->is_CFG(), "must be control node");
@@ -147,7 +90,7 @@
 // This code is also used to clone predicates to clonned loops.
 ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
                                                       Deoptimization::DeoptReason reason) {
-  assert(is_uncommon_trap_if_pattern(cont_proj, reason), "must be a uct if pattern!");
+  assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!");
   IfNode* iff = cont_proj->in(0)->as_If();
 
   ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con);
@@ -235,7 +178,7 @@
 ProjNode* PhaseIterGVN::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
                                                     Deoptimization::DeoptReason reason) {
   assert(new_entry != 0, "only used for clone predicate");
-  assert(PhaseIdealLoop::is_uncommon_trap_if_pattern(cont_proj, reason), "must be a uct if pattern!");
+  assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!");
   IfNode* iff = cont_proj->in(0)->as_If();
 
   ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con);
@@ -422,7 +365,7 @@
 ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c, Deoptimization::DeoptReason reason) {
   if (start_c == NULL || !start_c->is_Proj())
     return NULL;
-  if (is_uncommon_trap_if_pattern(start_c->as_Proj(), reason)) {
+  if (start_c->as_Proj()->is_uncommon_trap_if_pattern(reason)) {
     return start_c->as_Proj();
   }
   return NULL;
@@ -773,7 +716,7 @@
     ProjNode* proj = if_proj_list.pop()->as_Proj();
     IfNode*   iff  = proj->in(0)->as_If();
 
-    if (!is_uncommon_trap_if_pattern(proj, Deoptimization::Reason_none)) {
+    if (!proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
       if (loop->is_loop_exit(iff)) {
         // stop processing the remaining projs in the list because the execution of them
         // depends on the condition of "iff" (iff->in(1)).
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -167,7 +167,7 @@
     // expensive nodes will notice the loop and skip over it to try to
     // move the node further up.
     if (ctl->is_CountedLoop() && ctl->in(1) != NULL && ctl->in(1)->in(0) != NULL && ctl->in(1)->in(0)->is_If()) {
-      if (!is_uncommon_trap_if_pattern(ctl->in(1)->as_Proj(), Deoptimization::Reason_none)) {
+      if (!ctl->in(1)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
         break;
       }
       next = idom(ctl->in(1)->in(0));
@@ -181,7 +181,7 @@
       } else if (parent_ctl->is_CountedLoopEnd() && parent_ctl->as_CountedLoopEnd()->loopnode() != NULL) {
         next = parent_ctl->as_CountedLoopEnd()->loopnode()->init_control();
       } else if (parent_ctl->is_If()) {
-        if (!is_uncommon_trap_if_pattern(ctl->as_Proj(), Deoptimization::Reason_none)) {
+        if (!ctl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
           break;
         }
         assert(idom(ctl) == parent_ctl, "strange");
--- a/hotspot/src/share/vm/opto/loopnode.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/loopnode.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -876,13 +876,6 @@
   // Return true if exp is a scaled induction var plus (or minus) constant
   bool is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset, int depth = 0);
 
-  // Return true if proj is for "proj->[region->..]call_uct"
-  static bool is_uncommon_trap_proj(ProjNode* proj, Deoptimization::DeoptReason reason);
-  // Return true for    "if(test)-> proj -> ...
-  //                          |
-  //                          V
-  //                      other_proj->[region->..]call_uct"
-  static bool is_uncommon_trap_if_pattern(ProjNode* proj, Deoptimization::DeoptReason reason);
   // Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted
   ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
                                         Deoptimization::DeoptReason reason);
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -238,7 +238,7 @@
   ProjNode* dp_proj  = dp->as_Proj();
   ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj();
   if (exclude_loop_predicate &&
-      is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate))
+      unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
     return; // Let IGVN transformation change control dependence.
 
   IdealLoopTree *old_loop = get_loop(dp);
--- a/hotspot/src/share/vm/opto/matcher.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/matcher.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -338,6 +338,7 @@
   static RegMask modL_proj_mask();
 
   static const RegMask mathExactI_result_proj_mask();
+  static const RegMask mathExactL_result_proj_mask();
   static const RegMask mathExactI_flags_proj_mask();
 
   // Use hardware DIV instruction when it is faster than
--- a/hotspot/src/share/vm/opto/mathexactnode.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/mathexactnode.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -31,10 +31,17 @@
 #include "opto/mathexactnode.hpp"
 #include "opto/subnode.hpp"
 
-MathExactNode::MathExactNode(Node* ctrl, Node* n1, Node* n2) : MultiNode(3) {
+MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) {
+  init_class_id(Class_MathExact);
   init_req(0, ctrl);
-  init_req(1, n1);
-  init_req(2, n2);
+  init_req(1, in1);
+}
+
+MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) {
+  init_class_id(Class_MathExact);
+  init_req(0, ctrl);
+  init_req(1, in1);
+  init_req(2, in2);
 }
 
 BoolNode* MathExactNode::bool_node() const {
@@ -64,23 +71,10 @@
   return ifnode->proj_out(1);
 }
 
-Node* AddExactINode::match(const ProjNode* proj, const Matcher* m) {
-  uint ideal_reg = proj->ideal_reg();
-  RegMask rm;
-  if (proj->_con == result_proj_node) {
-    rm = m->mathExactI_result_proj_mask();
-  } else {
-    assert(proj->_con == flags_proj_node, "must be result or flags");
-    assert(ideal_reg == Op_RegFlags, "sanity");
-    rm = m->mathExactI_flags_proj_mask();
-  }
-  return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
-}
-
 // If the MathExactNode won't overflow we have to replace the
 // FlagsProjNode and ProjNode that is generated by the MathExactNode
-Node* MathExactNode::no_overflow(PhaseGVN *phase, Node* new_result) {
-  PhaseIterGVN *igvn = phase->is_IterGVN();
+Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) {
+  PhaseIterGVN* igvn = phase->is_IterGVN();
   if (igvn) {
     ProjNode* result = result_node();
     ProjNode* flags = flags_node();
@@ -110,9 +104,35 @@
   return new_result;
 }
 
-Node *AddExactINode::Ideal(PhaseGVN *phase, bool can_reshape) {
-  Node *arg1 = in(1);
-  Node *arg2 = in(2);
+Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) {
+  uint ideal_reg = proj->ideal_reg();
+  RegMask rm;
+  if (proj->_con == result_proj_node) {
+    rm = m->mathExactI_result_proj_mask();
+  } else {
+    assert(proj->_con == flags_proj_node, "must be result or flags");
+    assert(ideal_reg == Op_RegFlags, "sanity");
+    rm = m->mathExactI_flags_proj_mask();
+  }
+  return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
+}
+
+Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) {
+  uint ideal_reg = proj->ideal_reg();
+  RegMask rm;
+  if (proj->_con == result_proj_node) {
+    rm = m->mathExactL_result_proj_mask();
+  } else {
+    assert(proj->_con == flags_proj_node, "must be result or flags");
+    assert(ideal_reg == Op_RegFlags, "sanity");
+    rm = m->mathExactI_flags_proj_mask();
+  }
+  return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
+}
+
+Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node* arg1 = in(1);
+  Node* arg2 = in(2);
 
   const Type* type1 = phase->type(arg1);
   const Type* type2 = phase->type(arg2);
@@ -130,12 +150,7 @@
     return NULL;
   }
 
-  if (type1 == TypeInt::ZERO) { // (Add 0 x) == x
-    Node* add_result = new (phase->C) AddINode(arg1, arg2);
-    return no_overflow(phase, add_result);
-  }
-
-  if (type2 == TypeInt::ZERO) { // (Add x 0) == x
+  if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x
     Node* add_result = new (phase->C) AddINode(arg1, arg2);
     return no_overflow(phase, add_result);
   }
@@ -169,3 +184,247 @@
   return NULL;
 }
 
+Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node* arg1 = in(1);
+  Node* arg2 = in(2);
+
+  const Type* type1 = phase->type(arg1);
+  const Type* type2 = phase->type(arg2);
+
+  if (type1 != Type::TOP && type1->singleton() &&
+      type2 != Type::TOP && type2->singleton()) {
+    jlong val1 = arg1->get_long();
+    jlong val2 = arg2->get_long();
+    jlong result = val1 + val2;
+    // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result
+    if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) {
+      Node* con_result = ConLNode::make(phase->C, result);
+      return no_overflow(phase, con_result);
+    }
+    return NULL;
+  }
+
+  if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x
+    Node* add_result = new (phase->C) AddLNode(arg1, arg2);
+    return no_overflow(phase, add_result);
+  }
+
+  if (type2->singleton()) {
+    return NULL; // no change - keep constant on the right
+  }
+
+  if (type1->singleton()) {
+    // Make it x + Constant - move constant to the right
+    swap_edges(1, 2);
+    return this;
+  }
+
+  if (arg2->is_Load()) {
+    return NULL; // no change - keep load on the right
+  }
+
+  if (arg1->is_Load()) {
+    // Make it x + Load - move load to the right
+    swap_edges(1, 2);
+    return this;
+  }
+
+  if (arg1->_idx > arg2->_idx) {
+    // Sort the edges
+    swap_edges(1, 2);
+    return this;
+  }
+
+  return NULL;
+}
+
+Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node* arg1 = in(1);
+  Node* arg2 = in(2);
+
+  const Type* type1 = phase->type(arg1);
+  const Type* type2 = phase->type(arg2);
+
+  if (type1 != Type::TOP && type1->singleton() &&
+      type2 != Type::TOP && type2->singleton()) {
+    jint val1 = arg1->get_int();
+    jint val2 = arg2->get_int();
+    jint result = val1 - val2;
+
+    // Hacker's Delight 2-12 Overflow iff the arguments have different signs and
+    // the sign of the result is different than the sign of arg1
+    if (((val1 ^ val2) & (val1 ^ result)) >= 0) {
+      Node* con_result = ConINode::make(phase->C, result);
+      return no_overflow(phase, con_result);
+    }
+    return NULL;
+  }
+
+  if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) {
+    // Sub with zero is the same as add with zero
+    Node* add_result = new (phase->C) AddINode(arg1, arg2);
+    return no_overflow(phase, add_result);
+  }
+
+  return NULL;
+}
+
+Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node* arg1 = in(1);
+  Node* arg2 = in(2);
+
+  const Type* type1 = phase->type(arg1);
+  const Type* type2 = phase->type(arg2);
+
+  if (type1 != Type::TOP && type1->singleton() &&
+      type2 != Type::TOP && type2->singleton()) {
+    jlong val1 = arg1->get_long();
+    jlong val2 = arg2->get_long();
+    jlong result = val1 - val2;
+
+    // Hacker's Delight 2-12 Overflow iff the arguments have different signs and
+    // the sign of the result is different than the sign of arg1
+    if (((val1 ^ val2) & (val1 ^ result)) >= 0) {
+      Node* con_result = ConLNode::make(phase->C, result);
+      return no_overflow(phase, con_result);
+    }
+    return NULL;
+  }
+
+  if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) {
+    // Sub with zero is the same as add with zero
+    Node* add_result = new (phase->C) AddLNode(arg1, arg2);
+    return no_overflow(phase, add_result);
+  }
+
+  return NULL;
+}
+
+Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node *arg = in(1);
+
+  const Type* type = phase->type(arg);
+  if (type != Type::TOP && type->singleton()) {
+    jint value = arg->get_int();
+    if (value != min_jint) {
+      Node* neg_result = ConINode::make(phase->C, -value);
+      return no_overflow(phase, neg_result);
+    }
+  }
+  return NULL;
+}
+
+Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node *arg = in(1);
+
+  const Type* type = phase->type(arg);
+  if (type != Type::TOP && type->singleton()) {
+    jlong value = arg->get_long();
+    if (value != min_jlong) {
+      Node* neg_result = ConLNode::make(phase->C, -value);
+      return no_overflow(phase, neg_result);
+    }
+  }
+  return NULL;
+}
+
+Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node* arg1 = in(1);
+  Node* arg2 = in(2);
+
+  const Type* type1 = phase->type(arg1);
+  const Type* type2 = phase->type(arg2);
+
+  if (type1 != Type::TOP && type1->singleton() &&
+      type2 != Type::TOP && type2->singleton()) {
+    jint val1 = arg1->get_int();
+    jint val2 = arg2->get_int();
+    jlong result = (jlong) val1 * (jlong) val2;
+    if ((jint) result == result) {
+      // no overflow
+      Node* mul_result = ConINode::make(phase->C, result);
+      return no_overflow(phase, mul_result);
+    }
+  }
+
+  if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) {
+    return no_overflow(phase, ConINode::make(phase->C, 0));
+  }
+
+  if (type1 == TypeInt::ONE) {
+    Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0));
+    return no_overflow(phase, mul_result);
+  }
+  if (type2 == TypeInt::ONE) {
+    Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0));
+    return no_overflow(phase, mul_result);
+  }
+
+  if (type1 == TypeInt::MINUS_1) {
+    return new (phase->C) NegExactINode(NULL, arg2);
+  }
+
+  if (type2 == TypeInt::MINUS_1) {
+    return new (phase->C) NegExactINode(NULL, arg1);
+  }
+
+  return NULL;
+}
+
+Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  Node* arg1 = in(1);
+  Node* arg2 = in(2);
+
+  const Type* type1 = phase->type(arg1);
+  const Type* type2 = phase->type(arg2);
+
+  if (type1 != Type::TOP && type1->singleton() &&
+      type2 != Type::TOP && type2->singleton()) {
+    jlong val1 = arg1->get_long();
+    jlong val2 = arg2->get_long();
+
+    jlong result = val1 * val2;
+    jlong ax = (val1 < 0 ? -val1 : val1);
+    jlong ay = (val2 < 0 ? -val2 : val2);
+
+    bool overflow = false;
+    if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) {
+      // potential overflow if any bit in upper 32 bits are set
+      if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) {
+        // -1 * Long.MIN_VALUE will overflow
+        overflow = true;
+      } else if (val2 != 0 && (result / val2 != val1)) {
+        overflow = true;
+      }
+    }
+
+    if (!overflow) {
+      Node* mul_result = ConLNode::make(phase->C, result);
+      return no_overflow(phase, mul_result);
+    }
+  }
+
+  if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) {
+    return no_overflow(phase, ConLNode::make(phase->C, 0));
+  }
+
+  if (type1 == TypeLong::ONE) {
+    Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0));
+    return no_overflow(phase, mul_result);
+  }
+  if (type2 == TypeLong::ONE) {
+    Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0));
+    return no_overflow(phase, mul_result);
+  }
+
+  if (type1 == TypeLong::MINUS_1) {
+    return new (phase->C) NegExactLNode(NULL, arg2);
+  }
+
+  if (type2 == TypeLong::MINUS_1) {
+    return new (phase->C) NegExactLNode(NULL, arg1);
+  }
+
+  return NULL;
+}
+
--- a/hotspot/src/share/vm/opto/mathexactnode.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/mathexactnode.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -39,6 +39,7 @@
 
 class MathExactNode : public MultiNode {
 public:
+  MathExactNode(Node* ctrl, Node* in1);
   MathExactNode(Node* ctrl, Node* in1, Node* in2);
   enum {
     result_proj_node = 0,
@@ -62,13 +63,78 @@
   Node* no_overflow(PhaseGVN *phase, Node* new_result);
 };
 
-class AddExactINode : public MathExactNode {
+class MathExactINode : public MathExactNode {
+ public:
+  MathExactINode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {}
+  MathExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node* match(const ProjNode* proj, const Matcher* m);
+  virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; }
+};
+
+class MathExactLNode : public MathExactNode {
 public:
-  AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
+  MathExactLNode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {}
+  MathExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node* match(const ProjNode* proj, const Matcher* m);
+  virtual const Type* bottom_type() const { return TypeTuple::LONG_CC_PAIR; }
+};
+
+class AddExactINode : public MathExactINode {
+public:
+  AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
+class AddExactLNode : public MathExactLNode {
+public:
+  AddExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class SubExactINode : public MathExactINode {
+public:
+  SubExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {}
   virtual int Opcode() const;
-  virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; }
-  virtual Node* match(const ProjNode* proj, const Matcher* m);
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class SubExactLNode : public MathExactLNode {
+public:
+  SubExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class NegExactINode : public MathExactINode {
+public:
+  NegExactINode(Node* ctrl, Node* in1) : MathExactINode(ctrl, in1) {}
+  virtual int Opcode() const;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class NegExactLNode : public MathExactLNode {
+public:
+  NegExactLNode(Node* ctrl, Node* in1) : MathExactLNode(ctrl, in1) {}
+  virtual int Opcode() const;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class MulExactINode : public MathExactINode {
+public:
+  MulExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class MulExactLNode : public MathExactLNode {
+public:
+  MulExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {}
+  virtual int Opcode() const;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
 };
 
 class FlagsProjNode : public ProjNode {
--- a/hotspot/src/share/vm/opto/multnode.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/multnode.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "opto/callnode.hpp"
+#include "opto/cfgnode.hpp"
 #include "opto/matcher.hpp"
 #include "opto/mathexactnode.hpp"
 #include "opto/multnode.hpp"
@@ -150,3 +151,59 @@
 uint ProjNode::ideal_reg() const {
   return bottom_type()->ideal_reg();
 }
+
+//-------------------------------is_uncommon_trap_proj----------------------------
+// Return true if proj is the form of "proj->[region->..]call_uct"
+bool ProjNode::is_uncommon_trap_proj(Deoptimization::DeoptReason reason) {
+  int path_limit = 10;
+  Node* out = this;
+  for (int ct = 0; ct < path_limit; ct++) {
+    out = out->unique_ctrl_out();
+    if (out == NULL)
+      return false;
+    if (out->is_CallStaticJava()) {
+      int req = out->as_CallStaticJava()->uncommon_trap_request();
+      if (req != 0) {
+        Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
+        if (trap_reason == reason || reason == Deoptimization::Reason_none) {
+           return true;
+        }
+      }
+      return false; // don't do further after call
+    }
+    if (out->Opcode() != Op_Region)
+      return false;
+  }
+  return false;
+}
+
+//-------------------------------is_uncommon_trap_if_pattern-------------------------
+// Return true  for "if(test)-> proj -> ...
+//                          |
+//                          V
+//                      other_proj->[region->..]call_uct"
+//
+// "must_reason_predicate" means the uct reason must be Reason_predicate
+bool ProjNode::is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason) {
+  Node *in0 = in(0);
+  if (!in0->is_If()) return false;
+  // Variation of a dead If node.
+  if (in0->outcnt() < 2)  return false;
+  IfNode* iff = in0->as_If();
+
+  // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate
+  if (reason != Deoptimization::Reason_none) {
+    if (iff->in(1)->Opcode() != Op_Conv2B ||
+       iff->in(1)->in(1)->Opcode() != Op_Opaque1) {
+      return false;
+    }
+  }
+
+  ProjNode* other_proj = iff->proj_out(1-_con)->as_Proj();
+  if (other_proj->is_uncommon_trap_proj(reason)) {
+    assert(reason == Deoptimization::Reason_none ||
+           Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list");
+    return true;
+  }
+  return false;
+}
--- a/hotspot/src/share/vm/opto/multnode.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/multnode.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -88,6 +88,14 @@
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
 #endif
+
+  // Return true if proj is for "proj->[region->..]call_uct"
+  bool is_uncommon_trap_proj(Deoptimization::DeoptReason reason);
+  // Return true for    "if(test)-> proj -> ...
+  //                          |
+  //                          V
+  //                      other_proj->[region->..]call_uct"
+  bool is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason);
 };
 
 #endif // SHARE_VM_OPTO_MULTNODE_HPP
--- a/hotspot/src/share/vm/opto/node.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/node.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -100,6 +100,7 @@
 class MachSpillCopyNode;
 class MachTempNode;
 class Matcher;
+class MathExactNode;
 class MemBarNode;
 class MemBarStoreStoreNode;
 class MemNode;
@@ -568,6 +569,7 @@
       DEFINE_CLASS_ID(MemBar,      Multi, 3)
         DEFINE_CLASS_ID(Initialize,       MemBar, 0)
         DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1)
+      DEFINE_CLASS_ID(MathExact,   Multi, 4)
 
     DEFINE_CLASS_ID(Mach,  Node, 1)
       DEFINE_CLASS_ID(MachReturn, Mach, 0)
@@ -757,6 +759,7 @@
   DEFINE_CLASS_QUERY(MachSafePoint)
   DEFINE_CLASS_QUERY(MachSpillCopy)
   DEFINE_CLASS_QUERY(MachTemp)
+  DEFINE_CLASS_QUERY(MathExact)
   DEFINE_CLASS_QUERY(Mem)
   DEFINE_CLASS_QUERY(MemBar)
   DEFINE_CLASS_QUERY(MemBarStoreStore)
--- a/hotspot/src/share/vm/opto/parse.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/parse.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -349,13 +349,15 @@
   int _est_switch_depth;        // Debugging SwitchRanges.
 #endif
 
+  // parser for the caller of the method of this object
+  Parse* const _parent;
+
  public:
   // Constructor
-  Parse(JVMState* caller, ciMethod* parse_method, float expected_uses);
+  Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent);
 
   virtual Parse* is_Parse() const { return (Parse*)this; }
 
- public:
   // Accessors.
   JVMState*     caller()        const { return _caller; }
   float         expected_uses() const { return _expected_uses; }
@@ -407,6 +409,8 @@
     return block()->successor_for_bci(bci);
   }
 
+  Parse* parent_parser() const { return _parent; }
+
  private:
   // Create a JVMS & map for the initial state of this method.
   SafePointNode* create_entry_map();
@@ -603,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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -381,8 +381,8 @@
 
 //------------------------------Parse------------------------------------------
 // Main parser constructor.
-Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
-  : _exits(caller)
+Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent)
+  : _exits(caller), _parent(parent)
 {
   // Init some variables
   _caller = caller;
@@ -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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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/reg_split.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/reg_split.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -51,15 +51,6 @@
 
 static const char out_of_nodes[] = "out of nodes during split";
 
-static bool contains_no_live_range_input(const Node* def) {
-  for (uint i = 1; i < def->req(); ++i) {
-    if (def->in(i) != NULL && def->in_RegMask(i).is_NotEmpty()) {
-      return false;
-    }
-  }
-  return true;
-}
-
 //------------------------------get_spillcopy_wide-----------------------------
 // Get a SpillCopy node with wide-enough masks.  Use the 'wide-mask', the
 // wide ideal-register spill-mask if possible.  If the 'wide-mask' does
@@ -326,12 +317,11 @@
   if( def->req() > 1 ) {
     for( uint i = 1; i < def->req(); i++ ) {
       Node *in = def->in(i);
-      // Check for single-def (LRG cannot redefined)
       uint lidx = _lrg_map.live_range_id(in);
-      if (lidx >= _lrg_map.max_lrg_id()) {
-        continue; // Value is a recent spill-copy
-      }
-      if (lrgs(lidx).is_singledef()) {
+      // We do not need this for live ranges that are only defined once.
+      // However, this is not true for spill copies that are added in this
+      // Split() pass, since they might get coalesced later on in this pass.
+      if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).is_singledef()) {
         continue;
       }
 
@@ -375,7 +365,6 @@
       }
 
       if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).reg() >= LRG::SPILL_REG) {
-        assert(Reachblock != NULL, "Reachblock must be non-NULL");
         Node *rdef = Reachblock[lrg2reach[lidx]];
         if (rdef) {
           spill->set_req(i, rdef);
@@ -486,7 +475,6 @@
 
   uint                 bidx, pidx, slidx, insidx, inpidx, twoidx;
   uint                 non_phi = 1, spill_cnt = 0;
-  Node               **Reachblock;
   Node                *n1, *n2, *n3;
   Node_List           *defs,*phis;
   bool                *UPblock;
@@ -569,7 +557,7 @@
 
     b  = _cfg.get_block(bidx);
     // Reaches & UP arrays for this block
-    Reachblock = Reaches[b->_pre_order];
+    Node** Reachblock = Reaches[b->_pre_order];
     UPblock    = UP[b->_pre_order];
     // Reset counter of start of non-Phi nodes in block
     non_phi = 1;
@@ -1325,9 +1313,10 @@
       pidx = pred->_pre_order;
       // Grab reaching def
       Node *def = Reaches[pidx][slidx];
+      Node** Reachblock = Reaches[pidx];
       assert( def, "must have reaching def" );
       // If input up/down sense and reg-pressure DISagree
-      if (def->rematerialize() && contains_no_live_range_input(def)) {
+      if (def->rematerialize()) {
         // Place the rematerialized node above any MSCs created during
         // phi node splitting.  end_idx points at the insertion point
         // so look at the node before it.
@@ -1337,8 +1326,7 @@
                _lrg_map.find(pred->get_node(insert - 1)) >= lrgs_before_phi_split) {
           insert--;
         }
-        // since the def cannot contain any live range input, we can pass in NULL as Reachlock parameter
-        def = split_Rematerialize(def, pred, insert, maxlrg, splits, slidx, lrg2reach, NULL, false);
+        def = split_Rematerialize(def, pred, insert, maxlrg, splits, slidx, lrg2reach, Reachblock, false);
         if (!def) {
           return 0;    // Bail out
         }
--- a/hotspot/src/share/vm/opto/type.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/type.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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);
 
@@ -435,6 +435,11 @@
   intccpair[1] = TypeInt::CC;
   TypeTuple::INT_CC_PAIR = TypeTuple::make(2, intccpair);
 
+  const Type **longccpair = TypeTuple::fields(2);
+  longccpair[0] = TypeLong::LONG;
+  longccpair[1] = TypeInt::CC;
+  TypeTuple::LONG_CC_PAIR = TypeTuple::make(2, longccpair);
+
   _const_basic_type[T_NARROWOOP]   = TypeNarrowOop::BOTTOM;
   _const_basic_type[T_NARROWKLASS] = Type::BOTTOM;
   _const_basic_type[T_BOOLEAN]     = TypeInt::BOOL;
@@ -577,7 +582,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 +600,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-------------------------------------------
@@ -1652,6 +1680,7 @@
 const TypeTuple *TypeTuple::INT_PAIR;
 const TypeTuple *TypeTuple::LONG_PAIR;
 const TypeTuple *TypeTuple::INT_CC_PAIR;
+const TypeTuple *TypeTuple::LONG_CC_PAIR;
 
 
 //------------------------------make-------------------------------------------
@@ -2407,14 +2436,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 +2511,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 +2524,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 +2554,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 +2620,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 +2633,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 +2651,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 +2742,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 +2842,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 +2860,7 @@
     (const_oop() ? const_oop()->hash() : 0) +
     _klass_is_exact +
     _instance_id +
+    hash_speculative() +
     TypePtr::hash();
 }
 
@@ -2825,6 +2880,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 +2906,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 +2934,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 +3027,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 +3040,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 +3062,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 +3095,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 +3107,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 +3123,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 +3144,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 +3166,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 +3200,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 +3222,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 +3236,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 +3250,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 +3271,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 +3309,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 +3338,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 +3380,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 +3457,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 +3468,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 +3492,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 +3548,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 +3576,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 +3608,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 +3677,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 +3726,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 +3760,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 +3790,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 +3808,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 +3836,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 +3844,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 +3861,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 +3888,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 +3910,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 +3924,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 +3935,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 +3987,8 @@
     st->print(",iid=top");
   else if (_instance_id != InstanceBot)
     st->print(",iid=%d",_instance_id);
+
+  dump_speculative(st);
 }
 #endif
 
@@ -3805,10 +3998,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	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/opto/type.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -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[];
@@ -585,6 +593,7 @@
   static const TypeTuple *INT_PAIR;
   static const TypeTuple *LONG_PAIR;
   static const TypeTuple *INT_CC_PAIR;
+  static const TypeTuple *LONG_CC_PAIR;
 #ifndef PRODUCT
   virtual void dump2( Dict &d, uint, outputStream *st  ) const; // Specialized per-Type dumping
 #endif
@@ -784,7 +793,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 +819,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 +866,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 +880,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 +894,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 +910,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 +940,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 +980,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 +1003,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 +1042,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 +1058,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/prims/methodHandles.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1194,9 +1194,7 @@
   } else if (vmtarget->is_klass()) {
     x = ((Klass*) vmtarget)->java_mirror();
   } else if (vmtarget->is_method()) {
-    Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
-    CallInfo info((Method*)vmtarget);
-    x = MethodHandles::init_method_MemberName(mname2, info);
+    x = mname();
   }
   result->obj_at_put(1, x);
   return JNIHandles::make_local(env, result());
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1957,12 +1957,6 @@
                 "please refer to the release notes for the combinations "
                 "allowed\n");
     status = false;
-  } else if (ReservedCodeCacheSize > 2*G) {
-    // Code cache size larger than MAXINT is not supported.
-    jio_fprintf(defaultStream::error_stream(),
-                "Invalid ReservedCodeCacheSize=%dM. Must be at most %uM.\n", ReservedCodeCacheSize/M,
-                (2*G)/M);
-    status = false;
   }
   return status;
 }
@@ -3721,6 +3715,18 @@
     // 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);
+  }
+#ifndef X86
+  // Only on x86 for now
+  FLAG_SET_DEFAULT(TypeProfileLevel, 0);
+#endif
 #endif
 
   if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
--- a/hotspot/src/share/vm/runtime/globals.hpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Thu Oct 24 16:14:28 2013 -0700
@@ -2671,13 +2671,18 @@
           "Enable aggressive optimizations - see arguments.cpp")            \
                                                                             \
   product_pd(uintx, TypeProfileLevel,                                       \
-          "=XY, with Y, Type profiling of arguments at call"                \
-          "          X, Type profiling of return value at call"             \
-          "X and Y in 0->off ; 1->js292 only; 2->all methods")              \
+          "=XYZ, with Z: Type profiling of arguments at call; "             \
+                     "Y: Type profiling of return value at call; "          \
+                     "X: Type profiling of parameters to methods; "         \
+          "X, Y and Z in 0=off ; 1=jsr292 only; 2=all methods")             \
                                                                             \
   product(intx, TypeProfileArgsLimit,     2,                                \
           "max number of call arguments to consider for type profiling")    \
                                                                             \
+  product(intx, TypeProfileParmsLimit,    2,                                \
+          "max number of incoming parameters to consider for type profiling"\
+          ", -1 for all")                                                   \
+                                                                            \
   /* statistics */                                                          \
   develop(bool, CountCompiledCalls, false,                                  \
           "Count method invocations")                                       \
--- a/hotspot/src/share/vm/runtime/java.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/runtime/java.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -193,6 +193,11 @@
       m->print_invocation_count();
       tty->print_cr("  mdo size: %d bytes", m->method_data()->size_in_bytes());
       tty->cr();
+      // Dump data on parameters if any
+      if (m->method_data() != NULL && m->method_data()->parameters_type_data() != NULL) {
+        tty->fill_to(2);
+        m->method_data()->parameters_type_data()->print_data_on(tty);
+      }
       m->print_codes();
       total_size += m->method_data()->size_in_bytes();
     }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Oct 24 16:14:28 2013 -0700
@@ -1938,7 +1938,13 @@
   declare_c2_type(CmpDNode, CmpNode)                                      \
   declare_c2_type(CmpD3Node, CmpDNode)                                    \
   declare_c2_type(MathExactNode, MultiNode)                               \
-  declare_c2_type(AddExactINode, MathExactNode)                           \
+  declare_c2_type(MathExactINode, MathExactNode)                          \
+  declare_c2_type(AddExactINode, MathExactINode)                          \
+  declare_c2_type(AddExactLNode, MathExactLNode)                          \
+  declare_c2_type(SubExactINode, MathExactINode)                          \
+  declare_c2_type(SubExactLNode, MathExactLNode)                          \
+  declare_c2_type(NegExactINode, MathExactINode)                          \
+  declare_c2_type(MulExactINode, MathExactINode)                          \
   declare_c2_type(FlagsProjNode, ProjNode)                                \
   declare_c2_type(BoolNode, Node)                                         \
   declare_c2_type(AbsNode, Node)                                          \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactICondTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactICondTest.java
+ * @run main AddExactICondTest
+ *
+ */
+
+public class AddExactICondTest {
+  public static int result = 0;
+
+  public static void main(String[] args) {
+    for (int i = 0; i < 50000; ++i) {
+      runTest();
+    }
+  }
+
+  public static void runTest() {
+    int i = 7;
+    while (java.lang.Math.addExact(i, result) < 89361) {
+        if ((java.lang.Math.addExact(i, i) & 1) == 1) {
+            i += 3;
+        } else if ((i & 5) == 4) {
+            i += 7;
+        } else if ((i & 0xf) == 6) {
+            i += 2;
+        } else {
+            i += 1;
+        }
+        result += 2;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8024924
+ * @summary Test constant addExact
+ * @compile AddExactIConstantTest.java Verify.java
+ * @run main AddExactIConstantTest
+ *
+ */
+
+public class AddExactIConstantTest {
+  public static void main(String[] args) {
+      Verify.ConstantTest.verify(new Verify.AddExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactILoadTest.java Verify.java
+ * @run main AddExactILoadTest
+ *
+ */
+
+public class AddExactILoadTest {
+  public static void main(String[] args) {
+      Verify.LoadTest.init();
+      Verify.LoadTest.verify(new Verify.AddExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactILoopDependentTest.java Verify.java
+ * @run main AddExactILoopDependentTest
+ *
+ */
+
+public class AddExactILoopDependentTest {
+  public static void main(String[] args) {
+    Verify.LoopDependentTest.verify(new Verify.AddExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactINonConstantTest.java Verify.java
+ * @run main AddExactINonConstantTest
+ *
+ */
+
+public class AddExactINonConstantTest {
+  public static void main(String[] args) {
+      Verify.NonConstantTest.verify(new Verify.AddExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,109 @@
+/*
+ * 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 8025657
+ * @summary Test repeating addExact
+ * @compile AddExactIRepeatTest.java Verify.java
+ * @run main AddExactIRepeatTest
+ *
+ */
+
+public class AddExactIRepeatTest {
+    public static void main(String[] args) {
+        runTest(new Verify.AddExactI());
+    }
+
+    public static int nonExact(int x, int y, Verify.BinaryMethod method) {
+        int result = method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        return result;
+    }
+
+    public static void runTest(Verify.BinaryMethod method) {
+        java.util.Random rnd = new java.util.Random();
+        for (int i = 0; i < 50000; ++i) {
+            int x = Integer.MAX_VALUE - 10;
+            int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
+
+            int c = rnd.nextInt() / 2;
+            int d = rnd.nextInt() / 2;
+
+            int a = catchingExact(x, y, method);
+
+            if (a != 36) {
+                throw new RuntimeException("a != 36 : " + a);
+            }
+
+            int b = nonExact(c, d, method);
+            int n = exact(c, d, method);
+
+
+            if (n != b) {
+                throw new RuntimeException("n != b : " + n + " != " + b);
+            }
+        }
+    }
+
+    public static int exact(int x, int y, Verify.BinaryMethod method) {
+        int result = 0;
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        return result;
+    }
+
+    public static int catchingExact(int x, int y, Verify.BinaryMethod method) {
+        int result = 0;
+        try {
+            result += 5;
+            result = method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 1;
+        }
+        try {
+            result += 6;
+
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 2;
+        }
+        try {
+            result += 7;
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 3;
+        }
+        try {
+            result += 8;
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 4;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant addExact
+ * @compile AddExactLConstantTest.java Verify.java
+ * @run main AddExactLConstantTest
+ *
+ */
+
+public class AddExactLConstantTest {
+    public static void main(String[] args) {
+        Verify.ConstantLongTest.verify(new Verify.AddExactL());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test non constant addExact
+ * @compile AddExactLNonConstantTest.java Verify.java
+ * @run main AddExactLNonConstantTest
+ *
+ */
+
+public class AddExactLNonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantLongTest.verify(new Verify.AddExactL());
+    }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/CondTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * 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 8024924
- * @summary Test non constant addExact
- * @compile CondTest.java Verify.java
- * @run main CondTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class CondTest {
-  public static int result = 0;
-
-  public static void main(String[] args) {
-    for (int i = 0; i < 50000; ++i) {
-      runTest();
-    }
-  }
-
-  public static void runTest() {
-    int i = 7;
-    while (java.lang.Math.addExact(i, result) < 89361) {
-        if ((java.lang.Math.addExact(i, i) & 1) == 1) {
-            i += 3;
-        } else if ((i & 5) == 4) {
-            i += 7;
-        } else if ((i & 0xf) == 6) {
-            i += 2;
-        } else {
-            i += 1;
-        }
-        result += 2;
-    }
-  }
-}
--- a/hotspot/test/compiler/intrinsics/mathexact/ConstantTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * 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 8024924
- * @summary Test constant addExact
- * @compile ConstantTest.java Verify.java
- * @run main ConstantTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class ConstantTest {
-  public static void main(String[] args) {
-    for (int i = 0; i < 50000; ++i) {
-      Verify.verify(5, 7);
-      Verify.verify(Integer.MAX_VALUE, 1);
-      Verify.verify(Integer.MIN_VALUE, -1);
-      Verify.verify(Integer.MAX_VALUE, -1);
-      Verify.verify(Integer.MIN_VALUE, 1);
-      Verify.verify(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2);
-      Verify.verify(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3);
-    }
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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 8026844
+ * @summary Test decrementExact
+ * @compile DecExactITest.java Verify.java
+ * @run main DecExactITest
+ *
+ */
+
+public class DecExactITest {
+    public static int[] values = {1, 1, 1, 1};
+    public static int[] minvalues = {Integer.MIN_VALUE, Integer.MIN_VALUE};
+
+    public static void main(String[] args) {
+        runTest(new Verify.DecExactI());
+    }
+
+    public static void runTest(Verify.UnaryMethod method) {
+        for (int i = 0; i < 20000; ++i) {
+            Verify.verifyUnary(Integer.MIN_VALUE, method);
+            Verify.verifyUnary(minvalues[0], method);
+            Verify.verifyUnary(Integer.MIN_VALUE - values[2], method);
+            Verify.verifyUnary(0, method);
+            Verify.verifyUnary(values[2], method);
+            Verify.verifyUnary(Integer.MAX_VALUE, method);
+            Verify.verifyUnary(Integer.MIN_VALUE - values[0] + values[3], method);
+            Verify.verifyUnary(Integer.MIN_VALUE + 1 - values[0], method);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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 8026844
+ * @summary Test decrementExact
+ * @compile DecExactITest.java Verify.java
+ * @run main DecExactITest
+ *
+ */
+
+public class DecExactLTest {
+    public static long[] values = {1, 1, 1, 1};
+    public static long[] minvalues = {Long.MIN_VALUE, Long.MIN_VALUE};
+
+    public static void main(String[] args) {
+        runTest(new Verify.DecExactL());
+    }
+
+    public static void runTest(Verify.UnaryLongMethod method) {
+        for (int i = 0; i < 20000; ++i) {
+            Verify.verifyUnary(Long.MIN_VALUE, method);
+            Verify.verifyUnary(minvalues[0], method);
+            Verify.verifyUnary(Long.MIN_VALUE - values[2], method);
+            Verify.verifyUnary(0, method);
+            Verify.verifyUnary(values[2], method);
+            Verify.verifyUnary(Long.MAX_VALUE, method);
+            Verify.verifyUnary(Long.MIN_VALUE - values[0] + values[3], method);
+            Verify.verifyUnary(Long.MIN_VALUE + 1 - values[0], method);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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 8026844
+ * @summary Test incrementExact
+ * @compile IncExactITest.java Verify.java
+ * @run main IncExactITest
+ *
+ */
+
+
+public class IncExactITest {
+    public static int[] values = {1, 1, 1, 1};
+    public static void main(String[] args) {
+        runTest(new Verify.IncExactI());
+    }
+
+    public static void runTest(Verify.UnaryMethod method) {
+        for (int i = 0; i < 20000; ++i) {
+            Verify.verifyUnary(Integer.MIN_VALUE, method);
+            Verify.verifyUnary(Integer.MAX_VALUE - 1, method);
+            Verify.verifyUnary(0, method);
+            Verify.verifyUnary(values[1], method);
+            Verify.verifyUnary(Integer.MAX_VALUE, method);
+            Verify.verifyUnary(Integer.MAX_VALUE - values[0] + values[3], method);
+            Verify.verifyUnary(Integer.MAX_VALUE - 1 + values[0], method);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,50 @@
+/*
+ * 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 8026844
+ * @summary Test incrementExact
+ * @compile IncExactLTest.java Verify.java
+ * @run main IncExactLTest
+ *
+ */
+
+public class IncExactLTest {
+    public static long[] values = {1, 1, 1, 1};
+    public static void main(String[] args) {
+        runTest(new Verify.IncExactL());
+    }
+
+    public static void runTest(Verify.UnaryLongMethod method) {
+        for (int i = 0; i < 20000; ++i) {
+            Verify.verifyUnary(Long.MIN_VALUE, method);
+            Verify.verifyUnary(Long.MAX_VALUE - 1, method);
+            Verify.verifyUnary(0, method);
+            Verify.verifyUnary(values[1], method);
+            Verify.verifyUnary(Long.MAX_VALUE, method);
+            Verify.verifyUnary(Long.MAX_VALUE - values[0] + values[3], method);
+            Verify.verifyUnary(Long.MAX_VALUE - 1 + values[0], method);
+        }
+    }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/LoadTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * 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 8024924
- * @summary Test non constant addExact
- * @compile LoadTest.java Verify.java
- * @run main LoadTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class LoadTest {
-  public static java.util.Random rnd = new java.util.Random();
-  public static int[] values = new int[256];
-
-  public static void main(String[] args) {
-    for (int i = 0; i < values.length; ++i) {
-        values[i] = rnd.nextInt();
-    }
-
-    for (int i = 0; i < 50000; ++i) {
-      Verify.verify(values[i & 255], values[i & 255] - i);
-      Verify.verify(values[i & 255] + i, values[i & 255] - i);
-      Verify.verify(values[i & 255], values[i & 255]);
-      if ((i & 1) == 1 && i > 5) {
-          Verify.verify(values[i & 255] + i, values[i & 255] - i);
-      } else {
-          Verify.verify(values[i & 255] - i, values[i & 255] + i);
-      }
-    }
-  }
-}
--- a/hotspot/test/compiler/intrinsics/mathexact/LoopDependentTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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 8024924
- * @summary Test non constant addExact
- * @compile LoopDependentTest.java Verify.java
- * @run main LoopDependentTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class LoopDependentTest {
-  public static java.util.Random rnd = new java.util.Random();
-
-  public static void main(String[] args) {
-    int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
-    for (int i = 0; i < 50000; ++i) {
-      Verify.verify(rnd1 + i, rnd2 + i);
-      Verify.verify(rnd1 + i, rnd2 + (i & 0xff));
-      Verify.verify(rnd1 - i, rnd2 - (i & 0xff));
-      Verify.verify(rnd1 + i + 1, rnd2 + i + 2);
-      Verify.verify(rnd1 + i * 2, rnd2 + i);
-    }
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactICondTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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 8026844
+ * @summary Test multiplyExact as condition
+ * @compile MulExactICondTest.java
+ * @run main MulExactICondTest
+ *
+ */
+
+public class MulExactICondTest {
+    public static int result = 0;
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 50000; ++i) {
+            runTest();
+        }
+    }
+
+    public static void runTest() {
+        int i = 7;
+        while (java.lang.Math.multiplyExact(i, result) < 89361) {
+            if ((java.lang.Math.multiplyExact(i, i) & 1) == 1) {
+                i += 3;
+            } else if ((i & 5) == 4) {
+                i += 7;
+            } else if ((i & 0xf) == 6) {
+                i += 2;
+            } else {
+                i += 1;
+            }
+            result += 2;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant multiplyExact
+ * @compile MulExactIConstantTest.java Verify.java
+ * @run main MulExactIConstantTest
+ *
+ */
+
+public class MulExactIConstantTest {
+    public static void main(String[] args) {
+        Verify.ConstantTest.verify(new Verify.MulExactI());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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 8026844
+ * @summary Test multiplyExact
+ * @compile MulExactILoadTest.java Verify.java
+ * @run main MulExactILoadTest
+ *
+ */
+
+public class MulExactILoadTest {
+    public static void main(String[] args) {
+        Verify.LoadTest.init();
+        Verify.LoadTest.verify(new Verify.MulExactI());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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 8026844
+ * @summary Test loop dependent multiplyExact
+ * @compile MulExactILoopDependentTest.java Verify.java
+ * @run main MulExactILoopDependentTest
+ *
+ */
+public class MulExactILoopDependentTest {
+    public static void main(String[] args) {
+        Verify.LoopDependentTest.verify(new Verify.MulExactI());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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 8026844
+ * @summary Test non constant multiplyExact
+ * @compile MulExactINonConstantTest.java Verify.java
+ * @run main MulExactINonConstantTest
+ *
+ */
+
+public class MulExactINonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantTest.verify(new Verify.MulExactI());
+        Verify.LoadTest.verify(new Verify.MulExactI());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,109 @@
+/*
+ * 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 8026844
+ * @summary Test repeating multiplyExact
+ * @compile MulExactIRepeatTest.java Verify.java
+ * @run main MulExactIRepeatTest
+ *
+ */
+
+public class MulExactIRepeatTest {
+    public static void main(String[] args) {
+        runTest(new Verify.MulExactI());
+    }
+
+    public static int nonExact(int x, int y, Verify.BinaryMethod method) {
+        int result = method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        return result;
+    }
+
+    public static void runTest(Verify.BinaryMethod method) {
+        java.util.Random rnd = new java.util.Random();
+        for (int i = 0; i < 50000; ++i) {
+            int x = Integer.MAX_VALUE - 10;
+            int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
+
+            int c = rnd.nextInt() / 10;
+            int d = rnd.nextInt(9);
+
+            int a = catchingExact(x, y, method);
+
+            if (a != 36) {
+                throw new RuntimeException("a != 36 : " + a);
+            }
+
+            int b = nonExact(c, d, method);
+            int n = exact(c, d, method);
+
+
+            if (n != b) {
+                throw new RuntimeException("n != b : " + n + " != " + b);
+            }
+        }
+    }
+
+    public static int exact(int x, int y, Verify.BinaryMethod method) {
+        int result = 0;
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        return result;
+    }
+
+    public static int catchingExact(int x, int y, Verify.BinaryMethod method) {
+        int result = 0;
+        try {
+            result += 5;
+            result = method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 1;
+        }
+        try {
+            result += 6;
+
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 2;
+        }
+        try {
+            result += 7;
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 3;
+        }
+        try {
+            result += 8;
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 4;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant mulExact
+ * @compile MulExactLConstantTest.java Verify.java
+ * @run main MulExactLConstantTest
+ *
+ */
+
+public class MulExactLConstantTest {
+    public static void main(String[] args) {
+        Verify.ConstantLongTest.verify(new Verify.MulExactL());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test non constant mulExact
+ * @compile MulExactLNonConstantTest.java Verify.java
+ * @run main MulExactLNonConstantTest
+ *
+ */
+
+public class MulExactLNonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantLongTest.verify(new Verify.MulExactL());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant negExact
+ * @compile NegExactIConstantTest.java Verify.java
+ * @run main NegExactIConstantTest
+ *
+ */
+
+public class NegExactIConstantTest {
+    public static void main(String[] args) {
+        Verify.ConstantTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,39 @@
+/*
+ * 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 8026844
+ * @summary Test negExact
+ * @compile NegExactILoadTest.java Verify.java
+ * @run main NegExactILoadTest
+ *
+ */
+
+public class NegExactILoadTest {
+    public static void main(String[] args) {
+        Verify.LoadTest.init();
+        Verify.LoadTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,36 @@
+/*
+ * 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 8026844
+ * @summary Test negExact loop dependent
+ * @compile NegExactILoopDependentTest.java Verify.java
+ * @run main NegExactILoopDependentTest
+ *
+ */
+public class NegExactILoopDependentTest {
+    public static void main(String[] args) {
+        Verify.LoopDependentTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test non constant negExact
+ * @compile NegExactINonConstantTest.java Verify.java
+ * @run main NegExactINonConstantTest
+ *
+ */
+
+public class NegExactINonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant negExact
+ * @compile NegExactLConstantTest.java Verify.java
+ * @run main NegExactLConstantTest
+ *
+ */
+
+public class NegExactLConstantTest {
+    public static void main(String[] args) {
+        Verify.ConstantLongTest.verify(new Verify.UnaryToBinaryLong(new Verify.NegExactL()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant negExact
+ * @compile NegExactLNonConstantTest.java Verify.java
+ * @run main NegExactLNonConstantTest
+ *
+ */
+
+public class NegExactLNonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantLongTest.verify(new Verify.UnaryToBinaryLong(new Verify.NegExactL()));
+    }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/NonConstantTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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 8024924
- * @summary Test non constant addExact
- * @compile NonConstantTest.java Verify.java
- * @run main NonConstantTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class NonConstantTest {
-  public static java.util.Random rnd = new java.util.Random();
-
-  public static void main(String[] args) {
-    for (int i = 0; i < 50000; ++i) {
-      int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
-      Verify.verify(rnd1, rnd2);
-      Verify.verify(rnd1, rnd2 + 1);
-      Verify.verify(rnd1 + 1, rnd2);
-      Verify.verify(rnd1 - 1, rnd2);
-      Verify.verify(rnd1, rnd2 - 1);
-    }
-  }
-}
--- a/hotspot/test/compiler/intrinsics/mathexact/RepeatTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * 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 8025657
- * @summary Test repeating addExact
- * @compile RepeatTest.java
- * @run main RepeatTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class RepeatTest {
-  public static void main(String[] args) {
-    java.util.Random rnd = new java.util.Random();
-    for (int i = 0; i < 50000; ++i) {
-      int x = Integer.MAX_VALUE - 10;
-      int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5); //rnd.nextInt() / 2;
-
-      int c = rnd.nextInt() / 2;
-      int d = rnd.nextInt() / 2;
-
-      int a = addExact(x, y);
-
-      if (a != 36) {
-          throw new RuntimeException("a != 0 : " + a);
-      }
-
-      int b = nonExact(c, d);
-      int n = addExact2(c, d);
-
-
-      if (n != b) {
-        throw new RuntimeException("n != b : " + n + " != " + b);
-      }
-    }
-  }
-
-  public static int addExact2(int x, int y) {
-      int result = 0;
-      result += java.lang.Math.addExact(x, y);
-      result += java.lang.Math.addExact(x, y);
-      result += java.lang.Math.addExact(x, y);
-      result += java.lang.Math.addExact(x, y);
-      return result;
-  }
-
-  public static int addExact(int x, int y) {
-    int result = 0;
-    try {
-        result += 5;
-        result = java.lang.Math.addExact(x, y);
-    } catch (ArithmeticException e) {
-        result += 1;
-    }
-    try {
-        result += 6;
-
-        result += java.lang.Math.addExact(x, y);
-    } catch (ArithmeticException e) {
-        result += 2;
-    }
-    try {
-        result += 7;
-        result += java.lang.Math.addExact(x, y);
-    } catch (ArithmeticException e) {
-        result += 3;
-    }
-    try {
-        result += 8;
-        result += java.lang.Math.addExact(x, y);
-    } catch (ArithmeticException e) {
-        result += 4;
-    }
-    return result;
-  }
-
-  public static int nonExact(int x, int y) {
-    int result = x + y;
-    result += x + y;
-    result += x + y;
-    result += x + y;
-    return result;
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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 8026844
+ * @summary Test subtractExact as condition
+ * @compile SubExactICondTest.java Verify.java
+ * @run main SubExactICondTest
+ *
+ */
+
+public class SubExactICondTest {
+  public static int result = 0;
+
+  public static void main(String[] args) {
+    for (int i = 0; i < 50000; ++i) {
+      runTest();
+    }
+  }
+
+  public static void runTest() {
+    int i = 7;
+    while (java.lang.Math.subtractExact(i, result) > -31361) {
+        if ((java.lang.Math.subtractExact(i, i) & 1) == 1) {
+            i -= 3;
+        } else if ((i & 5) == 4) {
+            i -= 7;
+        } else if ((i & 0xf) == 6) {
+            i -= 2;
+        } else {
+            i -= 1;
+        }
+        result += 2;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant subtractExact
+ * @compile SubExactIConstantTest.java Verify.java
+ * @run main SubExactIConstantTest
+ *
+ */
+
+public class SubExactIConstantTest {
+  public static void main(String[] args) {
+      Verify.ConstantTest.verify(new Verify.SubExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactILoadTest.java Verify.java
+ * @run main SubExactILoadTest
+ *
+ */
+
+public class SubExactILoadTest {
+  public static void main(String[] args) {
+      Verify.LoadTest.init();
+      Verify.LoadTest.verify(new Verify.SubExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactILoopDependentTest.java Verify.java
+ * @run main SubExactILoopDependentTest
+ *
+ */
+
+public class SubExactILoopDependentTest {
+  public static void main(String[] args) {
+      Verify.LoopDependentTest.verify(new Verify.SubExactI());
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactINonConstantTest.java Verify.java
+ * @run main SubExactINonConstantTest
+ *
+ */
+
+public class SubExactINonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantTest.verify(new Verify.SubExactI());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,111 @@
+/*
+ * 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 8026844
+ * @summary Test repeating subtractExact
+ * @compile SubExactIRepeatTest.java Verify.java
+ * @run main SubExactIRepeatTest
+ *
+ */
+
+import java.lang.ArithmeticException;
+
+public class SubExactIRepeatTest {
+    public static void main(String[] args) {
+        runTest(new Verify.SubExactI());
+    }
+
+    public static int nonExact(int x, int y, Verify.BinaryMethod method) {
+        int result = method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        result += method.unchecked(x, y);
+        return result;
+    }
+
+    public static void runTest(Verify.BinaryMethod method) {
+        java.util.Random rnd = new java.util.Random();
+        for (int i = 0; i < 50000; ++i) {
+            int x = Integer.MIN_VALUE + 10;
+            int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
+
+            int c = rnd.nextInt() / 2;
+            int d = rnd.nextInt() / 2;
+
+            int a = catchingExact(x, y, method);
+
+            if (a != 36) {
+                throw new RuntimeException("a != 36 : " + a);
+            }
+
+            int b = nonExact(c, d, method);
+            int n = exact(c, d, method);
+
+
+            if (n != b) {
+                throw new RuntimeException("n != b : " + n + " != " + b);
+            }
+        }
+    }
+
+    public static int exact(int x, int y, Verify.BinaryMethod method) {
+        int result = 0;
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        result += method.checkMethod(x, y);
+        return result;
+    }
+
+    public static int catchingExact(int x, int y, Verify.BinaryMethod method) {
+        int result = 0;
+        try {
+            result += 5;
+            result = method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 1;
+        }
+        try {
+            result += 6;
+
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 2;
+        }
+        try {
+            result += 7;
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 3;
+        }
+        try {
+            result += 8;
+            result += method.checkMethod(x, y);
+        } catch (ArithmeticException e) {
+            result += 4;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test constant subtractExact
+ * @compile SubExactLConstantTest.java Verify.java
+ * @run main SubExactLConstantTest
+ *
+ */
+
+public class SubExactLConstantTest {
+    public static void main(String[] args) {
+        Verify.ConstantLongTest.verify(new Verify.SubExactL());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactLNonConstantTest.java Verify.java
+ * @run main SubExactLNonConstantTest
+ *
+ */
+
+public class SubExactLNonConstantTest {
+    public static void main(String[] args) {
+        Verify.NonConstantLongTest.verify(new Verify.SubExactL());
+    }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/Verify.java	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/test/compiler/intrinsics/mathexact/Verify.java	Thu Oct 24 16:14:28 2013 -0700
@@ -22,47 +22,641 @@
  */
 
 public class Verify {
-  public static String throwWord(boolean threw) {
-    return (threw ? "threw" : "didn't throw");
-  }
+    public static String throwWord(boolean threw) {
+        return (threw ? "threw" : "didn't throw");
+    }
+
+    public static void verifyResult(UnaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int value) {
+        if (exception1 != exception2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value);
+        }
+        if (result1 != result2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+        }
+    }
+
+    public static void verifyResult(UnaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long value) {
+        if (exception1 != exception2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value);
+        }
+        if (result1 != result2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+        }
+    }
+
+    private static void verifyResult(BinaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int a, int b) {
+        if (exception1 != exception2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
+        }
+        if (result1 != result2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+        }
+    }
+
+    private static void verifyResult(BinaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long a, long b) {
+        if (exception1 != exception2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
+        }
+        if (result1 != result2) {
+            throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+        }
+    }
+
+
+    public static void verifyUnary(int a, UnaryMethod method) {
+        boolean exception1 = false, exception2 = false;
+        int result1 = 0, result2 = 0;
+        try {
+            result1 = method.checkMethod(a);
+        } catch (ArithmeticException e) {
+            exception1 = true;
+        }
+        try {
+            result2 = method.safeMethod(a);
+        } catch (ArithmeticException e) {
+            exception2 = true;
+        }
+
+        verifyResult(method, result1, result2, exception1, exception2, a);
+    }
+
+    public static void verifyUnary(long a, UnaryLongMethod method) {
+        boolean exception1 = false, exception2 = false;
+        long result1 = 0, result2 = 0;
+        try {
+            result1 = method.checkMethod(a);
+        } catch (ArithmeticException e) {
+            exception1 = true;
+        }
+        try {
+            result2 = method.safeMethod(a);
+        } catch (ArithmeticException e) {
+            exception2 = true;
+        }
+
+        verifyResult(method, result1, result2, exception1, exception2, a);
+    }
+
+
+    public static void verifyBinary(int a, int b, BinaryMethod method) {
+        boolean exception1 = false, exception2 = false;
+        int result1 = 0, result2 = 0;
+        try {
+            result1 = method.checkMethod(a, b);
+        } catch (ArithmeticException e) {
+            exception1 = true;
+        }
+        try {
+            result2 = method.safeMethod(a, b);
+        } catch (ArithmeticException e) {
+            exception2 = true;
+        }
+
+        verifyResult(method, result1, result2, exception1, exception2, a, b);
+    }
+
+    public static void verifyBinary(long a, long b, BinaryLongMethod method) {
+        boolean exception1 = false, exception2 = false;
+        long result1 = 0, result2 = 0;
+        try {
+            result1 = method.checkMethod(a, b);
+        } catch (ArithmeticException e) {
+            exception1 = true;
+        }
+        try {
+            result2 = method.safeMethod(a, b);
+        } catch (ArithmeticException e) {
+            exception2 = true;
+        }
+
+        verifyResult(method, result1, result2, exception1, exception2, a, b);
+    }
+
+
+    public static class LoadTest {
+        public static java.util.Random rnd = new java.util.Random();
+        public static int[] values = new int[256];
+
+        public static void init() {
+            for (int i = 0; i < values.length; ++i) {
+                values[i] = rnd.nextInt();
+            }
+        }
+
+        public static void verify(BinaryMethod method) {
+            for (int i = 0; i < 50000; ++i) {
+                Verify.verifyBinary(values[i & 255], values[i & 255] - i, method);
+                Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method);
+                Verify.verifyBinary(values[i & 255], values[i & 255], method);
+                if ((i & 1) == 1 && i > 5) {
+                    Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method);
+                } else {
+                    Verify.verifyBinary(values[i & 255] - i, values[i & 255] + i, method);
+                }
+                Verify.verifyBinary(values[i & 255], values[(i + 1) & 255], method);
+            }
+        }
+    }
+
+    public static class NonConstantTest {
+        public static java.util.Random rnd = new java.util.Random();
+
+        public static void verify(BinaryMethod method) {
+            for (int i = 0; i < 50000; ++i) {
+                int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
+                Verify.verifyBinary(rnd1, rnd2, method);
+                Verify.verifyBinary(rnd1, rnd2 + 1, method);
+                Verify.verifyBinary(rnd1 + 1, rnd2, method);
+                Verify.verifyBinary(rnd1 - 1, rnd2, method);
+                Verify.verifyBinary(rnd1, rnd2 - 1, method);
+            }
+        }
+    }
 
-  public static void verify(int a, int b) {
-    boolean exception1 = false, exception2 = false;
-    int result1 = 0, result2 = 0;
-    try {
-      result1 = testIntrinsic(a, b);
-    } catch (ArithmeticException e) {
-      exception1 = true;
+    public static class NonConstantLongTest {
+        public static long[] values = { Long.MIN_VALUE, Long.MAX_VALUE, 0, Long.MAX_VALUE - 1831 };
+        public static java.util.Random rnd = new java.util.Random();
+
+        public static void verify(BinaryLongMethod method) {
+            for (int i = 0; i < 50000; ++i) {
+                long rnd1 = rnd.nextLong(), rnd2 = rnd.nextLong();
+                Verify.verifyBinary(rnd1, rnd2, method);
+                Verify.verifyBinary(rnd1, rnd2 + 1, method);
+                Verify.verifyBinary(rnd1 + 1, rnd2, method);
+                Verify.verifyBinary(rnd1 - 1, rnd2, method);
+                Verify.verifyBinary(rnd1, rnd2 - 1, method);
+                Verify.verifyBinary(rnd1 + Long.MAX_VALUE - rnd2, rnd2 + 1, method);
+                Verify.verifyBinary(values[0], values[2], method);
+                Verify.verifyBinary(values[1], values[2], method);
+                Verify.verifyBinary(values[3], 74L, method);
+            }
+        }
+    }
+
+    public static class LoopDependentTest {
+        public static java.util.Random rnd = new java.util.Random();
+
+        public static void verify(BinaryMethod method) {
+            int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
+            runTest(rnd1, rnd2, method);
+        }
+
+        private static void runTest(int rnd1, int rnd2, BinaryMethod method) {
+            for (int i = 0; i < 50000; ++i) {
+                Verify.verifyBinary(rnd1 + i, rnd2 + i, method);
+                Verify.verifyBinary(rnd1 + i, rnd2 + (i & 0xff), method);
+                Verify.verifyBinary(rnd1 - i, rnd2 - (i & 0xff), method);
+                Verify.verifyBinary(rnd1 + i + 1, rnd2 + i + 2, method);
+                Verify.verifyBinary(rnd1 + i * 2, rnd2 + i, method);
+            }
+        }
+    }
+
+    public static class ConstantTest {
+        public static void verify(BinaryMethod method) {
+            for (int i = 0; i < 50000; ++i) {
+                Verify.verifyBinary(5, 7, method);
+                Verify.verifyBinary(Integer.MAX_VALUE, 1, method);
+                Verify.verifyBinary(Integer.MIN_VALUE, -1, method);
+                Verify.verifyBinary(Integer.MAX_VALUE, -1, method);
+                Verify.verifyBinary(Integer.MIN_VALUE, 1, method);
+                Verify.verifyBinary(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2, method);
+                Verify.verifyBinary(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3, method);
+                Verify.verifyBinary(Integer.MAX_VALUE, Integer.MIN_VALUE, method);
+            }
+        }
+    }
+
+    public static class ConstantLongTest {
+        public static void verify(BinaryLongMethod method) {
+            for (int i = 0; i < 50000; ++i) {
+                Verify.verifyBinary(5, 7, method);
+                Verify.verifyBinary(Long.MAX_VALUE, 1, method);
+                Verify.verifyBinary(Long.MIN_VALUE, -1, method);
+                Verify.verifyBinary(Long.MAX_VALUE, -1, method);
+                Verify.verifyBinary(Long.MIN_VALUE, 1, method);
+                Verify.verifyBinary(Long.MAX_VALUE / 2, Long.MAX_VALUE / 2, method);
+                Verify.verifyBinary(Long.MAX_VALUE / 2, (Long.MAX_VALUE / 2) + 3, method);
+                Verify.verifyBinary(Long.MAX_VALUE, Long.MIN_VALUE, method);
+            }
+        }
+    }
+
+    public static interface BinaryMethod {
+        int safeMethod(int a, int b);
+        int checkMethod(int a, int b);
+        int unchecked(int a, int b);
+        String name();
     }
-    try {
-      result2 = testNonIntrinsic(a, b);
-    } catch (ArithmeticException e) {
-      exception2 = true;
+
+    public static interface UnaryMethod {
+        int safeMethod(int value);
+        int checkMethod(int value);
+        int unchecked(int value);
+        String name();
+    }
+
+    public static interface BinaryLongMethod {
+        long safeMethod(long a, long b);
+        long checkMethod(long a, long b);
+        long unchecked(long a, long b);
+        String name();
+    }
+
+    public static interface UnaryLongMethod {
+        long safeMethod(long value);
+        long checkMethod(long value);
+        long unchecked(long value);
+        String name();
+    }
+
+    public static class UnaryToBinary implements BinaryMethod {
+        private final UnaryMethod method;
+        public UnaryToBinary(UnaryMethod method) {
+            this.method = method;
+        }
+
+        @Override
+        public int safeMethod(int a, int b) {
+            return method.safeMethod(a);
+        }
+
+        @Override
+        public int checkMethod(int a, int b) {
+            return method.checkMethod(a);
+        }
+
+        @Override
+        public int unchecked(int a, int b) {
+            return method.unchecked(a);
+
+        }
+
+        @Override
+        public String name() {
+            return method.name();
+        }
+    }
+
+    public static class UnaryToBinaryLong implements BinaryLongMethod {
+        private final UnaryLongMethod method;
+        public UnaryToBinaryLong(UnaryLongMethod method) {
+            this.method = method;
+        }
+
+        @Override
+        public long safeMethod(long a, long b) {
+            return method.safeMethod(a);
+        }
+
+        @Override
+        public long checkMethod(long a, long b) {
+            return method.checkMethod(a);
+        }
+
+        @Override
+        public long unchecked(long a, long b) {
+            return method.unchecked(a);
+
+        }
+
+        @Override
+        public String name() {
+            return method.name();
+        }
     }
 
-    if (exception1 != exception2) {
-      throw new RuntimeException("Intrinsic version " + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
+
+    public static class AddExactI implements BinaryMethod {
+        @Override
+        public int safeMethod(int x, int y) {
+            int r = x + y;
+            // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+            if (((x ^ r) & (y ^ r)) < 0) {
+                throw new ArithmeticException("integer overflow");
+            }
+            return r;
+
+        }
+
+        @Override
+        public int checkMethod(int a, int b) {
+            return Math.addExact(a, b);
+        }
+
+        @Override
+        public String name() {
+            return "addExact";
+        }
+
+        @Override
+        public int unchecked(int a, int b) {
+            return a + b;
+        }
     }
-    if (result1 != result2) {
-      throw new RuntimeException("Intrinsic version returned: " + a + " while NonIntrinsic version returned: " + b);
+
+    public static class AddExactL implements BinaryLongMethod {
+        @Override
+        public long safeMethod(long x, long y) {
+            long r = x + y;
+            // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+            if (((x ^ r) & (y ^ r)) < 0) {
+                throw new ArithmeticException("integer overflow");
+            }
+            return r;
+
+        }
+
+        @Override
+        public long checkMethod(long a, long b) {
+            return Math.addExact(a, b);
+        }
+
+        @Override
+        public String name() {
+            return "addExactLong";
+        }
+
+        @Override
+        public long unchecked(long a, long b) {
+            return a + b;
+        }
+    }
+
+    public static class MulExactI implements BinaryMethod {
+        @Override
+        public int safeMethod(int x, int y) {
+            long r = (long)x * (long)y;
+            if ((int)r != r) {
+                throw new ArithmeticException("integer overflow");
+            }
+            return (int)r;
+
+        }
+
+        @Override
+        public int checkMethod(int a, int b) {
+            return Math.multiplyExact(a, b);
+        }
+
+        @Override
+        public int unchecked(int a, int b) {
+            return a * b;
+        }
+
+        @Override
+        public String name() {
+            return "multiplyExact";
+        }
     }
-  }
+
+    public static class MulExactL implements BinaryLongMethod {
+        @Override
+        public long safeMethod(long x, long y) {
+            long r = x * y;
+            long ax = Math.abs(x);
+            long ay = Math.abs(y);
+            if (((ax | ay) >>> 31 != 0)) {
+                // Some bits greater than 2^31 that might cause overflow
+                // Check the result using the divide operator
+                // and check for the special case of Long.MIN_VALUE * -1
+                if (((y != 0) && (r / y != x)) ||
+                        (x == Long.MIN_VALUE && y == -1)) {
+                    throw new ArithmeticException("long overflow");
+                }
+            }
+            return r;
+        }
+
+        @Override
+        public long checkMethod(long a, long b) {
+            return Math.multiplyExact(a, b);
+        }
+
+        @Override
+        public long unchecked(long a, long b) {
+            return a * b;
+        }
+
+        @Override
+        public String name() {
+            return "multiplyExact";
+        }
+    }
 
-  public static int testIntrinsic(int a, int b) {
-    return java.lang.Math.addExact(a, b);
-  }
+    public static class NegExactL implements UnaryLongMethod {
+        @Override
+        public long safeMethod(long a) {
+            if (a == Long.MIN_VALUE) {
+                throw new ArithmeticException("long overflow");
+            }
+
+            return -a;
+
+        }
+
+        @Override
+        public long checkMethod(long value) {
+            return Math.negateExact(value);
+        }
+
+        @Override
+        public long unchecked(long value) {
+            return -value;
+        }
+
+        @Override
+        public String name() {
+            return "negateExactLong";
+        }
+    }
+
+    public static class NegExactI implements UnaryMethod {
+        @Override
+        public int safeMethod(int a) {
+            if (a == Integer.MIN_VALUE) {
+                throw new ArithmeticException("integer overflow");
+            }
+
+            return -a;
+
+        }
+
+        @Override
+        public int checkMethod(int value) {
+            return Math.negateExact(value);
+        }
+
+        @Override
+        public int unchecked(int value) {
+            return -value;
+        }
 
-  public static int testNonIntrinsic(int a, int b) {
-    return safeAddExact(a, b);
-  }
+        @Override
+        public String name() {
+            return "negateExact";
+        }
+    }
+
+    public static class SubExactI implements BinaryMethod {
+        @Override
+        public int safeMethod(int x, int y) {
+            int r = x - y;
+            // HD 2-12 Overflow iff the arguments have different signs and
+            // the sign of the result is different than the sign of x
+            if (((x ^ y) & (x ^ r)) < 0) {
+                throw new ArithmeticException("integer overflow");
+            }
+            return r;
+        }
+
+        @Override
+        public int checkMethod(int a, int b) {
+            return Math.subtractExact(a, b);
+        }
+
+        @Override
+        public int unchecked(int a, int b) {
+            return a - b;
+        }
+
+        @Override
+        public String name() {
+            return "subtractExact";
+        }
+    }
+
+    public static class SubExactL implements BinaryLongMethod {
+        @Override
+        public long safeMethod(long x, long y) {
+            long r = x - y;
+            // HD 2-12 Overflow iff the arguments have different signs and
+            // the sign of the result is different than the sign of x
+            if (((x ^ y) & (x ^ r)) < 0) {
+                throw new ArithmeticException("integer overflow");
+            }
+            return r;
+        }
+
+        @Override
+        public long checkMethod(long a, long b) {
+            return Math.subtractExact(a, b);
+        }
+
+        @Override
+        public long unchecked(long a, long b) {
+            return a - b;
+        }
+
+        @Override
+        public String name() {
+            return "subtractExactLong";
+        }
+    }
+
+    static class IncExactL implements UnaryLongMethod {
+        @Override
+        public long safeMethod(long a) {
+            if (a == Long.MAX_VALUE) {
+                throw new ArithmeticException("long overflow");
+            }
+
+            return a + 1L;
+
+        }
+
+        @Override
+        public long checkMethod(long value) {
+            return Math.incrementExact(value);
+        }
+
+        @Override
+        public long unchecked(long value) {
+            return value + 1;
+        }
 
-  // Copied java.lang.Math.addExact to avoid intrinsification
-  public static int safeAddExact(int x, int y) {
-    int r = x + y;
-    // HD 2-12 Overflow iff both arguments have the opposite sign of the result
-    if (((x ^ r) & (y ^ r)) < 0) {
-      throw new ArithmeticException("integer overflow");
+        @Override
+        public String name() {
+            return "incrementExactLong";
+        }
+    }
+
+    static class IncExactI implements UnaryMethod {
+        @Override
+        public int safeMethod(int a) {
+            if (a == Integer.MAX_VALUE) {
+                throw new ArithmeticException("integer overflow");
+            }
+
+            return a + 1;
+        }
+
+        @Override
+        public int checkMethod(int value) {
+            return Math.incrementExact(value);
+        }
+
+        @Override
+        public int unchecked(int value) {
+            return value + 1;
+        }
+
+        @Override
+        public String name() {
+            return "incrementExact";
+        }
     }
-    return r;
-  }
+
+    static class DecExactL implements UnaryLongMethod {
+        @Override
+        public long safeMethod(long a) {
+            if (a == Long.MIN_VALUE) {
+                throw new ArithmeticException("long overflow");
+            }
+
+            return a - 1L;
+        }
+
+        @Override
+        public long checkMethod(long value) {
+            return Math.decrementExact(value);
+        }
+
+        @Override
+        public long unchecked(long value) {
+            return value - 1;
+        }
+
+        @Override
+        public String name() {
+            return "decExactLong";
+        }
+    }
+
+    static class DecExactI implements UnaryMethod {
+        @Override
+        public int safeMethod(int a) {
+            if (a == Integer.MIN_VALUE) {
+                throw new ArithmeticException("integer overflow");
+            }
+
+            return a - 1;
+        }
+
+        @Override
+        public int checkMethod(int value) {
+            return Math.decrementExact(value);
+        }
+
+        @Override
+        public int unchecked(int value) {
+            return value - 1;
+        }
+
+        @Override
+        public String name() {
+            return "decrementExact";
+        }
+    }
+
 }
--- a/hotspot/test/compiler/print/PrintInlining.java	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/test/compiler/print/PrintInlining.java	Thu Oct 24 16:14:28 2013 -0700
@@ -25,7 +25,7 @@
  * @test
  * @bug 8022585
  * @summary VM crashes when ran with -XX:+PrintInlining
- * @run main/othervm -Xcomp -XX:+PrintInlining PrintInlining
+ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining PrintInlining
  *
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/tiered/CompLevelsTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+/**
+ * Abstract class for testing of used compilation levels correctness.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public abstract class CompLevelsTest extends CompilerWhiteBoxTest {
+    protected CompLevelsTest(TestCase testCase) {
+        super(testCase);
+        // to prevent inlining of #method
+        WHITE_BOX.testSetDontInlineMethod(method, true);
+    }
+
+    /**
+     * Checks that level is available.
+     * @param compLevel level to check
+     */
+    protected void testAvailableLevel(int compLevel, int bci) {
+        if (IS_VERBOSE) {
+            System.out.printf("testAvailableLevel(level = %d, bci = %d)%n",
+                    compLevel, bci);
+        }
+        WHITE_BOX.enqueueMethodForCompilation(method, compLevel, bci);
+        checkCompiled();
+        checkLevel(compLevel, getCompLevel());
+        deoptimize();
+    }
+
+    /**
+     * Checks that level is unavailable.
+     * @param compLevel level to check
+     */
+    protected void testUnavailableLevel(int compLevel, int bci) {
+        if (IS_VERBOSE) {
+            System.out.printf("testUnavailableLevel(level = %d, bci = %d)%n",
+                    compLevel, bci);
+        }
+        WHITE_BOX.enqueueMethodForCompilation(method, compLevel, bci);
+        checkNotCompiled();
+    }
+
+    /**
+     * Checks validity of compilation level.
+     * @param expected expected level
+     * @param actual actually level
+     */
+    protected void checkLevel(int expected, int actual) {
+        if (expected != actual) {
+            throw new RuntimeException("expected[" + expected + "] != actual["
+                    + actual + "]");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+import java.util.function.IntPredicate;
+
+/**
+ * @test NonTieredLevelsTest
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build NonTieredLevelsTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:-TieredCompilation
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:CompileCommand=compileonly,TestCase$Helper::*
+ *                   NonTieredLevelsTest
+ * @summary Verify that only one level can be used
+ * @author igor.ignatyev@oracle.com
+ */
+public class NonTieredLevelsTest extends CompLevelsTest {
+    private static final int AVAILABLE_COMP_LEVEL;
+    private static final IntPredicate IS_AVAILABLE_COMPLEVEL;
+    static {
+        String vmName = System.getProperty("java.vm.name");
+        if (vmName.endsWith(" Server VM")) {
+            AVAILABLE_COMP_LEVEL = COMP_LEVEL_FULL_OPTIMIZATION;
+            IS_AVAILABLE_COMPLEVEL = x -> x == COMP_LEVEL_FULL_OPTIMIZATION;
+        } else if (vmName.endsWith(" Client VM")
+                || vmName.endsWith(" Minimal VM")) {
+            AVAILABLE_COMP_LEVEL = COMP_LEVEL_SIMPLE;
+            IS_AVAILABLE_COMPLEVEL = x -> x >= COMP_LEVEL_SIMPLE
+                    && x <= COMP_LEVEL_FULL_PROFILE;
+        } else {
+            throw new RuntimeException("Unknown VM: " + vmName);
+        }
+
+    }
+    public static void main(String[] args) throws Exception {
+        if (TIERED_COMPILATION) {
+            System.err.println("Test isn't applicable w/ enabled "
+                    + "TieredCompilation. Skip test.");
+            return;
+        }
+        for (TestCase test : TestCase.values()) {
+            new NonTieredLevelsTest(test).runTest();
+        }
+    }
+
+    private NonTieredLevelsTest(TestCase testCase) {
+        super(testCase);
+        // to prevent inlining of #method
+        WHITE_BOX.testSetDontInlineMethod(method, true);
+    }
+
+    @Override
+    protected void test() throws Exception {
+        checkNotCompiled();
+        compile();
+        checkCompiled();
+
+        int compLevel = getCompLevel();
+        checkLevel(AVAILABLE_COMP_LEVEL, compLevel);
+        int bci = WHITE_BOX.getMethodEntryBci(method);
+        deoptimize();
+        if (!testCase.isOsr) {
+            for (int level = 1; level <= COMP_LEVEL_MAX; ++level) {
+                if (IS_AVAILABLE_COMPLEVEL.test(level)) {
+                    testAvailableLevel(level, bci);
+                } else {
+                    testUnavailableLevel(level, bci);
+                }
+            }
+        } else {
+            System.out.println("skip other levels testing in OSR");
+            testAvailableLevel(AVAILABLE_COMP_LEVEL, bci);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/tiered/TieredLevelsTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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 TieredLevelsTest
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build TieredLevelsTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+TieredCompilation
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:CompileCommand=compileonly,TestCase$Helper::*
+ *                   TieredLevelsTest
+ * @summary Verify that all levels &lt; 'TieredStopAtLevel' can be used
+ * @author igor.ignatyev@oracle.com
+ */
+public class TieredLevelsTest extends CompLevelsTest {
+    public static void main(String[] args) throws Exception {
+        if (!TIERED_COMPILATION) {
+            System.err.println("Test isn't applicable w/ disabled "
+                    + "TieredCompilation. Skip test.");
+            return;
+        }
+        for (TestCase test : TestCase.values()) {
+            new TieredLevelsTest(test).runTest();
+        }
+    }
+
+    private TieredLevelsTest(TestCase testCase) {
+        super(testCase);
+        // to prevent inlining of #method
+        WHITE_BOX.testSetDontInlineMethod(method, true);
+    }
+
+    @Override
+    protected void test() throws Exception {
+        checkNotCompiled();
+        compile();
+        checkCompiled();
+
+        int compLevel = getCompLevel();
+        if (compLevel > TIERED_STOP_AT_LEVEL) {
+            throw new RuntimeException("method.compLevel[" + compLevel
+                    + "] > TieredStopAtLevel [" + TIERED_STOP_AT_LEVEL + "]");
+        }
+        int bci = WHITE_BOX.getMethodEntryBci(method);
+        deoptimize();
+
+        for (int testedTier = 1; testedTier <= TIERED_STOP_AT_LEVEL;
+                ++testedTier) {
+            testAvailableLevel(testedTier, bci);
+        }
+        for (int testedTier = TIERED_STOP_AT_LEVEL + 1;
+                testedTier <= COMP_LEVEL_MAX; ++testedTier) {
+            testUnavailableLevel(testedTier, bci);
+        }
+    }
+
+
+    @Override
+    protected void checkLevel(int expected, int actual) {
+        if (expected == COMP_LEVEL_FULL_PROFILE
+                && actual == COMP_LEVEL_LIMITED_PROFILE) {
+            // for simple method full_profile may be replaced by limited_profile
+            return;
+        }
+        super.checkLevel(expected, actual);
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/TypeSpeculation.java	Thu Oct 24 16:14:28 2013 -0700
@@ -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");
+        }
+    }
+}
--- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java	Mon Oct 21 22:36:43 2013 -0400
+++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java	Thu Oct 24 16:14:28 2013 -0700
@@ -80,8 +80,7 @@
 
     static {
         if (TIERED_COMPILATION) {
-            THRESHOLD = 150000;
-            BACKEDGE_THRESHOLD = 0xFFFFFFFFL;
+            BACKEDGE_THRESHOLD = THRESHOLD = 150000;
         } else {
             THRESHOLD = COMPILE_THRESHOLD;
             BACKEDGE_THRESHOLD = COMPILE_THRESHOLD * Long.parseLong(getVMOption(
@@ -364,7 +363,7 @@
     /** OSR constructor test case */
     OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR,
             Helper.OSR_CONSTRUCTOR_CALLABLE, true),
-     /** OSR method test case */
+    /** OSR method test case */
     OSR_METOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true),
     /** OSR static method test case */
     OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true);
@@ -373,7 +372,7 @@
     final Executable executable;
     /** object to invoke {@linkplain #executable} */
     final Callable<Integer> callable;
-   /** flag for OSR test case */
+    /** flag for OSR test case */
     final boolean isOsr;
 
     private TestCase(Executable executable, Callable<Integer> callable,