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) {
|
||||
method_data = get_profiling_method_data(method, CHECK);
|
||||
} else {
|
||||
method_data->initialize();
|
||||
CompilerThreadCanCallJava canCallJava(THREAD, true);
|
||||
method_data->reinitialize();
|
||||
}
|
||||
C2V_END
|
||||
|
||||
|
@ -59,9 +59,14 @@ bool DataLayout::needs_array_len(u1 tag) {
|
||||
// Perform generic initialization of the data. More specific
|
||||
// initialization occurs in overrides of ProfileData::post_initialize.
|
||||
void DataLayout::initialize(u1 tag, u2 bci, int cell_count) {
|
||||
_header._bits = (intptr_t)0;
|
||||
_header._struct._tag = tag;
|
||||
_header._struct._bci = bci;
|
||||
DataLayout temp;
|
||||
temp._header._bits = (intptr_t)0;
|
||||
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++) {
|
||||
set_cell_at(i, (intptr_t)0);
|
||||
}
|
||||
@ -1224,6 +1229,28 @@ MethodData::MethodData(const methodHandle& method)
|
||||
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() {
|
||||
Thread* thread = Thread::current();
|
||||
NoSafepointVerifier no_safepoint; // init function atomic wrt GC
|
||||
|
@ -1949,6 +1949,7 @@ class MethodData : public Metadata {
|
||||
friend class ProfileData;
|
||||
friend class TypeEntriesAtCall;
|
||||
friend class ciMethodData;
|
||||
friend class VM_ReinitializeMDO;
|
||||
|
||||
// If you add a new field that points to any metaspace object, you
|
||||
// must add this field to MethodData::metaspace_pointers_do().
|
||||
@ -1965,11 +1966,18 @@ class MethodData : public Metadata {
|
||||
Mutex _extra_data_lock;
|
||||
|
||||
MethodData(const methodHandle& method);
|
||||
|
||||
void initialize();
|
||||
|
||||
public:
|
||||
static MethodData* allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS);
|
||||
|
||||
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
|
||||
enum {
|
||||
|
@ -114,7 +114,8 @@
|
||||
template(GTestStopSafepoint) \
|
||||
template(JFROldObject) \
|
||||
template(JvmtiPostObjectFree) \
|
||||
template(RendezvousGCThreads)
|
||||
template(RendezvousGCThreads) \
|
||||
template(ReinitializeMDO)
|
||||
|
||||
class Thread;
|
||||
class outputStream;
|
||||
|
Loading…
Reference in New Issue
Block a user