Skip to content
Permalink
Browse files

8203883: Remove State from InvocationCounters

Reviewed-by: redestad, thartmann
  • Loading branch information
Nils Eliasson
Nils Eliasson committed Feb 12, 2020
1 parent b4b8ead commit 18c01206d00b2d368f737345a5b615bd14743b24
@@ -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 @@ class CompilationPolicy : public CHeapObj<mtCompiler> {
// 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(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();
}

0 comments on commit 18c0120

Please sign in to comment.