src/share/vm/interpreter/invocationCounter.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hs-comp Cdiff src/share/vm/interpreter/invocationCounter.cpp
src/share/vm/interpreter/invocationCounter.cpp
Print this page
rev 7045 : 7115356: assert(!m->was_never_executed()) failed
Summary: Race when asserting on invocation counters
Reviewed-by:
*** 30,150 ****
// 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_carry() {
! set_carry_flag();
! // 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));
// 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);
! }
! 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::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::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];
int InvocationCounter::InterpreterInvocationLimit;
int InvocationCounter::InterpreterBackwardBranchLimit;
int InvocationCounter::InterpreterProfileLimit;
-
- 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";
- }
- 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";
- }
- ShouldNotReachHere();
- return NULL;
- }
-
-
- static address do_nothing(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(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;
- }
-
- address dummy_invocation_counter_overflow(methodHandle m, TRAPS) {
- ShouldNotReachHere();
- return NULL;
- }
-
void InvocationCounter::reinitialize(bool delay_overflow) {
- // define states
- guarantee((int)number_of_states <= (int)state_limit, "adjust number_of_state_bits");
- def(wait_for_nothing, 0, do_nothing);
- if (delay_overflow) {
- def(wait_for_compile, 0, do_decay);
- } else {
- def(wait_for_compile, 0, dummy_invocation_counter_overflow);
- }
-
InterpreterInvocationLimit = CompileThreshold << number_of_noncount_bits;
InterpreterProfileLimit = ((CompileThreshold * InterpreterProfilePercentage) / 100)<< number_of_noncount_bits;
// When methodData is collected, the backward branch limit is compared against a
// methodData counter, rather than an InvocationCounter. In the former case, we
--- 30,98 ----
// Implementation of InvocationCounter
void InvocationCounter::init() {
_counter = 0; // reset all the bits, including the sticky carry
}
void InvocationCounter::reset() {
! uint counter = raw_counter();
! int init = 0;
! // prevent from going to zero, to distinguish from never-executed methods
! if (count(counter) > 0) {
! init = 1;
! }
! counter = (init << number_of_noncount_bits) | (counter & carry_mask);
! set_raw(counter);
}
! void InvocationCounter::set_carry_and_reduce() {
! // single read
! uint counter = raw_counter();
!
! //update
! set_carry_flag(&counter);
! int old_count = count(counter);
int new_count = MIN2(old_count, (int) (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_count(&counter, new_count);
! }
! // single write
! set_raw(counter);
}
+ void InvocationCounter::set_carry_if_necessary() {
+ // single read
+ uint counter = raw_counter();
+
+ //update
+ if (!carry(counter) && count(counter) > count_limit / 2) {
+ set_carry_flag(&counter);
+ set_raw(counter);
+ }
+ }
void InvocationCounter::print() {
! tty->print_cr("invocation count: up = %d, carry = %s",
! count(), carry() ? "true" : "false");
}
void InvocationCounter::print_short() {
! tty->print(" [%d%s]", count(), carry()?"+carry":"");
}
// Initialization
int InvocationCounter::InterpreterInvocationLimit;
int InvocationCounter::InterpreterBackwardBranchLimit;
int InvocationCounter::InterpreterProfileLimit;
void InvocationCounter::reinitialize(bool delay_overflow) {
InterpreterInvocationLimit = CompileThreshold << number_of_noncount_bits;
InterpreterProfileLimit = ((CompileThreshold * InterpreterProfilePercentage) / 100)<< number_of_noncount_bits;
// When methodData is collected, the backward branch limit is compared against a
// methodData counter, rather than an InvocationCounter. In the former case, we
src/share/vm/interpreter/invocationCounter.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File