8024468: PPC64 (part 201): cppInterpreter: implement bytecode profiling
Implement profiling for c2 jit compilation. Also enable new cppInterpreter features. Reviewed-by: kvn
This commit is contained in:
parent
34c8023949
commit
0732a739b3
@ -220,7 +220,7 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
|||||||
}
|
}
|
||||||
InvocationCounter *counter = mcs->invocation_counter();
|
InvocationCounter *counter = mcs->invocation_counter();
|
||||||
counter->increment();
|
counter->increment();
|
||||||
if (counter->reached_InvocationLimit()) {
|
if (counter->reached_InvocationLimit(mcs->backedge_counter())) {
|
||||||
CALL_VM_NOCHECK(
|
CALL_VM_NOCHECK(
|
||||||
InterpreterRuntime::frequency_counter_overflow(thread, NULL));
|
InterpreterRuntime::frequency_counter_overflow(thread, NULL));
|
||||||
if (HAS_PENDING_EXCEPTION)
|
if (HAS_PENDING_EXCEPTION)
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "interpreter/bytecodeHistogram.hpp"
|
#include "interpreter/bytecodeHistogram.hpp"
|
||||||
#include "interpreter/bytecodeInterpreter.hpp"
|
#include "interpreter/bytecodeInterpreter.hpp"
|
||||||
#include "interpreter/bytecodeInterpreter.inline.hpp"
|
#include "interpreter/bytecodeInterpreter.inline.hpp"
|
||||||
|
#include "interpreter/bytecodeInterpreterProfiling.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/interpreterRuntime.hpp"
|
#include "interpreter/interpreterRuntime.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
@ -142,19 +143,20 @@
|
|||||||
* is no entry point to do the transition to vm so we just
|
* is no entry point to do the transition to vm so we just
|
||||||
* do it by hand here.
|
* 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(); \
|
DECACHE_STATE(); \
|
||||||
SET_LAST_JAVA_FRAME(); \
|
SET_LAST_JAVA_FRAME(); \
|
||||||
{ \
|
{ \
|
||||||
|
InterpreterRuntime::note_a_trap(THREAD, istate->method(), BCI()); \
|
||||||
ThreadInVMfromJava trans(THREAD); \
|
ThreadInVMfromJava trans(THREAD); \
|
||||||
Exceptions::_throw_msg(THREAD, __FILE__, __LINE__, name, msg); \
|
Exceptions::_throw_msg(THREAD, __FILE__, __LINE__, name, msg); \
|
||||||
} \
|
} \
|
||||||
RESET_LAST_JAVA_FRAME(); \
|
RESET_LAST_JAVA_FRAME(); \
|
||||||
CACHE_STATE();
|
CACHE_STATE();
|
||||||
|
|
||||||
// Normal throw of a java error
|
// Normal throw of a java error.
|
||||||
#define VM_JAVA_ERROR(name, msg) \
|
#define VM_JAVA_ERROR(name, msg, note_a_trap) \
|
||||||
VM_JAVA_ERROR_NO_JUMP(name, msg) \
|
VM_JAVA_ERROR_NO_JUMP(name, msg, note_a_trap) \
|
||||||
goto handle_exception;
|
goto handle_exception;
|
||||||
|
|
||||||
#ifdef PRODUCT
|
#ifdef PRODUCT
|
||||||
@ -340,9 +342,25 @@
|
|||||||
if (UseLoopCounter) { \
|
if (UseLoopCounter) { \
|
||||||
bool do_OSR = UseOnStackReplacement; \
|
bool do_OSR = UseOnStackReplacement; \
|
||||||
mcs->backedge_counter()->increment(); \
|
mcs->backedge_counter()->increment(); \
|
||||||
if (do_OSR) do_OSR = mcs->backedge_counter()->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 \
|
||||||
|
&& mcs->invocation_counter()->reached_InvocationLimit(mcs->backedge_counter()); \
|
||||||
|
} \
|
||||||
if (do_OSR) { \
|
if (do_OSR) { \
|
||||||
nmethod* osr_nmethod; \
|
nmethod* osr_nmethod; \
|
||||||
OSR_REQUEST(osr_nmethod, branch_pc); \
|
OSR_REQUEST(osr_nmethod, branch_pc); \
|
||||||
if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \
|
if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \
|
||||||
intptr_t* buf; \
|
intptr_t* buf; \
|
||||||
@ -355,7 +373,6 @@
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} /* UseCompiler ... */ \
|
} /* UseCompiler ... */ \
|
||||||
mcs->invocation_counter()->increment(); \
|
|
||||||
SAFEPOINT; \
|
SAFEPOINT; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,17 +405,21 @@
|
|||||||
#undef CACHE_FRAME
|
#undef CACHE_FRAME
|
||||||
#define 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
|
* CHECK_NULL - Macro for throwing a NullPointerException if the object
|
||||||
* passed is a null ref.
|
* passed is a null ref.
|
||||||
* On some architectures/platforms it should be possible to do this implicitly
|
* On some architectures/platforms it should be possible to do this implicitly
|
||||||
*/
|
*/
|
||||||
#undef CHECK_NULL
|
#undef CHECK_NULL
|
||||||
#define CHECK_NULL(obj_) \
|
#define CHECK_NULL(obj_) \
|
||||||
if ((obj_) == NULL) { \
|
if ((obj_) == NULL) { \
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), ""); \
|
VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), "", note_nullCheck_trap); \
|
||||||
} \
|
} \
|
||||||
VERIFY_OOP(obj_)
|
VERIFY_OOP(obj_)
|
||||||
|
|
||||||
#define VMdoubleConstZero() 0.0
|
#define VMdoubleConstZero() 0.0
|
||||||
#define VMdoubleConstOne() 1.0
|
#define VMdoubleConstOne() 1.0
|
||||||
@ -635,9 +656,16 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
topOfStack < istate->stack_base(),
|
topOfStack < istate->stack_base(),
|
||||||
"Stack top out of range");
|
"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()) {
|
switch (istate->msg()) {
|
||||||
case initialize: {
|
case initialize: {
|
||||||
if (initialized++) ShouldNotReachHere(); // Only one initialize call
|
if (initialized++) ShouldNotReachHere(); // Only one initialize call.
|
||||||
_compiling = (UseCompiler || CountCompiledCalls);
|
_compiling = (UseCompiler || CountCompiledCalls);
|
||||||
#ifdef VM_JVMTI
|
#ifdef VM_JVMTI
|
||||||
_jvmti_interp_events = JvmtiExport::can_post_interpreter_events();
|
_jvmti_interp_events = JvmtiExport::can_post_interpreter_events();
|
||||||
@ -656,15 +684,12 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
METHOD->increment_interpreter_invocation_count(THREAD);
|
METHOD->increment_interpreter_invocation_count(THREAD);
|
||||||
}
|
}
|
||||||
mcs->invocation_counter()->increment();
|
mcs->invocation_counter()->increment();
|
||||||
if (mcs->invocation_counter()->reached_InvocationLimit()) {
|
if (mcs->invocation_counter()->reached_InvocationLimit(mcs->backedge_counter())) {
|
||||||
CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception);
|
CALL_VM((void)InterpreterRuntime::frequency_counter_overflow(THREAD, NULL), handle_exception);
|
||||||
|
// We no longer retry on a counter overflow.
|
||||||
// We no longer retry on a counter overflow
|
|
||||||
|
|
||||||
// istate->set_msg(retry_method);
|
|
||||||
// THREAD->clr_do_not_unlock();
|
|
||||||
// return;
|
|
||||||
}
|
}
|
||||||
|
// Get or create profile data. Check for pending (async) exceptions.
|
||||||
|
BI_PROFILE_GET_OR_CREATE_METHOD_DATA(handle_exception);
|
||||||
SAFEPOINT;
|
SAFEPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,8 +711,7 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
}
|
}
|
||||||
#endif // HACK
|
#endif // HACK
|
||||||
|
|
||||||
|
// Lock method if synchronized.
|
||||||
// lock method if synchronized
|
|
||||||
if (METHOD->is_synchronized()) {
|
if (METHOD->is_synchronized()) {
|
||||||
// oop rcvr = locals[0].j.r;
|
// oop rcvr = locals[0].j.r;
|
||||||
oop rcvr;
|
oop rcvr;
|
||||||
@ -697,7 +721,7 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
rcvr = LOCALS_OBJECT(0);
|
rcvr = LOCALS_OBJECT(0);
|
||||||
VERIFY_OOP(rcvr);
|
VERIFY_OOP(rcvr);
|
||||||
}
|
}
|
||||||
// The initial monitor is ours for the taking
|
// The initial monitor is ours for the taking.
|
||||||
// Monitor not filled in frame manager any longer as this caused race condition with biased locking.
|
// Monitor not filled in frame manager any longer as this caused race condition with biased locking.
|
||||||
BasicObjectLock* mon = &istate->monitor_base()[-1];
|
BasicObjectLock* mon = &istate->monitor_base()[-1];
|
||||||
mon->set_obj(rcvr);
|
mon->set_obj(rcvr);
|
||||||
@ -803,6 +827,12 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
// clear the message so we don't confuse ourselves later
|
// clear the message so we don't confuse ourselves later
|
||||||
assert(THREAD->pop_frame_in_process(), "wrong frame pop state");
|
assert(THREAD->pop_frame_in_process(), "wrong frame pop state");
|
||||||
istate->set_msg(no_request);
|
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();
|
THREAD->clr_pop_frame_in_process();
|
||||||
goto run;
|
goto run;
|
||||||
}
|
}
|
||||||
@ -836,6 +866,11 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
if (THREAD->has_pending_exception()) goto handle_exception;
|
if (THREAD->has_pending_exception()) goto handle_exception;
|
||||||
// Update the pc by the saved amount of the invoke bytecode size
|
// Update the pc by the saved amount of the invoke bytecode size
|
||||||
UPDATE_PC(istate->bcp_advance());
|
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;
|
goto run;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,6 +878,11 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
// Returned from an opcode that will reexecute. Deopt was
|
// Returned from an opcode that will reexecute. Deopt was
|
||||||
// a result of a PopFrame request.
|
// 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;
|
goto run;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,6 +905,11 @@ BytecodeInterpreter::run(interpreterState istate) {
|
|||||||
}
|
}
|
||||||
UPDATE_PC(Bytecodes::length_at(METHOD, pc));
|
UPDATE_PC(Bytecodes::length_at(METHOD, pc));
|
||||||
if (THREAD->has_pending_exception()) goto handle_exception;
|
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;
|
goto run;
|
||||||
}
|
}
|
||||||
case got_monitors: {
|
case got_monitors: {
|
||||||
@ -1115,6 +1160,11 @@ run:
|
|||||||
uint16_t reg = Bytes::get_Java_u2(pc + 2);
|
uint16_t reg = Bytes::get_Java_u2(pc + 2);
|
||||||
|
|
||||||
opcode = pc[1];
|
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) {
|
switch(opcode) {
|
||||||
case Bytecodes::_aload:
|
case Bytecodes::_aload:
|
||||||
VERIFY_OOP(LOCALS_OBJECT(reg));
|
VERIFY_OOP(LOCALS_OBJECT(reg));
|
||||||
@ -1158,10 +1208,13 @@ run:
|
|||||||
UPDATE_PC_AND_CONTINUE(6);
|
UPDATE_PC_AND_CONTINUE(6);
|
||||||
}
|
}
|
||||||
case Bytecodes::_ret:
|
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));
|
pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(reg));
|
||||||
UPDATE_PC_AND_CONTINUE(0);
|
UPDATE_PC_AND_CONTINUE(0);
|
||||||
default:
|
default:
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode");
|
VM_JAVA_ERROR(vmSymbols::java_lang_InternalError(), "undefined opcode", note_no_trap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1242,7 +1295,7 @@ run:
|
|||||||
CASE(_i##opcname): \
|
CASE(_i##opcname): \
|
||||||
if (test && (STACK_INT(-1) == 0)) { \
|
if (test && (STACK_INT(-1) == 0)) { \
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \
|
VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \
|
||||||
"/ by zero"); \
|
"/ by zero", note_div0Check_trap); \
|
||||||
} \
|
} \
|
||||||
SET_STACK_INT(VMint##opname(STACK_INT(-2), \
|
SET_STACK_INT(VMint##opname(STACK_INT(-2), \
|
||||||
STACK_INT(-1)), \
|
STACK_INT(-1)), \
|
||||||
@ -1254,7 +1307,7 @@ run:
|
|||||||
jlong l1 = STACK_LONG(-1); \
|
jlong l1 = STACK_LONG(-1); \
|
||||||
if (VMlongEqz(l1)) { \
|
if (VMlongEqz(l1)) { \
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_ArithmeticException(), \
|
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) */ \
|
/* First long at (-1,-2) next long at (-3,-4) */ \
|
||||||
@ -1467,17 +1520,23 @@ run:
|
|||||||
|
|
||||||
#define COMPARISON_OP(name, comparison) \
|
#define COMPARISON_OP(name, comparison) \
|
||||||
CASE(_if_icmp##name): { \
|
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; \
|
? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \
|
||||||
address branch_pc = pc; \
|
address branch_pc = pc; \
|
||||||
|
/* Profile branch. */ \
|
||||||
|
BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \
|
||||||
UPDATE_PC_AND_TOS(skip, -2); \
|
UPDATE_PC_AND_TOS(skip, -2); \
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
||||||
CONTINUE; \
|
CONTINUE; \
|
||||||
} \
|
} \
|
||||||
CASE(_if##name): { \
|
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; \
|
? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \
|
||||||
address branch_pc = pc; \
|
address branch_pc = pc; \
|
||||||
|
/* Profile branch. */ \
|
||||||
|
BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \
|
||||||
UPDATE_PC_AND_TOS(skip, -1); \
|
UPDATE_PC_AND_TOS(skip, -1); \
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
||||||
CONTINUE; \
|
CONTINUE; \
|
||||||
@ -1486,9 +1545,12 @@ run:
|
|||||||
#define COMPARISON_OP2(name, comparison) \
|
#define COMPARISON_OP2(name, comparison) \
|
||||||
COMPARISON_OP(name, comparison) \
|
COMPARISON_OP(name, comparison) \
|
||||||
CASE(_if_acmp##name): { \
|
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; \
|
? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \
|
||||||
address branch_pc = pc; \
|
address branch_pc = pc; \
|
||||||
|
/* Profile branch. */ \
|
||||||
|
BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \
|
||||||
UPDATE_PC_AND_TOS(skip, -2); \
|
UPDATE_PC_AND_TOS(skip, -2); \
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
||||||
CONTINUE; \
|
CONTINUE; \
|
||||||
@ -1496,9 +1558,12 @@ run:
|
|||||||
|
|
||||||
#define NULL_COMPARISON_NOT_OP(name) \
|
#define NULL_COMPARISON_NOT_OP(name) \
|
||||||
CASE(_if##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; \
|
? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \
|
||||||
address branch_pc = pc; \
|
address branch_pc = pc; \
|
||||||
|
/* Profile branch. */ \
|
||||||
|
BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \
|
||||||
UPDATE_PC_AND_TOS(skip, -1); \
|
UPDATE_PC_AND_TOS(skip, -1); \
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
||||||
CONTINUE; \
|
CONTINUE; \
|
||||||
@ -1506,9 +1571,12 @@ run:
|
|||||||
|
|
||||||
#define NULL_COMPARISON_OP(name) \
|
#define NULL_COMPARISON_OP(name) \
|
||||||
CASE(_if##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; \
|
? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \
|
||||||
address branch_pc = pc; \
|
address branch_pc = pc; \
|
||||||
|
/* Profile branch. */ \
|
||||||
|
BI_PROFILE_UPDATE_BRANCH(/*is_taken=*/cmp); \
|
||||||
UPDATE_PC_AND_TOS(skip, -1); \
|
UPDATE_PC_AND_TOS(skip, -1); \
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
DO_BACKEDGE_CHECKS(skip, branch_pc); \
|
||||||
CONTINUE; \
|
CONTINUE; \
|
||||||
@ -1531,30 +1599,42 @@ run:
|
|||||||
int32_t high = Bytes::get_Java_u4((address)&lpc[2]);
|
int32_t high = Bytes::get_Java_u4((address)&lpc[2]);
|
||||||
int32_t skip;
|
int32_t skip;
|
||||||
key -= low;
|
key -= low;
|
||||||
skip = ((uint32_t) key > (uint32_t)(high - low))
|
if (((uint32_t) key > (uint32_t)(high - low))) {
|
||||||
? Bytes::get_Java_u4((address)&lpc[0])
|
key = -1;
|
||||||
: Bytes::get_Java_u4((address)&lpc[key + 3]);
|
skip = Bytes::get_Java_u4((address)&lpc[0]);
|
||||||
// Does this really need a full backedge check (osr?)
|
} 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;
|
address branch_pc = pc;
|
||||||
UPDATE_PC_AND_TOS(skip, -1);
|
UPDATE_PC_AND_TOS(skip, -1);
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc);
|
DO_BACKEDGE_CHECKS(skip, branch_pc);
|
||||||
CONTINUE;
|
CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Goto pc whose table entry matches specified key */
|
/* Goto pc whose table entry matches specified key. */
|
||||||
|
|
||||||
CASE(_lookupswitch): {
|
CASE(_lookupswitch): {
|
||||||
jint* lpc = (jint*)VMalignWordUp(pc+1);
|
jint* lpc = (jint*)VMalignWordUp(pc+1);
|
||||||
int32_t key = STACK_INT(-1);
|
int32_t key = STACK_INT(-1);
|
||||||
int32_t skip = Bytes::get_Java_u4((address) lpc); /* default amount */
|
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]);
|
int32_t npairs = Bytes::get_Java_u4((address) &lpc[1]);
|
||||||
while (--npairs >= 0) {
|
while (--npairs >= 0) {
|
||||||
lpc += 2;
|
lpc += 2;
|
||||||
if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) {
|
if (key == (int32_t)Bytes::get_Java_u4((address)lpc)) {
|
||||||
skip = Bytes::get_Java_u4((address)&lpc[1]);
|
skip = Bytes::get_Java_u4((address)&lpc[1]);
|
||||||
break;
|
index = newindex;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
newindex += 1;
|
||||||
}
|
}
|
||||||
|
// Profile switch.
|
||||||
|
BI_PROFILE_UPDATE_SWITCH(/*switch_index=*/index);
|
||||||
address branch_pc = pc;
|
address branch_pc = pc;
|
||||||
UPDATE_PC_AND_TOS(skip, -1);
|
UPDATE_PC_AND_TOS(skip, -1);
|
||||||
DO_BACKEDGE_CHECKS(skip, branch_pc);
|
DO_BACKEDGE_CHECKS(skip, branch_pc);
|
||||||
@ -1639,7 +1719,7 @@ run:
|
|||||||
if ((uint32_t)index >= (uint32_t)arrObj->length()) { \
|
if ((uint32_t)index >= (uint32_t)arrObj->length()) { \
|
||||||
sprintf(message, "%d", index); \
|
sprintf(message, "%d", index); \
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), \
|
VM_JAVA_ERROR(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), \
|
||||||
message); \
|
message, note_rangeCheck_trap); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 32-bit loads. These handle conversion from < 32-bit types */
|
/* 32-bit loads. These handle conversion from < 32-bit types */
|
||||||
@ -1713,15 +1793,22 @@ run:
|
|||||||
// arrObj, index are set
|
// arrObj, index are set
|
||||||
if (rhsObject != NULL) {
|
if (rhsObject != NULL) {
|
||||||
/* Check assignability of rhsObject into arrObj */
|
/* Check assignability of rhsObject into arrObj */
|
||||||
Klass* rhsKlassOop = rhsObject->klass(); // EBX (subclass)
|
Klass* rhsKlass = rhsObject->klass(); // EBX (subclass)
|
||||||
Klass* elemKlassOop = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX
|
Klass* elemKlass = ObjArrayKlass::cast(arrObj->klass())->element_klass(); // superklass EAX
|
||||||
//
|
//
|
||||||
// Check for compatibilty. This check must not GC!!
|
// Check for compatibilty. This check must not GC!!
|
||||||
// Seems way more expensive now that we must dispatch
|
// Seems way more expensive now that we must dispatch
|
||||||
//
|
//
|
||||||
if (rhsKlassOop != elemKlassOop && !rhsKlassOop->is_subtype_of(elemKlassOop)) { // ebx->is...
|
if (rhsKlass != elemKlass && !rhsKlass->is_subtype_of(elemKlass)) { // ebx->is...
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_ArrayStoreException(), "");
|
// 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);
|
||||||
}
|
}
|
||||||
((objArrayOopDesc *) arrObj)->obj_at_put(index, rhsObject);
|
((objArrayOopDesc *) arrObj)->obj_at_put(index, rhsObject);
|
||||||
UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3);
|
UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3);
|
||||||
@ -2119,10 +2206,14 @@ run:
|
|||||||
if (UseTLAB) {
|
if (UseTLAB) {
|
||||||
result = (oop) THREAD->tlab().allocate(obj_size);
|
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) {
|
if (result == NULL) {
|
||||||
need_zero = true;
|
need_zero = true;
|
||||||
// Try allocate in shared eden
|
// Try allocate in shared eden
|
||||||
retry:
|
retry:
|
||||||
HeapWord* compare_to = *Universe::heap()->top_addr();
|
HeapWord* compare_to = *Universe::heap()->top_addr();
|
||||||
HeapWord* new_top = compare_to + obj_size;
|
HeapWord* new_top = compare_to + obj_size;
|
||||||
if (new_top <= *Universe::heap()->end_addr()) {
|
if (new_top <= *Universe::heap()->end_addr()) {
|
||||||
@ -2132,6 +2223,7 @@ run:
|
|||||||
result = (oop) compare_to;
|
result = (oop) compare_to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
// Initialize object (if nonzero size and need) and then the header
|
// Initialize object (if nonzero size and need) and then the header
|
||||||
if (need_zero ) {
|
if (need_zero ) {
|
||||||
@ -2187,61 +2279,63 @@ run:
|
|||||||
if (STACK_OBJECT(-1) != NULL) {
|
if (STACK_OBJECT(-1) != NULL) {
|
||||||
VERIFY_OOP(STACK_OBJECT(-1));
|
VERIFY_OOP(STACK_OBJECT(-1));
|
||||||
u2 index = Bytes::get_Java_u2(pc+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
|
// Constant pool may have actual klass or unresolved klass. If it is
|
||||||
// unresolved we must resolve it
|
// unresolved we must resolve it.
|
||||||
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
||||||
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
||||||
}
|
}
|
||||||
Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
|
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!!
|
// Check for compatibilty. This check must not GC!!
|
||||||
// Seems way more expensive now that we must dispatch
|
// Seems way more expensive now that we must dispatch.
|
||||||
//
|
//
|
||||||
if (objKlassOop != klassOf &&
|
if (objKlass != klassOf && !objKlass->is_subtype_of(klassOf)) {
|
||||||
!objKlassOop->is_subtype_of(klassOf)) {
|
// Decrement counter at checkcast.
|
||||||
|
BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
const char* objName = objKlassOop->external_name();
|
const char* objName = objKlass->external_name();
|
||||||
const char* klassName = klassOf->external_name();
|
const char* klassName = klassOf->external_name();
|
||||||
char* message = SharedRuntime::generate_class_cast_message(
|
char* message = SharedRuntime::generate_class_cast_message(
|
||||||
objName, klassName);
|
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 {
|
} else {
|
||||||
if (UncommonNullCast) {
|
// Profile checkcast with null_seen and receiver.
|
||||||
// istate->method()->set_null_cast_seen();
|
BI_PROFILE_UPDATE_CHECKCAST(/*null_seen=*/true, NULL);
|
||||||
// [RGV] Not sure what to do here!
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
UPDATE_PC_AND_CONTINUE(3);
|
UPDATE_PC_AND_CONTINUE(3);
|
||||||
|
|
||||||
CASE(_instanceof):
|
CASE(_instanceof):
|
||||||
if (STACK_OBJECT(-1) == NULL) {
|
if (STACK_OBJECT(-1) == NULL) {
|
||||||
SET_STACK_INT(0, -1);
|
SET_STACK_INT(0, -1);
|
||||||
|
// Profile instanceof with null_seen and receiver.
|
||||||
|
BI_PROFILE_UPDATE_INSTANCEOF(/*null_seen=*/true, NULL);
|
||||||
} else {
|
} else {
|
||||||
VERIFY_OOP(STACK_OBJECT(-1));
|
VERIFY_OOP(STACK_OBJECT(-1));
|
||||||
u2 index = Bytes::get_Java_u2(pc+1);
|
u2 index = Bytes::get_Java_u2(pc+1);
|
||||||
// Constant pool may have actual klass or unresolved klass. If it is
|
// Constant pool may have actual klass or unresolved klass. If it is
|
||||||
// unresolved we must resolve it
|
// unresolved we must resolve it.
|
||||||
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
if (METHOD->constants()->tag_at(index).is_unresolved_klass()) {
|
||||||
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
CALL_VM(InterpreterRuntime::quicken_io_cc(THREAD), handle_exception);
|
||||||
}
|
}
|
||||||
Klass* klassOf = (Klass*) METHOD->constants()->slot_at(index).get_klass();
|
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!!
|
// Check for compatibilty. This check must not GC!!
|
||||||
// Seems way more expensive now that we must dispatch
|
// 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);
|
SET_STACK_INT(1, -1);
|
||||||
} else {
|
} else {
|
||||||
SET_STACK_INT(0, -1);
|
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);
|
UPDATE_PC_AND_CONTINUE(3);
|
||||||
|
|
||||||
@ -2384,6 +2478,9 @@ run:
|
|||||||
istate->set_callee_entry_point(method->from_interpreted_entry());
|
istate->set_callee_entry_point(method->from_interpreted_entry());
|
||||||
istate->set_bcp_advance(5);
|
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...
|
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2416,6 +2513,9 @@ run:
|
|||||||
istate->set_callee_entry_point(method->from_interpreted_entry());
|
istate->set_callee_entry_point(method->from_interpreted_entry());
|
||||||
istate->set_bcp_advance(3);
|
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...
|
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2443,14 +2543,18 @@ run:
|
|||||||
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
|
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
|
||||||
if (cache->is_vfinal()) {
|
if (cache->is_vfinal()) {
|
||||||
callee = cache->f2_as_vfinal_method();
|
callee = cache->f2_as_vfinal_method();
|
||||||
|
// Profile 'special case of invokeinterface' final call.
|
||||||
|
BI_PROFILE_UPDATE_FINALCALL();
|
||||||
} else {
|
} else {
|
||||||
// get receiver
|
// Get receiver.
|
||||||
int parms = cache->parameter_size();
|
int parms = cache->parameter_size();
|
||||||
// Same comments as invokevirtual apply here
|
// Same comments as invokevirtual apply here.
|
||||||
VERIFY_OOP(STACK_OBJECT(-parms));
|
oop rcvr = STACK_OBJECT(-parms);
|
||||||
InstanceKlass* rcvrKlass = (InstanceKlass*)
|
VERIFY_OOP(rcvr);
|
||||||
STACK_OBJECT(-parms)->klass();
|
InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass();
|
||||||
callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
|
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(callee);
|
||||||
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
||||||
@ -2481,15 +2585,18 @@ run:
|
|||||||
// interface. The link resolver checks this but only for the first
|
// interface. The link resolver checks this but only for the first
|
||||||
// time this interface is called.
|
// time this interface is called.
|
||||||
if (i == int2->itable_length()) {
|
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();
|
int mindex = cache->f2_as_index();
|
||||||
itableMethodEntry* im = ki->first_method_entry(rcvr->klass());
|
itableMethodEntry* im = ki->first_method_entry(rcvr->klass());
|
||||||
callee = im[mindex].method();
|
callee = im[mindex].method();
|
||||||
if (callee == NULL) {
|
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(callee);
|
||||||
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
istate->set_callee_entry_point(callee->from_interpreted_entry());
|
||||||
#ifdef VM_JVMTI
|
#ifdef VM_JVMTI
|
||||||
@ -2521,8 +2628,11 @@ run:
|
|||||||
Method* callee;
|
Method* callee;
|
||||||
if ((Bytecodes::Code)opcode == Bytecodes::_invokevirtual) {
|
if ((Bytecodes::Code)opcode == Bytecodes::_invokevirtual) {
|
||||||
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
|
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
|
||||||
if (cache->is_vfinal()) callee = cache->f2_as_vfinal_method();
|
if (cache->is_vfinal()) {
|
||||||
else {
|
callee = cache->f2_as_vfinal_method();
|
||||||
|
// Profile final call.
|
||||||
|
BI_PROFILE_UPDATE_FINALCALL();
|
||||||
|
} else {
|
||||||
// get receiver
|
// get receiver
|
||||||
int parms = cache->parameter_size();
|
int parms = cache->parameter_size();
|
||||||
// this works but needs a resourcemark and seems to create a vtable on every call:
|
// this works but needs a resourcemark and seems to create a vtable on every call:
|
||||||
@ -2531,8 +2641,9 @@ run:
|
|||||||
// this fails with an assert
|
// this fails with an assert
|
||||||
// InstanceKlass* rcvrKlass = InstanceKlass::cast(STACK_OBJECT(-parms)->klass());
|
// InstanceKlass* rcvrKlass = InstanceKlass::cast(STACK_OBJECT(-parms)->klass());
|
||||||
// but this works
|
// but this works
|
||||||
VERIFY_OOP(STACK_OBJECT(-parms));
|
oop rcvr = STACK_OBJECT(-parms);
|
||||||
InstanceKlass* rcvrKlass = (InstanceKlass*) STACK_OBJECT(-parms)->klass();
|
VERIFY_OOP(rcvr);
|
||||||
|
InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass();
|
||||||
/*
|
/*
|
||||||
Executing this code in java.lang.String:
|
Executing this code in java.lang.String:
|
||||||
public String(char value[]) {
|
public String(char value[]) {
|
||||||
@ -2550,12 +2661,17 @@ run:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
|
callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
|
||||||
|
// Profile virtual call.
|
||||||
|
BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) {
|
if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) {
|
||||||
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
|
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
|
||||||
}
|
}
|
||||||
callee = cache->f1_as_method();
|
callee = cache->f1_as_method();
|
||||||
|
|
||||||
|
// Profile call.
|
||||||
|
BI_PROFILE_UPDATE_CALL();
|
||||||
}
|
}
|
||||||
|
|
||||||
istate->set_callee(callee);
|
istate->set_callee(callee);
|
||||||
@ -2607,6 +2723,8 @@ run:
|
|||||||
CASE(_goto):
|
CASE(_goto):
|
||||||
{
|
{
|
||||||
int16_t offset = (int16_t)Bytes::get_Java_u2(pc + 1);
|
int16_t offset = (int16_t)Bytes::get_Java_u2(pc + 1);
|
||||||
|
// Profile jump.
|
||||||
|
BI_PROFILE_UPDATE_JUMP();
|
||||||
address branch_pc = pc;
|
address branch_pc = pc;
|
||||||
UPDATE_PC(offset);
|
UPDATE_PC(offset);
|
||||||
DO_BACKEDGE_CHECKS(offset, branch_pc);
|
DO_BACKEDGE_CHECKS(offset, branch_pc);
|
||||||
@ -2623,6 +2741,8 @@ run:
|
|||||||
CASE(_goto_w):
|
CASE(_goto_w):
|
||||||
{
|
{
|
||||||
int32_t offset = Bytes::get_Java_u4(pc + 1);
|
int32_t offset = Bytes::get_Java_u4(pc + 1);
|
||||||
|
// Profile jump.
|
||||||
|
BI_PROFILE_UPDATE_JUMP();
|
||||||
address branch_pc = pc;
|
address branch_pc = pc;
|
||||||
UPDATE_PC(offset);
|
UPDATE_PC(offset);
|
||||||
DO_BACKEDGE_CHECKS(offset, branch_pc);
|
DO_BACKEDGE_CHECKS(offset, branch_pc);
|
||||||
@ -2632,6 +2752,9 @@ run:
|
|||||||
/* return from a jsr or jsr_w */
|
/* return from a jsr or jsr_w */
|
||||||
|
|
||||||
CASE(_ret): {
|
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]));
|
pc = istate->method()->code_base() + (intptr_t)(LOCALS_ADDR(pc[1]));
|
||||||
UPDATE_PC_AND_CONTINUE(0);
|
UPDATE_PC_AND_CONTINUE(0);
|
||||||
}
|
}
|
||||||
@ -2713,6 +2836,9 @@ run:
|
|||||||
}
|
}
|
||||||
// for AbortVMOnException flag
|
// for AbortVMOnException flag
|
||||||
NOT_PRODUCT(Exceptions::debug_check_abort(except_oop));
|
NOT_PRODUCT(Exceptions::debug_check_abort(except_oop));
|
||||||
|
|
||||||
|
// Update profiling data.
|
||||||
|
BI_PROFILE_ALIGN_TO_CURRENT_BCI();
|
||||||
goto run;
|
goto run;
|
||||||
}
|
}
|
||||||
if (TraceExceptions) {
|
if (TraceExceptions) {
|
||||||
@ -2920,7 +3046,7 @@ run:
|
|||||||
oop rcvr = base->obj();
|
oop rcvr = base->obj();
|
||||||
if (rcvr == NULL) {
|
if (rcvr == NULL) {
|
||||||
if (!suppress_error) {
|
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();
|
illegal_state_oop = THREAD->pending_exception();
|
||||||
THREAD->clear_pending_exception();
|
THREAD->clear_pending_exception();
|
||||||
}
|
}
|
||||||
@ -3008,9 +3134,9 @@ run:
|
|||||||
// A pending exception that was pending prior to a possible popping frame
|
// A pending exception that was pending prior to a possible popping frame
|
||||||
// overrides the 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) {
|
if (illegal_state_oop() != NULL || original_exception() != NULL) {
|
||||||
// inform the frame manager we have no result
|
// Inform the frame manager we have no result.
|
||||||
istate->set_msg(throwing_exception);
|
istate->set_msg(throwing_exception);
|
||||||
if (illegal_state_oop() != NULL)
|
if (illegal_state_oop() != NULL)
|
||||||
THREAD->set_pending_exception(illegal_state_oop(), NULL, 0);
|
THREAD->set_pending_exception(illegal_state_oop(), NULL, 0);
|
||||||
|
@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* Copyright 2012, 2013 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)
|
||||||
|
#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 (mcs->invocation_counter() \
|
||||||
|
->reached_ProfileLimit(mcs->backedge_counter())) { \
|
||||||
|
/* 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
|
@ -241,18 +241,15 @@ IRT_END
|
|||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
// Exceptions
|
// Exceptions
|
||||||
|
|
||||||
// Assume the compiler is (or will be) interested in this event.
|
void InterpreterRuntime::note_trap_inner(JavaThread* thread, int reason,
|
||||||
// If necessary, create an MDO to hold the information, and record it.
|
methodHandle trap_method, int trap_bci, TRAPS) {
|
||||||
void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
|
|
||||||
assert(ProfileTraps, "call me only if profiling");
|
|
||||||
methodHandle trap_method(thread, method(thread));
|
|
||||||
|
|
||||||
if (trap_method.not_null()) {
|
if (trap_method.not_null()) {
|
||||||
MethodData* trap_mdo = trap_method->method_data();
|
MethodData* trap_mdo = trap_method->method_data();
|
||||||
if (trap_mdo == NULL) {
|
if (trap_mdo == NULL) {
|
||||||
Method::build_interpreter_method_data(trap_method, THREAD);
|
Method::build_interpreter_method_data(trap_method, THREAD);
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
|
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())),
|
||||||
|
"we expect only an OOM error here");
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
}
|
}
|
||||||
trap_mdo = trap_method->method_data();
|
trap_mdo = trap_method->method_data();
|
||||||
@ -261,12 +258,42 @@ void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
|
|||||||
if (trap_mdo != NULL) {
|
if (trap_mdo != NULL) {
|
||||||
// Update per-method count of trap events. The interpreter
|
// Update per-method count of trap events. The interpreter
|
||||||
// is updating the MDO to simulate the effect of compiler traps.
|
// is updating the MDO to simulate the effect of compiler traps.
|
||||||
int trap_bci = trap_method->bci_from(bcp(thread));
|
|
||||||
Deoptimization::update_method_data_from_interpreter(trap_mdo, trap_bci, reason);
|
Deoptimization::update_method_data_from_interpreter(trap_mdo, trap_bci, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assume the compiler is (or will be) interested in this event.
|
||||||
|
// If necessary, create an MDO to hold the information, and record it.
|
||||||
|
void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
|
||||||
|
assert(ProfileTraps, "call me only if profiling");
|
||||||
|
methodHandle trap_method(thread, method(thread));
|
||||||
|
int trap_bci = trap_method->bci_from(bcp(thread));
|
||||||
|
note_trap_inner(thread, reason, trap_method, trap_bci, THREAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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);
|
||||||
|
note_trap_inner(thread, reason, trap_method, trap_bci, THREAD);
|
||||||
|
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) {
|
static Handle get_preinitialized_exception(Klass* k, TRAPS) {
|
||||||
// get klass
|
// get klass
|
||||||
InstanceKlass* klass = InstanceKlass::cast(k);
|
InstanceKlass* klass = InstanceKlass::cast(k);
|
||||||
|
@ -66,9 +66,15 @@ class InterpreterRuntime: AllStatic {
|
|||||||
|
|
||||||
static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); }
|
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 ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); }
|
||||||
|
static void note_trap_inner(JavaThread* thread, int reason,
|
||||||
|
methodHandle trap_method, int trap_bci, TRAPS);
|
||||||
static void note_trap(JavaThread *thread, int reason, TRAPS);
|
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
|
// Inner work method for Interpreter's frequency counter overflow.
|
||||||
static nmethod* frequency_counter_overflow_inner(JavaThread* thread, address branch_bcp);
|
static nmethod* frequency_counter_overflow_inner(JavaThread* thread, address branch_bcp);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -100,6 +106,17 @@ class InterpreterRuntime: AllStatic {
|
|||||||
#endif
|
#endif
|
||||||
static void throw_pending_exception(JavaThread* thread);
|
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
|
// Statics & fields
|
||||||
static void resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode);
|
static void resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode);
|
||||||
|
|
||||||
|
@ -99,16 +99,24 @@ class InvocationCounter VALUE_OBJ_CLASS_SPEC {
|
|||||||
int get_BackwardBranchLimit() const { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; }
|
int get_BackwardBranchLimit() const { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; }
|
||||||
int get_ProfileLimit() const { return InterpreterProfileLimit >> number_of_noncount_bits; }
|
int get_ProfileLimit() const { return InterpreterProfileLimit >> number_of_noncount_bits; }
|
||||||
|
|
||||||
|
#ifdef CC_INTERP
|
||||||
// Test counter using scaled limits like the asm interpreter would do rather than doing
|
// Test counter using scaled limits like the asm interpreter would do rather than doing
|
||||||
// the shifts to normalize the counter.
|
// the shifts to normalize the counter.
|
||||||
|
// Checks sum of invocation_counter and backedge_counter as the template interpreter does.
|
||||||
bool reached_InvocationLimit() const { return _counter >= (unsigned int) InterpreterInvocationLimit; }
|
bool reached_InvocationLimit(InvocationCounter *back_edge_count) const {
|
||||||
bool reached_BackwardBranchLimit() const { return _counter >= (unsigned int) InterpreterBackwardBranchLimit; }
|
return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >=
|
||||||
|
(unsigned int) InterpreterInvocationLimit;
|
||||||
// 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_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 & count_mask) >=
|
||||||
|
(unsigned int) InterpreterProfileLimit;
|
||||||
|
}
|
||||||
|
#endif // CC_INTERP
|
||||||
|
|
||||||
void increment() { _counter += count_increment; }
|
void increment() { _counter += count_increment; }
|
||||||
|
|
||||||
|
@ -244,6 +244,11 @@ address RetData::fixup_ret(int return_bci, MethodData* h_mdo) {
|
|||||||
return mdp;
|
return mdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CC_INTERP
|
||||||
|
DataLayout* RetData::advance(MethodData *md, int bci) {
|
||||||
|
return (DataLayout*) md->bci_to_dp(bci);
|
||||||
|
}
|
||||||
|
#endif // CC_INTERP
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void RetData::print_data_on(outputStream* st) {
|
void RetData::print_data_on(outputStream* st) {
|
||||||
|
@ -225,6 +225,11 @@ public:
|
|||||||
static ByteSize cell_offset(int index) {
|
static ByteSize cell_offset(int index) {
|
||||||
return byte_offset_of(DataLayout, _cells) + in_ByteSize(index * cell_size);
|
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.
|
// 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) {
|
static int flag_number_to_byte_constant(int flag_number) {
|
||||||
assert(0 <= flag_number && flag_number < flag_limit, "oob");
|
assert(0 <= flag_number && flag_number < flag_limit, "oob");
|
||||||
@ -356,6 +361,41 @@ protected:
|
|||||||
_data = data;
|
_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:
|
public:
|
||||||
// Constructor for invalid ProfileData.
|
// Constructor for invalid ProfileData.
|
||||||
ProfileData();
|
ProfileData();
|
||||||
@ -495,6 +535,20 @@ public:
|
|||||||
return cell_offset(bit_cell_count);
|
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
|
#ifndef PRODUCT
|
||||||
void print_data_on(outputStream* st);
|
void print_data_on(outputStream* st);
|
||||||
#endif
|
#endif
|
||||||
@ -539,6 +593,25 @@ public:
|
|||||||
set_uint_at(count_off, count);
|
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
|
#ifndef PRODUCT
|
||||||
void print_data_on(outputStream* st);
|
void print_data_on(outputStream* st);
|
||||||
#endif
|
#endif
|
||||||
@ -609,6 +682,20 @@ public:
|
|||||||
return cell_offset(displacement_off_set);
|
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.
|
// Specific initialization.
|
||||||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||||
|
|
||||||
@ -718,6 +805,43 @@ public:
|
|||||||
// GC support
|
// GC support
|
||||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
|
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
|
#ifndef PRODUCT
|
||||||
void print_receiver_data_on(outputStream* st);
|
void print_receiver_data_on(outputStream* st);
|
||||||
void print_data_on(outputStream* st);
|
void print_data_on(outputStream* st);
|
||||||
@ -751,6 +875,16 @@ public:
|
|||||||
return cell_offset(static_cell_count());
|
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
|
#ifndef PRODUCT
|
||||||
void print_data_on(outputStream* st);
|
void print_data_on(outputStream* st);
|
||||||
#endif
|
#endif
|
||||||
@ -847,6 +981,10 @@ public:
|
|||||||
return cell_offset(bci_displacement_cell_index(row));
|
return cell_offset(bci_displacement_cell_index(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CC_INTERP
|
||||||
|
static DataLayout* advance(MethodData *md, int bci);
|
||||||
|
#endif // CC_INTERP
|
||||||
|
|
||||||
// Specific initialization.
|
// Specific initialization.
|
||||||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||||
|
|
||||||
@ -911,6 +1049,20 @@ public:
|
|||||||
return cell_offset(branch_cell_count);
|
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.
|
// Specific initialization.
|
||||||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||||
|
|
||||||
@ -950,6 +1102,20 @@ protected:
|
|||||||
set_int_at(aindex, value);
|
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.
|
// Code generation support for subclasses.
|
||||||
static ByteSize array_element_offset(int index) {
|
static ByteSize array_element_offset(int index) {
|
||||||
return cell_offset(array_start_off_set + index);
|
return cell_offset(array_start_off_set + index);
|
||||||
@ -1068,6 +1234,28 @@ public:
|
|||||||
return in_ByteSize(relative_displacement_off_set) * cell_size;
|
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.
|
// Specific initialization.
|
||||||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||||
|
|
||||||
@ -1146,8 +1334,11 @@ public:
|
|||||||
// adjusted in the event of a change in control flow.
|
// adjusted in the event of a change in control flow.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
CC_INTERP_ONLY(class BytecodeInterpreter;)
|
||||||
|
|
||||||
class MethodData : public Metadata {
|
class MethodData : public Metadata {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
CC_INTERP_ONLY(friend class BytecodeInterpreter;)
|
||||||
private:
|
private:
|
||||||
friend class ProfileData;
|
friend class ProfileData;
|
||||||
|
|
||||||
|
@ -117,10 +117,10 @@ jvmtiCapabilities JvmtiManageCapabilities::init_onload_capabilities() {
|
|||||||
jvmtiCapabilities jc;
|
jvmtiCapabilities jc;
|
||||||
|
|
||||||
memset(&jc, 0, sizeof(jc));
|
memset(&jc, 0, sizeof(jc));
|
||||||
#ifndef CC_INTERP
|
#ifndef ZERO
|
||||||
jc.can_pop_frame = 1;
|
jc.can_pop_frame = 1;
|
||||||
jc.can_force_early_return = 1;
|
jc.can_force_early_return = 1;
|
||||||
#endif // !CC_INTERP
|
#endif // !ZERO
|
||||||
jc.can_get_source_debug_extension = 1;
|
jc.can_get_source_debug_extension = 1;
|
||||||
jc.can_access_local_variables = 1;
|
jc.can_access_local_variables = 1;
|
||||||
jc.can_maintain_original_method_order = 1;
|
jc.can_maintain_original_method_order = 1;
|
||||||
|
@ -3592,8 +3592,8 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
|||||||
UseBiasedLocking = false;
|
UseBiasedLocking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CC_INTERP
|
#ifdef ZERO
|
||||||
// Clear flags not supported by the C++ interpreter
|
// Clear flags not supported on zero.
|
||||||
FLAG_SET_DEFAULT(ProfileInterpreter, false);
|
FLAG_SET_DEFAULT(ProfileInterpreter, false);
|
||||||
FLAG_SET_DEFAULT(UseBiasedLocking, false);
|
FLAG_SET_DEFAULT(UseBiasedLocking, false);
|
||||||
LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false));
|
LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false));
|
||||||
|
@ -2727,6 +2727,11 @@ class CommandLineFlags {
|
|||||||
product_pd(bool, ProfileInterpreter, \
|
product_pd(bool, ProfileInterpreter, \
|
||||||
"Profile at the bytecode level during interpretation") \
|
"Profile at the bytecode level during interpretation") \
|
||||||
\
|
\
|
||||||
|
develop(bool, TraceProfileInterpreter, false, \
|
||||||
|
"Trace profiling at the bytecode level during interpretation. " \
|
||||||
|
"This outputs the profiling information collected to improve " \
|
||||||
|
"jit compilation.") \
|
||||||
|
\
|
||||||
develop_pd(bool, ProfileTraps, \
|
develop_pd(bool, ProfileTraps, \
|
||||||
"Profile deoptimization traps at the bytecode level") \
|
"Profile deoptimization traps at the bytecode level") \
|
||||||
\
|
\
|
||||||
|
Loading…
x
Reference in New Issue
Block a user