--- old/src/share/vm/oops/methodDataOop.hpp 2011-12-15 13:31:25.841727085 +0100 +++ new/src/share/vm/oops/methodDataOop.hpp 2011-12-15 13:31:25.644913793 +0100 @@ -172,6 +172,11 @@ _header._struct._flags = (new_state << trap_shift) | old_flags; } +#ifdef COMPILER1 + void set_profile_state(int state) { assert(C1ProfileInlining, "c1 profiling only"); _header._struct._flags = state; } + int profile_state() { assert(C1ProfileInlining, "c1 profiling only"); return _header._struct._flags; } +#endif + u1 flags() { return _header._struct._flags; } @@ -364,6 +369,12 @@ _data = data; } +#ifdef COMPILER1 + protected: + void set_profile_state(int state) { data()->set_profile_state(state); } + int profile_state() { return data()->profile_state(); } +#endif + public: // Constructor for invalid ProfileData. ProfileData(); @@ -533,7 +544,7 @@ virtual bool is_CounterData() { return true; } static int static_cell_count() { - return counter_cell_count; + return counter_cell_count + ( COMPILER1_PRESENT(C1ProfileInlining ? BytesPerLong/BytesPerWord :) 0 ); } virtual int cell_count() { @@ -550,7 +561,7 @@ return cell_offset(count_off); } static ByteSize counter_data_size() { - return cell_offset(counter_cell_count); + return cell_offset(counter_cell_count + ( COMPILER1_PRESENT(C1ProfileInlining ? BytesPerLong/BytesPerWord :) 0 )); } void set_count(uint count) { @@ -560,6 +571,67 @@ #ifndef PRODUCT void print_data_on(outputStream* st); #endif + +#ifdef COMPILER1 + // C1 implements profile based inlining. To detect a hot call site, + // a count of the number of times the call is taken and a timestamp + // of the first time the call is taken are needed. Together, they + // are used to compute a call site frequency = + // count / (current time - timestamp) + // that, can can be compared to thresholds to identify hot or warm + // or cold call sites. The state of a call site is kept here as + // well. This way it persists during the execution: a hot call site + // can be marked as such once for all and subsequent compilation + // will attempt inlining. + private: + union stamp { + jlong l; + uint u[BytesPerLong/BytesPerWord]; + }; + + enum state { + unseen_yet = 0, + seen, + hot, + warm, + cold + }; + + public: + bool is_unseen_yet() { return profile_state() == unseen_yet; } + bool is_seen() { return profile_state() == seen; } + bool is_hot() { return profile_state() == hot; } + bool is_warm() { return profile_state() == warm; } + bool is_cold() { return profile_state() == cold; } + void set_seen() { set_profile_state(seen); } + void set_hot() { set_profile_state(hot); } + void set_warm() { set_profile_state(warm); } + void set_cold() { set_profile_state(cold); } + + jlong timestamp() { + union stamp ts; + for(int i = 0; i < BytesPerLong/BytesPerWord; i++) { + ts.u[i] = uint_at(counter_cell_count + i); + } + return ts.l; + } + + void set_timestamp(jlong stamp) { + union stamp ts; + ts.l = stamp; + for(int i = 0; i < BytesPerLong/BytesPerWord; i++) { + set_uint_at(counter_cell_count + i, ts.u[i]); + } + } + + void init_if_first_seen() { + if (is_unseen_yet()) { + set_seen(); + jlong now = os::javaTimeNanos(); + set_timestamp(now); + } + } +#endif }; // JumpData @@ -644,7 +716,7 @@ class ReceiverTypeData : public CounterData { protected: enum { - receiver0_offset = counter_cell_count, + receiver0_offset, count0_offset, receiver_type_row_cell_count = (count0_offset + 1) - receiver0_offset }; @@ -658,7 +730,7 @@ virtual bool is_ReceiverTypeData() { return true; } static int static_cell_count() { - return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count; + return CounterData::static_cell_count() + (uint) TypeProfileWidth * receiver_type_row_cell_count; } virtual int cell_count() { @@ -670,10 +742,10 @@ return TypeProfileWidth; } static int receiver_cell_index(uint row) { - return receiver0_offset + row * receiver_type_row_cell_count; + return CounterData::static_cell_count() + receiver0_offset + row * receiver_type_row_cell_count; } static int receiver_count_cell_index(uint row) { - return count0_offset + row * receiver_type_row_cell_count; + return CounterData::static_cell_count() + count0_offset + row * receiver_type_row_cell_count; } // Get the receiver at row. The 'unchecked' version is needed by parallel old @@ -791,6 +863,18 @@ return cell_offset(static_cell_count()); } + void new_receiver(Handle r) { + assert(TypeProfileWidth >= 2, "should be"); + + if (receiver(0) == NULL || receiver(0) == r->klass()) { + set_receiver(0, r->klass()); + set_receiver_count(0, DataLayout::counter_increment); + } else if (row_limit() > 1 && (receiver(1) == NULL || receiver(1) == r->klass())) { + set_receiver(1, r->klass()); + set_receiver_count(1, DataLayout::counter_increment); + } + } + #ifndef PRODUCT void print_data_on(outputStream* st); #endif