8132547: [AOT] support invokedynamic instructions
Reviewed-by: iveresov, kvn
This commit is contained in:
parent
8db461922a
commit
e7270b8965
src
hotspot/share
aot
classfile
jvmci
compilerRuntime.cppcompilerRuntime.hppjvmciCodeInstaller.cppjvmciCodeInstaller.hppjvmciCompilerToVM.cppjvmciJavaClasses.hppvmStructs_compiler_runtime.hppvmStructs_jvmci.cpp
oops
jdk.aot/share/classes
jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat
jdk.tools.jaotc/src/jdk/tools/jaotc
jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot
test/hotspot/jtreg/compiler
aot/calls/fromAot
AotInvokeDynamic2AotTest.javaAotInvokeDynamic2CompiledTest.javaAotInvokeDynamic2InterpretedTest.javaAotInvokeDynamic2NativeTest.java
jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot
@ -60,7 +60,14 @@ Klass* AOTCodeHeap::get_klass_from_got(const char* klass_name, int klass_len, co
|
||||
fatal("Shared file %s error: klass %s should be resolved already", _lib->name(), klass_name);
|
||||
vm_exit(1);
|
||||
}
|
||||
// Patch now to avoid extra runtime lookup
|
||||
_klasses_got[klass_data->_got_index] = k;
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
if (ik->is_initialized()) {
|
||||
_klasses_got[klass_data->_got_index - 1] = ik;
|
||||
}
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
@ -433,6 +440,7 @@ void AOTCodeHeap::link_shared_runtime_symbols() {
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_exception_handler_for_return_address", address, SharedRuntime::exception_handler_for_return_address);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_register_finalizer", address, SharedRuntime::register_finalizer);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_OSR_migration_end", address, SharedRuntime::OSR_migration_end);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_dynamic_invoke", address, CompilerRuntime::resolve_dynamic_invoke);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_string_by_symbol", address, CompilerRuntime::resolve_string_by_symbol);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_klass_by_symbol", address, CompilerRuntime::resolve_klass_by_symbol);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_method_by_symbol_and_load_counters", address, CompilerRuntime::resolve_method_by_symbol_and_load_counters);
|
||||
@ -609,9 +617,13 @@ Method* AOTCodeHeap::find_method(Klass* klass, Thread* thread, const char* metho
|
||||
return m;
|
||||
}
|
||||
|
||||
AOTKlassData* AOTCodeHeap::find_klass(const char *name) {
|
||||
return (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), name);
|
||||
}
|
||||
|
||||
AOTKlassData* AOTCodeHeap::find_klass(InstanceKlass* ik) {
|
||||
ResourceMark rm;
|
||||
AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), ik->signature_name());
|
||||
AOTKlassData* klass_data = find_klass(ik->signature_name());
|
||||
return klass_data;
|
||||
}
|
||||
|
||||
@ -640,35 +652,52 @@ bool AOTCodeHeap::is_dependent_method(Klass* dependee, AOTCompiledMethod* aot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void AOTCodeHeap::sweep_dependent_methods(int* indexes, int methods_cnt) {
|
||||
int marked = 0;
|
||||
for (int i = 0; i < methods_cnt; ++i) {
|
||||
int code_id = indexes[i];
|
||||
// Invalidate aot code.
|
||||
if (Atomic::cmpxchg(invalid, &_code_to_aot[code_id]._state, not_set) != not_set) {
|
||||
if (_code_to_aot[code_id]._state == in_use) {
|
||||
AOTCompiledMethod* aot = _code_to_aot[code_id]._aot;
|
||||
assert(aot != NULL, "aot should be set");
|
||||
if (!aot->is_runtime_stub()) { // Something is wrong - should not invalidate stubs.
|
||||
aot->mark_for_deoptimization(false);
|
||||
marked++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (marked > 0) {
|
||||
VM_Deoptimize op;
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
}
|
||||
|
||||
void AOTCodeHeap::sweep_dependent_methods(AOTKlassData* klass_data) {
|
||||
// Make dependent methods non_entrant forever.
|
||||
int methods_offset = klass_data->_dependent_methods_offset;
|
||||
if (methods_offset >= 0) {
|
||||
int marked = 0;
|
||||
address methods_cnt_adr = _dependencies + methods_offset;
|
||||
int methods_cnt = *(int*)methods_cnt_adr;
|
||||
int* indexes = (int*)(methods_cnt_adr + 4);
|
||||
for (int i = 0; i < methods_cnt; ++i) {
|
||||
int code_id = indexes[i];
|
||||
// Invalidate aot code.
|
||||
if (Atomic::cmpxchg(invalid, &_code_to_aot[code_id]._state, not_set) != not_set) {
|
||||
if (_code_to_aot[code_id]._state == in_use) {
|
||||
AOTCompiledMethod* aot = _code_to_aot[code_id]._aot;
|
||||
assert(aot != NULL, "aot should be set");
|
||||
if (!aot->is_runtime_stub()) { // Something is wrong - should not invalidate stubs.
|
||||
aot->mark_for_deoptimization(false);
|
||||
marked++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (marked > 0) {
|
||||
VM_Deoptimize op;
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
sweep_dependent_methods(indexes, methods_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
void AOTCodeHeap::sweep_dependent_methods(InstanceKlass* ik) {
|
||||
AOTKlassData* klass_data = find_klass(ik);
|
||||
vmassert(klass_data != NULL, "dependency data missing");
|
||||
sweep_dependent_methods(klass_data);
|
||||
}
|
||||
|
||||
void AOTCodeHeap::sweep_method(AOTCompiledMethod *aot) {
|
||||
int indexes[] = {aot->method_index()};
|
||||
sweep_dependent_methods(indexes, 1);
|
||||
vmassert(aot->method()->code() != aot && aot->method()->aot_code() == NULL, "method still active");
|
||||
}
|
||||
|
||||
|
||||
bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) {
|
||||
ResourceMark rm;
|
||||
|
||||
@ -718,6 +747,9 @@ bool AOTCodeHeap::load_klass_data(InstanceKlass* ik, Thread* thread) {
|
||||
aot_class->_classloader = ik->class_loader_data();
|
||||
// Set klass's Resolve (second) got cell.
|
||||
_klasses_got[klass_data->_got_index] = ik;
|
||||
if (ik->is_initialized()) {
|
||||
_klasses_got[klass_data->_got_index - 1] = ik;
|
||||
}
|
||||
|
||||
// Initialize global symbols of the DSO to the corresponding VM symbol values.
|
||||
link_global_lib_symbols();
|
||||
@ -837,7 +869,7 @@ void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
|
||||
f(md);
|
||||
} else {
|
||||
intptr_t meta = (intptr_t)md;
|
||||
fatal("Invalid value in _metaspace_got[%d] = " INTPTR_FORMAT, i, meta);
|
||||
fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -886,6 +918,127 @@ void AOTCodeHeap::metadata_do(void f(Metadata*)) {
|
||||
aot->metadata_do(f);
|
||||
}
|
||||
}
|
||||
// Scan metaspace_got cells.
|
||||
// Scan klasses_got cells.
|
||||
got_metadata_do(f);
|
||||
}
|
||||
|
||||
bool AOTCodeHeap::reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno_klass, const char *descriptor1, const char *descriptor2) {
|
||||
const char * const descriptors[2] = {descriptor1, descriptor2};
|
||||
JavaThread *thread = JavaThread::current();
|
||||
ResourceMark rm(thread);
|
||||
|
||||
AOTKlassData* holder_data = find_klass(holder);
|
||||
vmassert(holder_data != NULL, "klass %s not found", holder->signature_name());
|
||||
vmassert(is_dependent_method(holder, caller), "sanity");
|
||||
|
||||
AOTKlassData* dyno_data = NULL;
|
||||
bool adapter_failed = false;
|
||||
char buf[64];
|
||||
int descriptor_index = 0;
|
||||
// descriptors[0] specific name ("adapter:<method_id>") for matching
|
||||
// descriptors[1] fall-back name ("adapter") for depdencies
|
||||
while (descriptor_index < 2) {
|
||||
const char *descriptor = descriptors[descriptor_index];
|
||||
if (descriptor == NULL) {
|
||||
break;
|
||||
}
|
||||
jio_snprintf(buf, sizeof buf, "%s<%d:%d>", descriptor, holder_data->_class_id, index);
|
||||
dyno_data = find_klass(buf);
|
||||
if (dyno_data != NULL) {
|
||||
break;
|
||||
}
|
||||
// If match failed then try fall-back for dependencies
|
||||
++descriptor_index;
|
||||
adapter_failed = true;
|
||||
}
|
||||
|
||||
if (dyno_data == NULL && dyno_klass == NULL) {
|
||||
// all is well, no (appendix) at compile-time, and still none
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dyno_data == NULL) {
|
||||
// no (appendix) at build-time, but now there is
|
||||
sweep_dependent_methods(holder_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (adapter_failed) {
|
||||
// adapter method mismatch
|
||||
sweep_dependent_methods(holder_data);
|
||||
sweep_dependent_methods(dyno_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dyno_klass == NULL) {
|
||||
// (appendix) at build-time, none now
|
||||
sweep_dependent_methods(holder_data);
|
||||
sweep_dependent_methods(dyno_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: support array appendix object
|
||||
if (!dyno_klass->is_instance_klass()) {
|
||||
sweep_dependent_methods(holder_data);
|
||||
sweep_dependent_methods(dyno_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
InstanceKlass* dyno = InstanceKlass::cast(dyno_klass);
|
||||
|
||||
if (!dyno->is_anonymous()) {
|
||||
if (_klasses_got[dyno_data->_got_index] != dyno) {
|
||||
// compile-time class different from runtime class, fail and deoptimize
|
||||
sweep_dependent_methods(holder_data);
|
||||
sweep_dependent_methods(dyno_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dyno->is_initialized()) {
|
||||
_klasses_got[dyno_data->_got_index - 1] = dyno;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: support anonymous supers
|
||||
if (!dyno->supers_have_passed_fingerprint_checks() || dyno->get_stored_fingerprint() != dyno_data->_fingerprint) {
|
||||
NOT_PRODUCT( aot_klasses_fp_miss++; )
|
||||
log_trace(aot, class, fingerprint)("class %s%s has bad fingerprint in %s tid=" INTPTR_FORMAT,
|
||||
dyno->internal_name(), dyno->is_shared() ? " (shared)" : "",
|
||||
_lib->name(), p2i(thread));
|
||||
sweep_dependent_methods(holder_data);
|
||||
sweep_dependent_methods(dyno_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
_klasses_got[dyno_data->_got_index] = dyno;
|
||||
if (dyno->is_initialized()) {
|
||||
_klasses_got[dyno_data->_got_index - 1] = dyno;
|
||||
}
|
||||
|
||||
// TODO: hook up any AOT code
|
||||
// load_klass_data(dyno_data, thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AOTCodeHeap::reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method) {
|
||||
InstanceKlass *adapter_klass = adapter_method->method_holder();
|
||||
char buf[64];
|
||||
jio_snprintf(buf, sizeof buf, "adapter:%d", adapter_method->method_idnum());
|
||||
if (!reconcile_dynamic_klass(caller, holder, index, adapter_klass, buf, "adapter")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AOTCodeHeap::reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass) {
|
||||
if (!reconcile_dynamic_klass(caller, holder, index, appendix_klass, "appendix")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!reconcile_dynamic_method(caller, holder, index, adapter_method)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -241,13 +241,14 @@ public:
|
||||
AOTKlassData* find_klass(InstanceKlass* ik);
|
||||
bool load_klass_data(InstanceKlass* ik, Thread* thread);
|
||||
Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method);
|
||||
void sweep_dependent_methods(AOTKlassData* klass_data);
|
||||
|
||||
bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot);
|
||||
|
||||
const char* get_name_at(int offset) {
|
||||
return _metaspace_names + offset;
|
||||
}
|
||||
|
||||
|
||||
void oops_do(OopClosure* f);
|
||||
void metadata_do(void f(Metadata*));
|
||||
void got_metadata_do(void f(Metadata*));
|
||||
@ -294,6 +295,21 @@ public:
|
||||
|
||||
static void print_statistics();
|
||||
#endif
|
||||
|
||||
bool reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass);
|
||||
|
||||
private:
|
||||
AOTKlassData* find_klass(const char* name);
|
||||
|
||||
void sweep_dependent_methods(int* indexes, int methods_cnt);
|
||||
void sweep_dependent_methods(AOTKlassData* klass_data);
|
||||
void sweep_dependent_methods(InstanceKlass* ik);
|
||||
void sweep_method(AOTCompiledMethod* aot);
|
||||
|
||||
bool reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno, const char *descriptor1, const char *descriptor2 = NULL);
|
||||
|
||||
bool reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method);
|
||||
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_AOT_AOTCODEHEAP_HPP
|
||||
|
@ -40,6 +40,10 @@ GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode)
|
||||
#define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator<AOTLib*> lib = libraries()->begin(); lib != libraries()->end(); ++lib)
|
||||
|
||||
void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) {
|
||||
if (ik->is_anonymous()) {
|
||||
// don't even bother
|
||||
return;
|
||||
}
|
||||
if (UseAOT) {
|
||||
FOR_ALL_AOT_HEAPS(heap) {
|
||||
(*heap)->load_klass_data(ik, thread);
|
||||
@ -48,6 +52,10 @@ void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) {
|
||||
}
|
||||
|
||||
uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) {
|
||||
if (ik->is_anonymous()) {
|
||||
// don't even bother
|
||||
return 0;
|
||||
}
|
||||
FOR_ALL_AOT_HEAPS(heap) {
|
||||
AOTKlassData* klass_data = (*heap)->find_klass(ik);
|
||||
if (klass_data != NULL) {
|
||||
@ -259,3 +267,34 @@ void AOTLoader::print_statistics() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool AOTLoader::reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass* appendix_klass) {
|
||||
if (!UseAOT) {
|
||||
return true;
|
||||
}
|
||||
JavaThread* thread = JavaThread::current();
|
||||
ResourceMark rm(thread);
|
||||
RegisterMap map(thread, false);
|
||||
frame caller_frame = thread->last_frame().sender(&map); // Skip stub
|
||||
CodeBlob* caller_cb = caller_frame.cb();
|
||||
guarantee(caller_cb != NULL && caller_cb->is_compiled(), "must be called from compiled method");
|
||||
CompiledMethod* cm = caller_cb->as_compiled_method();
|
||||
|
||||
if (!cm->is_aot()) {
|
||||
return true;
|
||||
}
|
||||
AOTCompiledMethod* aot = (AOTCompiledMethod*)cm;
|
||||
|
||||
AOTCodeHeap* caller_heap = NULL;
|
||||
FOR_ALL_AOT_HEAPS(heap) {
|
||||
if ((*heap)->contains_blob(aot)) {
|
||||
caller_heap = *heap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
guarantee(caller_heap != NULL, "CodeHeap not found");
|
||||
bool success = caller_heap->reconcile_dynamic_invoke(aot, holder, index, adapter_method, appendix_klass);
|
||||
vmassert(success || thread->last_frame().sender(&map).is_deoptimized_frame(), "caller not deoptimized on failure");
|
||||
return success;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "runtime/handles.hpp"
|
||||
|
||||
class AOTCodeHeap;
|
||||
class AOTCompiledMethod;
|
||||
class AOTLib;
|
||||
class CodeBlob;
|
||||
template <class T> class GrowableArray;
|
||||
@ -71,6 +72,7 @@ public:
|
||||
static void flush_evol_dependents_on(InstanceKlass* dependee) NOT_AOT_RETURN;
|
||||
#endif // HOTSWAP
|
||||
|
||||
static bool reconcile_dynamic_invoke(InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass) NOT_AOT({ return true; });
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_AOT_AOTLOADER_HPP
|
||||
|
@ -223,8 +223,8 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
|
||||
result->set_cached_class_file(cached_class_file);
|
||||
}
|
||||
|
||||
if (InstanceKlass::should_store_fingerprint()) {
|
||||
result->store_fingerprint(!result->is_anonymous() ? stream->compute_fingerprint() : 0);
|
||||
if (result->should_store_fingerprint()) {
|
||||
result->store_fingerprint(stream->compute_fingerprint());
|
||||
}
|
||||
|
||||
TRACE_KLASS_CREATION(result, parser, THREAD);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,10 +24,14 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "interpreter/linkResolver.hpp"
|
||||
#include "jvmci/compilerRuntime.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/compilationPolicy.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/interfaceSupport.hpp"
|
||||
#include "runtime/vframe.hpp"
|
||||
#include "aot/aotLoader.hpp"
|
||||
|
||||
// Resolve and allocate String
|
||||
JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_string_by_symbol(JavaThread *thread, void* string_result, const char* name))
|
||||
@ -119,6 +123,62 @@ Method* CompilerRuntime::resolve_method_helper(Klass* klass, const char* method_
|
||||
return m;
|
||||
}
|
||||
|
||||
JRT_BLOCK_ENTRY(void, CompilerRuntime::resolve_dynamic_invoke(JavaThread *thread, oop* appendix_result))
|
||||
JRT_BLOCK
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
vframeStream vfst(thread, true); // Do not skip and javaCalls
|
||||
assert(!vfst.at_end(), "Java frame must exist");
|
||||
methodHandle caller(THREAD, vfst.method());
|
||||
InstanceKlass* holder = caller->method_holder();
|
||||
int bci = vfst.bci();
|
||||
Bytecode_invoke bytecode(caller, bci);
|
||||
int index = bytecode.index();
|
||||
|
||||
// Make sure it's resolved first
|
||||
CallInfo callInfo;
|
||||
constantPoolHandle cp(holder->constants());
|
||||
ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index, true));
|
||||
Bytecodes::Code invoke_code = bytecode.invoke_code();
|
||||
if (!cp_cache_entry->is_resolved(invoke_code)) {
|
||||
LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, invoke_code, CHECK);
|
||||
if (bytecode.is_invokedynamic()) {
|
||||
cp_cache_entry->set_dynamic_call(cp, callInfo);
|
||||
} else {
|
||||
cp_cache_entry->set_method_handle(cp, callInfo);
|
||||
}
|
||||
vmassert(cp_cache_entry->is_resolved(invoke_code), "sanity");
|
||||
}
|
||||
|
||||
Handle appendix(THREAD, cp_cache_entry->appendix_if_resolved(cp));
|
||||
Klass *appendix_klass = appendix.is_null() ? NULL : appendix->klass();
|
||||
|
||||
methodHandle adapter_method(cp_cache_entry->f1_as_method());
|
||||
InstanceKlass *adapter_klass = adapter_method->method_holder();
|
||||
|
||||
if (appendix_klass != NULL && appendix_klass->is_instance_klass()) {
|
||||
vmassert(InstanceKlass::cast(appendix_klass)->is_initialized(), "sanity");
|
||||
}
|
||||
if (!adapter_klass->is_initialized()) {
|
||||
// Force initialization of adapter class
|
||||
adapter_klass->initialize(CHECK);
|
||||
// Double-check that it was really initialized,
|
||||
// because we could be doing a recursive call
|
||||
// from inside <clinit>.
|
||||
}
|
||||
|
||||
int cpi = cp_cache_entry->constant_pool_index();
|
||||
if (!AOTLoader::reconcile_dynamic_invoke(holder, cpi, adapter_method(),
|
||||
appendix_klass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
*appendix_result = appendix();
|
||||
thread->set_vm_result(appendix());
|
||||
}
|
||||
JRT_BLOCK_END
|
||||
JRT_END
|
||||
|
||||
JRT_BLOCK_ENTRY(MethodCounters*, CompilerRuntime::resolve_method_by_symbol_and_load_counters(JavaThread *thread, MethodCounters** counters_result, Klass* klass, const char* data))
|
||||
MethodCounters* c = *counters_result; // Is it resolved already?
|
||||
JRT_BLOCK
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,8 @@ class CompilerRuntime : AllStatic {
|
||||
const char* signature_name, int signature_name_len);
|
||||
// Resolution methods for aot compiled code.
|
||||
static void resolve_string_by_symbol(JavaThread *thread, void* string_result, const char* name);
|
||||
static void resolve_dynamic_invoke(JavaThread *thread, oop* appendix_result);
|
||||
|
||||
static Klass* resolve_klass_by_symbol(JavaThread *thread, Klass** klass_result, const char* name);
|
||||
static Klass* initialize_klass_by_symbol(JavaThread *thread, Klass** klass_result, const char* name);
|
||||
static MethodCounters* resolve_method_by_symbol_and_load_counters(JavaThread *thread, MethodCounters** counters_result, Klass* klass_hint, const char* data);
|
||||
|
@ -174,43 +174,42 @@ OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) {
|
||||
}
|
||||
|
||||
AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
|
||||
_meta_strings = new GrowableArray<const char*>();
|
||||
_meta_refs = new GrowableArray<jobject>();
|
||||
}
|
||||
|
||||
int AOTOopRecorder::nr_meta_strings() const {
|
||||
return _meta_strings->length();
|
||||
int AOTOopRecorder::nr_meta_refs() const {
|
||||
return _meta_refs->length();
|
||||
}
|
||||
|
||||
const char* AOTOopRecorder::meta_element(int pos) const {
|
||||
return _meta_strings->at(pos);
|
||||
jobject AOTOopRecorder::meta_element(int pos) const {
|
||||
return _meta_refs->at(pos);
|
||||
}
|
||||
|
||||
int AOTOopRecorder::find_index(Metadata* h) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
int oldCount = metadata_count();
|
||||
int index = this->OopRecorder::find_index(h);
|
||||
int newCount = metadata_count();
|
||||
|
||||
if (oldCount == newCount) {
|
||||
// found a match
|
||||
return index;
|
||||
}
|
||||
|
||||
vmassert(index + 1 == newCount, "must be last");
|
||||
|
||||
Klass* klass = NULL;
|
||||
oop result = NULL;
|
||||
if (h->is_klass()) {
|
||||
klass = (Klass*) h;
|
||||
record_meta_string(klass->signature_name(), index);
|
||||
result = CompilerToVM::get_jvmci_type(klass, CATCH);
|
||||
} else if (h->is_method()) {
|
||||
Method* method = (Method*) h;
|
||||
// Need klass->signature_name() in method name
|
||||
klass = method->method_holder();
|
||||
const char* klass_name = klass->signature_name();
|
||||
int klass_name_len = (int)strlen(klass_name);
|
||||
Symbol* method_name = method->name();
|
||||
Symbol* signature = method->signature();
|
||||
int method_name_len = method_name->utf8_length();
|
||||
int method_sign_len = signature->utf8_length();
|
||||
int len = klass_name_len + 1 + method_name_len + method_sign_len;
|
||||
char* dest = NEW_RESOURCE_ARRAY(char, len + 1);
|
||||
strcpy(dest, klass_name);
|
||||
dest[klass_name_len] = '.';
|
||||
strcpy(&dest[klass_name_len + 1], method_name->as_C_string());
|
||||
strcpy(&dest[klass_name_len + 1 + method_name_len], signature->as_C_string());
|
||||
dest[len] = 0;
|
||||
record_meta_string(dest, index);
|
||||
methodHandle mh(method);
|
||||
result = CompilerToVM::get_jvmci_method(method, CATCH);
|
||||
}
|
||||
jobject ref = JNIHandles::make_local(THREAD, result);
|
||||
record_meta_ref(ref, index);
|
||||
|
||||
return index;
|
||||
}
|
||||
@ -224,16 +223,12 @@ int AOTOopRecorder::find_index(jobject h) {
|
||||
return find_index(klass);
|
||||
}
|
||||
|
||||
void AOTOopRecorder::record_meta_string(const char* name, int index) {
|
||||
void AOTOopRecorder::record_meta_ref(jobject o, int index) {
|
||||
assert(index > 0, "must be 1..n");
|
||||
index -= 1; // reduce by one to convert to array index
|
||||
|
||||
if (index < _meta_strings->length()) {
|
||||
assert(strcmp(name, _meta_strings->at(index)) == 0, "must match");
|
||||
} else {
|
||||
assert(index == _meta_strings->length(), "must be last");
|
||||
_meta_strings->append(name);
|
||||
}
|
||||
assert(index == _meta_refs->length(), "must be last");
|
||||
_meta_refs->append(o);
|
||||
}
|
||||
|
||||
void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
|
||||
|
@ -49,13 +49,13 @@ public:
|
||||
|
||||
virtual int find_index(Metadata* h);
|
||||
virtual int find_index(jobject h);
|
||||
int nr_meta_strings() const;
|
||||
const char* meta_element(int pos) const;
|
||||
int nr_meta_refs() const;
|
||||
jobject meta_element(int pos) const;
|
||||
|
||||
private:
|
||||
void record_meta_string(const char* name, int index);
|
||||
void record_meta_ref(jobject ref, int index);
|
||||
|
||||
GrowableArray<const char*>* _meta_strings;
|
||||
GrowableArray<jobject>* _meta_refs;
|
||||
};
|
||||
|
||||
class CodeMetadata {
|
||||
|
@ -1118,13 +1118,15 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject
|
||||
|
||||
AOTOopRecorder* recorder = code_metadata.get_oop_recorder();
|
||||
|
||||
int nr_meta_strings = recorder->nr_meta_strings();
|
||||
objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_strings, CHECK_(JVMCIEnv::cache_full));
|
||||
int nr_meta_refs = recorder->nr_meta_refs();
|
||||
objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_refs, CHECK_(JVMCIEnv::cache_full));
|
||||
objArrayHandle metadataArrayHandle(THREAD, metadataArray);
|
||||
for (int i = 0; i < nr_meta_strings; ++i) {
|
||||
const char* element = recorder->meta_element(i);
|
||||
Handle java_string = java_lang_String::create_from_str(element, CHECK_(JVMCIEnv::cache_full));
|
||||
metadataArrayHandle->obj_at_put(i, java_string());
|
||||
for (int i = 0; i < nr_meta_refs; ++i) {
|
||||
jobject element = recorder->meta_element(i);
|
||||
if (element == NULL) {
|
||||
return JVMCIEnv::cache_full;
|
||||
}
|
||||
metadataArrayHandle->obj_at_put(i, JNIHandles::resolve(element));
|
||||
}
|
||||
HotSpotMetaData::set_metadata(metadata_handle, metadataArrayHandle());
|
||||
|
||||
@ -1519,6 +1521,48 @@ C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_co
|
||||
}
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
|
||||
constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
|
||||
ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
|
||||
if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) {
|
||||
// MethodHandle.invoke* --> LambdaForm?
|
||||
ResourceMark rm;
|
||||
|
||||
LinkInfo link_info(cp, index, CATCH);
|
||||
|
||||
Klass* resolved_klass = link_info.resolved_klass();
|
||||
|
||||
Symbol* name_sym = cp->name_ref_at(index);
|
||||
|
||||
vmassert(MethodHandles::is_method_handle_invoke_name(resolved_klass, name_sym), "!");
|
||||
vmassert(MethodHandles::is_signature_polymorphic_name(resolved_klass, name_sym), "!");
|
||||
|
||||
methodHandle adapter_method(cp_cache_entry->f1_as_method());
|
||||
|
||||
methodHandle resolved_method(adapter_method);
|
||||
|
||||
// Can we treat it as a regular invokevirtual?
|
||||
if (resolved_method->method_holder() == resolved_klass && resolved_method->name() == name_sym) {
|
||||
vmassert(!resolved_method->is_static(),"!");
|
||||
vmassert(MethodHandles::is_signature_polymorphic_method(resolved_method()),"!");
|
||||
vmassert(!MethodHandles::is_signature_polymorphic_static(resolved_method->intrinsic_id()), "!");
|
||||
vmassert(cp_cache_entry->appendix_if_resolved(cp) == NULL, "!");
|
||||
vmassert(cp_cache_entry->method_type_if_resolved(cp) == NULL, "!");
|
||||
|
||||
methodHandle m(LinkResolver::linktime_resolve_virtual_method_or_null(link_info));
|
||||
vmassert(m == resolved_method, "!!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return Bytecodes::_invokevirtual;
|
||||
}
|
||||
if (cp_cache_entry->is_resolved(Bytecodes::_invokedynamic)) {
|
||||
return Bytecodes::_invokedynamic;
|
||||
}
|
||||
return -1;
|
||||
C2V_END
|
||||
|
||||
|
||||
C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject))
|
||||
objArrayHandle holders = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), 2, CHECK_NULL);
|
||||
Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL);
|
||||
@ -1795,6 +1839,7 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||
{CC "resolveFieldInPool", CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[I)" HS_RESOLVED_KLASS, FN_PTR(resolveFieldInPool)},
|
||||
{CC "resolveInvokeDynamicInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeDynamicInPool)},
|
||||
{CC "resolveInvokeHandleInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeHandleInPool)},
|
||||
{CC "isResolvedInvokeHandleInPool", CC "(" HS_CONSTANT_POOL "I)I", FN_PTR(isResolvedInvokeHandleInPool)},
|
||||
{CC "resolveMethod", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
|
||||
{CC "getSignaturePolymorphicHolders", CC "()[" STRING, FN_PTR(getSignaturePolymorphicHolders)},
|
||||
{CC "getVtableIndexForInterfaceMethod", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD ")I", FN_PTR(getVtableIndexForInterfaceMethod)},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -299,7 +299,7 @@ class JVMCIJavaClasses : AllStatic {
|
||||
typeArrayOop_field(HotSpotMetaData, relocBytes, "[B") \
|
||||
typeArrayOop_field(HotSpotMetaData, exceptionBytes, "[B") \
|
||||
typeArrayOop_field(HotSpotMetaData, oopMaps, "[B") \
|
||||
objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/String;") \
|
||||
objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;") \
|
||||
end_class \
|
||||
start_class(HotSpotConstantPool) \
|
||||
long_field(HotSpotConstantPool, metaspaceConstantPool) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,6 +28,7 @@
|
||||
#include "jvmci/compilerRuntime.hpp"
|
||||
|
||||
#define VM_ADDRESSES_COMPILER_RUNTIME(declare_address, declare_preprocessor_address, declare_function) \
|
||||
declare_function(CompilerRuntime::resolve_dynamic_invoke) \
|
||||
declare_function(CompilerRuntime::resolve_string_by_symbol) \
|
||||
declare_function(CompilerRuntime::resolve_klass_by_symbol) \
|
||||
declare_function(CompilerRuntime::resolve_method_by_symbol_and_load_counters) \
|
||||
|
@ -125,6 +125,7 @@
|
||||
nonstatic_field(ConstMethod, _code_size, u2) \
|
||||
nonstatic_field(ConstMethod, _name_index, u2) \
|
||||
nonstatic_field(ConstMethod, _signature_index, u2) \
|
||||
nonstatic_field(ConstMethod, _method_idnum, u2) \
|
||||
nonstatic_field(ConstMethod, _max_stack, u2) \
|
||||
nonstatic_field(ConstMethod, _max_locals, u2) \
|
||||
\
|
||||
@ -157,6 +158,7 @@
|
||||
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
|
||||
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
|
||||
nonstatic_field(InstanceKlass, _init_state, u1) \
|
||||
nonstatic_field(InstanceKlass, _misc_flags, u2) \
|
||||
\
|
||||
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_sp, intptr_t*) \
|
||||
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_pc, address) \
|
||||
@ -521,6 +523,7 @@
|
||||
\
|
||||
declare_constant(InstanceKlass::linked) \
|
||||
declare_constant(InstanceKlass::fully_initialized) \
|
||||
declare_constant(InstanceKlass::_misc_is_anonymous) \
|
||||
\
|
||||
declare_constant(JumpData::taken_off_set) \
|
||||
declare_constant(JumpData::displacement_off_set) \
|
||||
|
@ -151,7 +151,7 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& par
|
||||
nonstatic_oop_map_size(parser.total_oop_map_count()),
|
||||
parser.is_interface(),
|
||||
parser.is_anonymous(),
|
||||
should_store_fingerprint());
|
||||
should_store_fingerprint(parser.is_anonymous()));
|
||||
|
||||
const Symbol* const class_name = parser.class_name();
|
||||
assert(class_name != NULL, "invariant");
|
||||
@ -1957,7 +1957,7 @@ bool InstanceKlass::supers_have_passed_fingerprint_checks() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InstanceKlass::should_store_fingerprint() {
|
||||
bool InstanceKlass::should_store_fingerprint(bool is_anonymous) {
|
||||
#if INCLUDE_AOT
|
||||
// We store the fingerprint into the InstanceKlass only in the following 2 cases:
|
||||
if (CalculateClassFingerprint) {
|
||||
@ -1968,6 +1968,10 @@ bool InstanceKlass::should_store_fingerprint() {
|
||||
// (2) We are running -Xshare:dump to create a shared archive
|
||||
return true;
|
||||
}
|
||||
if (UseAOT && is_anonymous) {
|
||||
// (3) We are using AOT code from a shared library and see an anonymous class
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// In all other cases we might set the _misc_has_passed_fingerprint_check bit,
|
||||
|
@ -731,7 +731,8 @@ class InstanceKlass: public Klass {
|
||||
}
|
||||
bool supers_have_passed_fingerprint_checks();
|
||||
|
||||
static bool should_store_fingerprint();
|
||||
static bool should_store_fingerprint(bool is_anonymous);
|
||||
bool should_store_fingerprint() const { return should_store_fingerprint(is_anonymous()); }
|
||||
bool has_stored_fingerprint() const;
|
||||
uint64_t get_stored_fingerprint() const;
|
||||
void store_fingerprint(uint64_t fingerprint);
|
||||
|
@ -144,6 +144,7 @@ public final class BinaryContainer implements SymbolTable {
|
||||
{"SharedRuntime::exception_handler_for_return_address", "_aot_exception_handler_for_return_address"},
|
||||
{"SharedRuntime::register_finalizer", "_aot_register_finalizer"},
|
||||
{"SharedRuntime::OSR_migration_end", "_aot_OSR_migration_end"},
|
||||
{"CompilerRuntime::resolve_dynamic_invoke", "_aot_resolve_dynamic_invoke"},
|
||||
{"CompilerRuntime::resolve_string_by_symbol", "_aot_resolve_string_by_symbol"},
|
||||
{"CompilerRuntime::resolve_klass_by_symbol", "_aot_resolve_klass_by_symbol"},
|
||||
{"CompilerRuntime::resolve_method_by_symbol_and_load_counters","_aot_resolve_method_by_symbol_and_load_counters"},
|
||||
|
@ -33,6 +33,7 @@ import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.hotspot.HotSpotBackend;
|
||||
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
|
||||
import org.graalvm.compiler.lir.phases.LIRSuites;
|
||||
@ -63,13 +64,13 @@ final class AOTBackend {
|
||||
private final PhaseSuite<HighTierContext> graphBuilderSuite;
|
||||
private final HighTierContext highTierContext;
|
||||
|
||||
AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend) {
|
||||
AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, HotSpotInvokeDynamicPlugin inokeDynamicPlugin) {
|
||||
this.main = main;
|
||||
this.graalOptions = graalOptions;
|
||||
this.backend = backend;
|
||||
providers = backend.getProviders();
|
||||
codeCache = providers.getCodeCache();
|
||||
graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
|
||||
graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions, inokeDynamicPlugin);
|
||||
highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
|
||||
}
|
||||
|
||||
@ -146,13 +147,14 @@ final class AOTBackend {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
|
||||
private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions, HotSpotInvokeDynamicPlugin inokeDynamicPlugin) {
|
||||
PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
|
||||
ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
|
||||
GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
|
||||
|
||||
// Use all default plugins.
|
||||
Plugins plugins = baseConfig.getPlugins();
|
||||
plugins.setInvokeDynamicPlugin(inokeDynamicPlugin);
|
||||
GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
|
||||
|
||||
iterator.next();
|
||||
|
@ -25,24 +25,35 @@ package jdk.tools.jaotc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.tools.jaotc.binformat.BinaryContainer;
|
||||
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
||||
import jdk.tools.jaotc.binformat.Symbol.Binding;
|
||||
import jdk.tools.jaotc.binformat.Symbol.Kind;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
import jdk.tools.jaotc.AOTDynamicTypeStore.AdapterLocation;
|
||||
import jdk.tools.jaotc.AOTDynamicTypeStore.AppendixLocation;
|
||||
import jdk.tools.jaotc.AOTDynamicTypeStore.Location;
|
||||
|
||||
/**
|
||||
* Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
|
||||
* of a class {@code className} are maintained in an array list.
|
||||
*/
|
||||
final class AOTCompiledClass {
|
||||
|
||||
private static AOTDynamicTypeStore dynoStore;
|
||||
|
||||
static void setDynamicTypeStore(AOTDynamicTypeStore s) {
|
||||
dynoStore = s;
|
||||
}
|
||||
|
||||
static class AOTKlassData {
|
||||
private int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
|
||||
private int classId; // Unique ID
|
||||
@ -50,29 +61,64 @@ final class AOTCompiledClass {
|
||||
private int compiledMethodsOffset;
|
||||
// Offset to dependent methods data.
|
||||
private int dependentMethodsOffset;
|
||||
private long fingerprint; // Class fingerprint
|
||||
|
||||
private final String name;
|
||||
private boolean isArray;
|
||||
private final String metadataName;
|
||||
HotSpotResolvedObjectType type;
|
||||
|
||||
/**
|
||||
* List of dependent compiled methods which have a reference to this class.
|
||||
*/
|
||||
private ArrayList<CompiledMethodInfo> dependentMethods;
|
||||
|
||||
AOTKlassData(BinaryContainer binaryContainer, String name, long fingerprint, int classId) {
|
||||
AOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type, int classId) {
|
||||
this.dependentMethods = new ArrayList<>();
|
||||
this.classId = classId;
|
||||
this.fingerprint = fingerprint;
|
||||
this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(name);
|
||||
this.type = type;
|
||||
this.metadataName = type.isAnonymous() ? "anon<"+ classId + ">": type.getName();
|
||||
this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(metadataName);
|
||||
this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
|
||||
this.dependentMethodsOffset = -1;
|
||||
this.name = name;
|
||||
this.isArray = name.length() > 0 && name.charAt(0) == '[';
|
||||
}
|
||||
|
||||
long getFingerprint() {
|
||||
return fingerprint;
|
||||
private String[] getMetaspaceNames() {
|
||||
String name = metadataName;
|
||||
Set<Location> locs = dynoStore.getDynamicClassLocationsForType(type);
|
||||
if (locs == null) {
|
||||
return new String[] {name};
|
||||
} else {
|
||||
ArrayList<String> names = new ArrayList<String>();
|
||||
names.add(name);
|
||||
for (Location l : locs) {
|
||||
HotSpotResolvedObjectType cpType = l.getHolder();
|
||||
AOTKlassData data = getAOTKlassData(cpType);
|
||||
// We collect dynamic types at parse time, but late inlining
|
||||
// may record types that don't make it into the final graph.
|
||||
// We can safely ignore those here.
|
||||
if (data == null) {
|
||||
// Not a compiled or inlined method
|
||||
continue;
|
||||
}
|
||||
int cpi = l.getCpi();
|
||||
String location = "<"+ data.classId + ":" + cpi + ">";
|
||||
if (l instanceof AdapterLocation) {
|
||||
names.add("adapter" + location);
|
||||
AdapterLocation a = (AdapterLocation)l;
|
||||
names.add("adapter:" + a.getMethodId() + location);
|
||||
} else {
|
||||
assert l instanceof AppendixLocation;
|
||||
names.add("appendix" + location);
|
||||
}
|
||||
}
|
||||
return names.toArray(new String[names.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
HotSpotResolvedObjectType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
String getMetadataName() {
|
||||
return metadataName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,6 +158,7 @@ final class AOTCompiledClass {
|
||||
for (CompiledMethodInfo methodInfo : dependentMethods) {
|
||||
dependenciesContainer.appendInt(methodInfo.getCodeId());
|
||||
}
|
||||
|
||||
verify();
|
||||
|
||||
// @formatter:off
|
||||
@ -119,7 +166,9 @@ final class AOTCompiledClass {
|
||||
* The offsets layout should match AOTKlassData structure in AOT JVM runtime
|
||||
*/
|
||||
int offset = container.getByteStreamSize();
|
||||
container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
|
||||
for (String name : getMetaspaceNames()) {
|
||||
container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
|
||||
}
|
||||
// Add index (offset/8) to the got in the .metaspace.got section
|
||||
container.appendInt(gotIndex).
|
||||
// Add unique ID
|
||||
@ -129,13 +178,16 @@ final class AOTCompiledClass {
|
||||
// Add the offset to dependent methods data in the .metaspace.offsets section.
|
||||
appendInt(dependentMethodsOffset).
|
||||
// Add fingerprint.
|
||||
appendLong(fingerprint);
|
||||
appendLong(type.getFingerprint());
|
||||
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private void verify() {
|
||||
String name = type.getName();
|
||||
assert gotIndex > 0 : "incorrect gotIndex: " + gotIndex + " for klass: " + name;
|
||||
assert isArray || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
|
||||
long fingerprint = type.getFingerprint();
|
||||
assert type.isArray() || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
|
||||
assert compiledMethodsOffset >= -1 : "incorrect compiledMethodsOffset: " + compiledMethodsOffset + " for klass: " + name;
|
||||
assert dependentMethodsOffset >= -1 : "incorrect dependentMethodsOffset: " + dependentMethodsOffset + " for klass: " + name;
|
||||
assert classId >= 0 : "incorrect classId: " + classId + " for klass: " + name;
|
||||
@ -148,7 +200,7 @@ final class AOTCompiledClass {
|
||||
/**
|
||||
* List of all collected class data.
|
||||
*/
|
||||
private static Map<String, AOTKlassData> klassData = new HashMap<>();
|
||||
private static HashMap<String, AOTKlassData> klassData = new HashMap<>();
|
||||
|
||||
/**
|
||||
* List of all methods to be compiled.
|
||||
@ -269,23 +321,25 @@ final class AOTCompiledClass {
|
||||
*/
|
||||
synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
|
||||
String name = type.getName();
|
||||
long fingerprint = type.getFingerprint();
|
||||
AOTKlassData data = klassData.get(name);
|
||||
if (data != null) {
|
||||
assert data.getFingerprint() == fingerprint : "incorrect fingerprint data for klass: " + name;
|
||||
assert data.getType() == type : "duplicate classes for name " + name;
|
||||
} else {
|
||||
data = new AOTKlassData(binaryContainer, name, fingerprint, classesCount++);
|
||||
data = new AOTKlassData(binaryContainer, type, classesCount++);
|
||||
klassData.put(name, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
synchronized static AOTKlassData getAOTKlassData(String name) {
|
||||
private synchronized static AOTKlassData getAOTKlassData(String name) {
|
||||
return klassData.get(name);
|
||||
}
|
||||
|
||||
synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
|
||||
return getAOTKlassData(type.getName());
|
||||
String name = type.getName();
|
||||
AOTKlassData data = getAOTKlassData(name);
|
||||
assert data == null || data.getType() == type : "duplicate classes for name " + name;
|
||||
return data;
|
||||
}
|
||||
|
||||
void addAOTKlassData(BinaryContainer binaryContainer) {
|
||||
@ -354,21 +408,55 @@ final class AOTCompiledClass {
|
||||
methodInfo.addMethodOffsets(binaryContainer, container);
|
||||
}
|
||||
String name = resolvedJavaType.getName();
|
||||
AOTKlassData data = klassData.get(name);
|
||||
AOTKlassData data = getAOTKlassData(resolvedJavaType);
|
||||
assert data != null : "missing data for klass: " + name;
|
||||
assert data.getFingerprint() == resolvedJavaType.getFingerprint() : "incorrect fingerprint for klass: " + name;
|
||||
int cntDepMethods = data.dependentMethods.size();
|
||||
assert cntDepMethods > 0 : "no dependent methods for compiled klass: " + name;
|
||||
data.setCompiledMethodsOffset(startMethods);
|
||||
}
|
||||
|
||||
static void putAOTKlassData(BinaryContainer binaryContainer) {
|
||||
// record dynamic types
|
||||
Set<HotSpotResolvedObjectType> dynoTypes = dynoStore.getDynamicTypes();
|
||||
if (dynoTypes != null) {
|
||||
for (HotSpotResolvedObjectType dynoType : dynoTypes) {
|
||||
addFingerprintKlassData(binaryContainer, dynoType);
|
||||
}
|
||||
}
|
||||
|
||||
ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
|
||||
for (AOTKlassData data : klassData.values()) {
|
||||
data.putAOTKlassData(binaryContainer, container);
|
||||
}
|
||||
}
|
||||
|
||||
static HotSpotResolvedObjectType getType(Object ref) {
|
||||
return (ref instanceof HotSpotResolvedObjectType) ?
|
||||
(HotSpotResolvedObjectType)ref :
|
||||
((HotSpotResolvedJavaMethod)ref).getDeclaringClass();
|
||||
}
|
||||
|
||||
static String metadataName(HotSpotResolvedObjectType type) {
|
||||
AOTKlassData data = getAOTKlassData(type);
|
||||
assert data != null : "no data for " + type;
|
||||
return getAOTKlassData(type).getMetadataName();
|
||||
}
|
||||
|
||||
private static String metadataName(HotSpotResolvedJavaMethod m) {
|
||||
return metadataName(m.getDeclaringClass()) + "." + m.getName() + m.getSignature().toMethodDescriptor();
|
||||
}
|
||||
|
||||
static String metadataName(Object ref) {
|
||||
if (ref instanceof HotSpotResolvedJavaMethod) {
|
||||
HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod)ref;
|
||||
return metadataName(m);
|
||||
} else {
|
||||
assert ref instanceof HotSpotResolvedObjectType : "unexpected object type " + ref.getClass().getName();
|
||||
HotSpotResolvedObjectType type = (HotSpotResolvedObjectType)ref;
|
||||
return metadataName(type);
|
||||
}
|
||||
}
|
||||
|
||||
boolean representsStubs() {
|
||||
return representsStubs;
|
||||
}
|
||||
|
169
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java
Normal file
169
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTDynamicTypeStore.java
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.tools.jaotc;
|
||||
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin.DynamicTypeStore;
|
||||
import org.graalvm.compiler.nodes.ConstantNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.ValueNode;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantPool;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
||||
import jdk.vm.ci.meta.ConstantPool;
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
final class AOTDynamicTypeStore implements DynamicTypeStore {
|
||||
|
||||
public static class Location {
|
||||
private HotSpotResolvedObjectType holder;
|
||||
private int cpi;
|
||||
|
||||
Location(HotSpotResolvedObjectType holder, int cpi) {
|
||||
this.holder = holder;
|
||||
this.cpi = cpi;
|
||||
}
|
||||
|
||||
public HotSpotResolvedObjectType getHolder() {
|
||||
return holder;
|
||||
}
|
||||
public int getCpi() {
|
||||
return cpi;
|
||||
}
|
||||
public String toString() {
|
||||
return getHolder().getName() + "@" + cpi;
|
||||
}
|
||||
public int hashCode() {
|
||||
return holder.hashCode() + getClass().hashCode() + cpi;
|
||||
}
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Location l = (Location)o;
|
||||
return cpi == l.cpi && holder.equals(l.holder);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AdapterLocation extends Location {
|
||||
private int methodId;
|
||||
|
||||
AdapterLocation(HotSpotResolvedObjectType holder, int cpi, int methodId) {
|
||||
super(holder, cpi);
|
||||
this.methodId = methodId;
|
||||
}
|
||||
public int getMethodId() {
|
||||
return methodId;
|
||||
}
|
||||
public String toString() {
|
||||
return "adapter:" + methodId + "@" + super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class AppendixLocation extends Location {
|
||||
AppendixLocation(HotSpotResolvedObjectType holder, int cpi) {
|
||||
super(holder, cpi);
|
||||
}
|
||||
public String toString() {
|
||||
return "appendix@" + super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<HotSpotResolvedObjectType, HashSet<Location>> typeMap = new HashMap<>();
|
||||
private HashMap<HotSpotResolvedObjectType, HashSet<HotSpotResolvedObjectType>> holderMap = new HashMap<>();
|
||||
|
||||
public Set<HotSpotResolvedObjectType> getDynamicTypes() {
|
||||
synchronized (typeMap) {
|
||||
return typeMap.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<HotSpotResolvedObjectType> getDynamicHolders() {
|
||||
synchronized (holderMap) {
|
||||
return holderMap.keySet();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordAdapter(int opcode, HotSpotResolvedObjectType holder, int index, HotSpotResolvedJavaMethod adapter) {
|
||||
int cpi = ((HotSpotConstantPool)holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
|
||||
int methodId = adapter.methodIdnum();
|
||||
HotSpotResolvedObjectType adapterType = adapter.getDeclaringClass();
|
||||
recordDynamicTypeLocation(new AdapterLocation(holder, cpi, methodId), adapterType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaConstant recordAppendix(int opcode, HotSpotResolvedObjectType holder, int index, JavaConstant appendix) {
|
||||
int cpi = ((HotSpotConstantPool)holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
|
||||
HotSpotResolvedObjectType appendixType = ((HotSpotObjectConstant)appendix).getType();
|
||||
recordDynamicTypeLocation(new AppendixLocation(holder, cpi), appendixType);
|
||||
// Make the constant locatable
|
||||
return HotSpotConstantPoolObject.forObject(holder, cpi, appendix);
|
||||
}
|
||||
|
||||
private static <T> void recordDynamicMapValue(HashMap<HotSpotResolvedObjectType, HashSet<T>> map, HotSpotResolvedObjectType type, T v) {
|
||||
synchronized (map) {
|
||||
HashSet<T> set = map.get(type);
|
||||
if (set == null) {
|
||||
set = new HashSet<>();
|
||||
map.put(type, set);
|
||||
}
|
||||
set.add(v);
|
||||
}
|
||||
}
|
||||
|
||||
private void recordDynamicTypeLocation(Location l, HotSpotResolvedObjectType type) {
|
||||
recordDynamicMapValue(typeMap, type, l);
|
||||
HotSpotResolvedObjectType holder = l.getHolder();
|
||||
recordDynamicMapValue(holderMap, holder, type);
|
||||
}
|
||||
|
||||
public Set<Location> getDynamicClassLocationsForType(HotSpotResolvedObjectType type) {
|
||||
synchronized (typeMap) {
|
||||
return typeMap.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<HotSpotResolvedObjectType> getDynamicTypesForHolder(HotSpotResolvedObjectType holder) {
|
||||
synchronized (holderMap) {
|
||||
return holderMap.get(holder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -32,9 +32,19 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
final class CallInfo {
|
||||
|
||||
static boolean isStaticTarget(Call call) {
|
||||
return !((HotSpotResolvedJavaMethod)call.target).hasReceiver();
|
||||
}
|
||||
|
||||
private static boolean isStaticOpcode(Call call) {
|
||||
int opcode = getByteCode(call) & 0xFF;
|
||||
return opcode == Bytecodes.INVOKESTATIC || opcode == Bytecodes.INVOKEDYNAMIC || opcode == Bytecodes.INVOKEVIRTUAL /* invokehandle */;
|
||||
}
|
||||
|
||||
static boolean isStaticCall(Call call) {
|
||||
if (isJavaCall(call)) {
|
||||
return ((getByteCode(call) & 0xFF) == Bytecodes.INVOKESTATIC);
|
||||
if (isJavaCall(call) && isStaticTarget(call)) {
|
||||
assert isStaticOpcode(call);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -54,7 +64,7 @@ final class CallInfo {
|
||||
}
|
||||
|
||||
static boolean isVirtualCall(CompiledMethodInfo methodInfo, Call call) {
|
||||
return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL);
|
||||
return isInvokeVirtual(call) && !methodInfo.hasMark(call, MarkId.INVOKESPECIAL) && !isStaticTarget(call);
|
||||
}
|
||||
|
||||
static boolean isOptVirtualCall(CompiledMethodInfo methodInfo, Call call) {
|
||||
|
@ -25,7 +25,7 @@ package jdk.tools.jaotc;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
|
||||
import jdk.tools.jaotc.binformat.BinaryContainer;
|
||||
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
|
||||
@ -182,12 +182,12 @@ final class CompiledMethodInfo {
|
||||
/**
|
||||
* List of stubs (PLT trampoline).
|
||||
*/
|
||||
private Map<String, StubInformation> stubs = new HashMap<>();
|
||||
private HashMap<String, StubInformation> stubs = new HashMap<>();
|
||||
|
||||
/**
|
||||
* List of referenced classes.
|
||||
*/
|
||||
private Map<String, AOTKlassData> dependentKlasses = new HashMap<>();
|
||||
private HashSet<AOTKlassData> dependentKlasses = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Methods count used to generate unique global method id.
|
||||
@ -209,7 +209,7 @@ final class CompiledMethodInfo {
|
||||
void addMethodOffsets(BinaryContainer binaryContainer, ReadOnlyDataContainer container) {
|
||||
this.methodOffsets.setNameOffset(binaryContainer.addMetaspaceName(name));
|
||||
this.methodOffsets.addMethodOffsets(container, name);
|
||||
for (AOTKlassData data : dependentKlasses.values()) {
|
||||
for (AOTKlassData data : dependentKlasses) {
|
||||
data.addDependentMethod(this);
|
||||
}
|
||||
}
|
||||
@ -291,17 +291,15 @@ final class CompiledMethodInfo {
|
||||
|
||||
void addDependentKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
|
||||
AOTKlassData klassData = AOTCompiledClass.addFingerprintKlassData(binaryContainer, type);
|
||||
String klassName = type.getName();
|
||||
|
||||
if (dependentKlasses.containsKey(klassName)) {
|
||||
assert dependentKlasses.get(klassName) == klassData : "duplicated data for klass: " + klassName;
|
||||
} else {
|
||||
dependentKlasses.put(klassName, klassData);
|
||||
}
|
||||
dependentKlasses.add(klassData);
|
||||
}
|
||||
|
||||
AOTKlassData getDependentKlassData(String klassName) {
|
||||
return dependentKlasses.get(klassName);
|
||||
AOTKlassData getDependentKlassData(HotSpotResolvedObjectType type) {
|
||||
AOTKlassData klassData = AOTCompiledClass.getAOTKlassData(type);
|
||||
if (dependentKlasses.contains(klassData)) {
|
||||
return klassData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean hasMark(Site call, MarkId id) {
|
||||
|
@ -32,6 +32,7 @@ import jdk.tools.jaotc.binformat.Relocation.RelocType;
|
||||
import jdk.tools.jaotc.binformat.Symbol;
|
||||
import jdk.tools.jaotc.binformat.Symbol.Binding;
|
||||
import jdk.tools.jaotc.binformat.Symbol.Kind;
|
||||
import jdk.tools.jaotc.AOTCompiledClass;
|
||||
import org.graalvm.compiler.code.DataSection;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
|
||||
|
||||
@ -40,6 +41,7 @@ import jdk.vm.ci.code.site.ConstantReference;
|
||||
import jdk.vm.ci.code.site.DataPatch;
|
||||
import jdk.vm.ci.code.site.DataSectionReference;
|
||||
import jdk.vm.ci.code.site.Reference;
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
||||
@ -84,18 +86,24 @@ final class DataPatchProcessor {
|
||||
HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant;
|
||||
if (metaspaceConstant.asResolvedJavaType() != null) {
|
||||
HotSpotResolvedObjectType type = metaspaceConstant.asResolvedJavaType();
|
||||
targetSymbol = type.getName();
|
||||
gotName = ((action == HotSpotConstantLoadAction.INITIALIZE) ? "got.init." : "got.") + targetSymbol;
|
||||
methodInfo.addDependentKlassData(binaryContainer, type);
|
||||
targetSymbol = AOTCompiledClass.metadataName(type);
|
||||
gotName = ((action == HotSpotConstantLoadAction.INITIALIZE) ? "got.init." : "got.") + targetSymbol;
|
||||
} else if (metaspaceConstant.asResolvedJavaMethod() != null && action == HotSpotConstantLoadAction.LOAD_COUNTERS) {
|
||||
targetSymbol = "counters." + JavaMethodInfo.uniqueMethodName(metaspaceConstant.asResolvedJavaMethod());
|
||||
gotName = "got." + targetSymbol;
|
||||
binaryContainer.addCountersSymbol(targetSymbol);
|
||||
}
|
||||
} else if (constant instanceof HotSpotObjectConstant) {
|
||||
// String constant.
|
||||
HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) constant;
|
||||
targetSymbol = "ldc." + oopConstant.toValueString();
|
||||
if (oopConstant instanceof HotSpotConstantPoolObject) {
|
||||
HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject)oopConstant;
|
||||
// Even if two locations use the same object, resolve separately
|
||||
targetSymbol = "ldc." + cpo.getCpType().getName() + cpo.getCpi();
|
||||
} else {
|
||||
// String constant.
|
||||
targetSymbol = "ldc." + oopConstant.toValueString();
|
||||
}
|
||||
Integer offset = binaryContainer.addOopSymbol(targetSymbol);
|
||||
gotName = "got.ldc." + offset;
|
||||
} else if (constant instanceof HotSpotSentinelConstant) {
|
||||
|
@ -124,6 +124,7 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
||||
private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) {
|
||||
String resolveSymbolName;
|
||||
if (CallInfo.isStaticCall(call)) {
|
||||
assert mi.hasMark(call, MarkId.INVOKESTATIC);
|
||||
resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName();
|
||||
} else if (CallInfo.isSpecialCall(call)) {
|
||||
resolveSymbolName = BinaryContainer.getResolveOptVirtualEntrySymbolName();
|
||||
|
@ -46,6 +46,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
@ -159,7 +160,10 @@ public final class Main {
|
||||
System.gc();
|
||||
}
|
||||
|
||||
AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend);
|
||||
AOTDynamicTypeStore dynoStore = new AOTDynamicTypeStore();
|
||||
AOTCompiledClass.setDynamicTypeStore(dynoStore);
|
||||
|
||||
AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, new HotSpotInvokeDynamicPlugin(dynoStore));
|
||||
SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection();
|
||||
AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads);
|
||||
classes = compiler.compileClasses(classes);
|
||||
|
@ -33,6 +33,7 @@ import jdk.tools.jaotc.utils.NativeOrderOutputStream;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
|
||||
|
||||
|
||||
import jdk.vm.ci.code.StackSlot;
|
||||
import jdk.vm.ci.code.site.DataPatch;
|
||||
import jdk.vm.ci.code.site.Infopoint;
|
||||
@ -40,6 +41,9 @@ import jdk.vm.ci.code.site.Mark;
|
||||
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaData;
|
||||
|
||||
import static jdk.tools.jaotc.AOTCompiledClass.getType;
|
||||
import static jdk.tools.jaotc.AOTCompiledClass.metadataName;
|
||||
|
||||
final class MetadataBuilder {
|
||||
|
||||
private final DataBuilder dataBuilder;
|
||||
@ -168,7 +172,7 @@ final class MetadataBuilder {
|
||||
}
|
||||
|
||||
private static int addMetadataEntries(BinaryContainer binaryContainer, HotSpotMetaData metaData, CompiledMethodInfo methodInfo) {
|
||||
String[] metaDataEntries = metaData.metadataEntries();
|
||||
Object[] metaDataEntries = metaData.metadataEntries();
|
||||
|
||||
if (metaDataEntries.length == 0) {
|
||||
return 0;
|
||||
@ -177,20 +181,13 @@ final class MetadataBuilder {
|
||||
int metadataGotSlotsStart = binaryContainer.getMetadataGotContainer().getByteStreamSize(); // binaryContainer.reserveMetadataGOTSlots(metaDataEntries.length);
|
||||
|
||||
for (int index = 0; index < metaDataEntries.length; index++) {
|
||||
String name = metaDataEntries[index];
|
||||
addMetadataEntry(binaryContainer, name);
|
||||
Object ref = metaDataEntries[index];
|
||||
String name = metadataName(ref);
|
||||
// Create GOT cells for klasses referenced in metadata
|
||||
String klassName = name;
|
||||
int len = name.length();
|
||||
int parenthesesIndex = name.lastIndexOf('(', len - 1);
|
||||
if (parenthesesIndex > 0) { // Method name
|
||||
int dotIndex = name.lastIndexOf('.', parenthesesIndex - 1);
|
||||
assert dotIndex > 0 : "method's full name should have '.' : " + name;
|
||||
klassName = name.substring(0, dotIndex);
|
||||
}
|
||||
addMetadataEntry(binaryContainer, name);
|
||||
// We should already have added entries for this klass
|
||||
assert AOTCompiledClass.getAOTKlassData(klassName) != null;
|
||||
assert methodInfo.getDependentKlassData(klassName) != null;
|
||||
assert AOTCompiledClass.getAOTKlassData(getType(ref)) != null;
|
||||
assert methodInfo.getDependentKlassData(getType(ref)) != null;
|
||||
}
|
||||
|
||||
return metadataGotSlotsStart;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -255,6 +255,15 @@ final class CompilerToVM {
|
||||
*/
|
||||
native void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
|
||||
|
||||
/**
|
||||
* If {@code cpi} denotes an entry representing a resolved dynamic adapter
|
||||
* (see {@code resolveInvokeDynamicInPool} and {@code resolveInvokeHandleInPool}),
|
||||
* return the opcode of the instruction for which the resolution was performed
|
||||
* ({@code invokedynamic} or {@code invokevirtual}}, or {@code -1} otherwise.
|
||||
*/
|
||||
native int isResolvedInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the list of type names (in the format of {@link JavaType#getName()}) denoting the
|
||||
* classes that define signature polymorphic methods.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -42,7 +42,7 @@ import jdk.vm.ci.meta.Signature;
|
||||
/**
|
||||
* Implementation of {@link ConstantPool} for HotSpot.
|
||||
*/
|
||||
final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
|
||||
public final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
|
||||
|
||||
/**
|
||||
* Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
|
||||
@ -215,14 +215,14 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a raw index from the bytecodes to a constant pool index by adding a
|
||||
* Converts a raw index from the bytecodes to a constant pool cache index by adding a
|
||||
* {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}.
|
||||
*
|
||||
* @param rawIndex index from the bytecode
|
||||
* @param opcode bytecode to convert the index for
|
||||
* @return constant pool index
|
||||
* @return constant pool cache index
|
||||
*/
|
||||
private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
|
||||
private static int rawIndexToConstantPoolCacheIndex(int rawIndex, int opcode) {
|
||||
int index;
|
||||
if (opcode == Bytecodes.INVOKEDYNAMIC) {
|
||||
index = rawIndex;
|
||||
@ -271,6 +271,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
return metaspaceConstantPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMetaspacePointer() {
|
||||
return getMetaspaceConstantPool();
|
||||
}
|
||||
@ -541,7 +542,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
@Override
|
||||
public JavaConstant lookupAppendix(int cpi, int opcode) {
|
||||
assert Bytecodes.isInvoke(opcode);
|
||||
final int index = rawIndexToConstantPoolIndex(cpi, opcode);
|
||||
final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
|
||||
Object appendix = compilerToVM().lookupAppendixInPool(this, index);
|
||||
if (appendix == null) {
|
||||
return null;
|
||||
@ -566,7 +567,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
|
||||
@Override
|
||||
public JavaMethod lookupMethod(int cpi, int opcode) {
|
||||
final int index = rawIndexToConstantPoolIndex(cpi, opcode);
|
||||
final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
|
||||
final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode);
|
||||
if (method != null) {
|
||||
return method;
|
||||
@ -603,7 +604,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
|
||||
@Override
|
||||
public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
|
||||
final int index = rawIndexToConstantPoolIndex(cpi, opcode);
|
||||
final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
|
||||
final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
|
||||
final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
|
||||
String typeName = lookupUtf8(typeIndex);
|
||||
@ -634,6 +635,25 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a raw index from the bytecodes to a constant pool index
|
||||
* (not a cache index).
|
||||
*
|
||||
* @param rawIndex index from the bytecode
|
||||
* @param opcode bytecode to convert the index for
|
||||
* @return constant pool index
|
||||
*/
|
||||
public int rawIndexToConstantPoolIndex(int index, int opcode) {
|
||||
if (isInvokedynamicIndex(index)) {
|
||||
assert opcode == Bytecodes.INVOKEDYNAMIC;
|
||||
index = decodeInvokedynamicIndex(index) + config().constantPoolCpCacheIndexTag;
|
||||
} else {
|
||||
assert opcode != Bytecodes.INVOKEDYNAMIC;
|
||||
index = rawIndexToConstantPoolCacheIndex(index, opcode);
|
||||
}
|
||||
return compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void loadReferencedType(int cpi, int opcode) {
|
||||
@ -664,7 +684,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
case Bytecodes.INVOKESTATIC:
|
||||
case Bytecodes.INVOKEINTERFACE: {
|
||||
// invoke and field instructions point to a constant pool cache entry.
|
||||
index = rawIndexToConstantPoolIndex(cpi, opcode);
|
||||
index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
|
||||
index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
|
||||
break;
|
||||
}
|
||||
@ -696,7 +716,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
}
|
||||
if (tag == JVM_CONSTANT.MethodRef) {
|
||||
if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
|
||||
final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
|
||||
final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
|
||||
assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
|
||||
compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
|
||||
}
|
||||
@ -734,6 +754,25 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a resolved dynamic adapter method at the specified index,
|
||||
* resulting from either a resolved invokedynamic or invokevirtual on a signature polymorphic
|
||||
* MethodHandle method (HotSpot invokehandle).
|
||||
*
|
||||
* @param cpi the constant pool index
|
||||
* @param opcode the opcode of the instruction for which the lookup is being performed
|
||||
* @return {@code true} if a signature polymorphic method reference was found, otherwise {@code false}
|
||||
*/
|
||||
public boolean isResolvedDynamicInvoke(int cpi, int opcode) {
|
||||
if (Bytecodes.isInvokeHandleAlias(opcode)) {
|
||||
final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
|
||||
assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
|
||||
int op = compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
|
||||
return op == opcode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
HotSpotResolvedObjectType holder = getHolder();
|
||||
|
75
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java
Normal file
75
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
|
||||
/**
|
||||
* Represents a constant that was retrieved from a constant pool.
|
||||
* Used to keep track of the constant pool slot for the constant.
|
||||
*/
|
||||
public final class HotSpotConstantPoolObject extends HotSpotObjectConstantImpl {
|
||||
|
||||
static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, Object object) {
|
||||
return new HotSpotConstantPoolObject(type, cpi, object);
|
||||
}
|
||||
|
||||
public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
|
||||
return forObject(type, cpi, ((HotSpotObjectConstantImpl)object).object());
|
||||
}
|
||||
|
||||
private final HotSpotResolvedObjectType type;
|
||||
private final int cpi;
|
||||
|
||||
public HotSpotResolvedObjectType getCpType() { return type; }
|
||||
public int getCpi() { return cpi; }
|
||||
|
||||
HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, Object object) {
|
||||
super(object, false);
|
||||
this.type = type;
|
||||
this.cpi = cpi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof HotSpotConstantPoolObject) {
|
||||
if (super.equals(o)) {
|
||||
HotSpotConstantPoolObject other = (HotSpotConstantPoolObject) o;
|
||||
return type == other.type && cpi == other.cpi;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toValueString() {
|
||||
return getCpType().getName() + getCpi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "@" + toValueString();
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,7 +32,7 @@ public class HotSpotMetaData {
|
||||
private byte[] relocBytes;
|
||||
private byte[] exceptionBytes;
|
||||
private byte[] oopMaps;
|
||||
private String[] metadata;
|
||||
private Object[] metadata;
|
||||
|
||||
public HotSpotMetaData(TargetDescription target, HotSpotCompiledCode compiledMethod) {
|
||||
// Assign the fields default values...
|
||||
@ -66,7 +66,7 @@ public class HotSpotMetaData {
|
||||
return oopMaps;
|
||||
}
|
||||
|
||||
public String[] metadataEntries() {
|
||||
public Object[] metadataEntries() {
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,7 +38,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
* Represents a constant non-{@code null} object reference, within the compiler and across the
|
||||
* compiler/runtime interface.
|
||||
*/
|
||||
final class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
|
||||
class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
|
||||
|
||||
static JavaConstant forObject(Object object) {
|
||||
return forObject(object, false);
|
||||
@ -73,7 +73,7 @@ final class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
|
||||
private final Object object;
|
||||
private final boolean compressed;
|
||||
|
||||
private HotSpotObjectConstantImpl(Object object, boolean compressed) {
|
||||
protected HotSpotObjectConstantImpl(Object object, boolean compressed) {
|
||||
this.object = object;
|
||||
this.compressed = compressed;
|
||||
assert object != null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -122,4 +122,6 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
|
||||
int allocateCompileId(int entryBCI);
|
||||
|
||||
boolean hasCodeAtLevel(int entryBCI, int level);
|
||||
|
||||
int methodIdnum();
|
||||
}
|
||||
|
@ -777,4 +777,8 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||
}
|
||||
return compilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
|
||||
}
|
||||
|
||||
public int methodIdnum() {
|
||||
return UNSAFE.getChar(getConstMethod() + config().constMethodMethodIdnumOffset);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -108,4 +108,7 @@ public interface HotSpotResolvedObjectType extends ResolvedJavaType {
|
||||
HotSpotResolvedObjectType getEnclosingType();
|
||||
|
||||
ResolvedJavaMethod getClassInitializer();
|
||||
|
||||
boolean isAnonymous();
|
||||
|
||||
}
|
||||
|
@ -934,4 +934,13 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
public boolean isCloneableWithAllocation() {
|
||||
return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
|
||||
}
|
||||
|
||||
private int getMiscFlags() {
|
||||
return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
|
||||
}
|
||||
|
||||
public boolean isAnonymous() {
|
||||
return (getMiscFlags() & config().instanceKlassMiscIsAnonymous) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,11 +92,13 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
|
||||
final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
|
||||
final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
|
||||
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags", Integer.class, "u2");
|
||||
final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
|
||||
final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
|
||||
|
||||
final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
|
||||
final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
|
||||
final int instanceKlassMiscIsAnonymous = getConstant("InstanceKlass::_misc_is_anonymous", Integer.class);
|
||||
|
||||
final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
|
||||
final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
|
||||
@ -185,6 +187,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
final int constMethodCodeSizeOffset = getFieldOffset("ConstMethod::_code_size", Integer.class, "u2");
|
||||
final int constMethodNameIndexOffset = getFieldOffset("ConstMethod::_name_index", Integer.class, "u2");
|
||||
final int constMethodSignatureIndexOffset = getFieldOffset("ConstMethod::_signature_index", Integer.class, "u2");
|
||||
final int constMethodMethodIdnumOffset = getFieldOffset("ConstMethod::_method_idnum", Integer.class, "u2");
|
||||
final int constMethodMaxStackOffset = getFieldOffset("ConstMethod::_max_stack", Integer.class, "u2");
|
||||
final int methodMaxLocalsOffset = getFieldOffset("ConstMethod::_max_locals", Integer.class, "u2");
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
* @test
|
||||
* @requires vm.aot
|
||||
* @library /test/lib /testlibrary /
|
||||
* @ignore 8132547
|
||||
* @modules java.base/jdk.internal.org.objectweb.asm
|
||||
* java.base/jdk.internal.misc
|
||||
* @build compiler.calls.common.InvokeDynamic
|
||||
|
@ -25,7 +25,6 @@
|
||||
* @test
|
||||
* @requires vm.aot
|
||||
* @library /test/lib /testlibrary /
|
||||
* @ignore 8132547
|
||||
* @modules java.base/jdk.internal.org.objectweb.asm
|
||||
* java.base/jdk.internal.misc
|
||||
* @build compiler.calls.common.InvokeDynamic
|
||||
|
@ -25,7 +25,6 @@
|
||||
* @test
|
||||
* @requires vm.aot
|
||||
* @library /test/lib /testlibrary /
|
||||
* @ignore 8132547
|
||||
* @modules java.base/jdk.internal.org.objectweb.asm
|
||||
* java.base/jdk.internal.misc
|
||||
* @build compiler.calls.common.InvokeDynamic
|
||||
|
@ -25,7 +25,6 @@
|
||||
* @test
|
||||
* @requires vm.aot
|
||||
* @library /test/lib /testlibrary /
|
||||
* @ignore 8132547
|
||||
* @modules java.base/jdk.internal.org.objectweb.asm
|
||||
* java.base/jdk.internal.misc
|
||||
* @build compiler.calls.common.InvokeDynamic
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -308,10 +308,6 @@ public class CompilerToVMHelper {
|
||||
return CompilerToVM.class;
|
||||
}
|
||||
|
||||
public static Class<?> HotSpotConstantPoolClass() {
|
||||
return HotSpotConstantPool.class;
|
||||
}
|
||||
|
||||
public static Class<?> getMirror(HotSpotResolvedObjectType type) {
|
||||
return ((HotSpotResolvedJavaType) type).mirror();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user