src/share/vm/oops/methodData.hpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/oops/methodData.hpp
src/share/vm/oops/methodData.hpp
Print this page
rev 5240 : 8023657: New type profiling points: arguments to call
Summary: x86 interpreter and c1 type profiling for arguments at calls
Reviewed-by:
*** 115,125 ****
receiver_type_data_tag,
virtual_call_data_tag,
ret_data_tag,
branch_data_tag,
multi_branch_data_tag,
! arg_info_data_tag
};
enum {
// The _struct._flags word is formatted as [trap_state:4 | flags:4].
// The trap state breaks down further as [recompile:1 | reason:3].
--- 115,127 ----
receiver_type_data_tag,
virtual_call_data_tag,
ret_data_tag,
branch_data_tag,
multi_branch_data_tag,
! arg_info_data_tag,
! call_type_data_tag,
! virtual_call_type_data_tag
};
enum {
// The _struct._flags word is formatted as [trap_state:4 | flags:4].
// The trap state breaks down further as [recompile:1 | reason:3].
*** 163,187 ****
// The associated trap histogram in the MDO itself tells whether
// traps are common or not. If a BCI shows that a trap X has
// occurred, and the MDO shows N occurrences of X, we make the
// simplifying assumption that all N occurrences can be blamed
// on that BCI.
! int trap_state() {
return ((_header._struct._flags >> trap_shift) & trap_mask);
}
void set_trap_state(int new_state) {
assert(ProfileTraps, "used only under +ProfileTraps");
uint old_flags = (_header._struct._flags & flag_mask);
_header._struct._flags = (new_state << trap_shift) | old_flags;
}
! u1 flags() {
return _header._struct._flags;
}
! u2 bci() {
return _header._struct._bci;
}
void set_header(intptr_t value) {
_header._bits = value;
--- 165,189 ----
// The associated trap histogram in the MDO itself tells whether
// traps are common or not. If a BCI shows that a trap X has
// occurred, and the MDO shows N occurrences of X, we make the
// simplifying assumption that all N occurrences can be blamed
// on that BCI.
! int trap_state() const {
return ((_header._struct._flags >> trap_shift) & trap_mask);
}
void set_trap_state(int new_state) {
assert(ProfileTraps, "used only under +ProfileTraps");
uint old_flags = (_header._struct._flags & flag_mask);
_header._struct._flags = (new_state << trap_shift) | old_flags;
}
! u1 flags() const {
return _header._struct._flags;
}
! u2 bci() const {
return _header._struct._bci;
}
void set_header(intptr_t value) {
_header._bits = value;
*** 196,214 ****
_cells[index] = value;
}
void release_set_cell_at(int index, intptr_t value) {
OrderAccess::release_store_ptr(&_cells[index], value);
}
! intptr_t cell_at(int index) {
return _cells[index];
}
void set_flag_at(int flag_number) {
assert(flag_number < flag_limit, "oob");
_header._struct._flags |= (0x1 << flag_number);
}
! bool flag_at(int flag_number) {
assert(flag_number < flag_limit, "oob");
return (_header._struct._flags & (0x1 << flag_number)) != 0;
}
// Low-level support for code generation.
--- 198,216 ----
_cells[index] = value;
}
void release_set_cell_at(int index, intptr_t value) {
OrderAccess::release_store_ptr(&_cells[index], value);
}
! intptr_t cell_at(int index) const {
return _cells[index];
}
void set_flag_at(int flag_number) {
assert(flag_number < flag_limit, "oob");
_header._struct._flags |= (0x1 << flag_number);
}
! bool flag_at(int flag_number) const {
assert(flag_number < flag_limit, "oob");
return (_header._struct._flags & (0x1 << flag_number)) != 0;
}
// Low-level support for code generation.
*** 252,274 ****
class ProfileData;
class BitData;
class CounterData;
class ReceiverTypeData;
class VirtualCallData;
class RetData;
class JumpData;
class BranchData;
class ArrayData;
class MultiBranchData;
class ArgInfoData;
-
// ProfileData
//
// A ProfileData object is created to refer to a section of profiling
// data in a structured way.
class ProfileData : public ResourceObj {
private:
#ifndef PRODUCT
enum {
tab_width_one = 16,
tab_width_two = 36
--- 254,279 ----
class ProfileData;
class BitData;
class CounterData;
class ReceiverTypeData;
class VirtualCallData;
+ class VirtualCallTypeData;
class RetData;
+ class CallTypeData;
class JumpData;
class BranchData;
class ArrayData;
class MultiBranchData;
class ArgInfoData;
// ProfileData
//
// A ProfileData object is created to refer to a section of profiling
// data in a structured way.
class ProfileData : public ResourceObj {
+ friend class TypeEntries;
+ friend class TypeStackSlotEntries;
private:
#ifndef PRODUCT
enum {
tab_width_one = 16,
tab_width_two = 36
*** 278,295 ****
// This is a pointer to a section of profiling data.
DataLayout* _data;
protected:
DataLayout* data() { return _data; }
enum {
cell_size = DataLayout::cell_size
};
public:
// How many cells are in this?
! virtual int cell_count() {
ShouldNotReachHere();
return -1;
}
// Return the size of this data.
--- 283,301 ----
// This is a pointer to a section of profiling data.
DataLayout* _data;
protected:
DataLayout* data() { return _data; }
+ const DataLayout* data() const { return _data; }
enum {
cell_size = DataLayout::cell_size
};
public:
// How many cells are in this?
! virtual int cell_count() const {
ShouldNotReachHere();
return -1;
}
// Return the size of this data.
*** 305,350 ****
}
void release_set_intptr_at(int index, intptr_t value) {
assert(0 <= index && index < cell_count(), "oob");
data()->release_set_cell_at(index, value);
}
! intptr_t intptr_at(int index) {
assert(0 <= index && index < cell_count(), "oob");
return data()->cell_at(index);
}
void set_uint_at(int index, uint value) {
set_intptr_at(index, (intptr_t) value);
}
void release_set_uint_at(int index, uint value) {
release_set_intptr_at(index, (intptr_t) value);
}
! uint uint_at(int index) {
return (uint)intptr_at(index);
}
void set_int_at(int index, int value) {
set_intptr_at(index, (intptr_t) value);
}
void release_set_int_at(int index, int value) {
release_set_intptr_at(index, (intptr_t) value);
}
! int int_at(int index) {
return (int)intptr_at(index);
}
! int int_at_unchecked(int index) {
return (int)data()->cell_at(index);
}
void set_oop_at(int index, oop value) {
set_intptr_at(index, (intptr_t) value);
}
! oop oop_at(int index) {
return (oop)intptr_at(index);
}
void set_flag_at(int flag_number) {
data()->set_flag_at(flag_number);
}
! bool flag_at(int flag_number) {
return data()->flag_at(flag_number);
}
// two convenient imports for use by subclasses:
static ByteSize cell_offset(int index) {
--- 311,359 ----
}
void release_set_intptr_at(int index, intptr_t value) {
assert(0 <= index && index < cell_count(), "oob");
data()->release_set_cell_at(index, value);
}
! intptr_t intptr_at(int index) const {
assert(0 <= index && index < cell_count(), "oob");
return data()->cell_at(index);
}
void set_uint_at(int index, uint value) {
set_intptr_at(index, (intptr_t) value);
}
void release_set_uint_at(int index, uint value) {
release_set_intptr_at(index, (intptr_t) value);
}
! uint uint_at(int index) const {
return (uint)intptr_at(index);
}
void set_int_at(int index, int value) {
set_intptr_at(index, (intptr_t) value);
}
+ void set_int_at_unchecked(int index, int value) {
+ data()->set_cell_at(index, (intptr_t) value);
+ }
void release_set_int_at(int index, int value) {
release_set_intptr_at(index, (intptr_t) value);
}
! int int_at(int index) const {
return (int)intptr_at(index);
}
! int int_at_unchecked(int index) const {
return (int)data()->cell_at(index);
}
void set_oop_at(int index, oop value) {
set_intptr_at(index, (intptr_t) value);
}
! oop oop_at(int index) const {
return (oop)intptr_at(index);
}
void set_flag_at(int flag_number) {
data()->set_flag_at(flag_number);
}
! bool flag_at(int flag_number) const {
return data()->flag_at(flag_number);
}
// two convenient imports for use by subclasses:
static ByteSize cell_offset(int index) {
*** 360,437 ****
public:
// Constructor for invalid ProfileData.
ProfileData();
! u2 bci() {
return data()->bci();
}
address dp() {
return (address)_data;
}
! int trap_state() {
return data()->trap_state();
}
void set_trap_state(int new_state) {
data()->set_trap_state(new_state);
}
// Type checking
! virtual bool is_BitData() { return false; }
! virtual bool is_CounterData() { return false; }
! virtual bool is_JumpData() { return false; }
! virtual bool is_ReceiverTypeData(){ return false; }
! virtual bool is_VirtualCallData() { return false; }
! virtual bool is_RetData() { return false; }
! virtual bool is_BranchData() { return false; }
! virtual bool is_ArrayData() { return false; }
! virtual bool is_MultiBranchData() { return false; }
! virtual bool is_ArgInfoData() { return false; }
! BitData* as_BitData() {
assert(is_BitData(), "wrong type");
return is_BitData() ? (BitData*) this : NULL;
}
! CounterData* as_CounterData() {
assert(is_CounterData(), "wrong type");
return is_CounterData() ? (CounterData*) this : NULL;
}
! JumpData* as_JumpData() {
assert(is_JumpData(), "wrong type");
return is_JumpData() ? (JumpData*) this : NULL;
}
! ReceiverTypeData* as_ReceiverTypeData() {
assert(is_ReceiverTypeData(), "wrong type");
return is_ReceiverTypeData() ? (ReceiverTypeData*)this : NULL;
}
! VirtualCallData* as_VirtualCallData() {
assert(is_VirtualCallData(), "wrong type");
return is_VirtualCallData() ? (VirtualCallData*)this : NULL;
}
! RetData* as_RetData() {
assert(is_RetData(), "wrong type");
return is_RetData() ? (RetData*) this : NULL;
}
! BranchData* as_BranchData() {
assert(is_BranchData(), "wrong type");
return is_BranchData() ? (BranchData*) this : NULL;
}
! ArrayData* as_ArrayData() {
assert(is_ArrayData(), "wrong type");
return is_ArrayData() ? (ArrayData*) this : NULL;
}
! MultiBranchData* as_MultiBranchData() {
assert(is_MultiBranchData(), "wrong type");
return is_MultiBranchData() ? (MultiBranchData*)this : NULL;
}
! ArgInfoData* as_ArgInfoData() {
assert(is_ArgInfoData(), "wrong type");
return is_ArgInfoData() ? (ArgInfoData*)this : NULL;
}
// Subclass specific initialization
virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
--- 369,456 ----
public:
// Constructor for invalid ProfileData.
ProfileData();
! u2 bci() const {
return data()->bci();
}
address dp() {
return (address)_data;
}
! int trap_state() const {
return data()->trap_state();
}
void set_trap_state(int new_state) {
data()->set_trap_state(new_state);
}
// Type checking
! virtual bool is_BitData() const { return false; }
! virtual bool is_CounterData() const { return false; }
! virtual bool is_JumpData() const { return false; }
! virtual bool is_ReceiverTypeData()const { return false; }
! virtual bool is_VirtualCallData() const { return false; }
! virtual bool is_RetData() const { return false; }
! virtual bool is_BranchData() const { return false; }
! virtual bool is_ArrayData() const { return false; }
! virtual bool is_MultiBranchData() const { return false; }
! virtual bool is_ArgInfoData() const { return false; }
! virtual bool is_CallTypeData() const { return false; }
! virtual bool is_VirtualCallTypeData()const { return false; }
! BitData* as_BitData() const {
assert(is_BitData(), "wrong type");
return is_BitData() ? (BitData*) this : NULL;
}
! CounterData* as_CounterData() const {
assert(is_CounterData(), "wrong type");
return is_CounterData() ? (CounterData*) this : NULL;
}
! JumpData* as_JumpData() const {
assert(is_JumpData(), "wrong type");
return is_JumpData() ? (JumpData*) this : NULL;
}
! ReceiverTypeData* as_ReceiverTypeData() const {
assert(is_ReceiverTypeData(), "wrong type");
return is_ReceiverTypeData() ? (ReceiverTypeData*)this : NULL;
}
! VirtualCallData* as_VirtualCallData() const {
assert(is_VirtualCallData(), "wrong type");
return is_VirtualCallData() ? (VirtualCallData*)this : NULL;
}
! RetData* as_RetData() const {
assert(is_RetData(), "wrong type");
return is_RetData() ? (RetData*) this : NULL;
}
! BranchData* as_BranchData() const {
assert(is_BranchData(), "wrong type");
return is_BranchData() ? (BranchData*) this : NULL;
}
! ArrayData* as_ArrayData() const {
assert(is_ArrayData(), "wrong type");
return is_ArrayData() ? (ArrayData*) this : NULL;
}
! MultiBranchData* as_MultiBranchData() const {
assert(is_MultiBranchData(), "wrong type");
return is_MultiBranchData() ? (MultiBranchData*)this : NULL;
}
! ArgInfoData* as_ArgInfoData() const {
assert(is_ArgInfoData(), "wrong type");
return is_ArgInfoData() ? (ArgInfoData*)this : NULL;
}
+ CallTypeData* as_CallTypeData() const {
+ assert(is_CallTypeData(), "wrong type");
+ return is_CallTypeData() ? (CallTypeData*)this : NULL;
+ }
+ VirtualCallTypeData* as_VirtualCallTypeData() const {
+ assert(is_VirtualCallTypeData(), "wrong type");
+ return is_VirtualCallTypeData() ? (VirtualCallTypeData*)this : NULL;
+ }
// Subclass specific initialization
virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
*** 441,459 ****
// CI translation: ProfileData can represent both MethodDataOop data
// as well as CIMethodData data. This function is provided for translating
// an oop in a ProfileData to the ci equivalent. Generally speaking,
// most ProfileData don't require any translation, so we provide the null
// translation here, and the required translators are in the ci subclasses.
! virtual void translate_from(ProfileData* data) {}
! virtual void print_data_on(outputStream* st) {
ShouldNotReachHere();
}
#ifndef PRODUCT
! void print_shared(outputStream* st, const char* name);
! void tab(outputStream* st);
#endif
};
// BitData
//
--- 460,478 ----
// CI translation: ProfileData can represent both MethodDataOop data
// as well as CIMethodData data. This function is provided for translating
// an oop in a ProfileData to the ci equivalent. Generally speaking,
// most ProfileData don't require any translation, so we provide the null
// translation here, and the required translators are in the ci subclasses.
! virtual void translate_from(const ProfileData* data) {}
! virtual void print_data_on(outputStream* st) const {
ShouldNotReachHere();
}
#ifndef PRODUCT
! void print_shared(outputStream* st, const char* name) const;
! void tab(outputStream* st, bool first = false) const;
#endif
};
// BitData
//
*** 468,484 ****
enum { bit_cell_count = 0 }; // no additional data fields needed.
public:
BitData(DataLayout* layout) : ProfileData(layout) {
}
! virtual bool is_BitData() { return true; }
static int static_cell_count() {
return bit_cell_count;
}
! virtual int cell_count() {
return static_cell_count();
}
// Accessor
--- 487,503 ----
enum { bit_cell_count = 0 }; // no additional data fields needed.
public:
BitData(DataLayout* layout) : ProfileData(layout) {
}
! virtual bool is_BitData() const { return true; }
static int static_cell_count() {
return bit_cell_count;
}
! virtual int cell_count() const {
return static_cell_count();
}
// Accessor
*** 496,506 ****
static ByteSize bit_data_size() {
return cell_offset(bit_cell_count);
}
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// CounterData
//
--- 515,525 ----
static ByteSize bit_data_size() {
return cell_offset(bit_cell_count);
}
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
#endif
};
// CounterData
//
*** 512,533 ****
counter_cell_count
};
public:
CounterData(DataLayout* layout) : BitData(layout) {}
! virtual bool is_CounterData() { return true; }
static int static_cell_count() {
return counter_cell_count;
}
! virtual int cell_count() {
return static_cell_count();
}
// Direct accessor
! uint count() {
return uint_at(count_off);
}
// Code generation support
static ByteSize count_offset() {
--- 531,552 ----
counter_cell_count
};
public:
CounterData(DataLayout* layout) : BitData(layout) {}
! virtual bool is_CounterData() const { return true; }
static int static_cell_count() {
return counter_cell_count;
}
! virtual int cell_count() const {
return static_cell_count();
}
// Direct accessor
! uint count() const {
return uint_at(count_off);
}
// Code generation support
static ByteSize count_offset() {
*** 540,550 ****
void set_count(uint count) {
set_uint_at(count_off, count);
}
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// JumpData
//
--- 559,569 ----
void set_count(uint count) {
set_uint_at(count_off, count);
}
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
#endif
};
// JumpData
//
*** 568,589 ****
JumpData(DataLayout* layout) : ProfileData(layout) {
assert(layout->tag() == DataLayout::jump_data_tag ||
layout->tag() == DataLayout::branch_data_tag, "wrong type");
}
! virtual bool is_JumpData() { return true; }
static int static_cell_count() {
return jump_cell_count;
}
! virtual int cell_count() {
return static_cell_count();
}
// Direct accessor
! uint taken() {
return uint_at(taken_off_set);
}
void set_taken(uint cnt) {
set_uint_at(taken_off_set, cnt);
--- 587,608 ----
JumpData(DataLayout* layout) : ProfileData(layout) {
assert(layout->tag() == DataLayout::jump_data_tag ||
layout->tag() == DataLayout::branch_data_tag, "wrong type");
}
! virtual bool is_JumpData() const { return true; }
static int static_cell_count() {
return jump_cell_count;
}
! virtual int cell_count() const {
return static_cell_count();
}
// Direct accessor
! uint taken() const {
return uint_at(taken_off_set);
}
void set_taken(uint cnt) {
set_uint_at(taken_off_set, cnt);
*** 596,606 ****
if (cnt == 0) cnt--;
set_uint_at(taken_off_set, cnt);
return cnt;
}
! int displacement() {
return int_at(displacement_off_set);
}
// Code generation support
static ByteSize taken_offset() {
--- 615,625 ----
if (cnt == 0) cnt--;
set_uint_at(taken_off_set, cnt);
return cnt;
}
! int displacement() const {
return int_at(displacement_off_set);
}
// Code generation support
static ByteSize taken_offset() {
*** 613,623 ****
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// ReceiverTypeData
//
--- 632,956 ----
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
! #endif
! };
!
! // Entries in a ProfileData object to record types: it can either be
! // none (no profile), unknown (conflicting profile data) or a klass if
! // a single one is seen. Whether a null reference was seen is also
! // recorded. No counter is associated with the type and a single type
! // is tracked (unlike VirtualCallData).
! class TypeEntries {
!
! public:
!
! // A single cell is used to record information for a type:
! // - the cell is initialized to 0
! // - when a type is discovered it is stored in the cell
! // - bit zero of the cell is used to record whether a null reference
! // was encountered or not
! // - bit 1 is set to record a conflict in the type information
!
! enum {
! null_seen = 1,
! type_mask = ~null_seen,
! type_unknown = 2,
! status_bits = null_seen | type_unknown,
! type_klass_mask = ~status_bits
! };
!
! // what to initialize a cell to
! static intptr_t type_none() {
! return NULL;
! }
!
! // null seen = bit 0 set?
! static bool was_null_seen(intptr_t v) {
! return v & null_seen;
! }
!
! // conflicting type information = bit 1 set?
! static bool is_type_unknown(intptr_t v) {
! return v & type_unknown;
! }
!
! // not type information yet = all bits cleared, ignoring bit 0?
! static bool is_type_none(intptr_t v) {
! return (v & type_mask) == 0;
! }
!
! // recorded type: cell without bit 0 and 1
! static intptr_t klass_part(intptr_t v) {
! intptr_t r = v & type_klass_mask;
! assert (r != NULL, "invalid");
! return r;
! }
!
! // type recorded
! static Klass* valid_klass(intptr_t k) {
! if (!is_type_none(k) &&
! !is_type_unknown(k)) {
! return (Klass*)klass_part(k);
! } else {
! return NULL;
! }
! }
!
! static intptr_t with_status(intptr_t k, intptr_t in) {
! return k | (in & status_bits);
! }
!
! #ifndef PRODUCT
! static void print_klass(outputStream* st, intptr_t k);
! #endif
!
! // GC support
! static bool is_loader_alive(BoolObjectClosure* is_alive_cl, intptr_t p);
!
! protected:
! // ProfileData object these entries are part of
! ProfileData* _pd;
! // offset within the ProfileData object where the entries start
! const int _base_off;
!
! TypeEntries(int base_off, ProfileData* pd)
! : _base_off(base_off), _pd(pd) {}
!
! void set_intptr_at(int index, intptr_t value) {
! _pd->set_intptr_at(index, value);
! }
!
! intptr_t intptr_at(int index) const {
! return _pd->intptr_at(index);
! }
! };
!
! // Type entries used for arguments passed at a call and parameters on
! // method entry. 2 cells per entry: one for the type encoded as in
! // TypeEntries and one initialized with the stack slot where the
! // profiled object is to be found so that the interpreter can locate
! // it quickly.
! class TypeStackSlotEntries : public TypeEntries {
!
! private:
! enum {
! stack_slot_entry,
! type_entry,
! per_arg_cell_count
! };
!
! // Start with a header if needed. It stores the number of cells used
! // for this call type information. Unless we collect only profiling
! // for a single argument the number of cells is unknown statically.
! static int header_cell_count() {
! return (TypeProfileArgsLimit > 1) ? 1 : 0;
! }
!
! static int cell_count_local_offset() {
! assert(arguments_profiling_enabled() && TypeProfileArgsLimit > 1, "no cell count");
! return 0;
! }
!
! int cell_count_global_offset() const {
! return _base_off + cell_count_local_offset();
! }
!
! // offset of cell for stack slot for entry i within ProfileData object
! int stack_slot_global_offset(int i) const {
! return _base_off + stack_slot_local_offset(i);
! }
!
! void check_number_of_arguments(uint total) {
! assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
! }
!
! // number of cells not counting the header
! int cell_count_no_header() const {
! return _pd->uint_at(cell_count_global_offset());
! }
!
! static bool arguments_profiling_enabled();
! static void assert_arguments_profiling_enabled() {
! assert(arguments_profiling_enabled(), "args profiling should be on");
! }
!
! protected:
!
! // offset of cell for type for entry i within ProfileData object
! int type_global_offset(int i) const {
! return _base_off + type_local_offset(i);
! }
!
! public:
!
! TypeStackSlotEntries(int base_off, ProfileData* pd)
! : TypeEntries(base_off, pd) {}
!
! static int compute_cell_count(BytecodeStream* stream);
!
! static void initialize(DataLayout* dl, int base, int cell_count) {
! if (TypeProfileArgsLimit > 1) {
! int off = base + cell_count_local_offset();
! dl->set_cell_at(off, cell_count - base - header_cell_count());
! }
! }
!
! void post_initialize(BytecodeStream* stream);
!
! uint number_of_arguments() const {
! assert_arguments_profiling_enabled();
! if (TypeProfileArgsLimit > 1) {
! int cell_count = cell_count_no_header();
! int nb = cell_count / TypeStackSlotEntries::per_arg_count();
! assert(nb > 0 && nb <= TypeProfileArgsLimit , "only when we profile args");
! return nb;
! } else {
! assert(TypeProfileArgsLimit == 1, "at least one arg");
! return 1;
! }
! }
!
! int cell_count() const {
! assert_arguments_profiling_enabled();
! if (TypeProfileArgsLimit > 1) {
! return _base_off + header_cell_count() + _pd->int_at_unchecked(cell_count_global_offset());
! } else {
! return _base_off + TypeStackSlotEntries::per_arg_count();
! }
! }
!
! // offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries
! static int stack_slot_local_offset(int i) {
! assert_arguments_profiling_enabled();
! return header_cell_count() + i * per_arg_cell_count + stack_slot_entry;
! }
!
! // offset of cell for type for entry i within this block of cells for a TypeStackSlotEntries
! static int type_local_offset(int i) {
! return header_cell_count() + i * per_arg_cell_count + type_entry;
! }
!
! // stack slot for entry i
! uint stack_slot(int i) const {
! assert(i >= 0 && i < number_of_arguments(), "oob");
! return _pd->uint_at(stack_slot_global_offset(i));
! }
!
! // set stack slot for entry i
! void set_stack_slot(int i, uint num) {
! assert(i >= 0 && i < number_of_arguments(), "oob");
! _pd->set_uint_at(stack_slot_global_offset(i), num);
! }
!
! // type for entry i
! intptr_t type(int i) const {
! assert(i >= 0 && i < number_of_arguments(), "oob");
! return _pd->intptr_at(type_global_offset(i));
! }
!
! // set type for entry i
! void set_type(int i, intptr_t k) {
! assert(i >= 0 && i < number_of_arguments(), "oob");
! _pd->set_intptr_at(type_global_offset(i), k);
! }
!
! static ByteSize per_arg_size() {
! return in_ByteSize(per_arg_cell_count * DataLayout::cell_size);
! }
!
! static int per_arg_count() {
! return per_arg_cell_count ;
! }
!
! // Code generation support
! static ByteSize cell_count_offset() {
! return in_ByteSize(cell_count_local_offset() * DataLayout::cell_size);
! }
!
! static ByteSize args_data_offset() {
! return in_ByteSize(header_cell_count() * DataLayout::cell_size);
! }
!
! static ByteSize stack_slot_offset(int i) {
! return in_ByteSize(stack_slot_local_offset(i) * DataLayout::cell_size);
! }
!
! static ByteSize type_offset(int i) {
! return in_ByteSize(type_local_offset(i) * DataLayout::cell_size);
! }
!
! // GC support
! void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
!
! #ifndef PRODUCT
! void print_data_on(outputStream* st) const;
! #endif
! };
!
! // CallTypeData
! //
! // A CallTypeData is used to access profiling information about a non
! // virtual call for which we collect type information about arguments.
! class CallTypeData : public CounterData {
! private:
! TypeStackSlotEntries _args;
!
! public:
! CallTypeData(DataLayout* layout) :
! CounterData(layout), _args(CounterData::static_cell_count(), this) {
! assert(layout->tag() == DataLayout::call_type_data_tag, "wrong type");
! }
!
! const TypeStackSlotEntries* args() const { return &_args; }
!
! virtual bool is_CallTypeData() const { return true; }
!
! static int static_cell_count() {
! return -1;
! }
!
! static int compute_cell_count(BytecodeStream* stream) {
! return CounterData::static_cell_count() + TypeStackSlotEntries::compute_cell_count(stream);
! }
!
! static void initialize(DataLayout* dl, int cell_count) {
! TypeStackSlotEntries::initialize(dl, CounterData::static_cell_count(), cell_count);
! }
!
! virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {
! _args.post_initialize(stream);
! }
!
! virtual int cell_count() const {
! return _args.cell_count();
! }
!
! uint number_of_arguments() const {
! return args()->number_of_arguments();
! }
!
! void set_argument_type(int i, Klass* k) {
! intptr_t current = _args.type(i);
! return _args.set_type(i, TypeEntries::with_status((intptr_t)k, current));
! }
!
! // Code generation support
! static ByteSize args_data_offset() {
! return cell_offset(CounterData::static_cell_count()) + TypeStackSlotEntries::args_data_offset();
! }
!
! // GC support
! virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
! _args.clean_weak_klass_links(is_alive_closure);
! }
!
! #ifndef PRODUCT
! virtual void print_data_on(outputStream* st) const;
#endif
};
// ReceiverTypeData
//
*** 634,653 ****
};
public:
ReceiverTypeData(DataLayout* layout) : CounterData(layout) {
assert(layout->tag() == DataLayout::receiver_type_data_tag ||
! layout->tag() == DataLayout::virtual_call_data_tag, "wrong type");
}
! virtual bool is_ReceiverTypeData() { return true; }
static int static_cell_count() {
return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count;
}
! virtual int cell_count() {
return static_cell_count();
}
// Direct accessors
static uint row_limit() {
--- 967,987 ----
};
public:
ReceiverTypeData(DataLayout* layout) : CounterData(layout) {
assert(layout->tag() == DataLayout::receiver_type_data_tag ||
! layout->tag() == DataLayout::virtual_call_data_tag ||
! layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
}
! virtual bool is_ReceiverTypeData() const { return true; }
static int static_cell_count() {
return counter_cell_count + (uint) TypeProfileWidth * receiver_type_row_cell_count;
}
! virtual int cell_count() const {
return static_cell_count();
}
// Direct accessors
static uint row_limit() {
*** 658,668 ****
}
static int receiver_count_cell_index(uint row) {
return count0_offset + row * receiver_type_row_cell_count;
}
! Klass* receiver(uint row) {
assert(row < row_limit(), "oob");
Klass* recv = (Klass*)intptr_at(receiver_cell_index(row));
assert(recv == NULL || recv->is_klass(), "wrong type");
return recv;
--- 992,1002 ----
}
static int receiver_count_cell_index(uint row) {
return count0_offset + row * receiver_type_row_cell_count;
}
! Klass* receiver(uint row) const {
assert(row < row_limit(), "oob");
Klass* recv = (Klass*)intptr_at(receiver_cell_index(row));
assert(recv == NULL || recv->is_klass(), "wrong type");
return recv;
*** 671,681 ****
void set_receiver(uint row, Klass* k) {
assert((uint)row < row_limit(), "oob");
set_intptr_at(receiver_cell_index(row), (uintptr_t)k);
}
! uint receiver_count(uint row) {
assert(row < row_limit(), "oob");
return uint_at(receiver_count_cell_index(row));
}
void set_receiver_count(uint row, uint count) {
--- 1005,1015 ----
void set_receiver(uint row, Klass* k) {
assert((uint)row < row_limit(), "oob");
set_intptr_at(receiver_cell_index(row), (uintptr_t)k);
}
! uint receiver_count(uint row) const {
assert(row < row_limit(), "oob");
return uint_at(receiver_count_cell_index(row));
}
void set_receiver_count(uint row, uint count) {
*** 719,762 ****
// GC support
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
#ifndef PRODUCT
! void print_receiver_data_on(outputStream* st);
! void print_data_on(outputStream* st);
#endif
};
// VirtualCallData
//
// A VirtualCallData is used to access profiling information about a
// virtual call. For now, it has nothing more than a ReceiverTypeData.
class VirtualCallData : public ReceiverTypeData {
public:
VirtualCallData(DataLayout* layout) : ReceiverTypeData(layout) {
! assert(layout->tag() == DataLayout::virtual_call_data_tag, "wrong type");
}
! virtual bool is_VirtualCallData() { return true; }
static int static_cell_count() {
// At this point we could add more profile state, e.g., for arguments.
// But for now it's the same size as the base record type.
return ReceiverTypeData::static_cell_count();
}
! virtual int cell_count() {
return static_cell_count();
}
// Direct accessors
static ByteSize virtual_call_data_size() {
return cell_offset(static_cell_count());
}
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// RetData
//
--- 1053,1161 ----
// GC support
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
#ifndef PRODUCT
! void print_receiver_data_on(outputStream* st) const;
! void print_data_on(outputStream* st) const;
#endif
};
// VirtualCallData
//
// A VirtualCallData is used to access profiling information about a
// virtual call. For now, it has nothing more than a ReceiverTypeData.
class VirtualCallData : public ReceiverTypeData {
public:
VirtualCallData(DataLayout* layout) : ReceiverTypeData(layout) {
! assert(layout->tag() == DataLayout::virtual_call_data_tag ||
! layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
}
! virtual bool is_VirtualCallData() const { return true; }
static int static_cell_count() {
// At this point we could add more profile state, e.g., for arguments.
// But for now it's the same size as the base record type.
return ReceiverTypeData::static_cell_count();
}
! virtual int cell_count() const {
return static_cell_count();
}
// Direct accessors
static ByteSize virtual_call_data_size() {
return cell_offset(static_cell_count());
}
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
! #endif
! };
!
! // VirtualCallTypeData
! //
! // A VirtualCallTypeData is used to access profiling information about
! // a virtual call for which we collect type information about
! // arguments.
! class VirtualCallTypeData : public VirtualCallData {
! private:
! TypeStackSlotEntries _args;
!
! public:
! VirtualCallTypeData(DataLayout* layout) :
! VirtualCallData(layout), _args(VirtualCallData::static_cell_count(), this) {
! assert(layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
! }
!
! const TypeStackSlotEntries* args() const { return &_args; }
!
! virtual bool is_VirtualCallTypeData() const { return true; }
!
! static int static_cell_count() {
! return -1;
! }
!
! static int compute_cell_count(BytecodeStream* stream) {
! return VirtualCallData::static_cell_count() + TypeStackSlotEntries::compute_cell_count(stream);
! }
!
! static void initialize(DataLayout* dl, int cell_count) {
! TypeStackSlotEntries::initialize(dl, VirtualCallData::static_cell_count(), cell_count);
! }
!
! virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {
! _args.post_initialize(stream);
! }
!
! virtual int cell_count() const {
! return _args.cell_count();
! }
!
! uint number_of_arguments() const {
! return args()->number_of_arguments();
! }
!
! void set_argument_type(int i, Klass* k) {
! intptr_t current = _args.type(i);
! return _args.set_type(i, TypeEntries::with_status((intptr_t)k, current));
! }
!
! // Code generation support
! static ByteSize args_data_offset() {
! return cell_offset(VirtualCallData::static_cell_count()) + TypeStackSlotEntries::args_data_offset();
! }
!
! // GC support
! virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
! ReceiverTypeData::clean_weak_klass_links(is_alive_closure);
! _args.clean_weak_klass_links(is_alive_closure);
! }
!
! #ifndef PRODUCT
! virtual void print_data_on(outputStream* st) const;
#endif
};
// RetData
//
*** 795,815 ****
public:
RetData(DataLayout* layout) : CounterData(layout) {
assert(layout->tag() == DataLayout::ret_data_tag, "wrong type");
}
! virtual bool is_RetData() { return true; }
enum {
no_bci = -1 // value of bci when bci1/2 are not in use.
};
static int static_cell_count() {
return counter_cell_count + (uint) BciProfileWidth * ret_row_cell_count;
}
! virtual int cell_count() {
return static_cell_count();
}
static uint row_limit() {
return BciProfileWidth;
--- 1194,1214 ----
public:
RetData(DataLayout* layout) : CounterData(layout) {
assert(layout->tag() == DataLayout::ret_data_tag, "wrong type");
}
! virtual bool is_RetData() const { return true; }
enum {
no_bci = -1 // value of bci when bci1/2 are not in use.
};
static int static_cell_count() {
return counter_cell_count + (uint) BciProfileWidth * ret_row_cell_count;
}
! virtual int cell_count() const {
return static_cell_count();
}
static uint row_limit() {
return BciProfileWidth;
*** 823,839 ****
static int bci_displacement_cell_index(uint row) {
return displacement0_offset + row * ret_row_cell_count;
}
// Direct accessors
! int bci(uint row) {
return int_at(bci_cell_index(row));
}
! uint bci_count(uint row) {
return uint_at(bci_count_cell_index(row));
}
! int bci_displacement(uint row) {
return int_at(bci_displacement_cell_index(row));
}
// Interpreter Runtime support
address fixup_ret(int return_bci, MethodData* mdo);
--- 1222,1238 ----
static int bci_displacement_cell_index(uint row) {
return displacement0_offset + row * ret_row_cell_count;
}
// Direct accessors
! int bci(uint row) const {
return int_at(bci_cell_index(row));
}
! uint bci_count(uint row) const {
return uint_at(bci_count_cell_index(row));
}
! int bci_displacement(uint row) const {
return int_at(bci_displacement_cell_index(row));
}
// Interpreter Runtime support
address fixup_ret(int return_bci, MethodData* mdo);
*** 851,861 ****
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// BranchData
//
--- 1250,1260 ----
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
#endif
};
// BranchData
//
*** 876,897 ****
public:
BranchData(DataLayout* layout) : JumpData(layout) {
assert(layout->tag() == DataLayout::branch_data_tag, "wrong type");
}
! virtual bool is_BranchData() { return true; }
static int static_cell_count() {
return branch_cell_count;
}
! virtual int cell_count() {
return static_cell_count();
}
// Direct accessor
! uint not_taken() {
return uint_at(not_taken_off_set);
}
void set_not_taken(uint cnt) {
set_uint_at(not_taken_off_set, cnt);
--- 1275,1296 ----
public:
BranchData(DataLayout* layout) : JumpData(layout) {
assert(layout->tag() == DataLayout::branch_data_tag, "wrong type");
}
! virtual bool is_BranchData() const { return true; }
static int static_cell_count() {
return branch_cell_count;
}
! virtual int cell_count() const {
return static_cell_count();
}
// Direct accessor
! uint not_taken() const {
return uint_at(not_taken_off_set);
}
void set_not_taken(uint cnt) {
set_uint_at(not_taken_off_set, cnt);
*** 915,925 ****
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// ArrayData
//
--- 1314,1324 ----
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
#endif
};
// ArrayData
//
*** 933,951 ****
enum {
array_len_off_set,
array_start_off_set
};
! uint array_uint_at(int index) {
int aindex = index + array_start_off_set;
return uint_at(aindex);
}
! int array_int_at(int index) {
int aindex = index + array_start_off_set;
return int_at(aindex);
}
! oop array_oop_at(int index) {
int aindex = index + array_start_off_set;
return oop_at(aindex);
}
void array_set_int_at(int index, int value) {
int aindex = index + array_start_off_set;
--- 1332,1350 ----
enum {
array_len_off_set,
array_start_off_set
};
! uint array_uint_at(int index) const {
int aindex = index + array_start_off_set;
return uint_at(aindex);
}
! int array_int_at(int index) const {
int aindex = index + array_start_off_set;
return int_at(aindex);
}
! oop array_oop_at(int index) const {
int aindex = index + array_start_off_set;
return oop_at(aindex);
}
void array_set_int_at(int index, int value) {
int aindex = index + array_start_off_set;
*** 958,978 ****
}
public:
ArrayData(DataLayout* layout) : ProfileData(layout) {}
! virtual bool is_ArrayData() { return true; }
static int static_cell_count() {
return -1;
}
! int array_len() {
return int_at_unchecked(array_len_off_set);
}
! virtual int cell_count() {
return array_len() + 1;
}
// Code generation support
static ByteSize array_len_offset() {
--- 1357,1377 ----
}
public:
ArrayData(DataLayout* layout) : ProfileData(layout) {}
! virtual bool is_ArrayData() const { return true; }
static int static_cell_count() {
return -1;
}
! int array_len() const {
return int_at_unchecked(array_len_off_set);
}
! virtual int cell_count() const {
return array_len() + 1;
}
// Code generation support
static ByteSize array_len_offset() {
*** 1015,1047 ****
public:
MultiBranchData(DataLayout* layout) : ArrayData(layout) {
assert(layout->tag() == DataLayout::multi_branch_data_tag, "wrong type");
}
! virtual bool is_MultiBranchData() { return true; }
static int compute_cell_count(BytecodeStream* stream);
! int number_of_cases() {
int alen = array_len() - 2; // get rid of default case here.
assert(alen % per_case_cell_count == 0, "must be even");
return (alen / per_case_cell_count);
}
! uint default_count() {
return array_uint_at(default_count_off_set);
}
! int default_displacement() {
return array_int_at(default_disaplacement_off_set);
}
! uint count_at(int index) {
return array_uint_at(case_array_start +
index * per_case_cell_count +
relative_count_off_set);
}
! int displacement_at(int index) {
return array_int_at(case_array_start +
index * per_case_cell_count +
relative_displacement_off_set);
}
--- 1414,1446 ----
public:
MultiBranchData(DataLayout* layout) : ArrayData(layout) {
assert(layout->tag() == DataLayout::multi_branch_data_tag, "wrong type");
}
! virtual bool is_MultiBranchData() const { return true; }
static int compute_cell_count(BytecodeStream* stream);
! int number_of_cases() const {
int alen = array_len() - 2; // get rid of default case here.
assert(alen % per_case_cell_count == 0, "must be even");
return (alen / per_case_cell_count);
}
! uint default_count() const {
return array_uint_at(default_count_off_set);
}
! int default_displacement() const {
return array_int_at(default_disaplacement_off_set);
}
! uint count_at(int index) const {
return array_uint_at(case_array_start +
index * per_case_cell_count +
relative_count_off_set);
}
! int displacement_at(int index) const {
return array_int_at(case_array_start +
index * per_case_cell_count +
relative_displacement_off_set);
}
*** 1072,1109 ****
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
class ArgInfoData : public ArrayData {
public:
ArgInfoData(DataLayout* layout) : ArrayData(layout) {
assert(layout->tag() == DataLayout::arg_info_data_tag, "wrong type");
}
! virtual bool is_ArgInfoData() { return true; }
! int number_of_args() {
return array_len();
}
! uint arg_modified(int arg) {
return array_uint_at(arg);
}
void set_arg_modified(int arg, uint val) {
array_set_int_at(arg, val);
}
#ifndef PRODUCT
! void print_data_on(outputStream* st);
#endif
};
// MethodData*
//
--- 1471,1508 ----
// Specific initialization.
void post_initialize(BytecodeStream* stream, MethodData* mdo);
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
#endif
};
class ArgInfoData : public ArrayData {
public:
ArgInfoData(DataLayout* layout) : ArrayData(layout) {
assert(layout->tag() == DataLayout::arg_info_data_tag, "wrong type");
}
! virtual bool is_ArgInfoData() const { return true; }
! int number_of_args() const {
return array_len();
}
! uint arg_modified(int arg) const {
return array_uint_at(arg);
}
void set_arg_modified(int arg, uint val) {
array_set_int_at(arg, val);
}
#ifndef PRODUCT
! void print_data_on(outputStream* st) const;
#endif
};
// MethodData*
//
*** 1269,1278 ****
--- 1668,1683 ----
ProfileData* bci_to_extra_data(int bci, bool create_if_missing);
// return the argument info cell
ArgInfoData *arg_info();
+ static bool profile_jsr292(methodHandle m, int bci);
+ static int profile_arguments_flag();
+ static bool profile_arguments_jsr292_only();
+ static bool profile_all_arguments();
+ static bool profile_arguments_for_invoke(methodHandle m, int bci);
+
public:
static int header_size() {
return sizeof(MethodData)/wordSize;
}
*** 1508,1515 ****
--- 1913,1922 ----
const char* internal_name() const { return "{method data}"; }
// verification
void verify_on(outputStream* st);
void verify_data_on(outputStream* st);
+
+ static bool profile_arguments();
};
#endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
src/share/vm/oops/methodData.hpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File