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 5774 : 8031752: Failed speculative optimizations should be reattempted when root of compilation is different
Summary: support for speculative traps that keep track of the root of the compilation in which a trap occurs.
Reviewed-by:
rev 5775 : imported patch spectrap-chris

*** 118,128 **** branch_data_tag, multi_branch_data_tag, arg_info_data_tag, call_type_data_tag, virtual_call_type_data_tag, ! parameters_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]. --- 118,129 ---- branch_data_tag, multi_branch_data_tag, arg_info_data_tag, call_type_data_tag, virtual_call_type_data_tag, ! parameters_type_data_tag, ! speculative_trap_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].
*** 187,198 **** } void set_header(intptr_t value) { _header._bits = value; } ! void release_set_header(intptr_t value) { ! OrderAccess::release_store_ptr(&_header._bits, value); } intptr_t header() { return _header._bits; } void set_cell_at(int index, intptr_t value) { --- 188,202 ---- } void set_header(intptr_t value) { _header._bits = value; } ! bool atomic_set_header(intptr_t value) { ! if (Atomic::cmpxchg_ptr(value, (volatile intptr_t*)&_header._bits, 0) == 0) { ! return true; ! } ! return false; } intptr_t header() { return _header._bits; } void set_cell_at(int index, intptr_t value) {
*** 264,273 **** --- 268,278 ---- class BranchData; class ArrayData; class MultiBranchData; class ArgInfoData; class ParametersTypeData; + class SpeculativeTrapData; // ProfileData // // A ProfileData object is created to refer to a section of profiling // data in a structured way.
*** 284,293 **** --- 289,300 ---- #endif // !PRODUCT // This is a pointer to a section of profiling data. DataLayout* _data; + char* print_data_on_helper(const MethodData* md) const; + protected: DataLayout* data() { return _data; } const DataLayout* data() const { return _data; } enum {
*** 398,407 **** --- 405,415 ---- 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; } virtual bool is_ParametersTypeData() const { return false; } + virtual bool is_SpeculativeTrapData()const { return false; } BitData* as_BitData() const { assert(is_BitData(), "wrong type"); return is_BitData() ? (BitData*) this : NULL;
*** 452,461 **** --- 460,473 ---- } ParametersTypeData* as_ParametersTypeData() const { assert(is_ParametersTypeData(), "wrong type"); return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL; } + SpeculativeTrapData* as_SpeculativeTrapData() const { + assert(is_SpeculativeTrapData(), "wrong type"); + return is_SpeculativeTrapData() ? (SpeculativeTrapData*)this : NULL; + } // Subclass specific initialization virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
*** 467,482 **** // 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 --- 479,496 ---- // 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 char* extra = NULL) const { ShouldNotReachHere(); } + void print_data_on(outputStream* st, const MethodData* md) const; + #ifndef PRODUCT ! void print_shared(outputStream* st, const char* name, const char* extra) const; void tab(outputStream* st, bool first = false) const; #endif }; // BitData
*** 520,530 **** static ByteSize bit_data_size() { return cell_offset(bit_cell_count); } #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; // CounterData // --- 534,544 ---- static ByteSize bit_data_size() { return cell_offset(bit_cell_count); } #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // CounterData //
*** 564,574 **** void set_count(uint count) { set_uint_at(count_off, count); } #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; // JumpData // --- 578,588 ---- void set_count(uint count) { set_uint_at(count_off, count); } #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // JumpData //
*** 637,647 **** // 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 --- 651,661 ---- // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) 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
*** 1048,1058 **** _ret.clean_weak_klass_links(is_alive_closure); } } #ifndef PRODUCT ! virtual void print_data_on(outputStream* st) const; #endif }; // ReceiverTypeData // --- 1062,1072 ---- _ret.clean_weak_klass_links(is_alive_closure); } } #ifndef PRODUCT ! virtual void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // ReceiverTypeData //
*** 1156,1166 **** // 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 // --- 1170,1180 ---- // 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 char* extra = NULL) const; #endif }; // VirtualCallData //
*** 1189,1199 **** static ByteSize virtual_call_data_size() { return cell_offset(static_cell_count()); } #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; // VirtualCallTypeData // --- 1203,1213 ---- static ByteSize virtual_call_data_size() { return cell_offset(static_cell_count()); } #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // VirtualCallTypeData //
*** 1315,1325 **** _ret.clean_weak_klass_links(is_alive_closure); } } #ifndef PRODUCT ! virtual void print_data_on(outputStream* st) const; #endif }; // RetData // --- 1329,1339 ---- _ret.clean_weak_klass_links(is_alive_closure); } } #ifndef PRODUCT ! virtual void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // RetData //
*** 1414,1424 **** // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; // BranchData // --- 1428,1438 ---- // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // BranchData //
*** 1478,1488 **** // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; // ArrayData // --- 1492,1502 ---- // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // ArrayData //
*** 1635,1645 **** // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; class ArgInfoData : public ArrayData { --- 1649,1659 ---- // Specific initialization. void post_initialize(BytecodeStream* stream, MethodData* mdo); #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; class ArgInfoData : public ArrayData {
*** 1662,1672 **** void set_arg_modified(int arg, uint val) { array_set_int_at(arg, val); } #ifndef PRODUCT ! void print_data_on(outputStream* st) const; #endif }; // ParametersTypeData // --- 1676,1686 ---- void set_arg_modified(int arg, uint val) { array_set_int_at(arg, val); } #ifndef PRODUCT ! void print_data_on(outputStream* st, const char* extra = NULL) const; #endif }; // ParametersTypeData //
*** 1723,1733 **** virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) { _parameters.clean_weak_klass_links(is_alive_closure); } #ifndef PRODUCT ! virtual void print_data_on(outputStream* st) const; #endif static ByteSize stack_slot_offset(int i) { return cell_offset(stack_slot_local_offset(i)); } --- 1737,1747 ---- virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) { _parameters.clean_weak_klass_links(is_alive_closure); } #ifndef PRODUCT ! virtual void print_data_on(outputStream* st, const char* extra = NULL) const; #endif static ByteSize stack_slot_offset(int i) { return cell_offset(stack_slot_local_offset(i)); }
*** 1735,1744 **** --- 1749,1806 ---- static ByteSize type_offset(int i) { return cell_offset(type_local_offset(i)); } }; + // SpeculativeTrapData + // + // A SpeculativeTrapData is used to record traps due to type + // speculation. It records the root of the compilation: that type + // speculation is wrong in the context of one compilation (for + // method1) doesn't mean it's wrong in the context of another one (for + // method2). Type speculation could have more/different data in the + // context of the compilation of method2 and it's worthwhile to try an + // optimization that failed for compilation of method1 in the context + // of compilation of method2. + // Space for SpeculativeTrapData entries is allocated from the extra + // data space in the MDO. If we run out of space, the trap data for + // the ProfileData at that bci is updated. + class SpeculativeTrapData : public ProfileData { + protected: + enum { + method_offset, + speculative_trap_cell_count + }; + public: + SpeculativeTrapData(DataLayout* layout) : ProfileData(layout) { + assert(layout->tag() == DataLayout::speculative_trap_data_tag, "wrong type"); + } + + virtual bool is_SpeculativeTrapData() const { return true; } + + static int static_cell_count() { + return speculative_trap_cell_count; + } + + virtual int cell_count() const { + return static_cell_count(); + } + + // Direct accessor + Method* method() const { + return (Method*)intptr_at(method_offset); + } + + void set_method(Method* m) { + set_intptr_at(method_offset, (intptr_t)m); + } + + #ifndef PRODUCT + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; + #endif + }; + // MethodData* // // A MethodData* holds information which has been collected about // a method. Its layout looks like this: //
*** 1801,1811 **** bool is_methodData() const volatile { return true; } // Whole-method sticky bits and flags enum { ! _trap_hist_limit = 17, // decoupled from Deoptimization::Reason_LIMIT _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values private: uint _nof_decompiles; // count of all nmethod removals --- 1863,1873 ---- bool is_methodData() const volatile { return true; } // Whole-method sticky bits and flags enum { ! _trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values private: uint _nof_decompiles; // count of all nmethod removals
*** 1856,1865 **** --- 1918,1928 ---- intptr_t _data[1]; // Helper for size computation static int compute_data_size(BytecodeStream* stream); static int bytecode_cell_count(Bytecodes::Code code); + static bool is_speculative_trap_bytecode(Bytecodes::Code code); enum { no_profile_data = -1, variable_cell_count = -2 }; // Helper for initialization DataLayout* data_layout_at(int data_index) const { assert(data_index % sizeof(intptr_t) == 0, "unaligned");
*** 1899,1910 **** } // What is the index of the first data entry? int first_di() const { return 0; } // Find or create an extra ProfileData: ! ProfileData* bci_to_extra_data(int bci, bool create_if_missing); // return the argument info cell ArgInfoData *arg_info(); enum { --- 1962,1974 ---- } // What is the index of the first data entry? int first_di() const { return 0; } + ProfileData* bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp); // Find or create an extra ProfileData: ! ProfileData* bci_to_extra_data(int bci, Method* m, bool create_if_missing); // return the argument info cell ArgInfoData *arg_info(); enum {
*** 1931,1941 **** } // Compute the size of a MethodData* before it is created. static int compute_allocation_size_in_bytes(methodHandle method); static int compute_allocation_size_in_words(methodHandle method); ! static int compute_extra_data_count(int data_size, int empty_bc_count); // Determine if a given bytecode can have profile information. static bool bytecode_has_profile(Bytecodes::Code code) { return bytecode_cell_count(code) != no_profile_data; } --- 1995,2005 ---- } // Compute the size of a MethodData* before it is created. static int compute_allocation_size_in_bytes(methodHandle method); static int compute_allocation_size_in_words(methodHandle method); ! static int compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps); // Determine if a given bytecode can have profile information. static bool bytecode_has_profile(Bytecodes::Code code) { return bytecode_cell_count(code) != no_profile_data; }
*** 2072,2092 **** // Get the data at an arbitrary bci, or NULL if there is none. ProfileData* bci_to_data(int bci); // Same, but try to create an extra_data record if one is needed: ! ProfileData* allocate_bci_to_data(int bci) { ! ProfileData* data = bci_to_data(bci); ! return (data != NULL) ? data : bci_to_extra_data(bci, true); } // Add a handful of extra data records, for trap tracking. DataLayout* extra_data_base() const { return limit_data_position(); } DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); } int extra_data_size() const { return (address)extra_data_limit() - (address)extra_data_base(); } ! static DataLayout* next_extra(DataLayout* dp) { return (DataLayout*)((address)dp + in_bytes(DataLayout::cell_offset(0))); } // Return (uint)-1 for overflow. uint trap_count(int reason) const { assert((uint)reason < _trap_hist_limit, "oob"); return (int)((_trap_hist._array[reason]+1) & _trap_hist_mask) - 1; --- 2136,2173 ---- // Get the data at an arbitrary bci, or NULL if there is none. ProfileData* bci_to_data(int bci); // Same, but try to create an extra_data record if one is needed: ! ProfileData* allocate_bci_to_data(int bci, Method* m) { ! ProfileData* data = NULL; ! // If m not NULL, try to allocate a SpeculativeTrapData entry ! if (m == NULL) { ! data = bci_to_data(bci); ! } ! if (data != NULL) { ! return data; ! } ! data = bci_to_extra_data(bci, m, true); ! if (data != NULL) { ! return data; ! } ! // If SpeculativeTrapData allocation fails try to allocate a ! // regular entry ! data = bci_to_data(bci); ! if (data != NULL) { ! return data; ! } ! return bci_to_extra_data(bci, NULL, true); } // Add a handful of extra data records, for trap tracking. DataLayout* extra_data_base() const { return limit_data_position(); } DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); } int extra_data_size() const { return (address)extra_data_limit() - (address)extra_data_base(); } ! static DataLayout* next_extra(DataLayout* dp); // Return (uint)-1 for overflow. uint trap_count(int reason) const { assert((uint)reason < _trap_hist_limit, "oob"); return (int)((_trap_hist._array[reason]+1) & _trap_hist_mask) - 1;
*** 2182,2189 **** --- 2263,2272 ---- static bool profile_parameters_for_method(methodHandle m); static bool profile_arguments(); static bool profile_return(); static bool profile_parameters(); static bool profile_return_jsr292_only(); + + void clean_method_data(BoolObjectClosure* is_alive); }; #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