8338007: [JVMCI] ResolvedJavaMethod.reprofile can crash ciMethodData
Reviewed-by: dnsimon, kvn
This commit is contained in:
parent
81752c4bcc
commit
c12b386d19
@ -1382,7 +1382,8 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
|
|||||||
if (method_data == nullptr) {
|
if (method_data == nullptr) {
|
||||||
method_data = get_profiling_method_data(method, CHECK);
|
method_data = get_profiling_method_data(method, CHECK);
|
||||||
} else {
|
} else {
|
||||||
method_data->initialize();
|
CompilerThreadCanCallJava canCallJava(THREAD, true);
|
||||||
|
method_data->reinitialize();
|
||||||
}
|
}
|
||||||
C2V_END
|
C2V_END
|
||||||
|
|
||||||
|
@ -59,9 +59,14 @@ bool DataLayout::needs_array_len(u1 tag) {
|
|||||||
// Perform generic initialization of the data. More specific
|
// Perform generic initialization of the data. More specific
|
||||||
// initialization occurs in overrides of ProfileData::post_initialize.
|
// initialization occurs in overrides of ProfileData::post_initialize.
|
||||||
void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
|
void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
|
||||||
_header._bits = (intptr_t)0;
|
DataLayout temp;
|
||||||
_header._struct._tag = tag;
|
temp._header._bits = (intptr_t)0;
|
||||||
_header._struct._bci = bci;
|
temp._header._struct._tag = tag;
|
||||||
|
temp._header._struct._bci = bci;
|
||||||
|
// Write the header using a single intptr_t write. This ensures that if the layout is
|
||||||
|
// reinitialized readers will never see the transient state where the header is 0.
|
||||||
|
_header = temp._header;
|
||||||
|
|
||||||
for (int i = 0; i < cell_count; i++) {
|
for (int i = 0; i < cell_count; i++) {
|
||||||
set_cell_at(i, (intptr_t)0);
|
set_cell_at(i, (intptr_t)0);
|
||||||
}
|
}
|
||||||
@ -1224,6 +1229,28 @@ MethodData::MethodData(const methodHandle& method)
|
|||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reinitialize the storage of an existing MDO at a safepoint. Doing it this way will ensure it's
|
||||||
|
// not being accessed while the contents are being rewritten.
|
||||||
|
class VM_ReinitializeMDO: public VM_Operation {
|
||||||
|
private:
|
||||||
|
MethodData* _mdo;
|
||||||
|
public:
|
||||||
|
VM_ReinitializeMDO(MethodData* mdo): _mdo(mdo) {}
|
||||||
|
VMOp_Type type() const { return VMOp_ReinitializeMDO; }
|
||||||
|
void doit() {
|
||||||
|
// The extra data is being zero'd, we'd like to acquire the extra_data_lock but it can't be held
|
||||||
|
// over a safepoint. This means that we don't actually need to acquire the lock.
|
||||||
|
_mdo->initialize();
|
||||||
|
}
|
||||||
|
bool allow_nested_vm_operations() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void MethodData::reinitialize() {
|
||||||
|
VM_ReinitializeMDO op(this);
|
||||||
|
VMThread::execute(&op);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MethodData::initialize() {
|
void MethodData::initialize() {
|
||||||
Thread* thread = Thread::current();
|
Thread* thread = Thread::current();
|
||||||
NoSafepointVerifier no_safepoint; // init function atomic wrt GC
|
NoSafepointVerifier no_safepoint; // init function atomic wrt GC
|
||||||
|
@ -1949,6 +1949,7 @@ class MethodData : public Metadata {
|
|||||||
friend class ProfileData;
|
friend class ProfileData;
|
||||||
friend class TypeEntriesAtCall;
|
friend class TypeEntriesAtCall;
|
||||||
friend class ciMethodData;
|
friend class ciMethodData;
|
||||||
|
friend class VM_ReinitializeMDO;
|
||||||
|
|
||||||
// If you add a new field that points to any metaspace object, you
|
// If you add a new field that points to any metaspace object, you
|
||||||
// must add this field to MethodData::metaspace_pointers_do().
|
// must add this field to MethodData::metaspace_pointers_do().
|
||||||
@ -1965,11 +1966,18 @@ class MethodData : public Metadata {
|
|||||||
Mutex _extra_data_lock;
|
Mutex _extra_data_lock;
|
||||||
|
|
||||||
MethodData(const methodHandle& method);
|
MethodData(const methodHandle& method);
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static MethodData* allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS);
|
static MethodData* allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS);
|
||||||
|
|
||||||
virtual bool is_methodData() const { return true; }
|
virtual bool is_methodData() const { return true; }
|
||||||
void initialize();
|
|
||||||
|
// Safely reinitialize the data in the MDO. This is intended as a testing facility as the
|
||||||
|
// reinitialization is performed at a safepoint so it's isn't cheap and it doesn't ensure that all
|
||||||
|
// readers will see consistent profile data.
|
||||||
|
void reinitialize();
|
||||||
|
|
||||||
// Whole-method sticky bits and flags
|
// Whole-method sticky bits and flags
|
||||||
enum {
|
enum {
|
||||||
|
@ -114,7 +114,8 @@
|
|||||||
template(GTestStopSafepoint) \
|
template(GTestStopSafepoint) \
|
||||||
template(JFROldObject) \
|
template(JFROldObject) \
|
||||||
template(JvmtiPostObjectFree) \
|
template(JvmtiPostObjectFree) \
|
||||||
template(RendezvousGCThreads)
|
template(RendezvousGCThreads) \
|
||||||
|
template(ReinitializeMDO)
|
||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
class outputStream;
|
class outputStream;
|
||||||
|
Loading…
Reference in New Issue
Block a user