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