mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8031752: Failed speculative optimizations should be reattempted when root of compilation is different
Support for speculative traps that keep track of the root of the compilation in which a trap occurs. Reviewed-by: kvn, twisti
This commit is contained in:
parent
532b570e81
commit
493557fc90
16 changed files with 772 additions and 164 deletions
|
@ -120,7 +120,8 @@ public:
|
|||
arg_info_data_tag,
|
||||
call_type_data_tag,
|
||||
virtual_call_type_data_tag,
|
||||
parameters_type_data_tag
|
||||
parameters_type_data_tag,
|
||||
speculative_trap_data_tag
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -189,8 +190,11 @@ public:
|
|||
void set_header(intptr_t value) {
|
||||
_header._bits = value;
|
||||
}
|
||||
void release_set_header(intptr_t value) {
|
||||
OrderAccess::release_store_ptr(&_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;
|
||||
|
@ -271,6 +275,7 @@ class ArrayData;
|
|||
class MultiBranchData;
|
||||
class ArgInfoData;
|
||||
class ParametersTypeData;
|
||||
class SpeculativeTrapData;
|
||||
|
||||
// ProfileData
|
||||
//
|
||||
|
@ -291,6 +296,8 @@ private:
|
|||
// 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; }
|
||||
|
@ -440,6 +447,7 @@ public:
|
|||
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 {
|
||||
|
@ -494,6 +502,10 @@ public:
|
|||
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
|
||||
|
@ -509,12 +521,14 @@ public:
|
|||
// 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 {
|
||||
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;
|
||||
void print_shared(outputStream* st, const char* name, const char* extra) const;
|
||||
void tab(outputStream* st, bool first = false) const;
|
||||
#endif
|
||||
};
|
||||
|
@ -576,7 +590,7 @@ public:
|
|||
#endif // CC_INTERP
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -639,7 +653,7 @@ public:
|
|||
#endif // CC_INTERP
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -726,7 +740,7 @@ public:
|
|||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1137,7 +1151,7 @@ public:
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void print_data_on(outputStream* st) const;
|
||||
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1282,7 +1296,7 @@ public:
|
|||
|
||||
#ifndef PRODUCT
|
||||
void print_receiver_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1325,7 +1339,7 @@ public:
|
|||
#endif // CC_INTERP
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1451,7 +1465,7 @@ public:
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void print_data_on(outputStream* st) const;
|
||||
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1554,7 +1568,7 @@ public:
|
|||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1632,7 +1646,7 @@ public:
|
|||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1825,7 +1839,7 @@ public:
|
|||
void post_initialize(BytecodeStream* stream, MethodData* mdo);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1852,7 +1866,7 @@ public:
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1913,7 +1927,7 @@ public:
|
|||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void print_data_on(outputStream* st) const;
|
||||
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
|
||||
static ByteSize stack_slot_offset(int i) {
|
||||
|
@ -1925,6 +1939,54 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
|
@ -1994,7 +2056,7 @@ public:
|
|||
|
||||
// Whole-method sticky bits and flags
|
||||
enum {
|
||||
_trap_hist_limit = 17, // decoupled from Deoptimization::Reason_LIMIT
|
||||
_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
|
||||
|
@ -2049,6 +2111,7 @@ private:
|
|||
// 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
|
||||
|
@ -2092,8 +2155,9 @@ private:
|
|||
// 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, bool create_if_missing);
|
||||
ProfileData* bci_to_extra_data(int bci, Method* m, bool create_if_missing);
|
||||
|
||||
// return the argument info cell
|
||||
ArgInfoData *arg_info();
|
||||
|
@ -2116,6 +2180,10 @@ private:
|
|||
static bool profile_parameters_jsr292_only();
|
||||
static bool profile_all_parameters();
|
||||
|
||||
void clean_extra_data(BoolObjectClosure* is_alive);
|
||||
void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false);
|
||||
void verify_extra_data_clean(BoolObjectClosure* is_alive);
|
||||
|
||||
public:
|
||||
static int header_size() {
|
||||
return sizeof(MethodData)/wordSize;
|
||||
|
@ -2124,7 +2192,7 @@ public:
|
|||
// 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);
|
||||
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) {
|
||||
|
@ -2265,9 +2333,26 @@ public:
|
|||
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);
|
||||
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.
|
||||
|
@ -2275,7 +2360,7 @@ public:
|
|||
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))); }
|
||||
static DataLayout* next_extra(DataLayout* dp);
|
||||
|
||||
// Return (uint)-1 for overflow.
|
||||
uint trap_count(int reason) const {
|
||||
|
@ -2375,6 +2460,8 @@ public:
|
|||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue