8010862: The Method counter fields used for profiling can be allocated lazily

Allocate the method's profiling related metadata until they are needed.

Reviewed-by: coleenp, roland
This commit is contained in:
Jiangli Zhou 2013-04-09 17:17:41 -04:00
parent 0afa77628c
commit 56370657b9
34 changed files with 773 additions and 295 deletions

View file

@ -31,6 +31,7 @@
#include "interpreter/invocationCounter.hpp"
#include "oops/annotations.hpp"
#include "oops/constantPool.hpp"
#include "oops/methodCounters.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.hpp"
#include "oops/typeArrayOop.hpp"
@ -100,6 +101,7 @@ class CheckedExceptionElement;
class LocalVariableTableElement;
class AdapterHandlerEntry;
class MethodData;
class MethodCounters;
class ConstMethod;
class InlineTableSizes;
class KlassSizeStats;
@ -109,7 +111,7 @@ class Method : public Metadata {
private:
ConstMethod* _constMethod; // Method read-only data.
MethodData* _method_data;
int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
MethodCounters* _method_counters;
AccessFlags _access_flags; // Access flags
int _vtable_index; // vtable index of this method (see VtableIndexFlag)
// note: can have vtables with >2**16 elements (because of inheritance)
@ -124,15 +126,6 @@ class Method : public Metadata {
_hidden : 1,
_dont_inline : 1,
: 3;
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
u2 _number_of_breakpoints; // fullspeed debugging support
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
#endif
#ifndef PRODUCT
int _compiled_invocation_count; // Number of nmethod invocations so far (for perf. debugging)
@ -247,11 +240,31 @@ class Method : public Metadata {
void clear_all_breakpoints();
// Tracking number of breakpoints, for fullspeed debugging.
// Only mutated by VM thread.
u2 number_of_breakpoints() const { return _number_of_breakpoints; }
void incr_number_of_breakpoints() { ++_number_of_breakpoints; }
void decr_number_of_breakpoints() { --_number_of_breakpoints; }
u2 number_of_breakpoints() const {
if (method_counters() == NULL) {
return 0;
} else {
return method_counters()->number_of_breakpoints();
}
}
void incr_number_of_breakpoints(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->incr_number_of_breakpoints();
}
}
void decr_number_of_breakpoints(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->decr_number_of_breakpoints();
}
}
// Initialization only
void clear_number_of_breakpoints() { _number_of_breakpoints = 0; }
void clear_number_of_breakpoints() {
if (method_counters() != NULL) {
method_counters()->clear_number_of_breakpoints();
}
}
// index into InstanceKlass methods() array
// note: also used by jfr
@ -288,14 +301,20 @@ class Method : public Metadata {
void set_highest_osr_comp_level(int level);
// Count of times method was exited via exception while interpreting
void interpreter_throwout_increment() {
if (_interpreter_throwout_count < 65534) {
_interpreter_throwout_count++;
void interpreter_throwout_increment(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->interpreter_throwout_increment();
}
}
int interpreter_throwout_count() const { return _interpreter_throwout_count; }
void set_interpreter_throwout_count(int count) { _interpreter_throwout_count = count; }
int interpreter_throwout_count() const {
if (method_counters() == NULL) {
return 0;
} else {
return method_counters()->interpreter_throwout_count();
}
}
// size of parameters
int size_of_parameters() const { return constMethod()->size_of_parameters(); }
@ -339,23 +358,54 @@ class Method : public Metadata {
MethodData* method_data() const {
return _method_data;
}
void set_method_data(MethodData* data) {
_method_data = data;
}
// invocation counter
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }
MethodCounters* method_counters() const {
return _method_counters;
}
void set_method_counters(MethodCounters* counters) {
_method_counters = counters;
}
#ifdef TIERED
// We are reusing interpreter_invocation_count as a holder for the previous event count!
// We can do that since interpreter_invocation_count is not used in tiered.
int prev_event_count() const { return _interpreter_invocation_count; }
void set_prev_event_count(int count) { _interpreter_invocation_count = count; }
jlong prev_time() const { return _prev_time; }
void set_prev_time(jlong time) { _prev_time = time; }
float rate() const { return _rate; }
void set_rate(float rate) { _rate = rate; }
int prev_event_count() const {
if (method_counters() == NULL) {
return 0;
} else {
return method_counters()->interpreter_invocation_count();
}
}
void set_prev_event_count(int count, TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->set_interpreter_invocation_count(count);
}
}
jlong prev_time() const {
return method_counters() == NULL ? 0 : method_counters()->prev_time();
}
void set_prev_time(jlong time, TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->set_prev_time(time);
}
}
float rate() const {
return method_counters() == NULL ? 0 : method_counters()->rate();
}
void set_rate(float rate, TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->set_rate(rate);
}
}
#endif
int invocation_count();
@ -366,14 +416,17 @@ class Method : public Metadata {
static void build_interpreter_method_data(methodHandle method, TRAPS);
static MethodCounters* build_method_counters(Method* m, TRAPS);
int interpreter_invocation_count() {
if (TieredCompilation) return invocation_count();
else return _interpreter_invocation_count;
else return (method_counters() == NULL) ? 0 :
method_counters()->interpreter_invocation_count();
}
void set_interpreter_invocation_count(int count) { _interpreter_invocation_count = count; }
int increment_interpreter_invocation_count() {
int increment_interpreter_invocation_count(TRAPS) {
if (TieredCompilation) ShouldNotReachHere();
return ++_interpreter_invocation_count;
MethodCounters* mcs = get_method_counters(CHECK_0);
return (mcs == NULL) ? 0 : mcs->increment_interpreter_invocation_count();
}
#ifndef PRODUCT
@ -582,12 +635,12 @@ class Method : public Metadata {
#endif /* CC_INTERP */
static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); }
static ByteSize code_offset() { return byte_offset_of(Method, _code); }
static ByteSize invocation_counter_offset() { return byte_offset_of(Method, _invocation_counter); }
static ByteSize backedge_counter_offset() { return byte_offset_of(Method, _backedge_counter); }
static ByteSize method_data_offset() {
return byte_offset_of(Method, _method_data);
}
static ByteSize interpreter_invocation_counter_offset() { return byte_offset_of(Method, _interpreter_invocation_count); }
static ByteSize method_counters_offset() {
return byte_offset_of(Method, _method_counters);
}
#ifndef PRODUCT
static ByteSize compiled_invocation_counter_offset() { return byte_offset_of(Method, _compiled_invocation_count); }
#endif // not PRODUCT
@ -598,8 +651,6 @@ class Method : public Metadata {
// for code generation
static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); }
static int interpreter_invocation_counter_offset_in_bytes()
{ return offset_of(Method, _interpreter_invocation_count); }
static int intrinsic_id_offset_in_bytes() { return offset_of(Method, _intrinsic_id); }
static int intrinsic_id_size_in_bytes() { return sizeof(u1); }
@ -757,6 +808,13 @@ class Method : public Metadata {
private:
void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason);
MethodCounters* get_method_counters(TRAPS) {
if (_method_counters == NULL) {
build_method_counters(this, CHECK_AND_CLEAR_NULL);
}
return _method_counters;
}
public:
bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); }
void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); }