diff ppc_patches/0201_C_interpreter-implement_bytecode_profiling.patch @ 4798:df79d76c17ab

Patch queue containing the ppc port. Applying this to the staging repository at tag hs25-b34 leads to the code contained in this repository. We will update the patches so that with the staging repo and the patches always a working hotspot for ppc can be built.
author Goetz
date Wed, 12 Jun 2013 15:55:20 +0200
parents
children edf2bb42e70f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ppc_patches/0201_C_interpreter-implement_bytecode_profiling.patch	Wed Jun 12 15:55:20 2013 +0200
@@ -0,0 +1,1391 @@
+# HG changeset patch
+# Parent 84fd980e69ee155f80ae36002f29703ea7d16205
+C-interpreter: implement bytecode profiling.
+
+diff -r 84fd980e69ee src/share/vm/interpreter/bytecodeInterpreter.cpp
+--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -28,6 +28,7 @@
+ #include "interpreter/bytecodeHistogram.hpp"
+ #include "interpreter/bytecodeInterpreter.hpp"
+ #include "interpreter/bytecodeInterpreter.inline.hpp"
++#include "interpreter/bytecodeInterpreterProfiling.hpp"
+ #include "interpreter/interpreter.hpp"
+ #include "interpreter/interpreterRuntime.hpp"
+ #include "memory/cardTableModRefBS.hpp"
+@@ -143,10 +144,11 @@
+  * is no entry point to do the transition to vm so we just
+  * do it by hand here.
+  */
+-#define VM_JAVA_ERROR_NO_JUMP(name, msg)                                          \
++#define VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap)                             \
+     DECACHE_STATE();                                                              \
+     SET_LAST_JAVA_FRAME();                                                        \
+     {                                                                             \
++       InterpreterRuntime::note_a_trap(THREAD, istate->method(), BCI());          \
+        ThreadInVMfromJava trans(THREAD);                                          \
+        Exceptions::_throw_msg(THREAD, __FILE__, __LINE__, name, msg);             \
+     }                                                                             \
+@@ -154,8 +156,8 @@
+     CACHE_STATE();
+ 
+ // Normal throw of a java error
+-#define VM_JAVA_ERROR(name, msg)                                                  \
+-    VM_JAVA_ERROR_NO_JUMP(name, msg)                                              \
++#define VM_JAVA_ERROR(name, msg, note_a_trap)                                     \
++    VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap)                                 \
+     goto handle_exception;
+ 
+ #ifdef PRODUCT
+@@ -346,7 +348,22 @@
+       if (UseLoopCounter) {                                                                         \
+         bool do_OSR = UseOnStackReplacement;                                                        \
+         INCR_BACKEDGE_COUNT(mcs);                                                                   \
+-        if (do_OSR) do_OSR = BACKEDGE_COUNT(mcs)->reached_InvocationLimit();                        \
++        if (ProfileInterpreter) {                                                                   \
++          BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);                                   \
++          /* Check for overflow against MDO count. */                                               \
++          do_OSR = do_OSR                                                                           \
++            && (mdo_last_branch_taken_count >= (uint)InvocationCounter::InterpreterBackwardBranchLimit)\
++            /* When ProfileInterpreter is on, the backedge_count comes     */                       \
++            /* from the methodDataOop, which value does not get reset on   */                       \
++            /* the call to frequency_counter_overflow().  To avoid         */                       \
++            /* excessive calls to the overflow routine while the method is */                       \
++            /* being compiled, add a second test to make sure the overflow */                       \
++            /* function is called only once every overflow_frequency.      */                       \
++            && (!(mdo_last_branch_taken_count & 1023));                                             \
++        } else {                                                                                    \
++          /* check for overflow of backedge counter */                                              \
++          do_OSR = do_OSR && INVOCATION_COUNT(mcs)->reached_InvocationLimit(BACKEDGE_COUNT(mcs));   \
++        }                                                                                           \
+         if (do_OSR) {                                                                               \
+           nmethod*  osr_nmethod;                                                                    \
+           OSR_REQUEST(osr_nmethod, branch_pc);                                                      \
+@@ -359,7 +376,6 @@
+           }                                                                                         \
+         }                                                                                           \
+       }  /* UseCompiler ... */                                                                      \
+-      mcs->invocation_counter()->increment();                                                       \
+       SAFEPOINT;                                                                                    \
+     }
+ 
+@@ -392,16 +408,20 @@
+ #undef CACHE_FRAME
+ #define CACHE_FRAME()
+ 
++// BCI() returns the current bytecode-index.
++#undef  BCI
++#define BCI()           ((int)(intptr_t)(pc - (intptr_t)istate->method()->code_base()))
++
+ /*
+  * CHECK_NULL - Macro for throwing a NullPointerException if the object
+  * passed is a null ref.
+  * On some architectures/platforms it should be possible to do this implicitly
+  */
+ #undef CHECK_NULL
+-#define CHECK_NULL(obj_)                                                 \
+-    if ((obj_) == NULL) {                                                \
+-        VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), "");  \
+-    }                                                                    \
++#define CHECK_NULL(obj_)                                                                      \
++    if ((obj_) == NULL) {                                                                     \
++      VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap);  \
++    }                                                                                         \
+     VERIFY_OOP(obj_)
+ 
+ #define VMdoubleConstZero() 0.0
+@@ -636,6 +656,13 @@
+          topOfStack < istate->stack_base(),
+          "Stack top out of range");
+ 
++#ifdef CC_INTERP_PROFILE
++  // MethodData's last branch taken count.
++  uint mdo_last_branch_taken_count = 0;
++#else
++  const uint mdo_last_branch_taken_count = 0;
++#endif
++
+   switch (istate->msg()) {
+     case initialize: {
+       if (initialized++) ShouldNotReachHere(); // Only one initialize call
+@@ -657,15 +684,12 @@
+           METHOD->increment_interpreter_invocation_count(THREAD);
+         }
+         INCR_INVOCATION_COUNT(mcs);
+-        if (INVOCATION_COUNT(mcs)->reached_InvocationLimit()) {
+-            CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception);
+-
+-            // We no longer retry on a counter overflow
+-
+-            // istate->set_msg(retry_method);
+-            // THREAD->clr_do_not_unlock();
+-            // return;
++        if (INVOCATION_COUNT(mcs)->reached_InvocationLimit(BACKEDGE_COUNT(mcs))) {
++          CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception);
++          // We no longer retry on a counter overflow
+         }
++        // Get or create profile data. Check for pending (async) exceptions.
++        BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);
+         SAFEPOINT;
+       }
+ 
+@@ -806,9 +830,18 @@
+     case popping_frame: {
+       // returned from a java call to pop the frame, restart the call
+       // clear the message so we don't confuse ourselves later
+-      ShouldNotReachHere();  // we don't return this.
++      // Commented out ShouldNotReachHere() below, because we do reach
++      // here when the frame manager calls the interpreter loop after
++      // popping the top frame.
++      // ShouldNotReachHere();  // we don't return this.
+       assert(THREAD->pop_frame_in_process(), "wrong frame pop state");
+       istate->set_msg(no_request);
++      if (_compiling) {
++        // Set MDX back to the ProfileData of the invoke bytecode that will be
++        // restarted.
++        SET_MDX(NULL);
++        BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);
++      }
+       THREAD->clr_pop_frame_in_process();
+       goto run;
+     }
+@@ -842,6 +875,11 @@
+       if (THREAD->has_pending_exception()) goto handle_exception;
+       // Update the pc by the saved amount of the invoke bytecode size
+       UPDATE_PC(istate->bcp_advance());
++
++      if (_compiling) {
++        // Get or create profile data. Check for pending (async) exceptions.
++        BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);
++      }
+       goto run;
+     }
+ 
+@@ -849,6 +887,11 @@
+       // Returned from an opcode that will reexecute. Deopt was
+       // a result of a PopFrame request.
+       //
++
++      if (_compiling) {
++        // Get or create profile data. Check for pending (async) exceptions.
++        BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);
++      }
+       goto run;
+     }
+ 
+@@ -871,6 +914,11 @@
+       }
+       UPDATE_PC(Bytecodes::length_at(METHOD, pc));
+       if (THREAD->has_pending_exception()) goto handle_exception;
++
++      if (_compiling) {
++        // Get or create profile data. Check for pending (async) exceptions.
++        BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);
++      }
+       goto run;
+     }
+     case got_monitors: {
+@@ -1124,6 +1172,11 @@
+           uint16_t reg = Bytes::get_Java_u2(pc + 2);
+ 
+           opcode = pc[1];
++
++          // Wide and it's sub-bytecode are counted as separate instructions. If we
++          // don't account for this here, the bytecode trace skips the next bytecode.
++          DO_UPDATE_INSTRUCTION_COUNT(opcode);
++
+           switch(opcode) {
+               case Bytecodes::_aload:
+                   VERIFY_OOP(LOCALS_OBJECT(reg));
+@@ -1167,10 +1220,13 @@
+                   UPDATE_PC_AND_CONTINUE(6);
+               }
+               case Bytecodes::_ret:
++                  // Profile ret.
++                  BI_PROFILE_UPDATE_RET(/*bci=*/((int)(intptr_t)(LOCALS_ADDR(reg))));
++                  // Now, update the pc.
+                   pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(reg));
+                   UPDATE_PC_AND_CONTINUE(0);
+               default:
+-                  VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode");
++                  VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode", note_no_trap);
+           }
+       }
+ 
+@@ -1251,7 +1307,7 @@
+       CASE(_i##opcname):                                                \
+           if (test && (STACK_INT(-1) == 0)) {                           \
+               VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \
+-                            "/ by zero");                               \
++                            "/ by zero", note_div0Check_trap);          \
+           }                                                             \
+           SET_STACK_INT(VMint##opname(STACK_INT(-2),                    \
+                                       STACK_INT(-1)),                   \
+@@ -1263,7 +1319,7 @@
+             jlong l1 = STACK_LONG(-1);                                  \
+             if (VMlongEqz(l1)) {                                        \
+               VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \
+-                            "/ by long zero");                          \
++                            "/ by long zero", note_div0Check_trap);     \
+             }                                                           \
+           }                                                             \
+           /* First long at (-1,-2) next long at (-3,-4) */              \
+@@ -1476,17 +1532,23 @@
+ 
+ #define COMPARISON_OP(name, comparison)                                      \
+       CASE(_if_icmp##name): {                                                \
+-          int skip = (STACK_INT(-2) comparison STACK_INT(-1))                \
++          const bool cmp = (STACK_INT(-2) comparison STACK_INT(-1));         \
++          int skip = cmp                                                     \
+                       ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3;             \
+           address branch_pc = pc;                                            \
++          /* Profile branch. */                                              \
++          BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp);                        \
+           UPDATE_PC_AND_TOS(skip, -2);                                       \
+           DO_BACKEDGE_CHECKS(skip, branch_pc);                               \
+           CONTINUE;                                                          \
+       }                                                                      \
+       CASE(_if##name): {                                                     \
+-          int skip = (STACK_INT(-1) comparison 0)                            \
++          const bool cmp = (STACK_INT(-1) comparison 0);                     \
++          int skip = cmp                                                     \
+                       ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3;             \
+           address branch_pc = pc;                                            \
++          /* Profile branch. */                                              \
++          BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp);                        \
+           UPDATE_PC_AND_TOS(skip, -1);                                       \
+           DO_BACKEDGE_CHECKS(skip, branch_pc);                               \
+           CONTINUE;                                                          \
+@@ -1495,9 +1557,12 @@
+ #define COMPARISON_OP2(name, comparison)                                     \
+       COMPARISON_OP(name, comparison)                                        \
+       CASE(_if_acmp##name): {                                                \
+-          int skip = (STACK_OBJECT(-2) comparison STACK_OBJECT(-1))          \
++          const bool cmp = (STACK_OBJECT(-2) comparison STACK_OBJECT(-1));   \
++          int skip = cmp                                                     \
+                        ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3;            \
+           address branch_pc = pc;                                            \
++          /* Profile branch. */                                              \
++          BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp);                        \
+           UPDATE_PC_AND_TOS(skip, -2);                                       \
+           DO_BACKEDGE_CHECKS(skip, branch_pc);                               \
+           CONTINUE;                                                          \
+@@ -1505,9 +1570,12 @@
+ 
+ #define NULL_COMPARISON_NOT_OP(name)                                         \
+       CASE(_if##name): {                                                     \
+-          int skip = (!(STACK_OBJECT(-1) == NULL))                           \
++          const bool cmp = (!(STACK_OBJECT(-1) == NULL));                    \
++          int skip = cmp                                                     \
+                       ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3;             \
+           address branch_pc = pc;                                            \
++          /* Profile branch. */                                              \
++          BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp);                        \
+           UPDATE_PC_AND_TOS(skip, -1);                                       \
+           DO_BACKEDGE_CHECKS(skip, branch_pc);                               \
+           CONTINUE;                                                          \
+@@ -1515,9 +1583,12 @@
+ 
+ #define NULL_COMPARISON_OP(name)                                             \
+       CASE(_if##name): {                                                     \
+-          int skip = ((STACK_OBJECT(-1) == NULL))                            \
++          const bool cmp = ((STACK_OBJECT(-1) == NULL));                     \
++          int skip = cmp                                                     \
+                       ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3;             \
+           address branch_pc = pc;                                            \
++          /* Profile branch. */                                              \
++          BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp);                        \
+           UPDATE_PC_AND_TOS(skip, -1);                                       \
+           DO_BACKEDGE_CHECKS(skip, branch_pc);                               \
+           CONTINUE;                                                          \
+@@ -1540,9 +1611,14 @@
+           int32_t  high = Bytes::get_Java_u4((address)&lpc[2]);
+           int32_t  skip;
+           key -= low;
+-          skip = ((uint32_t) key > (uint32_t)(high - low))
+-                      ? Bytes::get_Java_u4((address)&lpc[0])
+-                      : Bytes::get_Java_u4((address)&lpc[key + 3]);
++          if (((uint32_t) key > (uint32_t)(high - low))) {
++            key = -1;
++            skip = Bytes::get_Java_u4((address)&lpc[0]);
++          } else {
++            skip = Bytes::get_Java_u4((address)&lpc[key + 3]);
++          }
++          // Profile switch.
++          BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/key);
+           // Does this really need a full backedge check (osr?)
+           address branch_pc = pc;
+           UPDATE_PC_AND_TOS(skip, -1);
+@@ -1556,14 +1632,21 @@
+           jint* lpc  = (jint*)VMalignWordUp(pc+1);
+           int32_t  key  = STACK_INT(-1);
+           int32_t  skip = Bytes::get_Java_u4((address) lpc); /* default amount */
++          // Remember index.
++          int      index = -1;
++          int      newindex = 0;
+           int32_t  npairs = Bytes::get_Java_u4((address) &lpc[1]);
+           while (--npairs >= 0) {
+-              lpc += 2;
+-              if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) {
+-                  skip = Bytes::get_Java_u4((address)&lpc[1]);
+-                  break;
+-              }
++            lpc += 2;
++            if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) {
++              skip = Bytes::get_Java_u4((address)&lpc[1]);
++              index = newindex;
++              break;
++            }
++            newindex += 1;
+           }
++          // Profile switch.
++          BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/index);
+           address branch_pc = pc;
+           UPDATE_PC_AND_TOS(skip, -1);
+           DO_BACKEDGE_CHECKS(skip, branch_pc);
+@@ -1648,7 +1731,7 @@
+       if ((uint32_t)index >= (uint32_t)arrObj->length()) {                     \
+           sprintf(message, "%d", index);                                       \
+           VM_JAVA_ERROR(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), \
+-                        message);                                              \
++                        message, note_rangeCheck_trap);                        \
+       }
+ 
+       /* 32-bit loads. These handle conversion from < 32-bit types */
+@@ -1729,15 +1812,22 @@
+           // arrObj, index are set
+           if (rhsObject != NULL) {
+             /* Check assignability of rhsObject into arrObj */
+-            Klass* rhsKlassOop = rhsObject->klass(); // EBX (subclass)
+-            Klass* elemKlassOop = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX
++            Klass* rhsKlass = rhsObject->klass(); // EBX (subclass)
++            Klass* elemKlass = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX
+             //
+             // Check for compatibilty. This check must not GC!!
+             // Seems way more expensive now that we must dispatch
+             //
+-            if (rhsKlassOop != elemKlassOop && !rhsKlassOop->is_subtype_of(elemKlassOop)) { // ebx->is...
+-              VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), "");
++            if (rhsKlass != elemKlass && !rhsKlass->is_subtype_of(elemKlass)) { // ebx->is...
++              // Decrement counter if subtype check failed.
++              BI_PROFILE_SUBTYPECHECK_FAILED(rhsKlass);
++              VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), "", note_arrayCheck_trap);
+             }
++            // Profile checkcast with null_seen and receiver.
++            BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/false, rhsKlass);
++          } else {
++            // Profile checkcast with null_seen and receiver.
++            BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL);
+           }
+           // G1GC port. Use accessor instead of storing manually.
+           // Takes care of write barriers internally and replaces the code above.
+@@ -2139,10 +2229,14 @@
+             if (UseTLAB) {
+               result = (oop) THREAD->tlab().allocate(obj_size);
+             }
++            // Disable non-TLAB-based fast-path, because profiling requires that all
++            // allocations go through InterpreterRuntime::_new() if THREAD->tlab().allocate
++            // returns NULL.
++#ifndef CC_INTERP_PROFILE
+             if (result == NULL) {
+               need_zero = true;
+               // Try allocate in shared eden
+-        retry:
++            retry:
+               HeapWord* compare_to = *Universe::heap()->top_addr();
+               HeapWord* new_top = compare_to + obj_size;
+               if (new_top <= *Universe::heap()->end_addr()) {
+@@ -2152,6 +2246,7 @@
+                 result = (oop) compare_to;
+               }
+             }
++#endif
+             if (result != NULL) {
+               // Initialize object (if nonzero size and need) and then the header
+               if (need_zero ) {
+@@ -2207,42 +2302,40 @@
+           if (STACK_OBJECT(-1) != NULL) {
+             VERIFY_OOP(STACK_OBJECT(-1));
+             u2 index = Bytes::get_Java_u2(pc+1);
+-            if (ProfileInterpreter) {
+-              // needs Profile_checkcast QQQ
+-              ShouldNotReachHere();
+-            }
+             // Constant pool may have actual klass or unresolved klass. If it is
+             // unresolved we must resolve it
+             if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
+               CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
+             }
+             Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
+-            Klass* objKlassOop = STACK_OBJECT(-1)->klass(); //ebx
++            Klass* objKlass = STACK_OBJECT(-1)->klass(); //ebx
+             //
+             // Check for compatibilty. This check must not GC!!
+             // Seems way more expensive now that we must dispatch
+             //
+-            if (objKlassOop != klassOf &&
+-                !objKlassOop->is_subtype_of(klassOf)) {
++            if (objKlass != klassOf && !objKlass->is_subtype_of(klassOf)) {
++              // Decrement counter at checkcast.
++              BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
+               ResourceMark rm(THREAD);
+-              const char* objName = objKlassOop->external_name();
++              const char* objName = objKlass->external_name();
+               const char* klassName = klassOf->external_name();
+               char* message = SharedRuntime::generate_class_cast_message(
+                 objName, klassName);
+-              VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message);
++              VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap);
+             }
++            // Profile checkcast with null_seen and receiver.
++            BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/false, objKlass);
+           } else {
+-            if (UncommonNullCast) {
+-//              istate->method()->set_null_cast_seen();
+-// [RGV] Not sure what to do here!
+-
+-            }
++            // Profile checkcast with null_seen and receiver.
++            BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL);
+           }
+           UPDATE_PC_AND_CONTINUE(3);
+ 
+       CASE(_instanceof):
+           if (STACK_OBJECT(-1) == NULL) {
+             SET_STACK_INT(0, -1);
++            // Profile instanceof with null_seen and receiver.
++            BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/true, NULL);
+           } else {
+             VERIFY_OOP(STACK_OBJECT(-1));
+             u2 index = Bytes::get_Java_u2(pc+1);
+@@ -2252,16 +2345,20 @@
+               CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
+             }
+             Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
+-            Klass* objKlassOop = STACK_OBJECT(-1)->klass();
++            Klass* objKlass = STACK_OBJECT(-1)->klass();
+             //
+             // Check for compatibilty. This check must not GC!!
+             // Seems way more expensive now that we must dispatch
+             //
+-            if ( objKlassOop == klassOf || objKlassOop->is_subtype_of(klassOf)) {
++            if ( objKlass == klassOf || objKlass->is_subtype_of(klassOf)) {
+               SET_STACK_INT(1, -1);
+             } else {
+               SET_STACK_INT(0, -1);
++              // Decrement counter at checkcast.
++              BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
+             }
++            // Profile instanceof with null_seen and receiver.
++            BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/false, objKlass);
+           }
+           UPDATE_PC_AND_CONTINUE(3);
+ 
+@@ -2404,6 +2501,9 @@
+         istate->set_callee_entry_point(method->from_interpreted_entry());
+         istate->set_bcp_advance(5);
+ 
++        // Invokedynamic has got a call counter, just like an invokestatic -> increment!
++        BI_PROFILE_UPDATE_CALL();
++
+         UPDATE_PC_AND_RETURN(0); // I'll be back...
+       }
+ 
+@@ -2437,6 +2537,9 @@
+         istate->set_callee_entry_point(method->from_interpreted_entry());
+         istate->set_bcp_advance(3);
+ 
++        // Invokehandle has got a call counter, just like a final call -> increment!
++        BI_PROFILE_UPDATE_FINALCALL();
++
+         UPDATE_PC_AND_RETURN(0); // I'll be back...
+       }
+ 
+@@ -2464,14 +2567,18 @@
+           CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
+           if (cache->is_vfinal()) {
+             callee = cache->f2_as_vfinal_method();
++            // Profile 'special case of invokeinterface' final call.
++            BI_PROFILE_UPDATE_FINALCALL();
+           } else {
+             // get receiver
+             int parms = cache->parameter_size();
+             // Same comments as invokevirtual apply here
+-            VERIFY_OOP(STACK_OBJECT(-parms));
+-            InstanceKlass* rcvrKlass = (InstanceKlass*)
+-                                 STACK_OBJECT(-parms)->klass();
++            oop rcvr = STACK_OBJECT(-parms);
++            VERIFY_OOP(rcvr);
++            InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass();
+             callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
++            // Profile 'special case of invokeinterface' virtual call.
++            BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass());
+           }
+           istate->set_callee(callee);
+           istate->set_callee_entry_point(callee->from_interpreted_entry());
+@@ -2502,15 +2609,18 @@
+         // interface.  The link resolver checks this but only for the first
+         // time this interface is called.
+         if (i == int2->itable_length()) {
+-          VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "");
++          VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "", note_no_trap);
+         }
+         int mindex = cache->f2_as_index();
+         itableMethodEntry* im = ki->first_method_entry(rcvr->klass());
+         callee = im[mindex].method();
+         if (callee == NULL) {
+-          VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), "");
++          VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), "", note_no_trap);
+         }
+ 
++        // Profile virtual call.
++        BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass());
++
+         istate->set_callee(callee);
+         istate->set_callee_entry_point(callee->from_interpreted_entry());
+ #ifdef VM_JVMTI
+@@ -2542,8 +2652,11 @@
+           Method* callee;
+           if ((Bytecodes::Code)opcode == Bytecodes::_invokevirtual) {
+             CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
+-            if (cache->is_vfinal()) callee = cache->f2_as_vfinal_method();
+-            else {
++            if (cache->is_vfinal()) {
++              callee = cache->f2_as_vfinal_method();
++              // Profile final call.
++              BI_PROFILE_UPDATE_FINALCALL();
++            } else {
+               // get receiver
+               int parms = cache->parameter_size();
+               // this works but needs a resourcemark and seems to create a vtable on every call:
+@@ -2552,8 +2665,9 @@
+               // this fails with an assert
+               // InstanceKlass* rcvrKlass = InstanceKlass::cast(STACK_OBJECT(-parms)->klass());
+               // but this works
+-              VERIFY_OOP(STACK_OBJECT(-parms));
+-              InstanceKlass* rcvrKlass = (InstanceKlass*) STACK_OBJECT(-parms)->klass();
++              oop rcvr = STACK_OBJECT(-parms);
++              VERIFY_OOP(rcvr);
++              InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass();
+               /*
+                 Executing this code in java.lang.String:
+                     public String(char value[]) {
+@@ -2571,12 +2685,17 @@
+ 
+               */
+               callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
++              // Profile virtual call.
++              BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass());
+             }
+           } else {
+             if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) {
+               CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
+             }
+             callee = cache->f1_as_method();
++
++            // Profile call.
++            BI_PROFILE_UPDATE_CALL();
+           }
+ 
+           istate->set_callee(callee);
+@@ -2628,6 +2747,8 @@
+       CASE(_goto):
+       {
+           int16_t offset = (int16_t)Bytes::get_Java_u2(pc + 1);
++          // Profile jump.
++          BI_PROFILE_UPDATE_JUMP();
+           address branch_pc = pc;
+           UPDATE_PC(offset);
+           DO_BACKEDGE_CHECKS(offset, branch_pc);
+@@ -2644,6 +2765,8 @@
+       CASE(_goto_w):
+       {
+           int32_t offset = Bytes::get_Java_u4(pc + 1);
++          // Profile jump.
++          BI_PROFILE_UPDATE_JUMP();
+           address branch_pc = pc;
+           UPDATE_PC(offset);
+           DO_BACKEDGE_CHECKS(offset, branch_pc);
+@@ -2653,6 +2776,9 @@
+       /* return from a jsr or jsr_w */
+ 
+       CASE(_ret): {
++          // Profile ret.
++          BI_PROFILE_UPDATE_RET(/*bci=*/((int)(intptr_t)(LOCALS_ADDR(pc[1]))));
++          // now, update the pc
+           pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(pc[1]));
+           UPDATE_PC_AND_CONTINUE(0);
+       }
+@@ -2734,6 +2860,9 @@
+       }
+       // for AbortVMOnException flag
+       NOT_PRODUCT(Exceptions::debug_check_abort(except_oop));
++
++      // Update profiling data.
++      BI_PROFILE_ALIGN_TO_CURRENT_BCI();
+       goto run;
+     }
+     if (TraceExceptions) {
+@@ -2936,7 +3065,7 @@
+           oop rcvr = base->obj();
+           if (rcvr == NULL) {
+             if (!suppress_error) {
+-              VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), "");
++              VM_JAVA_ERROR_NO_JUMP(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap);
+               illegal_state_oop = THREAD->pending_exception();
+               THREAD->clear_pending_exception();
+             }
+@@ -3014,7 +3143,7 @@
+     // A pending exception that was pending prior to a possible popping frame
+     // overrides the popping frame.
+     //
+-    assert(!suppress_error || suppress_error && illegal_state_oop() == NULL, "Error was not suppressed");
++    assert(!suppress_error || (suppress_error && illegal_state_oop() == NULL), "Error was not suppressed");
+     if (illegal_state_oop() != NULL || original_exception() != NULL) {
+       // inform the frame manager we have no result
+       istate->set_msg(throwing_exception);
+diff -r 84fd980e69ee src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/src/share/vm/interpreter/bytecodeInterpreterProfiling.hpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -0,0 +1,307 @@
++/*
++ * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright 2012 SAP AG. 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.
++ *
++ */
++
++// This file defines a set of macros which are used by the c++-interpreter
++// for updating a method's methodData object.
++
++
++#ifndef SHARE_VM_INTERPRETER_BYTECODEINTERPRETERPROFILING_HPP
++#define SHARE_VM_INTERPRETER_BYTECODEINTERPRETERPROFILING_HPP
++
++
++// Global settings /////////////////////////////////////////////////////////////
++
++
++// Enables profiling support
++#if defined(COMPILER2) && defined(PPC64)
++#define CC_INTERP_PROFILE
++#endif
++
++// Enables assertions for profiling code (also works in product-builds).
++// #define CC_INTERP_PROFILE_WITH_ASSERTIONS
++
++
++#ifdef CC_INTERP
++
++// Empty dummy implementations if profiling code is switched off. //////////////
++
++#ifndef CC_INTERP_PROFILE
++
++#define SET_MDX(mdx)
++
++#define BI_PROFILE_GET_OR_CREATE_METHOD_DATA(exception_handler)                \
++  if (ProfileInterpreter) {                                                    \
++    ShouldNotReachHere();                                                      \
++  }
++
++#define BI_PROFILE_ALIGN_TO_CURRENT_BCI()
++
++#define BI_PROFILE_UPDATE_JUMP()
++#define BI_PROFILE_UPDATE_BRANCH(is_taken)
++#define BI_PROFILE_UPDATE_RET(bci)
++#define BI_PROFILE_SUBTYPECHECK_FAILED(receiver)
++#define BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver)
++#define BI_PROFILE_UPDATE_INSTANCEOF(null_seen, receiver)
++#define BI_PROFILE_UPDATE_CALL()
++#define BI_PROFILE_UPDATE_FINALCALL()
++#define BI_PROFILE_UPDATE_VIRTUALCALL(receiver)
++#define BI_PROFILE_UPDATE_SWITCH(switch_index)
++
++
++#else
++
++
++// Non-dummy implementations ///////////////////////////////////////////////////
++
++// Accessors for the current method data pointer 'mdx'.
++#define MDX()        (istate->mdx())
++#define SET_MDX(mdx)                                                           \
++  if (TraceProfileInterpreter) {                                               \
++    /* Let it look like TraceBytecodes' format. */                             \
++    tty->print_cr("[%d]           %4d  "                                       \
++                  "mdx " PTR_FORMAT "(%d)"                                     \
++                  "  "                                                         \
++                  " \t-> " PTR_FORMAT "(%d)",                                  \
++                (int) THREAD->osthread()->thread_id(),                         \
++                BCI(),                                                         \
++                MDX(),                                                         \
++                (MDX() == NULL                                                 \
++                 ? 0                                                           \
++                 : istate->method()->method_data()->dp_to_di((address)MDX())), \
++                mdx,                                                           \
++                istate->method()->method_data()->dp_to_di((address)mdx)        \
++                );                                                             \
++  };                                                                           \
++  istate->set_mdx(mdx);
++
++
++// Dumps the profiling method data for the current method.
++#ifdef PRODUCT
++#define BI_PROFILE_PRINT_METHOD_DATA()
++#else  // PRODUCT
++#define BI_PROFILE_PRINT_METHOD_DATA()                                         \
++  {                                                                            \
++    ttyLocker ttyl;                                                            \
++    MethodData *md = istate->method()->method_data();                          \
++    tty->cr();                                                                 \
++    tty->print("method data at mdx " PTR_FORMAT "(0) for",                     \
++               md->data_layout_at(md->bci_to_di(0)));                          \
++    istate->method()->print_short_name(tty);                                   \
++    tty->cr();                                                                 \
++    if (md != NULL) {                                                          \
++      md->print_data_on(tty);                                                  \
++      address mdx = (address) MDX();                                           \
++      if (mdx != NULL) {                                                       \
++        tty->print_cr("current mdx " PTR_FORMAT "(%d)",                        \
++                      mdx,                                                     \
++                      istate->method()->method_data()->dp_to_di(mdx));         \
++      }                                                                        \
++    } else {                                                                   \
++      tty->print_cr("no method data");                                         \
++    }                                                                          \
++  }
++#endif // PRODUCT
++
++
++// Gets or creates the profiling method data and initializes mdx.
++#define BI_PROFILE_GET_OR_CREATE_METHOD_DATA(exception_handler)                \
++  if (ProfileInterpreter && MDX() == NULL) {                                   \
++    /* Mdx is not yet initialized for this activation. */                      \
++    MethodData *md = istate->method()->method_data();                          \
++    if (md == NULL) {                                                          \
++      MethodCounters* mcs;                                                     \
++      GET_METHOD_COUNTERS(mcs);                                                \
++      /* The profiling method data doesn't exist for this method, */           \
++      /* create it if the counters have overflowed. */                         \
++      if (INVOCATION_COUNT(mcs)->reached_ProfileLimit(BACKEDGE_COUNT(mcs))) {  \
++        /* Must use CALL_VM, because an async exception may be pending. */     \
++        CALL_VM((InterpreterRuntime::profile_method(THREAD)),                  \
++                exception_handler);                                            \
++        md = istate->method()->method_data();                                  \
++        if (md != NULL) {                                                      \
++          if (TraceProfileInterpreter) {                                       \
++            BI_PROFILE_PRINT_METHOD_DATA();                                    \
++          }                                                                    \
++          Method *m = istate->method();                                        \
++          int bci = m->bci_from(pc);                                           \
++          jint di = md->bci_to_di(bci);                                        \
++          SET_MDX(md->data_layout_at(di));                                     \
++        }                                                                      \
++      }                                                                        \
++    } else {                                                                   \
++      /* The profiling method data exists, align the method data pointer */    \
++      /* mdx to the current bytecode index. */                                 \
++      if (TraceProfileInterpreter) {                                           \
++        BI_PROFILE_PRINT_METHOD_DATA();                                        \
++      }                                                                        \
++      SET_MDX(md->data_layout_at(md->bci_to_di(BCI())));                       \
++    }                                                                          \
++  }
++
++
++// Asserts that the current method data pointer mdx corresponds
++// to the current bytecode.
++#if defined(CC_INTERP_PROFILE_WITH_ASSERTIONS)
++#define BI_PROFILE_CHECK_MDX()                                                 \
++  {                                                                            \
++    MethodData *md = istate->method()->method_data();                          \
++    address mdx  = (address) MDX();                                            \
++    address mdx2 = (address) md->data_layout_at(md->bci_to_di(BCI()));         \
++    guarantee(md  != NULL, "1");                                               \
++    guarantee(mdx  != NULL, "2");                                              \
++    guarantee(mdx2 != NULL, "3");                                              \
++    if (mdx != mdx2) {                                                         \
++      BI_PROFILE_PRINT_METHOD_DATA();                                          \
++      fatal3("invalid mdx at bci %d:"                                          \
++             " was " PTR_FORMAT                                                \
++             " but expected " PTR_FORMAT,                                      \
++             BCI(),                                                            \
++             mdx,                                                              \
++             mdx2);                                                            \
++    }                                                                          \
++  }
++#else
++#define BI_PROFILE_CHECK_MDX()
++#endif
++
++
++// Aligns the method data pointer mdx to the current bytecode index.
++#define BI_PROFILE_ALIGN_TO_CURRENT_BCI()                                      \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    MethodData *md = istate->method()->method_data();                          \
++    SET_MDX(md->data_layout_at(md->bci_to_di(BCI())));                         \
++  }
++
++
++// Updates profiling data for a jump.
++#define BI_PROFILE_UPDATE_JUMP()                                               \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    JumpData::increment_taken_count_no_overflow(MDX());                        \
++    /* Remember last branch taken count. */                                    \
++    mdo_last_branch_taken_count = JumpData::taken_count(MDX());                \
++    SET_MDX(JumpData::advance_taken(MDX()));                                   \
++  }
++
++
++// Updates profiling data for a taken/not taken branch.
++#define BI_PROFILE_UPDATE_BRANCH(is_taken)                                     \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    if (is_taken) {                                                            \
++      BranchData::increment_taken_count_no_overflow(MDX());                    \
++      /* Remember last branch taken count. */                                  \
++      mdo_last_branch_taken_count = BranchData::taken_count(MDX());            \
++      SET_MDX(BranchData::advance_taken(MDX()));                               \
++    } else {                                                                   \
++      BranchData::increment_not_taken_count_no_overflow(MDX());                \
++      SET_MDX(BranchData::advance_not_taken(MDX()));                           \
++    }                                                                          \
++  }
++
++
++// Updates profiling data for a ret with given bci.
++#define BI_PROFILE_UPDATE_RET(bci)                                             \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    MethodData *md = istate->method()->method_data();                          \
++/* FIXME: there is more to do here than increment and advance(mdx)! */         \
++    CounterData::increment_count_no_overflow(MDX());                           \
++    SET_MDX(RetData::advance(md, bci));                                        \
++  }
++
++// Decrement counter at checkcast if the subtype check fails (as template
++// interpreter does!).
++#define BI_PROFILE_SUBTYPECHECK_FAILED(receiver)                               \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    ReceiverTypeData::increment_receiver_count_no_overflow(MDX(), receiver);   \
++    ReceiverTypeData::decrement_count(MDX());                                  \
++  }
++
++// Updates profiling data for a checkcast (was a null seen? which receiver?).
++#define BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver)                       \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    if (null_seen) {                                                           \
++      ReceiverTypeData::set_null_seen(MDX());                                  \
++    } else {                                                                   \
++      /* Template interpreter doesn't increment count. */                      \
++      /* ReceiverTypeData::increment_count_no_overflow(MDX());*/               \
++      ReceiverTypeData::increment_receiver_count_no_overflow(MDX(), receiver); \
++    }                                                                          \
++    SET_MDX(ReceiverTypeData::advance(MDX()));                                 \
++  }
++
++
++// Updates profiling data for an instanceof (was a null seen? which receiver?).
++#define BI_PROFILE_UPDATE_INSTANCEOF(null_seen, receiver)                      \
++  BI_PROFILE_UPDATE_CHECKCAST(null_seen, receiver)
++
++
++// Updates profiling data for a call.
++#define BI_PROFILE_UPDATE_CALL()                                               \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    CounterData::increment_count_no_overflow(MDX());                           \
++    SET_MDX(CounterData::advance(MDX()));                                      \
++  }
++
++
++// Updates profiling data for a final call.
++#define BI_PROFILE_UPDATE_FINALCALL()                                          \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    VirtualCallData::increment_count_no_overflow(MDX());                       \
++    SET_MDX(VirtualCallData::advance(MDX()));                                  \
++  }
++
++
++// Updates profiling data for a virtual call with given receiver Klass.
++#define BI_PROFILE_UPDATE_VIRTUALCALL(receiver)                                \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    VirtualCallData::increment_receiver_count_no_overflow(MDX(), receiver);    \
++    SET_MDX(VirtualCallData::advance(MDX()));                                  \
++  }
++
++
++// Updates profiling data for a switch (tabelswitch or lookupswitch) with
++// given taken index (-1 means default case was taken).
++#define BI_PROFILE_UPDATE_SWITCH(switch_index)                                 \
++  if (ProfileInterpreter && MDX() != NULL) {                                   \
++    BI_PROFILE_CHECK_MDX();                                                    \
++    MultiBranchData::increment_count_no_overflow(MDX(), switch_index);         \
++    SET_MDX(MultiBranchData::advance(MDX(), switch_index));                    \
++  }
++
++
++// The end /////////////////////////////////////////////////////////////////////
++
++#endif // CC_INTERP_PROFILE
++
++#endif // CC_INTERP
++
++#endif // SHARE_VM_INTERPRETER_BYTECODECINTERPRETERPROFILING_HPP
+diff -r 84fd980e69ee src/share/vm/interpreter/interpreterRuntime.cpp
+--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -267,6 +267,49 @@
+   }
+ }
+ 
++#ifdef CC_INTERP
++// As legacy note_trap, but we have more arguments.
++IRT_ENTRY(void, InterpreterRuntime::note_trap(JavaThread* thread, int reason, Method *method, int trap_bci))
++  methodHandle trap_method(method);
++
++  // START derived from note_trap
++  // passed as arg: methodHandle trap_method(thread, method(thread));
++  if (trap_method.not_null()) {
++    MethodData *trap_md = trap_method->method_data();
++    if (trap_md == NULL) {
++      Method::build_interpreter_method_data(trap_method, THREAD);
++      if (HAS_PENDING_EXCEPTION) {
++        assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
++        CLEAR_PENDING_EXCEPTION;
++      }
++      trap_md = trap_method->method_data();
++      // and fall through...
++    }
++    if (trap_md != NULL) {
++      // Update per-method count of trap events. The interpreter
++      // is updating the MDO to simulate the effect of compiler traps.
++      // Passed as arg int trap_bci = trap_method->bci_from(bcp(thread));
++      Deoptimization::update_method_data_from_interpreter(trap_md, trap_bci, reason);
++    }
++  }
++  // END derived from note_trap
++IRT_END
++
++// Class Deoptimization is not visible in BytecodeInterpreter, so we need a wrapper
++// for each exception.
++void InterpreterRuntime::note_nullCheck_trap(JavaThread* thread, Method *method, int trap_bci)
++  { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_null_check, method, trap_bci); }
++void InterpreterRuntime::note_div0Check_trap(JavaThread* thread, Method *method, int trap_bci)
++  { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_div0_check, method, trap_bci); }
++void InterpreterRuntime::note_rangeCheck_trap(JavaThread* thread, Method *method, int trap_bci)
++  { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_range_check, method, trap_bci); }
++void InterpreterRuntime::note_classCheck_trap(JavaThread* thread, Method *method, int trap_bci)
++  { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_class_check, method, trap_bci); }
++void InterpreterRuntime::note_arrayCheck_trap(JavaThread* thread, Method *method, int trap_bci)
++  { if (ProfileTraps) note_trap(thread, Deoptimization::Reason_array_check, method, trap_bci); }
++#endif // CC_INTERP
++
++
+ static Handle get_preinitialized_exception(Klass* k, TRAPS) {
+   // get klass
+   InstanceKlass* klass = InstanceKlass::cast(k);
+diff -r 84fd980e69ee src/share/vm/interpreter/interpreterRuntime.hpp
+--- a/src/share/vm/interpreter/interpreterRuntime.hpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/interpreter/interpreterRuntime.hpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -67,6 +67,10 @@
+   static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i)  { return method(thread)->constants()->cache()->entry_at(i); }
+   static ConstantPoolCacheEntry* cache_entry(JavaThread *thread)            { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); }
+   static void      note_trap(JavaThread *thread, int reason, TRAPS);
++#ifdef CC_INTERP
++  // Profile traps in C++ interpreter.
++  static void      note_trap(JavaThread* thread, int reason, Method *method, int trap_bci);
++#endif // CC_INTERP
+ 
+   // Inner work method for Interpreter's frequency counter overflow
+   static nmethod* frequency_counter_overflow_inner(JavaThread* thread, address branch_bcp);
+@@ -97,6 +101,17 @@
+   static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
+   static void    throw_pending_exception(JavaThread* thread);
+ 
++#ifdef CC_INTERP
++  // Profile traps in C++ interpreter
++  static void    note_nullCheck_trap (JavaThread* thread, Method *method, int trap_bci);
++  static void    note_div0Check_trap (JavaThread* thread, Method *method, int trap_bci);
++  static void    note_rangeCheck_trap(JavaThread* thread, Method *method, int trap_bci);
++  static void    note_classCheck_trap(JavaThread* thread, Method *method, int trap_bci);
++  static void    note_arrayCheck_trap(JavaThread* thread, Method *method, int trap_bci);
++  // A dummy for makros that shall not profile traps
++  static void    note_no_trap(JavaThread* thread, Method *method, int trap_bci) {}
++#endif // CC_INTERP
++
+   // Statics & fields
+   static void    resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode);
+ 
+diff -r 84fd980e69ee src/share/vm/interpreter/invocationCounter.hpp
+--- a/src/share/vm/interpreter/invocationCounter.hpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/interpreter/invocationCounter.hpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -101,13 +101,17 @@
+ 
+   // Test counter using scaled limits like the asm interpreter would do rather than doing
+   // the shifts to normalize the counter.
+-
+-  bool   reached_InvocationLimit() const         { return _counter >= (unsigned int) InterpreterInvocationLimit; }
+-  bool   reached_BackwardBranchLimit() const     { return _counter >= (unsigned int) InterpreterBackwardBranchLimit; }
++  // Checks sum of invocation_counter and backedge_counter as the template interpreter does.
++  bool reached_InvocationLimit(InvocationCounter *back_edge_count) const {
++    return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= (unsigned int) InterpreterInvocationLimit;
++  }
++  bool reached_BackwardBranchLimit(InvocationCounter *back_edge_count) const {
++    return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= (unsigned int) InterpreterBackwardBranchLimit;
++  }
+ 
+   // Do this just like asm interpreter does for max speed
+-  bool   reached_ProfileLimit(InvocationCounter *back_edge_count) const {
+-    return (_counter && count_mask) + back_edge_count->_counter >= (unsigned int) InterpreterProfileLimit;
++  bool reached_ProfileLimit(InvocationCounter *back_edge_count) const {
++    return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >= (unsigned int) InterpreterProfileLimit;
+   }
+ 
+   void increment()                               { _counter += count_increment; }
+diff -r 84fd980e69ee src/share/vm/oops/methodData.cpp
+--- a/src/share/vm/oops/methodData.cpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/oops/methodData.cpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -244,6 +244,11 @@
+   return mdp;
+ }
+ 
++#ifdef CC_INTERP
++DataLayout* RetData::advance(MethodData *md, int bci) {
++  return (DataLayout*) md->bci_to_dp(bci);
++}
++#endif // CC_INTERP
+ 
+ #ifndef PRODUCT
+ void RetData::print_data_on(outputStream* st) {
+diff -r 84fd980e69ee src/share/vm/oops/methodData.hpp
+--- a/src/share/vm/oops/methodData.hpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/oops/methodData.hpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -225,6 +225,11 @@
+   static ByteSize cell_offset(int index) {
+     return byte_offset_of(DataLayout, _cells) + in_ByteSize(index * cell_size);
+   }
++#ifdef CC_INTERP
++  static int cell_offset_in_bytes(int index) {
++    return (int)offset_of(DataLayout, _cells[index]);
++  }
++#endif // CC_INTERP
+   // Return a value which, when or-ed as a byte into _flags, sets the flag.
+   static int flag_number_to_byte_constant(int flag_number) {
+     assert(0 <= flag_number && flag_number < flag_limit, "oob");
+@@ -356,6 +361,41 @@
+     _data = data;
+   }
+ 
++#ifdef CC_INTERP
++  // Static low level accessors for DataLayout with ProfileData's semantics.
++
++  static int cell_offset_in_bytes(int index) {
++    return DataLayout::cell_offset_in_bytes(index);
++  }
++
++  static void increment_uint_at_no_overflow(DataLayout* layout, int index,
++                                            int inc = DataLayout::counter_increment) {
++    uint count = ((uint)layout->cell_at(index)) + inc;
++    if (count == 0) return;
++    layout->set_cell_at(index, (intptr_t) count);
++  }
++
++  static int int_at(DataLayout* layout, int index) {
++    return (int)layout->cell_at(index);
++  }
++
++  static int uint_at(DataLayout* layout, int index) {
++    return (uint)layout->cell_at(index);
++  }
++
++  static oop oop_at(DataLayout* layout, int index) {
++    return (oop)layout->cell_at(index);
++  }
++
++  static void set_intptr_at(DataLayout* layout, int index, intptr_t value) {
++    layout->set_cell_at(index, (intptr_t) value);
++  }
++
++  static void set_flag_at(DataLayout* layout, int flag_number) {
++    layout->set_flag_at(flag_number);
++  }
++#endif // CC_INTERP
++
+ public:
+   // Constructor for invalid ProfileData.
+   ProfileData();
+@@ -495,6 +535,20 @@
+     return cell_offset(bit_cell_count);
+   }
+ 
++#ifdef CC_INTERP
++  static int bit_data_size_in_bytes() {
++    return cell_offset_in_bytes(bit_cell_count);
++  }
++
++  static void set_null_seen(DataLayout* layout) {
++    set_flag_at(layout, null_seen_flag);
++  }
++
++  static DataLayout* advance(DataLayout* layout) {
++    return (DataLayout*) (((address)layout) + (ssize_t)BitData::bit_data_size_in_bytes());
++  }
++#endif // CC_INTERP
++
+ #ifndef PRODUCT
+   void print_data_on(outputStream* st);
+ #endif
+@@ -539,6 +593,25 @@
+     set_uint_at(count_off, count);
+   }
+ 
++#ifdef CC_INTERP
++  static int counter_data_size_in_bytes() {
++    return cell_offset_in_bytes(counter_cell_count);
++  }
++
++  static void increment_count_no_overflow(DataLayout* layout) {
++    increment_uint_at_no_overflow(layout, count_off);
++  }
++
++  // Support counter decrementation at checkcast / subtype check failed
++  static void decrement_count(DataLayout* layout) {
++    increment_uint_at_no_overflow(layout, count_off, -1);
++  }
++
++  static DataLayout* advance(DataLayout* layout) {
++    return (DataLayout*) (((address)layout) + (ssize_t)CounterData::counter_data_size_in_bytes());
++  }
++#endif // CC_INTERP
++
+ #ifndef PRODUCT
+   void print_data_on(outputStream* st);
+ #endif
+@@ -609,6 +682,20 @@
+     return cell_offset(displacement_off_set);
+   }
+ 
++#ifdef CC_INTERP
++  static void increment_taken_count_no_overflow(DataLayout* layout) {
++    increment_uint_at_no_overflow(layout, taken_off_set);
++  }
++
++  static DataLayout* advance_taken(DataLayout* layout) {
++    return (DataLayout*) (((address)layout) + (ssize_t)int_at(layout, displacement_off_set));
++  }
++
++  static uint taken_count(DataLayout* layout) {
++    return (uint) uint_at(layout, taken_off_set);
++  }
++#endif // CC_INTERP
++
+   // Specific initialization.
+   void post_initialize(BytecodeStream* stream, MethodData* mdo);
+ 
+@@ -718,6 +805,43 @@
+   // GC support
+   virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+ 
++#ifdef CC_INTERP
++  static int receiver_type_data_size_in_bytes() {
++    return cell_offset_in_bytes(static_cell_count());
++  }
++
++  static Klass *receiver_unchecked(DataLayout* layout, uint row) {
++    oop recv = oop_at(layout, receiver_cell_index(row));
++    return (Klass *)recv;
++  }
++
++  static void increment_receiver_count_no_overflow(DataLayout* layout, Klass *rcvr) {
++    const int num_rows = row_limit();
++    // Receiver already exists?
++    for (int row = 0; row < num_rows; row++) {
++      if (receiver_unchecked(layout, row) == rcvr) {
++        increment_uint_at_no_overflow(layout, receiver_count_cell_index(row));
++        return;
++      }
++    }
++    // New receiver, find a free slot.
++    for (int row = 0; row < num_rows; row++) {
++      if (receiver_unchecked(layout, row) == NULL) {
++        set_intptr_at(layout, receiver_cell_index(row), (intptr_t)rcvr);
++        increment_uint_at_no_overflow(layout, receiver_count_cell_index(row));
++        return;
++      }
++    }
++    // Receiver did not match any saved receiver and there is no empty row for it.
++    // Increment total counter to indicate polymorphic case.
++    increment_count_no_overflow(layout);
++  }
++
++  static DataLayout* advance(DataLayout* layout) {
++    return (DataLayout*) (((address)layout) + (ssize_t)ReceiverTypeData::receiver_type_data_size_in_bytes());
++  }
++#endif // CC_INTERP
++
+ #ifndef PRODUCT
+   void print_receiver_data_on(outputStream* st);
+   void print_data_on(outputStream* st);
+@@ -751,6 +875,16 @@
+     return cell_offset(static_cell_count());
+   }
+ 
++#ifdef CC_INTERP
++  static int virtual_call_data_size_in_bytes() {
++    return cell_offset_in_bytes(static_cell_count());
++  }
++
++  static DataLayout* advance(DataLayout* layout) {
++    return (DataLayout*) (((address)layout) + (ssize_t)VirtualCallData::virtual_call_data_size_in_bytes());
++  }
++#endif // CC_INTERP
++
+ #ifndef PRODUCT
+   void print_data_on(outputStream* st);
+ #endif
+@@ -847,6 +981,10 @@
+     return cell_offset(bci_displacement_cell_index(row));
+   }
+ 
++#ifdef CC_INTERP
++  static DataLayout* advance(MethodData *md, int bci);
++#endif // CC_INTERP
++
+   // Specific initialization.
+   void post_initialize(BytecodeStream* stream, MethodData* mdo);
+ 
+@@ -911,6 +1049,20 @@
+     return cell_offset(branch_cell_count);
+   }
+ 
++#ifdef CC_INTERP
++  static int branch_data_size_in_bytes() {
++    return cell_offset_in_bytes(branch_cell_count);
++  }
++
++  static void increment_not_taken_count_no_overflow(DataLayout* layout) {
++    increment_uint_at_no_overflow(layout, not_taken_off_set);
++  }
++
++  static DataLayout* advance_not_taken(DataLayout* layout) {
++    return (DataLayout*) (((address)layout) + (ssize_t)BranchData::branch_data_size_in_bytes());
++  }
++#endif // CC_INTERP
++
+   // Specific initialization.
+   void post_initialize(BytecodeStream* stream, MethodData* mdo);
+ 
+@@ -950,6 +1102,20 @@
+     set_int_at(aindex, value);
+   }
+ 
++#ifdef CC_INTERP
++  // Static low level accessors for DataLayout with ArrayData's semantics.
++
++  static void increment_array_uint_at_no_overflow(DataLayout* layout, int index) {
++    int aindex = index + array_start_off_set;
++    increment_uint_at_no_overflow(layout, aindex);
++  }
++
++  static int array_int_at(DataLayout* layout, int index) {
++    int aindex = index + array_start_off_set;
++    return int_at(layout, aindex);
++  }
++#endif // CC_INTERP
++
+   // Code generation support for subclasses.
+   static ByteSize array_element_offset(int index) {
+     return cell_offset(array_start_off_set + index);
+@@ -1068,6 +1234,28 @@
+     return in_ByteSize(relative_displacement_off_set) * cell_size;
+   }
+ 
++#ifdef CC_INTERP
++  static void increment_count_no_overflow(DataLayout* layout, int index) {
++    if (index == -1) {
++      increment_array_uint_at_no_overflow(layout, default_count_off_set);
++    } else {
++      increment_array_uint_at_no_overflow(layout, case_array_start +
++                                                  index * per_case_cell_count +
++                                                  relative_count_off_set);
++    }
++  }
++
++  static DataLayout* advance(DataLayout* layout, int index) {
++    if (index == -1) {
++      return (DataLayout*) (((address)layout) + (ssize_t)array_int_at(layout, default_disaplacement_off_set));
++    } else {
++      return (DataLayout*) (((address)layout) + (ssize_t)array_int_at(layout, case_array_start +
++                                                                              index * per_case_cell_count +
++                                                                              relative_displacement_off_set));
++    }
++  }
++#endif // CC_INTERP
++
+   // Specific initialization.
+   void post_initialize(BytecodeStream* stream, MethodData* mdo);
+ 
+@@ -1146,8 +1334,11 @@
+ // adjusted in the event of a change in control flow.
+ //
+ 
++CC_INTERP_ONLY(class BytecodeInterpreter;)
++
+ class MethodData : public Metadata {
+   friend class VMStructs;
++  CC_INTERP_ONLY(friend class BytecodeInterpreter;)
+ private:
+   friend class ProfileData;
+ 
+diff -r 84fd980e69ee src/share/vm/runtime/arguments.cpp
+--- a/src/share/vm/runtime/arguments.cpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/runtime/arguments.cpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -3578,10 +3578,10 @@
+   // Clear flags not supported by the C++ interpreter
+ #if !defined(PPC64)
+   FLAG_SET_DEFAULT(UseBiasedLocking, false);
++  FLAG_SET_DEFAULT(ProfileInterpreter, false);
+   LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false));
+   LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedKlassPointers, false));
+ #endif // !PPC64
+-  FLAG_SET_DEFAULT(ProfileInterpreter, false);
+ #endif // CC_INTERP
+ 
+ #ifdef COMPILER2
+diff -r 84fd980e69ee src/share/vm/runtime/globals.hpp
+--- a/src/share/vm/runtime/globals.hpp	Fri Jun 07 12:50:21 2013 +0200
++++ b/src/share/vm/runtime/globals.hpp	Fri Jun 07 12:51:22 2013 +0200
+@@ -2708,6 +2708,9 @@
+   product_pd(bool, ProfileInterpreter,                                      \
+            "Profile at the bytecode level during interpretation")           \
+                                                                             \
++  develop(bool, TraceProfileInterpreter, false,                             \
++           "Trace profiling at the bytecode level during interpretation")   \
++                                                                            \
+   develop_pd(bool, ProfileTraps,                                            \
+           "Profile deoptimization traps at the bytecode level")             \
+                                                                             \