8203883: Remove State from InvocationCounters
Reviewed-by: redestad, thartmann
This commit is contained in:
parent
b4b8ead78b
commit
18c01206d0
@ -295,8 +295,8 @@ void SimpleCompPolicy::reset_counter_for_invocation_event(const methodHandle& m)
|
||||
// Set carry bit and reduce counter's value to min(count, CompileThreshold/2).
|
||||
MethodCounters* mcs = m->method_counters();
|
||||
assert(mcs != NULL, "MethodCounters cannot be NULL for profiling");
|
||||
mcs->invocation_counter()->set_carry();
|
||||
mcs->backedge_counter()->set_carry();
|
||||
mcs->invocation_counter()->set_carry_and_reduce();
|
||||
mcs->backedge_counter()->set_carry_and_reduce();
|
||||
|
||||
assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed");
|
||||
}
|
||||
@ -312,9 +312,9 @@ void SimpleCompPolicy::reset_counter_for_back_branch_event(const methodHandle& m
|
||||
// Don't set invocation_counter's value too low otherwise the method will
|
||||
// look like immature (ic < ~5300) which prevents the inlining based on
|
||||
// the type profiling.
|
||||
i->set(i->state(), CompileThreshold);
|
||||
i->set(CompileThreshold);
|
||||
// Don't reset counter too low - it is used to check if OSR method is ready.
|
||||
b->set(b->state(), CompileThreshold / 2);
|
||||
b->set(CompileThreshold / 2);
|
||||
}
|
||||
|
||||
// Called at the end of the safepoint
|
||||
@ -340,7 +340,7 @@ void SimpleCompPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) {
|
||||
c = mcs->invocation_counter();
|
||||
if (is_osr) {
|
||||
// It was an OSR method, so bump the count higher.
|
||||
c->set(c->state(), CompileThreshold);
|
||||
c->set(CompileThreshold);
|
||||
} else {
|
||||
c->reset();
|
||||
}
|
||||
@ -358,14 +358,6 @@ void SimpleCompPolicy::delay_compilation(Method* method) {
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleCompPolicy::disable_compilation(Method* method) {
|
||||
MethodCounters* mcs = method->method_counters();
|
||||
if (mcs != NULL) {
|
||||
mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing);
|
||||
mcs->backedge_counter()->set_state(InvocationCounter::wait_for_nothing);
|
||||
}
|
||||
}
|
||||
|
||||
CompileTask* SimpleCompPolicy::select_task(CompileQueue* compile_queue) {
|
||||
return select_task_helper(compile_queue);
|
||||
}
|
||||
|
@ -71,9 +71,6 @@ public:
|
||||
// delay_compilation(method) can be called by any component of the runtime to notify the policy
|
||||
// that it's recommended to delay the compilation of this method.
|
||||
virtual void delay_compilation(Method* method) = 0;
|
||||
// disable_compilation() is called whenever the runtime decides to disable compilation of the
|
||||
// specified method.
|
||||
virtual void disable_compilation(Method* method) = 0;
|
||||
// Select task is called by CompileBroker. The queue is guaranteed to have at least one
|
||||
// element and is locked. The function should select one and return it.
|
||||
virtual CompileTask* select_task(CompileQueue* compile_queue) = 0;
|
||||
@ -102,7 +99,6 @@ class SimpleCompPolicy : public CompilationPolicy {
|
||||
virtual void do_safepoint_work();
|
||||
virtual void reprofile(ScopeDesc* trap_scope, bool is_osr);
|
||||
virtual void delay_compilation(Method* method);
|
||||
virtual void disable_compilation(Method* method);
|
||||
virtual bool is_mature(Method* method);
|
||||
virtual void initialize();
|
||||
virtual CompileTask* select_task(CompileQueue* compile_queue);
|
||||
|
@ -379,23 +379,17 @@ CompLevel TieredThresholdPolicy::initial_compile_level(const methodHandle& metho
|
||||
return limit_level(initial_compile_level_helper(method));
|
||||
}
|
||||
|
||||
void TieredThresholdPolicy::set_carry_if_necessary(InvocationCounter *counter) {
|
||||
if (!counter->carry() && counter->count() > InvocationCounter::count_limit / 2) {
|
||||
counter->set_carry_flag();
|
||||
}
|
||||
}
|
||||
|
||||
// Set carry flags on the counters if necessary
|
||||
void TieredThresholdPolicy::handle_counter_overflow(Method* method) {
|
||||
MethodCounters *mcs = method->method_counters();
|
||||
if (mcs != NULL) {
|
||||
set_carry_if_necessary(mcs->invocation_counter());
|
||||
set_carry_if_necessary(mcs->backedge_counter());
|
||||
mcs->invocation_counter()->set_carry_on_overflow();
|
||||
mcs->backedge_counter()->set_carry_on_overflow();
|
||||
}
|
||||
MethodData* mdo = method->method_data();
|
||||
if (mdo != NULL) {
|
||||
set_carry_if_necessary(mdo->invocation_counter());
|
||||
set_carry_if_necessary(mdo->backedge_counter());
|
||||
mdo->invocation_counter()->set_carry_on_overflow();
|
||||
mdo->backedge_counter()->set_carry_on_overflow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,6 @@ void AbstractInterpreter::initialize() {
|
||||
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset();
|
||||
if (PrintBytecodeHistogram) BytecodeHistogram::reset();
|
||||
if (PrintBytecodePairHistogram) BytecodePairHistogram::reset();
|
||||
|
||||
InvocationCounter::reinitialize();
|
||||
|
||||
}
|
||||
|
||||
void AbstractInterpreter::print() {
|
||||
|
@ -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_carry() {
|
||||
set_carry_flag();
|
||||
void InvocationCounter::set(uint count) {
|
||||
uint carry = (_counter & carry_mask); // the carry bit is sticky
|
||||
_counter = (count << number_of_noncount_bits) | carry;
|
||||
}
|
||||
|
||||
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::reset() {
|
||||
update(0);
|
||||
}
|
||||
|
||||
void InvocationCounter::decay() {
|
||||
update(count() >> 1);
|
||||
}
|
||||
|
||||
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()));
|
||||
uint counter = raw_counter();
|
||||
tty->print_cr("invocation count: up = %d, limit = %d, carry = %s",
|
||||
extract_count(counter), limit(),
|
||||
extract_carry(counter) ? "true" : "false");
|
||||
}
|
||||
|
||||
void InvocationCounter::print_short() {
|
||||
tty->print(" [%d%s;%s]", count(), carry()?"+carry":"", state_as_short_string(state()));
|
||||
}
|
||||
|
||||
// Initialization
|
||||
|
||||
int InvocationCounter::_init [InvocationCounter::number_of_states];
|
||||
InvocationCounter::Action InvocationCounter::_action[InvocationCounter::number_of_states];
|
||||
|
||||
#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();
|
||||
}
|
||||
|
@ -29,36 +29,26 @@
|
||||
#include "utilities/exceptions.hpp"
|
||||
|
||||
// InvocationCounters are used to trigger actions when a limit (threshold) is reached.
|
||||
// For different states, different limits and actions can be defined in the initialization
|
||||
// routine of InvocationCounters.
|
||||
//
|
||||
// Implementation notes: For space reasons, state & counter are both encoded in one word,
|
||||
// The state is encoded using some of the least significant bits, the counter is using the
|
||||
// more significant bits. The counter is incremented before a method is activated and an
|
||||
// The counter is incremented before a method is activated and an
|
||||
// action is triggered when count() > limit().
|
||||
|
||||
class InvocationCounter {
|
||||
friend class VMStructs;
|
||||
friend class JVMCIVMStructs;
|
||||
friend class ciReplay;
|
||||
private: // bit no: |31 3| 2 | 1 0 |
|
||||
unsigned int _counter; // format: [count|carry|state]
|
||||
private: // bit no: |31 1| 0 |
|
||||
uint _counter; // format: [count|carry|
|
||||
|
||||
enum PrivateConstants {
|
||||
number_of_state_bits = 2,
|
||||
number_of_carry_bits = 1,
|
||||
number_of_noncount_bits = number_of_state_bits + number_of_carry_bits,
|
||||
state_limit = nth_bit(number_of_state_bits),
|
||||
count_grain = nth_bit(number_of_state_bits + number_of_carry_bits),
|
||||
carry_mask = right_n_bits(number_of_carry_bits) << number_of_state_bits,
|
||||
state_mask = right_n_bits(number_of_state_bits),
|
||||
status_mask = right_n_bits(number_of_state_bits + number_of_carry_bits),
|
||||
count_mask = ((int)(-1) ^ status_mask)
|
||||
number_of_carry_bits = 1,
|
||||
number_of_noncount_bits = number_of_carry_bits,
|
||||
count_grain = nth_bit(number_of_carry_bits),
|
||||
carry_mask = right_n_bits(number_of_carry_bits),
|
||||
count_mask = ((int)(-1) ^ carry_mask)
|
||||
};
|
||||
|
||||
public:
|
||||
typedef address (*Action)(const methodHandle& method, TRAPS);
|
||||
|
||||
enum PublicConstants {
|
||||
count_increment = count_grain, // use this value to increment the 32bit _counter word
|
||||
count_mask_value = count_mask, // use this value to mask the backedge counter
|
||||
@ -67,30 +57,31 @@ class InvocationCounter {
|
||||
count_limit = nth_bit(number_of_count_bits - 1)
|
||||
};
|
||||
|
||||
enum State {
|
||||
wait_for_nothing, // do nothing when count() > limit()
|
||||
wait_for_compile, // introduce nmethod when count() > limit()
|
||||
number_of_states // must be <= state_limit
|
||||
};
|
||||
|
||||
// Manipulation
|
||||
void reset(); // sets state to wait state
|
||||
void init(); // sets state into original state
|
||||
void set_state(State state); // sets state and initializes counter correspondingly
|
||||
inline void set(State state, int count); // sets state and counter
|
||||
inline void decay(); // decay counter (divide by two)
|
||||
void set_carry(); // set the sticky carry bit
|
||||
void set_carry_flag() { _counter |= carry_mask; }
|
||||
|
||||
int raw_counter() { return _counter; }
|
||||
void reset();
|
||||
void init();
|
||||
void decay(); // decay counter (divide by two)
|
||||
void set_carry_and_reduce(); // set the sticky carry bit
|
||||
void set_carry_on_overflow();
|
||||
void set(uint count);
|
||||
void increment() { _counter += count_increment; }
|
||||
|
||||
// Accessors
|
||||
State state() const { return (State)(_counter & state_mask); }
|
||||
bool carry() const { return (_counter & carry_mask) != 0; }
|
||||
int limit() const { return CompileThreshold; }
|
||||
Action action() const { return _action[state()]; }
|
||||
int count() const { return _counter >> number_of_noncount_bits; }
|
||||
bool carry() const { return (_counter & carry_mask) != 0; }
|
||||
uint count() const { return _counter >> number_of_noncount_bits; }
|
||||
uint limit() const { return CompileThreshold; }
|
||||
uint raw_counter() const { return _counter; }
|
||||
|
||||
void print();
|
||||
|
||||
private:
|
||||
void set_carry() { _counter |= carry_mask; }
|
||||
uint extract_carry(uint raw) const { return (raw & carry_mask); }
|
||||
uint extract_count(uint raw) const { return raw >> number_of_noncount_bits; }
|
||||
void update(uint new_count);
|
||||
void set(uint count, uint carry);
|
||||
|
||||
public:
|
||||
#ifdef CC_INTERP
|
||||
static int InterpreterInvocationLimit; // CompileThreshold scaled for interpreter use
|
||||
static int InterpreterBackwardBranchLimit; // A separate threshold for on stack replacement
|
||||
@ -100,47 +91,16 @@ class InvocationCounter {
|
||||
// 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;
|
||||
(uint) InterpreterInvocationLimit;
|
||||
}
|
||||
bool reached_BackwardBranchLimit(InvocationCounter *back_edge_count) const {
|
||||
return (_counter & count_mask) + (back_edge_count->_counter & count_mask) >=
|
||||
(unsigned int) InterpreterBackwardBranchLimit;
|
||||
(uint) InterpreterBackwardBranchLimit;
|
||||
}
|
||||
#endif // CC_INTERP
|
||||
|
||||
void increment() { _counter += count_increment; }
|
||||
|
||||
|
||||
// Printing
|
||||
void print();
|
||||
void print_short();
|
||||
|
||||
// Miscellaneous
|
||||
static ByteSize counter_offset() { return byte_offset_of(InvocationCounter, _counter); }
|
||||
static void reinitialize();
|
||||
|
||||
private:
|
||||
static int _init [number_of_states]; // the counter limits
|
||||
static Action _action[number_of_states]; // the actions
|
||||
|
||||
static void def(State state, int init, Action action);
|
||||
static const char* state_as_string(State state);
|
||||
static const char* state_as_short_string(State state);
|
||||
};
|
||||
|
||||
inline void InvocationCounter::set(State state, int count) {
|
||||
assert(0 <= state && state < number_of_states, "illegal state");
|
||||
int carry = (_counter & carry_mask); // the carry bit is sticky
|
||||
_counter = (count << number_of_noncount_bits) | carry | state;
|
||||
}
|
||||
|
||||
inline void InvocationCounter::decay() {
|
||||
int c = count();
|
||||
int new_count = c >> 1;
|
||||
// prevent from going to zero, to distinguish from never-executed methods
|
||||
if (c > 0 && new_count == 0) new_count = 1;
|
||||
set(state(), new_count);
|
||||
}
|
||||
|
||||
|
||||
#endif // SHARE_INTERPRETER_INVOCATIONCOUNTER_HPP
|
||||
|
@ -1001,7 +1001,6 @@ void Method::set_not_compilable(const char* reason, int comp_level, bool report)
|
||||
if (is_c2_compile(comp_level))
|
||||
set_not_c2_compilable();
|
||||
}
|
||||
CompilationPolicy::policy()->disable_compilation(this);
|
||||
assert(!CompilationPolicy::can_be_compiled(methodHandle(Thread::current(), this), comp_level), "sanity check");
|
||||
}
|
||||
|
||||
@ -1028,7 +1027,6 @@ void Method::set_not_osr_compilable(const char* reason, int comp_level, bool rep
|
||||
if (is_c2_compile(comp_level))
|
||||
set_not_c2_osr_compilable();
|
||||
}
|
||||
CompilationPolicy::policy()->disable_compilation(this);
|
||||
assert(!CompilationPolicy::can_be_osr_compiled(methodHandle(Thread::current(), this), comp_level), "sanity check");
|
||||
}
|
||||
|
||||
|
@ -1130,8 +1130,8 @@ WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
|
||||
InvocationCounter* icnt = mdo->invocation_counter();
|
||||
InvocationCounter* bcnt = mdo->backedge_counter();
|
||||
// set i-counter according to TieredThresholdPolicy::is_method_profiled
|
||||
icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold);
|
||||
bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold);
|
||||
icnt->set(Tier4MinInvocationThreshold);
|
||||
bcnt->set(Tier4CompileThreshold);
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
|
||||
|
Loading…
x
Reference in New Issue
Block a user