--- old/src/share/vm/runtime/compilationPolicy.cpp 2014-09-17 15:59:02.248954523 +0200 +++ new/src/share/vm/runtime/compilationPolicy.cpp 2014-09-17 15:59:02.148954519 +0200 @@ -227,8 +227,9 @@ // 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"); } @@ -244,9 +245,9 @@ // 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_count(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_count(CompileThreshold / 2); } // @@ -313,7 +314,7 @@ c = mcs->invocation_counter(); if (is_osr) { // It was an OSR method, so bump the count higher. - c->set(c->state(), CompileThreshold); + c->set_count(CompileThreshold); } else { c->reset(); } @@ -334,8 +335,8 @@ void NonTieredCompPolicy::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); + mcs->invocation_counter()->reset(); + mcs->backedge_counter()->reset(); } } --- old/src/share/vm/runtime/simpleThresholdPolicy.cpp 2014-09-17 15:59:02.260954524 +0200 +++ new/src/share/vm/runtime/simpleThresholdPolicy.cpp 2014-09-17 15:59:02.164954520 +0200 @@ -146,23 +146,17 @@ FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count()); } -void SimpleThresholdPolicy::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 SimpleThresholdPolicy::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_if_necessary(); + mcs->backedge_counter()->set_carry_if_necessary(); } 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_if_necessary(); + mdo->backedge_counter()->set_carry_if_necessary(); } } --- old/src/share/vm/interpreter/invocationCounter.hpp 2014-09-17 15:59:02.268954524 +0200 +++ new/src/share/vm/interpreter/invocationCounter.hpp 2014-09-17 15:59:02.160954520 +0200 @@ -30,31 +30,25 @@ #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 +// Implementation notes: For space reasons, counter & carry are both encoded in one word, +// The carry is encoded using the least significant bits the counter is using the // more significant bits. The counter is incremented before a method is activated and an -// action is triggered when when count() > limit(). +// action is triggered when when count() > the limit for that counter type. class InvocationCounter VALUE_OBJ_CLASS_SPEC { friend class VMStructs; friend class ciReplay; - private: // bit no: |31 3| 2 | 1 0 | - unsigned int _counter; // format: [count|carry|state] + private: // bit no: |31 1| 0 | + unsigned int _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, + number_of_noncount_bits = number_of_carry_bits, number_of_count_bits = BitsPerInt - number_of_noncount_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) + count_grain = nth_bit(number_of_carry_bits), + carry_mask = right_n_bits(number_of_carry_bits), + count_mask = ((int)(-1) ^ carry_mask) }; public: @@ -62,8 +56,6 @@ static int InterpreterBackwardBranchLimit; // A separate threshold for on stack replacement static int InterpreterProfileLimit; // Profiling threshold scaled for interpreter use - typedef address (*Action)(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 @@ -71,29 +63,30 @@ 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 + void reset(); // reset counter, but not to zero + void init(); // sets counters into original state + inline void set_count(int count); // sets counter inline void decay(); // decay counter (divide by two) - void set_carry(); // set the sticky carry bit - void set_carry_flag() { _counter |= carry_mask; } + void set_carry_and_reduce(); // set the sticky carry bit and reduce counter + void set_carry_if_necessary(); // set carry if counter is big enough + void increment() { _counter += count_increment; } - int raw_counter() { return _counter; } + // primitive read and write + uint raw_counter() { return _counter; } +private: + void set_raw(uint counter) { _counter = counter; } + + // operate on local counter without committing to memory + inline void set_count(uint* counter, int count); + void set_carry_flag(uint* counter) { *counter |= carry_mask; } + int count(uint counter) { return counter >> number_of_noncount_bits; } + bool carry(uint counter) { return (counter & carry_mask) != 0; } +public: // 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; } + int count() const { return _counter >> number_of_noncount_bits; } int get_InvocationLimit() const { return InterpreterInvocationLimit >> number_of_noncount_bits; } int get_BackwardBranchLimit() const { return InterpreterBackwardBranchLimit >> number_of_noncount_bits; } @@ -118,9 +111,6 @@ } #endif // CC_INTERP - void increment() { _counter += count_increment; } - - // Printing void print(); void print_short(); @@ -128,20 +118,14 @@ // Miscellaneous static ByteSize counter_offset() { return byte_offset_of(InvocationCounter, _counter); } static void reinitialize(bool delay_overflow); - - 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::set_count(int count) { + _counter = (count << number_of_noncount_bits) | (_counter & carry_mask); +} + +inline void InvocationCounter::set_count(uint *counter, int count) { + *counter = (count << number_of_noncount_bits) | (*counter & carry_mask); } inline void InvocationCounter::decay() { @@ -149,8 +133,7 @@ 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); + set_count(new_count); } - #endif // SHARE_VM_INTERPRETER_INVOCATIONCOUNTER_HPP --- old/src/share/vm/interpreter/invocationCounter.cpp 2014-09-17 15:59:02.268954524 +0200 +++ new/src/share/vm/interpreter/invocationCounter.cpp 2014-09-17 15:59:02.152954519 +0200 @@ -32,117 +32,65 @@ 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); + 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() { - 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(); +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(state(), new_count); -} + if (new_count == 0) { + new_count = 1; + } + if (old_count != new_count) { + set_count(&counter, 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; + // 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, limit = %d, carry = %s, state = %s", - count(), limit(), - carry() ? "true" : "false", - state_as_string(state())); + tty->print_cr("invocation count: up = %d, carry = %s", + count(), carry() ? "true" : "false"); } void InvocationCounter::print_short() { - tty->print(" [%d%s;%s]", count(), carry()?"+carry":"", state_as_short_string(state())); + tty->print(" [%d%s]", count(), carry()?"+carry":""); } // 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;