8138922: StubCodeDesc constructor publishes partially-constructed objects on StubCodeDesc::_list
Reviewed-by: kvn, coleenp, dholmes
This commit is contained in:
parent
596b56f6c7
commit
e675738256
@ -291,6 +291,9 @@ MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) {
|
||||
{
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
blob = new (size) MethodHandlesAdapterBlob(size);
|
||||
if (blob == NULL) {
|
||||
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for method handle adapter blob");
|
||||
}
|
||||
}
|
||||
// Track memory usage statistic after releasing CodeCache_lock
|
||||
MemoryService::track_code_cache_memory_usage();
|
||||
|
@ -63,30 +63,21 @@
|
||||
bool MethodHandles::_enabled = false; // set true after successful native linkage
|
||||
MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Generates method handle adapters. Returns 'false' if memory allocation
|
||||
* failed and true otherwise.
|
||||
*/
|
||||
bool MethodHandles::generate_adapters() {
|
||||
if (SystemDictionary::MethodHandle_klass() == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MethodHandles::generate_adapters() {
|
||||
assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
|
||||
assert(_adapter_code == NULL, "generate only once");
|
||||
|
||||
ResourceMark rm;
|
||||
TraceTime timer("MethodHandles adapters generation", TraceStartupTime);
|
||||
_adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size);
|
||||
if (_adapter_code == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CodeBuffer code(_adapter_code);
|
||||
MethodHandlesAdapterGenerator g(&code);
|
||||
g.generate();
|
||||
code.log_section_sizes("MethodHandlesAdapterBlob");
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1435,54 +1426,32 @@ static JNINativeMethod MH_methods[] = {
|
||||
{CC "invokeExact", CC "([" OBJ ")" OBJ, FN_PTR(MH_invokeExact_UOE)}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method to register native methods.
|
||||
*/
|
||||
static bool register_natives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
|
||||
int status = env->RegisterNatives(clazz, methods, nMethods);
|
||||
if (status != JNI_OK || env->ExceptionOccurred()) {
|
||||
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This one function is exported, used by NativeLookup.
|
||||
*/
|
||||
JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
|
||||
assert(!MethodHandles::enabled(), "must not be enabled");
|
||||
bool enable_MH = true;
|
||||
assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
|
||||
|
||||
jclass MH_class = NULL;
|
||||
if (SystemDictionary::MethodHandle_klass() == NULL) {
|
||||
enable_MH = false;
|
||||
} else {
|
||||
oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
|
||||
MH_class = (jclass) JNIHandles::make_local(env, mirror);
|
||||
}
|
||||
oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
|
||||
jclass MH_class = (jclass) JNIHandles::make_local(env, mirror);
|
||||
|
||||
if (enable_MH) {
|
||||
{
|
||||
ThreadToNativeFromVM ttnfv(thread);
|
||||
|
||||
if (enable_MH) {
|
||||
enable_MH = register_natives(env, MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
|
||||
}
|
||||
if (enable_MH) {
|
||||
enable_MH = register_natives(env, MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
|
||||
}
|
||||
int status = env->RegisterNatives(MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
|
||||
guarantee(status == JNI_OK && !env->ExceptionOccurred(),
|
||||
"register java.lang.invoke.MethodHandleNative natives");
|
||||
|
||||
status = env->RegisterNatives(MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
|
||||
guarantee(status == JNI_OK && !env->ExceptionOccurred(),
|
||||
"register java.lang.invoke.MethodHandle natives");
|
||||
}
|
||||
|
||||
if (TraceInvokeDynamic) {
|
||||
tty->print_cr("MethodHandle support loaded (using LambdaForms)");
|
||||
}
|
||||
|
||||
if (enable_MH) {
|
||||
if (MethodHandles::generate_adapters() == false) {
|
||||
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for method handle adapters");
|
||||
}
|
||||
MethodHandles::set_enabled(true);
|
||||
}
|
||||
MethodHandles::set_enabled(true);
|
||||
}
|
||||
JVM_END
|
||||
|
@ -81,7 +81,7 @@ class MethodHandles: AllStatic {
|
||||
static void flush_dependent_nmethods(Handle call_site, Handle target);
|
||||
|
||||
// Generate MethodHandles adapters.
|
||||
static bool generate_adapters();
|
||||
static void generate_adapters();
|
||||
|
||||
// Called from MethodHandlesAdapterGenerator.
|
||||
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid);
|
||||
|
@ -145,6 +145,7 @@ jint init_globals() {
|
||||
}
|
||||
javaClasses_init(); // must happen after vtable initialization
|
||||
stubRoutines_init2(); // note: StubRoutines need 2-phase init
|
||||
MethodHandles::generate_adapters();
|
||||
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::StubRoutines2);
|
||||
|
||||
#if INCLUDE_NMT
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
StubCodeDesc* StubCodeDesc::_list = NULL;
|
||||
int StubCodeDesc::_count = 0;
|
||||
|
||||
bool StubCodeDesc::_frozen = false;
|
||||
|
||||
StubCodeDesc* StubCodeDesc::desc_for(address pc) {
|
||||
StubCodeDesc* p = _list;
|
||||
@ -46,20 +46,23 @@ StubCodeDesc* StubCodeDesc::desc_for(address pc) {
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
StubCodeDesc* StubCodeDesc::desc_for_index(int index) {
|
||||
StubCodeDesc* p = _list;
|
||||
while (p != NULL && p->index() != index) p = p->_next;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
const char* StubCodeDesc::name_for(address pc) {
|
||||
StubCodeDesc* p = desc_for(pc);
|
||||
return p == NULL ? NULL : p->name();
|
||||
}
|
||||
|
||||
|
||||
void StubCodeDesc::freeze() {
|
||||
assert(!_frozen, "repeated freeze operation");
|
||||
_frozen = true;
|
||||
}
|
||||
|
||||
void StubCodeDesc::print_on(outputStream* st) const {
|
||||
st->print("%s", group());
|
||||
st->print("::");
|
||||
@ -110,12 +113,10 @@ StubCodeGenerator::~StubCodeGenerator() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
|
||||
// default implementation - do nothing
|
||||
}
|
||||
|
||||
|
||||
void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
|
||||
// default implementation - record the cdesc
|
||||
if (_first_stub == NULL) _first_stub = cdesc;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "asm/assembler.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
// All the basic framework for stubcode generation/debugging/printing.
|
||||
// All the basic framework for stub code generation/debugging/printing.
|
||||
|
||||
|
||||
// A StubCodeDesc describes a piece of generated code (usually stubs).
|
||||
@ -37,9 +37,10 @@
|
||||
// this may have to change if searching becomes too slow.
|
||||
|
||||
class StubCodeDesc: public CHeapObj<mtCode> {
|
||||
protected:
|
||||
private:
|
||||
static StubCodeDesc* _list; // the list of all descriptors
|
||||
static int _count; // length of list
|
||||
static bool _frozen; // determines whether _list modifications are allowed
|
||||
|
||||
StubCodeDesc* _next; // the next element in the linked list
|
||||
const char* _group; // the group to which the stub code belongs
|
||||
@ -68,6 +69,7 @@ class StubCodeDesc: public CHeapObj<mtCode> {
|
||||
static const char* name_for(address pc); // returns the name of the code containing pc or NULL
|
||||
|
||||
StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) {
|
||||
assert(!_frozen, "no modifications allowed");
|
||||
assert(name != NULL, "no name specified");
|
||||
_next = _list;
|
||||
_group = group;
|
||||
@ -78,6 +80,8 @@ class StubCodeDesc: public CHeapObj<mtCode> {
|
||||
_list = this;
|
||||
};
|
||||
|
||||
static void freeze();
|
||||
|
||||
const char* group() const { return _group; }
|
||||
const char* name() const { return _name; }
|
||||
int index() const { return _index; }
|
||||
@ -117,7 +121,7 @@ class StubCodeGenerator: public StackObj {
|
||||
// later via an address pointing into it.
|
||||
|
||||
class StubCodeMark: public StackObj {
|
||||
protected:
|
||||
private:
|
||||
StubCodeGenerator* _cgen;
|
||||
StubCodeDesc* _cdesc;
|
||||
|
||||
|
@ -3600,6 +3600,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||
vm_exit_during_initialization("Failed to initialize tracing backend");
|
||||
}
|
||||
|
||||
// No more stub generation allowed after that point.
|
||||
StubCodeDesc::freeze();
|
||||
|
||||
// Set flag that basic initialization has completed. Used by exceptions and various
|
||||
// debug stuff, that does not work until all basic classes have been initialized.
|
||||
set_init_completed();
|
||||
|
Loading…
Reference in New Issue
Block a user