Skip to content
Open
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
870 changes: 870 additions & 0 deletions doc/portable-mdo-design.md

Large diffs are not rendered by default.

1,191 changes: 1,191 additions & 0 deletions doc/portable-mdo-slides.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/hotspot/share/ci/ciClassList.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ friend class ciObjectFactory; \
#define CI_PACKAGE_ACCESS_TO \
friend class ciObjectFactory; \
friend class VMStructs; \
friend class MDOReplayDump; \
friend class ciCallSite; \
friend class ciConstantPoolCache; \
friend class ciField; \
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/ci/ciEnv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class ciEnv : StackObj {
friend class Dependencies; // for get_object, during logging
friend class RecordLocation;
friend class PrepareExtraDataClosure;
friend class MDOReplayDump; // allow helper to access private getters
friend class VM_DumpMDOReplay; // nested op helper

private:
Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects()
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/ci/ciMethodData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ class ciSpeculativeTrapData : public SpeculativeTrapData {
class ciMethodData : public ciMetadata {
CI_PACKAGE_ACCESS
friend class ciReplay;
friend class MDOReplayDump;

private:
// Size in bytes
Expand Down
19 changes: 19 additions & 0 deletions src/hotspot/share/include/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ JVM_IsSupportedJNIVersion(jint version);
JNIEXPORT jobjectArray JNICALL
JVM_GetVmArguments(JNIEnv *env);

/*
* Drain the Portable MDO eager-compilation queue.
* Walks all imported MDO entries, ensures the holder classes are loaded
* and linked, installs the reconstructed MDOs, queues compilation at the
* recorded comp level, and blocks until the compile queues are empty.
* No-op when ImportMDOFile / EagerCompilePortableMDO are unset.
*/
JNIEXPORT void JNICALL
JVM_WaitForEagerCompilation(JNIEnv *env, jclass ignored);

JNIEXPORT jboolean JNICALL
JVM_IsPreviewEnabled(void);

Expand Down Expand Up @@ -1091,6 +1101,15 @@ JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
JNIEXPORT jstring JNICALL
JVM_GetTemporaryDirectory(JNIEnv *env);

/*
* HotSpot profile checkpoint support.
*/
JNIEXPORT void JNICALL
JVM_ProfileCheckpointDump(JNIEnv *env, jstring path);

JNIEXPORT void JNICALL
JVM_ProfileCheckpointLoad(JNIEnv *env, jstring path);

/* Generics reflection support.
*
* Returns information about the given class's EnclosingMethod
Expand Down
11 changes: 11 additions & 0 deletions src/hotspot/share/oops/instanceKlass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#include "oops/instanceStackChunkKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.hpp"
#include "oops/portableMDO.hpp"
#include "oops/oop.inline.hpp"
#include "oops/recordComponent.hpp"
#include "oops/symbol.hpp"
Expand Down Expand Up @@ -1065,6 +1066,16 @@ bool InstanceKlass::link_class_impl(TRAPS) {
}
}
}

// Proactively install imported MDO profiles and queue eager compilation
// for methods in this class, now that linking is complete.
// Must be outside the ObjectLocker scope — reconstruct_mdo may trigger
// class resolution which could need to acquire other init locks.
if (is_linked()) {
PortableMDO::on_class_linked(this, THREAD);
if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; }
}

return true;
}

Expand Down
16 changes: 16 additions & 0 deletions src/hotspot/share/oops/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/portableMDO.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
Expand Down Expand Up @@ -638,6 +639,21 @@ void Method::build_profiling_method_data(const methodHandle& method, TRAPS) {
if (install_training_method_data(method)) {
return;
}
// Try to import a pre-populated MDO from the portable MDO file.
if (PortableMDO::has_import_data()) {
MethodData* imported = PortableMDO::try_import(method, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
}
if (imported != nullptr) {
if (!Atomic::replace_if_null(&method->_method_data, imported)) {
ClassLoaderData* ld = method->method_holder()->class_loader_data();
MetadataFactory::free_metadata(ld, imported);
}
return;
}
}

// Do not profile the method if metaspace has hit an OOM previously
// allocating profiling data. Callers clear pending exception so don't
// add one here.
Expand Down
50 changes: 50 additions & 0 deletions src/hotspot/share/oops/methodData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,56 @@ void MethodData::print_data_on(outputStream* st) const {
}
}

void MethodData::snapshot_header(HeaderSnapshot* dst) const {
assert(dst != nullptr, "must be");
Copy::conjoint_jbytes((const char*)&_compiler_counters,
(char*)&dst->_compiler_counters,
sizeof(CompilerCounters));
dst->_invocation_counter = _invocation_counter;
dst->_backedge_counter = _backedge_counter;
dst->_invocation_counter_start = _invocation_counter_start;
dst->_backedge_counter_start = _backedge_counter_start;
dst->_tenure_traps = _tenure_traps;
dst->_invoke_mask = _invoke_mask;
dst->_backedge_mask = _backedge_mask;
dst->_num_loops = _num_loops;
dst->_num_blocks = _num_blocks;
dst->_would_profile = _would_profile;
dst->_eflags = _eflags;
dst->_arg_local = _arg_local;
dst->_arg_stack = _arg_stack;
dst->_arg_returned = _arg_returned;
dst->_data_size = _data_size;
dst->_parameters_type_data_di = _parameters_type_data_di;
dst->_exception_handler_data_di = _exception_handler_data_di;
}

bool MethodData::restore_header(const HeaderSnapshot& src) {
if (_data_size != src._data_size ||
_parameters_type_data_di != src._parameters_type_data_di ||
_exception_handler_data_di != src._exception_handler_data_di) {
return false;
}
Copy::conjoint_jbytes((const char*)&src._compiler_counters,
(char*)&_compiler_counters,
sizeof(CompilerCounters));
_invocation_counter = src._invocation_counter;
_backedge_counter = src._backedge_counter;
_invocation_counter_start = src._invocation_counter_start;
_backedge_counter_start = src._backedge_counter_start;
_tenure_traps = src._tenure_traps;
_invoke_mask = src._invoke_mask;
_backedge_mask = src._backedge_mask;
_num_loops = src._num_loops;
_num_blocks = src._num_blocks;
_would_profile = src._would_profile;
_eflags = src._eflags;
_arg_local = src._arg_local;
_arg_stack = src._arg_stack;
_arg_returned = src._arg_returned;
return true;
}

// Verification

void MethodData::verify_on(outputStream* st) {
Expand Down
24 changes: 24 additions & 0 deletions src/hotspot/share/oops/methodData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,27 @@ class MethodData : public Metadata {
DataLayout* exception_handler_bci_to_data_helper(int bci);

public:
struct HeaderSnapshot {
CompilerCounters _compiler_counters;
InvocationCounter _invocation_counter;
InvocationCounter _backedge_counter;
int _invocation_counter_start;
int _backedge_counter_start;
uint _tenure_traps;
int _invoke_mask;
int _backedge_mask;
short _num_loops;
short _num_blocks;
WouldProfile _would_profile;
intx _eflags;
intx _arg_local;
intx _arg_stack;
intx _arg_returned;
int _data_size;
int _parameters_type_data_di;
int _exception_handler_data_di;
};

void clean_extra_data(CleanExtraDataClosure* cl);

static int header_size() {
Expand Down Expand Up @@ -2308,6 +2329,9 @@ class MethodData : public Metadata {
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }

void snapshot_header(HeaderSnapshot* dst) const;
bool restore_header(const HeaderSnapshot& src);

#if INCLUDE_JVMCI
FailedSpeculation** get_failed_speculations_address() {
return &_failed_speculations;
Expand Down
Loading