8026251: New type profiling points: parameters to methods
authorroland
Tue, 22 Oct 2013 09:51:47 +0200
changeset 21095 1a04f7b3946e
parent 21094 aa393745eae7
child 21097 ef128c67048d
8026251: New type profiling points: parameters to methods Summary: x86 interpreter and c1 type profiling for parameters on method entries Reviewed-by: kvn, twisti
hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp
hotspot/src/cpu/x86/vm/globals_x86.hpp
hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86.hpp
hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp
hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp
hotspot/src/cpu/x86/vm/register_definitions_x86.cpp
hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp
hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp
hotspot/src/share/vm/c1/c1_Compilation.hpp
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/c1/c1_GraphBuilder.hpp
hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
hotspot/src/share/vm/ci/ciMethodData.cpp
hotspot/src/share/vm/ci/ciMethodData.hpp
hotspot/src/share/vm/interpreter/abstractInterpreter.hpp
hotspot/src/share/vm/interpreter/templateTable.hpp
hotspot/src/share/vm/oops/methodData.cpp
hotspot/src/share/vm/oops/methodData.hpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/java.cpp
--- a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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/globals_x86.hpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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	Tue Oct 22 09:51:47 2013 +0200
@@ -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	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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_32.cpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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/share/vm/c1/c1_Compilation.hpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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);
   }
 
@@ -3820,7 +3828,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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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_LIRGenerator.cpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -2647,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
@@ -2722,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);
   }
@@ -3081,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;
@@ -3111,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++;
+        }
+      }
     }
   }
 }
@@ -3126,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();
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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/ci/ciMethodData.cpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -43,6 +43,7 @@
 class ciArgInfoData;
 class ciCallTypeData;
 class ciVirtualCallTypeData;
+class ciParametersTypeData;
 
 typedef ProfileData ciProfileData;
 
@@ -124,7 +125,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());
     }
@@ -290,6 +291,25 @@
   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);
+  }
+
+#ifndef PRODUCT
+  void print_data_on(outputStream* st) const;
+#endif
+};
+
 // ciMethodData
 //
 // This class represents a MethodData* in the HotSpot virtual
@@ -335,6 +355,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 +427,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 +492,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/interpreter/abstractInterpreter.hpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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/runtime/globals.hpp	Mon Oct 21 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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 17:34:27 2013 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp	Tue Oct 22 09:51:47 2013 +0200
@@ -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();
     }