< prev index next >

src/hotspot/share/aot/aotCodeHeap.cpp

Print this page
rev 47466 : 8132547: [AOT] support invokedynamic instructions
Reviewed-by: iveresov, kvn

*** 58,68 **** --- 58,75 ---- // Note, exceptions are cleared. if (k == NULL) { 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; } Klass* AOTCodeHeap::lookup_klass(const char* name, int len, const Method* method, Thread* thread) {
*** 431,440 **** --- 438,448 ---- SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_ic_miss_stub", address, SharedRuntime::get_ic_miss_stub()); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_handle_wrong_method_stub", address, SharedRuntime::get_handle_wrong_method_stub()); 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); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_initialize_klass_by_symbol", address, CompilerRuntime::initialize_klass_by_symbol); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_invocation_event", address, CompilerRuntime::invocation_event);
*** 607,619 **** } NOT_PRODUCT( aot_methods_found++; ) return m; } AOTKlassData* AOTCodeHeap::find_klass(InstanceKlass* ik) { ResourceMark rm; ! AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), ik->signature_name()); return klass_data; } bool AOTCodeHeap::is_dependent_method(Klass* dependee, AOTCompiledMethod* aot) { InstanceKlass *dependee_ik = InstanceKlass::cast(dependee); --- 615,631 ---- } NOT_PRODUCT( aot_methods_found++; ) 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 = find_klass(ik->signature_name()); return klass_data; } bool AOTCodeHeap::is_dependent_method(Klass* dependee, AOTCompiledMethod* aot) { InstanceKlass *dependee_ik = InstanceKlass::cast(dependee);
*** 638,655 **** } } return false; } ! 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) { --- 650,661 ---- } } 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) {
*** 664,676 **** --- 670,705 ---- } 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) { + address methods_cnt_adr = _dependencies + methods_offset; + int methods_cnt = *(int*)methods_cnt_adr; + int* indexes = (int*)(methods_cnt_adr + 4); + 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; NOT_PRODUCT( klasses_seen++; )
*** 716,725 **** --- 745,757 ---- log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, ik->internal_name(), _lib->name(), ik->class_loader_data(), p2i(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(); int methods_offset = klass_data->_compiled_methods_offset;
*** 835,845 **** if (md == NULL) continue; // skip non-oops if (Metaspace::contains(md)) { f(md); } else { intptr_t meta = (intptr_t)md; ! fatal("Invalid value in _metaspace_got[%d] = " INTPTR_FORMAT, i, meta); } } } void AOTCodeHeap::cleanup_inline_caches() { --- 867,877 ---- if (md == NULL) continue; // skip non-oops if (Metaspace::contains(md)) { f(md); } else { intptr_t meta = (intptr_t)md; ! fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta); } } } void AOTCodeHeap::cleanup_inline_caches() {
*** 884,891 **** AOTCompiledMethod* aot = _code_to_aot[index]._aot; if (aot->_is_alive()) { aot->metadata_do(f); } } ! // Scan metaspace_got cells. got_metadata_do(f); } --- 916,1044 ---- AOTCompiledMethod* aot = _code_to_aot[index]._aot; if (aot->_is_alive()) { aot->metadata_do(f); } } ! // 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; + }
< prev index next >