Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
33 changes: 30 additions & 3 deletions src/hotspot/share/oops/methodData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion src/hotspot/share/oops/methodData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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().
Expand All @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/runtime/vmOperation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@
template(GTestStopSafepoint) \
template(JFROldObject) \
template(JvmtiPostObjectFree) \
template(RendezvousGCThreads)
template(RendezvousGCThreads) \
template(ReinitializeMDO)

class Thread;
class outputStream;
Expand Down