|
@@ -24,119 +24,69 @@ |
|
|
|
|
|
#include "precompiled.hpp" |
|
|
#include "interpreter/invocationCounter.hpp" |
|
|
#include "runtime/frame.hpp" |
|
|
#include "runtime/handles.inline.hpp" |
|
|
|
|
|
|
|
|
// Implementation of InvocationCounter |
|
|
|
|
|
void InvocationCounter::init() { |
|
|
_counter = 0; // reset all the bits, including the sticky carry |
|
|
reset(); |
|
|
} |
|
|
|
|
|
void InvocationCounter::reset() { |
|
|
// Only reset the state and don't make the method look like it's never |
|
|
// been executed |
|
|
set_state(wait_for_compile); |
|
|
void InvocationCounter::set(uint count, uint flag) { |
|
|
_counter = (count << number_of_noncount_bits) | (flag & carry_mask); |
|
|
} |
|
|
|
|
|
void InvocationCounter::set(uint count) { |
|
|
uint carry = (_counter & carry_mask); // the carry bit is sticky |
|
|
_counter = (count << number_of_noncount_bits) | carry; |
|
|
} |
|
|
|
|
|
void InvocationCounter::set_carry() { |
|
|
set_carry_flag(); |
|
|
void InvocationCounter::update(uint new_count) { |
|
|
// Don't make the method look like it's never been executed |
|
|
uint counter = raw_counter(); |
|
|
uint c = extract_count(counter); |
|
|
uint f = extract_carry(counter); |
|
|
// prevent from going to zero, to distinguish from never-executed methods |
|
|
if (c > 0 && new_count == 0) new_count = 1; |
|
|
set(new_count, f); |
|
|
} |
|
|
|
|
|
void InvocationCounter::set_carry_and_reduce() { |
|
|
uint counter = raw_counter(); |
|
|
// The carry bit now indicates that this counter had achieved a very |
|
|
// large value. Now reduce the value, so that the method can be |
|
|
// executed many more times before re-entering the VM. |
|
|
int old_count = count(); |
|
|
int new_count = MIN2(old_count, (int) (CompileThreshold / 2)); |
|
|
uint old_count = extract_count(counter); |
|
|
uint new_count = MIN2(old_count, (uint)(CompileThreshold / 2)); |
|
|
// prevent from going to zero, to distinguish from never-executed methods |
|
|
if (new_count == 0) new_count = 1; |
|
|
if (old_count != new_count) set(state(), new_count); |
|
|
if (old_count != new_count) set(new_count, carry_mask); |
|
|
} |
|
|
|
|
|
void InvocationCounter::set_state(State state) { |
|
|
assert(0 <= state && state < number_of_states, "illegal state"); |
|
|
int init = _init[state]; |
|
|
// prevent from going to zero, to distinguish from never-executed methods |
|
|
if (init == 0 && count() > 0) init = 1; |
|
|
int carry = (_counter & carry_mask); // the carry bit is sticky |
|
|
_counter = (init << number_of_noncount_bits) | carry | state; |
|
|
void InvocationCounter::set_carry_on_overflow() { |
|
|
if (!carry() && count() > InvocationCounter::count_limit / 2) { |
|
|
set_carry(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void InvocationCounter::print() { |
|
|
tty->print_cr("invocation count: up = %d, limit = %d, carry = %s, state = %s", |
|
|
count(), limit(), |
|
|
carry() ? "true" : "false", |
|
|
state_as_string(state())); |
|
|
void InvocationCounter::reset() { |
|
|
update(0); |
|
|
} |
|
|
|
|
|
void InvocationCounter::print_short() { |
|
|
tty->print(" [%d%s;%s]", count(), carry()?"+carry":"", state_as_short_string(state())); |
|
|
void InvocationCounter::decay() { |
|
|
update(count() >> 1); |
|
|
} |
|
|
|
|
|
// Initialization |
|
|
|
|
|
int InvocationCounter::_init [InvocationCounter::number_of_states]; |
|
|
InvocationCounter::Action InvocationCounter::_action[InvocationCounter::number_of_states]; |
|
|
void InvocationCounter::print() { |
|
|
uint counter = raw_counter(); |
|
|
tty->print_cr("invocation count: up = %d, limit = %d, carry = %s", |
|
|
extract_count(counter), limit(), |
|
|
extract_carry(counter) ? "true" : "false"); |
|
|
} |
|
|
|
|
|
#ifdef CC_INTERP |
|
|
int InvocationCounter::InterpreterInvocationLimit; |
|
|
int InvocationCounter::InterpreterBackwardBranchLimit; |
|
|
#endif |
|
|
|
|
|
const char* InvocationCounter::state_as_string(State state) { |
|
|
switch (state) { |
|
|
case wait_for_nothing : return "wait_for_nothing"; |
|
|
case wait_for_compile : return "wait_for_compile"; |
|
|
default: |
|
|
ShouldNotReachHere(); |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
const char* InvocationCounter::state_as_short_string(State state) { |
|
|
switch (state) { |
|
|
case wait_for_nothing : return "not comp."; |
|
|
case wait_for_compile : return "compileable"; |
|
|
default: |
|
|
ShouldNotReachHere(); |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static address do_nothing(const methodHandle& method, TRAPS) { |
|
|
// dummy action for inactive invocation counters |
|
|
MethodCounters* mcs = method->method_counters(); |
|
|
assert(mcs != NULL, ""); |
|
|
mcs->invocation_counter()->set_carry(); |
|
|
mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
|
|
|
static address do_decay(const methodHandle& method, TRAPS) { |
|
|
// decay invocation counters so compilation gets delayed |
|
|
MethodCounters* mcs = method->method_counters(); |
|
|
assert(mcs != NULL, ""); |
|
|
mcs->invocation_counter()->decay(); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
|
|
|
void InvocationCounter::def(State state, int init, Action action) { |
|
|
assert(0 <= state && state < number_of_states, "illegal state"); |
|
|
assert(0 <= init && init < count_limit, "initial value out of range"); |
|
|
_init [state] = init; |
|
|
_action[state] = action; |
|
|
} |
|
|
|
|
|
void InvocationCounter::reinitialize() { |
|
|
// define states |
|
|
guarantee((int)number_of_states <= (int)state_limit, "adjust number_of_state_bits"); |
|
|
def(wait_for_nothing, 0, do_nothing); |
|
|
def(wait_for_compile, 0, do_decay); |
|
|
|
|
|
void invocationCounter_init() { |
|
|
#ifdef CC_INTERP |
|
|
InterpreterInvocationLimit = CompileThreshold << number_of_noncount_bits; |
|
|
|
|
@@ -153,7 +103,3 @@ void InvocationCounter::reinitialize() { |
|
|
assert(0 <= InterpreterBackwardBranchLimit, "OSR threshold should be non-negative"); |
|
|
#endif |
|
|
} |
|
|
|
|
|
void invocationCounter_init() { |
|
|
InvocationCounter::reinitialize(); |
|
|
} |