8132547: [AOT] support invokedynamic instructions

Reviewed-by: iveresov, kvn
This commit is contained in:
Dean Long 2017-10-19 19:23:48 -07:00
parent 8db461922a
commit e7270b8965
40 changed files with 894 additions and 159 deletions

@ -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;
}

@ -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();

@ -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();
}