Path: blob/master/src/hotspot/share/jvmci/jvmciRuntime.cpp
40949 views
/*1* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "classfile/javaClasses.inline.hpp"25#include "classfile/symbolTable.hpp"26#include "classfile/systemDictionary.hpp"27#include "classfile/vmClasses.hpp"28#include "compiler/compileBroker.hpp"29#include "gc/shared/collectedHeap.hpp"30#include "gc/shared/oopStorage.inline.hpp"31#include "jvmci/jniAccessMark.inline.hpp"32#include "jvmci/jvmciCompilerToVM.hpp"33#include "jvmci/jvmciRuntime.hpp"34#include "jvmci/metadataHandles.hpp"35#include "logging/log.hpp"36#include "memory/oopFactory.hpp"37#include "memory/universe.hpp"38#include "oops/constantPool.inline.hpp"39#include "oops/klass.inline.hpp"40#include "oops/method.inline.hpp"41#include "oops/objArrayKlass.hpp"42#include "oops/oop.inline.hpp"43#include "oops/typeArrayOop.inline.hpp"44#include "prims/jvmtiExport.hpp"45#include "prims/methodHandles.hpp"46#include "runtime/atomic.hpp"47#include "runtime/biasedLocking.hpp"48#include "runtime/deoptimization.hpp"49#include "runtime/fieldDescriptor.inline.hpp"50#include "runtime/frame.inline.hpp"51#include "runtime/java.hpp"52#include "runtime/jniHandles.inline.hpp"53#include "runtime/reflectionUtils.hpp"54#include "runtime/sharedRuntime.hpp"55#if INCLUDE_G1GC56#include "gc/g1/g1BarrierSetRuntime.hpp"57#endif // INCLUDE_G1GC5859// Simple helper to see if the caller of a runtime stub which60// entered the VM has been deoptimized6162static bool caller_is_deopted() {63JavaThread* thread = JavaThread::current();64RegisterMap reg_map(thread, false);65frame runtime_frame = thread->last_frame();66frame caller_frame = runtime_frame.sender(®_map);67assert(caller_frame.is_compiled_frame(), "must be compiled");68return caller_frame.is_deoptimized_frame();69}7071// Stress deoptimization72static void deopt_caller() {73if ( !caller_is_deopted()) {74JavaThread* thread = JavaThread::current();75RegisterMap reg_map(thread, false);76frame runtime_frame = thread->last_frame();77frame caller_frame = runtime_frame.sender(®_map);78Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);79assert(caller_is_deopted(), "Must be deoptimized");80}81}8283// Manages a scope for a JVMCI runtime call that attempts a heap allocation.84// If there is a pending nonasync exception upon closing the scope and the runtime85// call is of the variety where allocation failure returns NULL without an86// exception, the following action is taken:87// 1. The pending nonasync exception is cleared88// 2. NULL is written to JavaThread::_vm_result89// 3. Checks that an OutOfMemoryError is Universe::out_of_memory_error_retry().90class RetryableAllocationMark: public StackObj {91private:92JavaThread* _thread;93public:94RetryableAllocationMark(JavaThread* thread, bool activate) {95if (activate) {96assert(!thread->in_retryable_allocation(), "retryable allocation scope is non-reentrant");97_thread = thread;98_thread->set_in_retryable_allocation(true);99} else {100_thread = NULL;101}102}103~RetryableAllocationMark() {104if (_thread != NULL) {105_thread->set_in_retryable_allocation(false);106JavaThread* THREAD = _thread; // For exception macros.107if (HAS_PENDING_EXCEPTION) {108oop ex = PENDING_EXCEPTION;109// Do not clear probable async exceptions.110CLEAR_PENDING_NONASYNC_EXCEPTION;111oop retry_oome = Universe::out_of_memory_error_retry();112if (ex->is_a(retry_oome->klass()) && retry_oome != ex) {113ResourceMark rm;114fatal("Unexpected exception in scope of retryable allocation: " INTPTR_FORMAT " of type %s", p2i(ex), ex->klass()->external_name());115}116_thread->set_vm_result(NULL);117}118}119}120};121122JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance_common(JavaThread* current, Klass* klass, bool null_on_fail))123JRT_BLOCK;124assert(klass->is_klass(), "not a class");125Handle holder(current, klass->klass_holder()); // keep the klass alive126InstanceKlass* h = InstanceKlass::cast(klass);127{128RetryableAllocationMark ram(current, null_on_fail);129h->check_valid_for_instantiation(true, CHECK);130oop obj;131if (null_on_fail) {132if (!h->is_initialized()) {133// Cannot re-execute class initialization without side effects134// so return without attempting the initialization135return;136}137} else {138// make sure klass is initialized139h->initialize(CHECK);140}141// allocate instance and return via TLS142obj = h->allocate_instance(CHECK);143current->set_vm_result(obj);144}145JRT_BLOCK_END;146SharedRuntime::on_slowpath_allocation_exit(current);147JRT_END148149JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array_common(JavaThread* current, Klass* array_klass, jint length, bool null_on_fail))150JRT_BLOCK;151// Note: no handle for klass needed since they are not used152// anymore after new_objArray() and no GC can happen before.153// (This may have to change if this code changes!)154assert(array_klass->is_klass(), "not a class");155oop obj;156if (array_klass->is_typeArray_klass()) {157BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();158RetryableAllocationMark ram(current, null_on_fail);159obj = oopFactory::new_typeArray(elt_type, length, CHECK);160} else {161Handle holder(current, array_klass->klass_holder()); // keep the klass alive162Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();163RetryableAllocationMark ram(current, null_on_fail);164obj = oopFactory::new_objArray(elem_klass, length, CHECK);165}166current->set_vm_result(obj);167// This is pretty rare but this runtime patch is stressful to deoptimization168// if we deoptimize here so force a deopt to stress the path.169if (DeoptimizeALot) {170static int deopts = 0;171// Alternate between deoptimizing and raising an error (which will also cause a deopt)172if (deopts++ % 2 == 0) {173if (null_on_fail) {174return;175} else {176ResourceMark rm(current);177THROW(vmSymbols::java_lang_OutOfMemoryError());178}179} else {180deopt_caller();181}182}183JRT_BLOCK_END;184SharedRuntime::on_slowpath_allocation_exit(current);185JRT_END186187JRT_ENTRY(void, JVMCIRuntime::new_multi_array_common(JavaThread* current, Klass* klass, int rank, jint* dims, bool null_on_fail))188assert(klass->is_klass(), "not a class");189assert(rank >= 1, "rank must be nonzero");190Handle holder(current, klass->klass_holder()); // keep the klass alive191RetryableAllocationMark ram(current, null_on_fail);192oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);193current->set_vm_result(obj);194JRT_END195196JRT_ENTRY(void, JVMCIRuntime::dynamic_new_array_common(JavaThread* current, oopDesc* element_mirror, jint length, bool null_on_fail))197RetryableAllocationMark ram(current, null_on_fail);198oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);199current->set_vm_result(obj);200JRT_END201202JRT_ENTRY(void, JVMCIRuntime::dynamic_new_instance_common(JavaThread* current, oopDesc* type_mirror, bool null_on_fail))203InstanceKlass* klass = InstanceKlass::cast(java_lang_Class::as_Klass(type_mirror));204205if (klass == NULL) {206ResourceMark rm(current);207THROW(vmSymbols::java_lang_InstantiationException());208}209RetryableAllocationMark ram(current, null_on_fail);210211// Create new instance (the receiver)212klass->check_valid_for_instantiation(false, CHECK);213214if (null_on_fail) {215if (!klass->is_initialized()) {216// Cannot re-execute class initialization without side effects217// so return without attempting the initialization218return;219}220} else {221// Make sure klass gets initialized222klass->initialize(CHECK);223}224225oop obj = klass->allocate_instance(CHECK);226current->set_vm_result(obj);227JRT_END228229extern void vm_exit(int code);230231// Enter this method from compiled code handler below. This is where we transition232// to VM mode. This is done as a helper routine so that the method called directly233// from compiled code does not have to transition to VM. This allows the entry234// method to see if the nmethod that we have just looked up a handler for has235// been deoptimized while we were in the vm. This simplifies the assembly code236// cpu directories.237//238// We are entering here from exception stub (via the entry method below)239// If there is a compiled exception handler in this method, we will continue there;240// otherwise we will unwind the stack and continue at the caller of top frame method241// Note: we enter in Java using a special JRT wrapper. This wrapper allows us to242// control the area where we can allow a safepoint. After we exit the safepoint area we can243// check to see if the handler we are going to return is now in a nmethod that has244// been deoptimized. If that is the case we return the deopt blob245// unpack_with_exception entry instead. This makes life for the exception blob easier246// because making that same check and diverting is painful from assembly language.247JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, CompiledMethod*& cm))248// Reset method handle flag.249current->set_is_method_handle_return(false);250251Handle exception(current, ex);252cm = CodeCache::find_compiled(pc);253assert(cm != NULL, "this is not a compiled method");254// Adjust the pc as needed/255if (cm->is_deopt_pc(pc)) {256RegisterMap map(current, false);257frame exception_frame = current->last_frame().sender(&map);258// if the frame isn't deopted then pc must not correspond to the caller of last_frame259assert(exception_frame.is_deoptimized_frame(), "must be deopted");260pc = exception_frame.pc();261}262assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");263assert(oopDesc::is_oop(exception()), "just checking");264// Check that exception is a subclass of Throwable265assert(exception->is_a(vmClasses::Throwable_klass()),266"Exception not subclass of Throwable");267268// debugging support269// tracing270if (log_is_enabled(Info, exceptions)) {271ResourceMark rm;272stringStream tempst;273assert(cm->method() != NULL, "Unexpected null method()");274tempst.print("JVMCI compiled method <%s>\n"275" at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,276cm->method()->print_value_string(), p2i(pc), p2i(current));277Exceptions::log_exception(exception, tempst.as_string());278}279// for AbortVMOnException flag280Exceptions::debug_check_abort(exception);281282// Check the stack guard pages and reenable them if necessary and there is283// enough space on the stack to do so. Use fast exceptions only if the guard284// pages are enabled.285bool guard_pages_enabled = current->stack_overflow_state()->reguard_stack_if_needed();286287if (JvmtiExport::can_post_on_exceptions()) {288// To ensure correct notification of exception catches and throws289// we have to deoptimize here. If we attempted to notify the290// catches and throws during this exception lookup it's possible291// we could deoptimize on the way out of the VM and end back in292// the interpreter at the throw site. This would result in double293// notifications since the interpreter would also notify about294// these same catches and throws as it unwound the frame.295296RegisterMap reg_map(current);297frame stub_frame = current->last_frame();298frame caller_frame = stub_frame.sender(®_map);299300// We don't really want to deoptimize the nmethod itself since we301// can actually continue in the exception handler ourselves but I302// don't see an easy way to have the desired effect.303Deoptimization::deoptimize_frame(current, caller_frame.id(), Deoptimization::Reason_constraint);304assert(caller_is_deopted(), "Must be deoptimized");305306return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();307}308309// ExceptionCache is used only for exceptions at call sites and not for implicit exceptions310if (guard_pages_enabled) {311address fast_continuation = cm->handler_for_exception_and_pc(exception, pc);312if (fast_continuation != NULL) {313// Set flag if return address is a method handle call site.314current->set_is_method_handle_return(cm->is_method_handle_return(pc));315return fast_continuation;316}317}318319// If the stack guard pages are enabled, check whether there is a handler in320// the current method. Otherwise (guard pages disabled), force an unwind and321// skip the exception cache update (i.e., just leave continuation==NULL).322address continuation = NULL;323if (guard_pages_enabled) {324325// New exception handling mechanism can support inlined methods326// with exception handlers since the mappings are from PC to PC327328// Clear out the exception oop and pc since looking up an329// exception handler can cause class loading, which might throw an330// exception and those fields are expected to be clear during331// normal bytecode execution.332current->clear_exception_oop_and_pc();333334bool recursive_exception = false;335continuation = SharedRuntime::compute_compiled_exc_handler(cm, pc, exception, false, false, recursive_exception);336// If an exception was thrown during exception dispatch, the exception oop may have changed337current->set_exception_oop(exception());338current->set_exception_pc(pc);339340// The exception cache is used only for non-implicit exceptions341// Update the exception cache only when another exception did342// occur during the computation of the compiled exception handler343// (e.g., when loading the class of the catch type).344// Checking for exception oop equality is not345// sufficient because some exceptions are pre-allocated and reused.346if (continuation != NULL && !recursive_exception && !SharedRuntime::deopt_blob()->contains(continuation)) {347cm->add_handler_for_exception_and_pc(exception, pc, continuation);348}349}350351// Set flag if return address is a method handle call site.352current->set_is_method_handle_return(cm->is_method_handle_return(pc));353354if (log_is_enabled(Info, exceptions)) {355ResourceMark rm;356log_info(exceptions)("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT357" for exception thrown at PC " PTR_FORMAT,358p2i(current), p2i(continuation), p2i(pc));359}360361return continuation;362JRT_END363364// Enter this method from compiled code only if there is a Java exception handler365// in the method handling the exception.366// We are entering here from exception stub. We don't do a normal VM transition here.367// We do it in a helper. This is so we can check to see if the nmethod we have just368// searched for an exception handler has been deoptimized in the meantime.369address JVMCIRuntime::exception_handler_for_pc(JavaThread* current) {370oop exception = current->exception_oop();371address pc = current->exception_pc();372// Still in Java mode373DEBUG_ONLY(NoHandleMark nhm);374CompiledMethod* cm = NULL;375address continuation = NULL;376{377// Enter VM mode by calling the helper378ResetNoHandleMark rnhm;379continuation = exception_handler_for_pc_helper(current, exception, pc, cm);380}381// Back in JAVA, use no oops DON'T safepoint382383// Now check to see if the compiled method we were called from is now deoptimized.384// If so we must return to the deopt blob and deoptimize the nmethod385if (cm != NULL && caller_is_deopted()) {386continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();387}388389assert(continuation != NULL, "no handler found");390return continuation;391}392393JRT_BLOCK_ENTRY(void, JVMCIRuntime::monitorenter(JavaThread* current, oopDesc* obj, BasicLock* lock))394SharedRuntime::monitor_enter_helper(obj, lock, current);395JRT_END396397JRT_LEAF(void, JVMCIRuntime::monitorexit(JavaThread* current, oopDesc* obj, BasicLock* lock))398assert(current->last_Java_sp(), "last_Java_sp must be set");399assert(oopDesc::is_oop(obj), "invalid lock object pointer dected");400SharedRuntime::monitor_exit_helper(obj, lock, current);401JRT_END402403// Object.notify() fast path, caller does slow path404JRT_LEAF(jboolean, JVMCIRuntime::object_notify(JavaThread* current, oopDesc* obj))405406// Very few notify/notifyAll operations find any threads on the waitset, so407// the dominant fast-path is to simply return.408// Relatedly, it's critical that notify/notifyAll be fast in order to409// reduce lock hold times.410if (!SafepointSynchronize::is_synchronizing()) {411if (ObjectSynchronizer::quick_notify(obj, current, false)) {412return true;413}414}415return false; // caller must perform slow path416417JRT_END418419// Object.notifyAll() fast path, caller does slow path420JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread* current, oopDesc* obj))421422if (!SafepointSynchronize::is_synchronizing() ) {423if (ObjectSynchronizer::quick_notify(obj, current, true)) {424return true;425}426}427return false; // caller must perform slow path428429JRT_END430431JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* current, const char* exception, const char* message))432JRT_BLOCK;433TempNewSymbol symbol = SymbolTable::new_symbol(exception);434SharedRuntime::throw_and_post_jvmti_exception(current, symbol, message);435JRT_BLOCK_END;436return caller_is_deopted();437JRT_END438439JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_klass_external_name_exception(JavaThread* current, const char* exception, Klass* klass))440JRT_BLOCK;441ResourceMark rm(current);442TempNewSymbol symbol = SymbolTable::new_symbol(exception);443SharedRuntime::throw_and_post_jvmti_exception(current, symbol, klass->external_name());444JRT_BLOCK_END;445return caller_is_deopted();446JRT_END447448JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_class_cast_exception(JavaThread* current, const char* exception, Klass* caster_klass, Klass* target_klass))449JRT_BLOCK;450ResourceMark rm(current);451const char* message = SharedRuntime::generate_class_cast_message(caster_klass, target_klass);452TempNewSymbol symbol = SymbolTable::new_symbol(exception);453SharedRuntime::throw_and_post_jvmti_exception(current, symbol, message);454JRT_BLOCK_END;455return caller_is_deopted();456JRT_END457458class ArgumentPusher : public SignatureIterator {459protected:460JavaCallArguments* _jca;461jlong _argument;462bool _pushed;463464jlong next_arg() {465guarantee(!_pushed, "one argument");466_pushed = true;467return _argument;468}469470float next_float() {471guarantee(!_pushed, "one argument");472_pushed = true;473jvalue v;474v.i = (jint) _argument;475return v.f;476}477478double next_double() {479guarantee(!_pushed, "one argument");480_pushed = true;481jvalue v;482v.j = _argument;483return v.d;484}485486Handle next_object() {487guarantee(!_pushed, "one argument");488_pushed = true;489return Handle(Thread::current(), cast_to_oop(_argument));490}491492public:493ArgumentPusher(Symbol* signature, JavaCallArguments* jca, jlong argument) : SignatureIterator(signature) {494this->_return_type = T_ILLEGAL;495_jca = jca;496_argument = argument;497_pushed = false;498do_parameters_on(this);499}500501void do_type(BasicType type) {502switch (type) {503case T_OBJECT:504case T_ARRAY: _jca->push_oop(next_object()); break;505case T_BOOLEAN: _jca->push_int((jboolean) next_arg()); break;506case T_CHAR: _jca->push_int((jchar) next_arg()); break;507case T_SHORT: _jca->push_int((jint) next_arg()); break;508case T_BYTE: _jca->push_int((jbyte) next_arg()); break;509case T_INT: _jca->push_int((jint) next_arg()); break;510case T_LONG: _jca->push_long((jlong) next_arg()); break;511case T_FLOAT: _jca->push_float(next_float()); break;512case T_DOUBLE: _jca->push_double(next_double()); break;513default: fatal("Unexpected type %s", type2name(type));514}515}516};517518519JRT_ENTRY(jlong, JVMCIRuntime::invoke_static_method_one_arg(JavaThread* current, Method* method, jlong argument))520ResourceMark rm;521HandleMark hm(current);522523methodHandle mh(current, method);524if (mh->size_of_parameters() > 1 && !mh->is_static()) {525THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Invoked method must be static and take at most one argument");526}527528Symbol* signature = mh->signature();529JavaCallArguments jca(mh->size_of_parameters());530ArgumentPusher jap(signature, &jca, argument);531BasicType return_type = jap.return_type();532JavaValue result(return_type);533JavaCalls::call(&result, mh, &jca, CHECK_0);534535if (return_type == T_VOID) {536return 0;537} else if (return_type == T_OBJECT || return_type == T_ARRAY) {538current->set_vm_result(result.get_oop());539return 0;540} else {541jvalue *value = (jvalue *) result.get_value_addr();542// Narrow the value down if required (Important on big endian machines)543switch (return_type) {544case T_BOOLEAN:545return (jboolean) value->i;546case T_BYTE:547return (jbyte) value->i;548case T_CHAR:549return (jchar) value->i;550case T_SHORT:551return (jshort) value->i;552case T_INT:553case T_FLOAT:554return value->i;555case T_LONG:556case T_DOUBLE:557return value->j;558default:559fatal("Unexpected type %s", type2name(return_type));560return 0;561}562}563JRT_END564565JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline))566ttyLocker ttyl;567568if (obj == NULL) {569tty->print("NULL");570} else if (oopDesc::is_oop_or_null(obj, true) && (!as_string || !java_lang_String::is_instance(obj))) {571if (oopDesc::is_oop_or_null(obj, true)) {572char buf[O_BUFLEN];573tty->print("%s@" INTPTR_FORMAT, obj->klass()->name()->as_C_string(buf, O_BUFLEN), p2i(obj));574} else {575tty->print(INTPTR_FORMAT, p2i(obj));576}577} else {578ResourceMark rm;579assert(obj != NULL && java_lang_String::is_instance(obj), "must be");580char *buf = java_lang_String::as_utf8_string(obj);581tty->print_raw(buf);582}583if (newline) {584tty->cr();585}586JRT_END587588#if INCLUDE_G1GC589590void JVMCIRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj) {591G1BarrierSetRuntime::write_ref_field_pre_entry(obj, thread);592}593594void JVMCIRuntime::write_barrier_post(JavaThread* thread, volatile CardValue* card_addr) {595G1BarrierSetRuntime::write_ref_field_post_entry(card_addr, thread);596}597598#endif // INCLUDE_G1GC599600JRT_LEAF(jboolean, JVMCIRuntime::validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child))601bool ret = true;602if(!Universe::heap()->is_in(parent)) {603tty->print_cr("Parent Object " INTPTR_FORMAT " not in heap", p2i(parent));604parent->print();605ret=false;606}607if(!Universe::heap()->is_in(child)) {608tty->print_cr("Child Object " INTPTR_FORMAT " not in heap", p2i(child));609child->print();610ret=false;611}612return (jint)ret;613JRT_END614615JRT_ENTRY(void, JVMCIRuntime::vm_error(JavaThread* current, jlong where, jlong format, jlong value))616ResourceMark rm(current);617const char *error_msg = where == 0L ? "<internal JVMCI error>" : (char*) (address) where;618char *detail_msg = NULL;619if (format != 0L) {620const char* buf = (char*) (address) format;621size_t detail_msg_length = strlen(buf) * 2;622detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);623jio_snprintf(detail_msg, detail_msg_length, buf, value);624}625report_vm_error(__FILE__, __LINE__, error_msg, "%s", detail_msg);626JRT_END627628JRT_LEAF(oopDesc*, JVMCIRuntime::load_and_clear_exception(JavaThread* thread))629oop exception = thread->exception_oop();630assert(exception != NULL, "npe");631thread->set_exception_oop(NULL);632thread->set_exception_pc(0);633return exception;634JRT_END635636PRAGMA_DIAG_PUSH637PRAGMA_FORMAT_NONLITERAL_IGNORED638JRT_LEAF(void, JVMCIRuntime::log_printf(JavaThread* thread, const char* format, jlong v1, jlong v2, jlong v3))639ResourceMark rm;640tty->print(format, v1, v2, v3);641JRT_END642PRAGMA_DIAG_POP643644static void decipher(jlong v, bool ignoreZero) {645if (v != 0 || !ignoreZero) {646void* p = (void *)(address) v;647CodeBlob* cb = CodeCache::find_blob(p);648if (cb) {649if (cb->is_nmethod()) {650char buf[O_BUFLEN];651tty->print("%s [" INTPTR_FORMAT "+" JLONG_FORMAT "]", cb->as_nmethod_or_null()->method()->name_and_sig_as_C_string(buf, O_BUFLEN), p2i(cb->code_begin()), (jlong)((address)v - cb->code_begin()));652return;653}654cb->print_value_on(tty);655return;656}657if (Universe::heap()->is_in(p)) {658oop obj = cast_to_oop(p);659obj->print_value_on(tty);660return;661}662tty->print(INTPTR_FORMAT " [long: " JLONG_FORMAT ", double %lf, char %c]",p2i((void *)v), (jlong)v, (jdouble)v, (char)v);663}664}665666PRAGMA_DIAG_PUSH667PRAGMA_FORMAT_NONLITERAL_IGNORED668JRT_LEAF(void, JVMCIRuntime::vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3))669ResourceMark rm;670const char *buf = (const char*) (address) format;671if (vmError) {672if (buf != NULL) {673fatal(buf, v1, v2, v3);674} else {675fatal("<anonymous error>");676}677} else if (buf != NULL) {678tty->print(buf, v1, v2, v3);679} else {680assert(v2 == 0, "v2 != 0");681assert(v3 == 0, "v3 != 0");682decipher(v1, false);683}684JRT_END685PRAGMA_DIAG_POP686687JRT_LEAF(void, JVMCIRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))688union {689jlong l;690jdouble d;691jfloat f;692} uu;693uu.l = value;694switch (typeChar) {695case 'Z': tty->print(value == 0 ? "false" : "true"); break;696case 'B': tty->print("%d", (jbyte) value); break;697case 'C': tty->print("%c", (jchar) value); break;698case 'S': tty->print("%d", (jshort) value); break;699case 'I': tty->print("%d", (jint) value); break;700case 'F': tty->print("%f", uu.f); break;701case 'J': tty->print(JLONG_FORMAT, value); break;702case 'D': tty->print("%lf", uu.d); break;703default: assert(false, "unknown typeChar"); break;704}705if (newline) {706tty->cr();707}708JRT_END709710JRT_ENTRY(jint, JVMCIRuntime::identity_hash_code(JavaThread* current, oopDesc* obj))711return (jint) obj->identity_hash();712JRT_END713714JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* current, int value))715deopt_caller();716return (jint) value;717JRT_END718719720// private static JVMCIRuntime JVMCI.initializeRuntime()721JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))722JNI_JVMCIENV(thread, env);723if (!EnableJVMCI) {724JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");725}726JVMCIENV->runtime()->initialize_HotSpotJVMCIRuntime(JVMCI_CHECK_NULL);727JVMCIObject runtime = JVMCIENV->runtime()->get_HotSpotJVMCIRuntime(JVMCI_CHECK_NULL);728return JVMCIENV->get_jobject(runtime);729JVM_END730731void JVMCIRuntime::call_getCompiler(TRAPS) {732THREAD_JVMCIENV(JavaThread::current());733JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK);734initialize(JVMCIENV);735JVMCIENV->call_HotSpotJVMCIRuntime_getCompiler(jvmciRuntime, JVMCI_CHECK);736}737738void JVMCINMethodData::initialize(739int nmethod_mirror_index,740const char* name,741FailedSpeculation** failed_speculations)742{743_failed_speculations = failed_speculations;744_nmethod_mirror_index = nmethod_mirror_index;745if (name != NULL) {746_has_name = true;747char* dest = (char*) this->name();748strcpy(dest, name);749} else {750_has_name = false;751}752}753754void JVMCINMethodData::add_failed_speculation(nmethod* nm, jlong speculation) {755jlong index = speculation >> JVMCINMethodData::SPECULATION_LENGTH_BITS;756guarantee(index >= 0 && index <= max_jint, "Encoded JVMCI speculation index is not a positive Java int: " INTPTR_FORMAT, index);757int length = speculation & JVMCINMethodData::SPECULATION_LENGTH_MASK;758if (index + length > (uint) nm->speculations_size()) {759fatal(INTPTR_FORMAT "[index: " JLONG_FORMAT ", length: %d out of bounds wrt encoded speculations of length %u", speculation, index, length, nm->speculations_size());760}761address data = nm->speculations_begin() + index;762FailedSpeculation::add_failed_speculation(nm, _failed_speculations, data, length);763}764765oop JVMCINMethodData::get_nmethod_mirror(nmethod* nm, bool phantom_ref) {766if (_nmethod_mirror_index == -1) {767return NULL;768}769if (phantom_ref) {770return nm->oop_at_phantom(_nmethod_mirror_index);771} else {772return nm->oop_at(_nmethod_mirror_index);773}774}775776void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {777assert(_nmethod_mirror_index != -1, "cannot set JVMCI mirror for nmethod");778oop* addr = nm->oop_addr_at(_nmethod_mirror_index);779assert(new_mirror != NULL, "use clear_nmethod_mirror to clear the mirror");780assert(*addr == NULL, "cannot overwrite non-null mirror");781782*addr = new_mirror;783784// Since we've patched some oops in the nmethod,785// (re)register it with the heap.786MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag);787Universe::heap()->register_nmethod(nm);788}789790void JVMCINMethodData::clear_nmethod_mirror(nmethod* nm) {791if (_nmethod_mirror_index != -1) {792oop* addr = nm->oop_addr_at(_nmethod_mirror_index);793*addr = NULL;794}795}796797void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {798oop nmethod_mirror = get_nmethod_mirror(nm, /* phantom_ref */ false);799if (nmethod_mirror == NULL) {800return;801}802803// Update the values in the mirror if it still refers to nm.804// We cannot use JVMCIObject to wrap the mirror as this is called805// during GC, forbidding the creation of JNIHandles.806JVMCIEnv* jvmciEnv = NULL;807nmethod* current = (nmethod*) HotSpotJVMCI::InstalledCode::address(jvmciEnv, nmethod_mirror);808if (nm == current) {809if (!nm->is_alive()) {810// Break the link from the mirror to nm such that811// future invocations via the mirror will result in812// an InvalidInstalledCodeException.813HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);814HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);815} else if (nm->is_not_entrant()) {816// Zero the entry point so any new invocation will fail but keep817// the address link around that so that existing activations can818// be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code).819HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);820}821}822823if (_nmethod_mirror_index != -1 && nm->is_unloaded()) {824// Drop the reference to the nmethod mirror object but don't clear the actual oop reference. Otherwise825// it would appear that the nmethod didn't need to be unloaded in the first place.826_nmethod_mirror_index = -1;827}828}829830JVMCIRuntime::JVMCIRuntime(int id) {831_init_state = uninitialized;832_shared_library_javavm = NULL;833_id = id;834_metadata_handles = new MetadataHandles();835JVMCI_event_1("created new JVMCI runtime %d (" PTR_FORMAT ")", id, p2i(this));836}837838// Handles to objects in the Hotspot heap.839static OopStorage* object_handles() {840return Universe::vm_global();841}842843jobject JVMCIRuntime::make_global(const Handle& obj) {844assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");845assert(oopDesc::is_oop(obj()), "not an oop");846oop* ptr = object_handles()->allocate();847jobject res = NULL;848if (ptr != NULL) {849assert(*ptr == NULL, "invariant");850NativeAccess<>::oop_store(ptr, obj());851res = reinterpret_cast<jobject>(ptr);852} else {853vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,854"Cannot create JVMCI oop handle");855}856MutexLocker ml(JVMCI_lock);857return res;858}859860void JVMCIRuntime::destroy_global(jobject handle) {861// Assert before nulling out, for better debugging.862assert(is_global_handle(handle), "precondition");863oop* oop_ptr = reinterpret_cast<oop*>(handle);864NativeAccess<>::oop_store(oop_ptr, (oop)NULL);865object_handles()->release(oop_ptr);866MutexLocker ml(JVMCI_lock);867}868869bool JVMCIRuntime::is_global_handle(jobject handle) {870const oop* ptr = reinterpret_cast<oop*>(handle);871return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;872}873874jmetadata JVMCIRuntime::allocate_handle(const methodHandle& handle) {875MutexLocker ml(JVMCI_lock);876return _metadata_handles->allocate_handle(handle);877}878879jmetadata JVMCIRuntime::allocate_handle(const constantPoolHandle& handle) {880MutexLocker ml(JVMCI_lock);881return _metadata_handles->allocate_handle(handle);882}883884void JVMCIRuntime::release_handle(jmetadata handle) {885MutexLocker ml(JVMCI_lock);886_metadata_handles->chain_free_list(handle);887}888889// Function for redirecting shared library JavaVM output to tty890static void _log(const char* buf, size_t count) {891tty->write((char*) buf, count);892}893894// Function for shared library JavaVM to flush tty895static void _flush_log() {896tty->flush();897}898899// Function for shared library JavaVM to exit HotSpot on a fatal error900static void _fatal() {901fatal("Fatal error in JVMCI shared library");902}903904JNIEnv* JVMCIRuntime::init_shared_library_javavm() {905JavaVM* javaVM = (JavaVM*) _shared_library_javavm;906if (javaVM == NULL) {907MutexLocker locker(JVMCI_lock);908// Check again under JVMCI_lock909javaVM = (JavaVM*) _shared_library_javavm;910if (javaVM != NULL) {911return NULL;912}913char* sl_path;914void* sl_handle = JVMCI::get_shared_library(sl_path, true);915916jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);917typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);918919JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(sl_handle, "JNI_CreateJavaVM"));920if (JNI_CreateJavaVM == NULL) {921fatal("Unable to find JNI_CreateJavaVM in %s", sl_path);922}923924ResourceMark rm;925JavaVMInitArgs vm_args;926vm_args.version = JNI_VERSION_1_2;927vm_args.ignoreUnrecognized = JNI_TRUE;928JavaVMOption options[4];929jlong javaVM_id = 0;930931// Protocol: JVMCI shared library JavaVM should support a non-standard "_javavm_id"932// option whose extraInfo info field is a pointer to which a unique id for the933// JavaVM should be written.934options[0].optionString = (char*) "_javavm_id";935options[0].extraInfo = &javaVM_id;936937options[1].optionString = (char*) "_log";938options[1].extraInfo = (void*) _log;939options[2].optionString = (char*) "_flush_log";940options[2].extraInfo = (void*) _flush_log;941options[3].optionString = (char*) "_fatal";942options[3].extraInfo = (void*) _fatal;943944vm_args.version = JNI_VERSION_1_2;945vm_args.options = options;946vm_args.nOptions = sizeof(options) / sizeof(JavaVMOption);947948JNIEnv* env = NULL;949int result = (*JNI_CreateJavaVM)(&javaVM, (void**) &env, &vm_args);950if (result == JNI_OK) {951guarantee(env != NULL, "missing env");952_shared_library_javavm = javaVM;953JVMCI_event_1("created JavaVM[%ld]@" PTR_FORMAT " for JVMCI runtime %d", javaVM_id, p2i(javaVM), _id);954return env;955} else {956fatal("JNI_CreateJavaVM failed with return value %d", result);957}958}959return NULL;960}961962void JVMCIRuntime::init_JavaVM_info(jlongArray info, JVMCI_TRAPS) {963if (info != NULL) {964typeArrayOop info_oop = (typeArrayOop) JNIHandles::resolve(info);965if (info_oop->length() < 4) {966JVMCI_THROW_MSG(ArrayIndexOutOfBoundsException, err_msg("%d < 4", info_oop->length()));967}968JavaVM* javaVM = (JavaVM*) _shared_library_javavm;969info_oop->long_at_put(0, (jlong) (address) javaVM);970info_oop->long_at_put(1, (jlong) (address) javaVM->functions->reserved0);971info_oop->long_at_put(2, (jlong) (address) javaVM->functions->reserved1);972info_oop->long_at_put(3, (jlong) (address) javaVM->functions->reserved2);973}974}975976#define JAVAVM_CALL_BLOCK \977guarantee(thread != NULL && _shared_library_javavm != NULL, "npe"); \978ThreadToNativeFromVM ttnfv(thread); \979JavaVM* javavm = (JavaVM*) _shared_library_javavm;980981jint JVMCIRuntime::AttachCurrentThread(JavaThread* thread, void **penv, void *args) {982JAVAVM_CALL_BLOCK983return javavm->AttachCurrentThread(penv, args);984}985986jint JVMCIRuntime::AttachCurrentThreadAsDaemon(JavaThread* thread, void **penv, void *args) {987JAVAVM_CALL_BLOCK988return javavm->AttachCurrentThreadAsDaemon(penv, args);989}990991jint JVMCIRuntime::DetachCurrentThread(JavaThread* thread) {992JAVAVM_CALL_BLOCK993return javavm->DetachCurrentThread();994}995996jint JVMCIRuntime::GetEnv(JavaThread* thread, void **penv, jint version) {997JAVAVM_CALL_BLOCK998return javavm->GetEnv(penv, version);999}1000#undef JAVAVM_CALL_BLOCK \10011002void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) {1003if (is_HotSpotJVMCIRuntime_initialized()) {1004if (JVMCIENV->is_hotspot() && UseJVMCINativeLibrary) {1005JVMCI_THROW_MSG(InternalError, "JVMCI has already been enabled in the JVMCI shared library");1006}1007}10081009initialize(JVMCIENV);10101011// This should only be called in the context of the JVMCI class being initialized1012JVMCIObject result = JVMCIENV->call_HotSpotJVMCIRuntime_runtime(JVMCI_CHECK);1013result = JVMCIENV->make_global(result);10141015OrderAccess::storestore(); // Ensure handle is fully constructed before publishing1016_HotSpotJVMCIRuntime_instance = result;10171018JVMCI::_is_initialized = true;1019}10201021void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) {1022// Check first without JVMCI_lock1023if (_init_state == fully_initialized) {1024return;1025}10261027MutexLocker locker(JVMCI_lock);1028// Check again under JVMCI_lock1029if (_init_state == fully_initialized) {1030return;1031}10321033while (_init_state == being_initialized) {1034JVMCI_event_1("waiting for initialization of JVMCI runtime %d", _id);1035JVMCI_lock->wait();1036if (_init_state == fully_initialized) {1037JVMCI_event_1("done waiting for initialization of JVMCI runtime %d", _id);1038return;1039}1040}10411042JVMCI_event_1("initializing JVMCI runtime %d", _id);1043_init_state = being_initialized;10441045{1046MutexUnlocker unlock(JVMCI_lock);10471048JavaThread* THREAD = JavaThread::current(); // For exception macros.1049HandleMark hm(THREAD);1050ResourceMark rm(THREAD);1051if (JVMCIENV->is_hotspot()) {1052HotSpotJVMCI::compute_offsets(CHECK_EXIT);1053} else {1054JNIAccessMark jni(JVMCIENV);10551056JNIJVMCI::initialize_ids(jni.env());1057if (jni()->ExceptionCheck()) {1058jni()->ExceptionDescribe();1059fatal("JNI exception during init");1060}1061}10621063if (!JVMCIENV->is_hotspot()) {1064JNIAccessMark jni(JVMCIENV, THREAD);1065JNIJVMCI::register_natives(jni.env());1066}1067create_jvmci_primitive_type(T_BOOLEAN, JVMCI_CHECK_EXIT_((void)0));1068create_jvmci_primitive_type(T_BYTE, JVMCI_CHECK_EXIT_((void)0));1069create_jvmci_primitive_type(T_CHAR, JVMCI_CHECK_EXIT_((void)0));1070create_jvmci_primitive_type(T_SHORT, JVMCI_CHECK_EXIT_((void)0));1071create_jvmci_primitive_type(T_INT, JVMCI_CHECK_EXIT_((void)0));1072create_jvmci_primitive_type(T_LONG, JVMCI_CHECK_EXIT_((void)0));1073create_jvmci_primitive_type(T_FLOAT, JVMCI_CHECK_EXIT_((void)0));1074create_jvmci_primitive_type(T_DOUBLE, JVMCI_CHECK_EXIT_((void)0));1075create_jvmci_primitive_type(T_VOID, JVMCI_CHECK_EXIT_((void)0));10761077if (!JVMCIENV->is_hotspot()) {1078JVMCIENV->copy_saved_properties();1079}1080}10811082_init_state = fully_initialized;1083JVMCI_event_1("initialized JVMCI runtime %d", _id);1084JVMCI_lock->notify_all();1085}10861087JVMCIObject JVMCIRuntime::create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS) {1088JavaThread* THREAD = JavaThread::current(); // For exception macros.1089// These primitive types are long lived and are created before the runtime is fully set up1090// so skip registering them for scanning.1091JVMCIObject mirror = JVMCIENV->get_object_constant(java_lang_Class::primitive_mirror(type), false, true);1092if (JVMCIENV->is_hotspot()) {1093JavaValue result(T_OBJECT);1094JavaCallArguments args;1095args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(mirror)));1096args.push_int(type2char(type));1097JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedPrimitiveType::klass(), vmSymbols::fromMetaspace_name(), vmSymbols::primitive_fromMetaspace_signature(), &args, CHECK_(JVMCIObject()));10981099return JVMCIENV->wrap(JNIHandles::make_local(result.get_oop()));1100} else {1101JNIAccessMark jni(JVMCIENV);1102jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedPrimitiveType::clazz(),1103JNIJVMCI::HotSpotResolvedPrimitiveType_fromMetaspace_method(),1104mirror.as_jobject(), type2char(type));1105if (jni()->ExceptionCheck()) {1106return JVMCIObject();1107}1108return JVMCIENV->wrap(result);1109}1110}11111112void JVMCIRuntime::initialize_JVMCI(JVMCI_TRAPS) {1113if (!is_HotSpotJVMCIRuntime_initialized()) {1114initialize(JVMCI_CHECK);1115JVMCIENV->call_JVMCI_getRuntime(JVMCI_CHECK);1116}1117}11181119JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) {1120initialize(JVMCIENV);1121initialize_JVMCI(JVMCI_CHECK_(JVMCIObject()));1122return _HotSpotJVMCIRuntime_instance;1123}11241125// private static void CompilerToVM.registerNatives()1126JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))1127JNI_JVMCIENV(thread, env);11281129if (!EnableJVMCI) {1130JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");1131}11321133JVMCIENV->runtime()->initialize(JVMCIENV);11341135{1136ResourceMark rm(thread);1137HandleMark hm(thread);1138ThreadToNativeFromVM trans(thread);11391140// Ensure _non_oop_bits is initialized1141Universe::non_oop_word();11421143if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count())) {1144if (!env->ExceptionCheck()) {1145for (int i = 0; i < CompilerToVM::methods_count(); i++) {1146if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods + i, 1)) {1147guarantee(false, "Error registering JNI method %s%s", CompilerToVM::methods[i].name, CompilerToVM::methods[i].signature);1148break;1149}1150}1151} else {1152env->ExceptionDescribe();1153}1154guarantee(false, "Failed registering CompilerToVM native methods");1155}1156}1157JVM_END115811591160void JVMCIRuntime::shutdown() {1161if (_HotSpotJVMCIRuntime_instance.is_non_null()) {1162JVMCI_event_1("shutting down HotSpotJVMCIRuntime for JVMCI runtime %d", _id);1163JVMCIEnv __stack_jvmci_env__(JavaThread::current(), _HotSpotJVMCIRuntime_instance.is_hotspot(), __FILE__, __LINE__);1164JVMCIEnv* JVMCIENV = &__stack_jvmci_env__;1165JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance);1166JVMCI_event_1("shut down HotSpotJVMCIRuntime for JVMCI runtime %d", _id);1167}1168}11691170void JVMCIRuntime::bootstrap_finished(TRAPS) {1171if (_HotSpotJVMCIRuntime_instance.is_non_null()) {1172THREAD_JVMCIENV(JavaThread::current());1173JVMCIENV->call_HotSpotJVMCIRuntime_bootstrapFinished(_HotSpotJVMCIRuntime_instance, JVMCIENV);1174}1175}11761177void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool clear) {1178if (HAS_PENDING_EXCEPTION) {1179Handle exception(THREAD, PENDING_EXCEPTION);1180const char* exception_file = THREAD->exception_file();1181int exception_line = THREAD->exception_line();1182CLEAR_PENDING_EXCEPTION;1183if (exception->is_a(vmClasses::ThreadDeath_klass())) {1184// Don't print anything if we are being killed.1185} else {1186java_lang_Throwable::print_stack_trace(exception, tty);11871188// Clear and ignore any exceptions raised during printing1189CLEAR_PENDING_EXCEPTION;1190}1191if (!clear) {1192THREAD->set_pending_exception(exception(), exception_file, exception_line);1193}1194}1195}119611971198void JVMCIRuntime::fatal_exception(JVMCIEnv* JVMCIENV, const char* message) {1199JavaThread* THREAD = JavaThread::current(); // For exception macros.12001201static volatile int report_error = 0;1202if (!report_error && Atomic::cmpxchg(&report_error, 0, 1) == 0) {1203// Only report an error once1204tty->print_raw_cr(message);1205if (JVMCIENV != NULL) {1206JVMCIENV->describe_pending_exception(true);1207} else {1208describe_pending_hotspot_exception(THREAD, true);1209}1210} else {1211// Allow error reporting thread to print the stack trace.1212THREAD->sleep(200);1213}1214fatal("Fatal exception in JVMCI: %s", message);1215}12161217// ------------------------------------------------------------------1218// Note: the logic of this method should mirror the logic of1219// constantPoolOopDesc::verify_constant_pool_resolve.1220bool JVMCIRuntime::check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass) {1221if (accessing_klass->is_objArray_klass()) {1222accessing_klass = ObjArrayKlass::cast(accessing_klass)->bottom_klass();1223}1224if (!accessing_klass->is_instance_klass()) {1225return true;1226}12271228if (resolved_klass->is_objArray_klass()) {1229// Find the element klass, if this is an array.1230resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();1231}1232if (resolved_klass->is_instance_klass()) {1233Reflection::VerifyClassAccessResults result =1234Reflection::verify_class_access(accessing_klass, InstanceKlass::cast(resolved_klass), true);1235return result == Reflection::ACCESS_OK;1236}1237return true;1238}12391240// ------------------------------------------------------------------1241Klass* JVMCIRuntime::get_klass_by_name_impl(Klass*& accessing_klass,1242const constantPoolHandle& cpool,1243Symbol* sym,1244bool require_local) {1245JVMCI_EXCEPTION_CONTEXT;12461247// Now we need to check the SystemDictionary1248if (sym->char_at(0) == JVM_SIGNATURE_CLASS &&1249sym->char_at(sym->utf8_length()-1) == JVM_SIGNATURE_ENDCLASS) {1250// This is a name from a signature. Strip off the trimmings.1251// Call recursive to keep scope of strippedsym.1252TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,1253sym->utf8_length()-2);1254return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local);1255}12561257Handle loader;1258Handle domain;1259if (accessing_klass != NULL) {1260loader = Handle(THREAD, accessing_klass->class_loader());1261domain = Handle(THREAD, accessing_klass->protection_domain());1262}12631264Klass* found_klass;1265{1266ttyUnlocker ttyul; // release tty lock to avoid ordering problems1267MutexLocker ml(THREAD, Compile_lock);1268if (!require_local) {1269found_klass = SystemDictionary::find_constrained_instance_or_array_klass(THREAD, sym, loader);1270} else {1271found_klass = SystemDictionary::find_instance_or_array_klass(sym, loader, domain);1272}1273}12741275// If we fail to find an array klass, look again for its element type.1276// The element type may be available either locally or via constraints.1277// In either case, if we can find the element type in the system dictionary,1278// we must build an array type around it. The CI requires array klasses1279// to be loaded if their element klasses are loaded, except when memory1280// is exhausted.1281if (sym->char_at(0) == JVM_SIGNATURE_ARRAY &&1282(sym->char_at(1) == JVM_SIGNATURE_ARRAY || sym->char_at(1) == JVM_SIGNATURE_CLASS)) {1283// We have an unloaded array.1284// Build it on the fly if the element class exists.1285TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,1286sym->utf8_length()-1);12871288// Get element Klass recursively.1289Klass* elem_klass =1290get_klass_by_name_impl(accessing_klass,1291cpool,1292elem_sym,1293require_local);1294if (elem_klass != NULL) {1295// Now make an array for it1296return elem_klass->array_klass(THREAD);1297}1298}12991300if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) {1301// Look inside the constant pool for pre-resolved class entries.1302for (int i = cpool->length() - 1; i >= 1; i--) {1303if (cpool->tag_at(i).is_klass()) {1304Klass* kls = cpool->resolved_klass_at(i);1305if (kls->name() == sym) {1306return kls;1307}1308}1309}1310}13111312return found_klass;1313}13141315// ------------------------------------------------------------------1316Klass* JVMCIRuntime::get_klass_by_name(Klass* accessing_klass,1317Symbol* klass_name,1318bool require_local) {1319ResourceMark rm;1320constantPoolHandle cpool;1321return get_klass_by_name_impl(accessing_klass,1322cpool,1323klass_name,1324require_local);1325}13261327// ------------------------------------------------------------------1328// Implementation of get_klass_by_index.1329Klass* JVMCIRuntime::get_klass_by_index_impl(const constantPoolHandle& cpool,1330int index,1331bool& is_accessible,1332Klass* accessor) {1333JVMCI_EXCEPTION_CONTEXT;1334Klass* klass = ConstantPool::klass_at_if_loaded(cpool, index);1335Symbol* klass_name = NULL;1336if (klass == NULL) {1337klass_name = cpool->klass_name_at(index);1338}13391340if (klass == NULL) {1341// Not found in constant pool. Use the name to do the lookup.1342Klass* k = get_klass_by_name_impl(accessor,1343cpool,1344klass_name,1345false);1346// Calculate accessibility the hard way.1347if (k == NULL) {1348is_accessible = false;1349} else if (k->class_loader() != accessor->class_loader() &&1350get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) {1351// Loaded only remotely. Not linked yet.1352is_accessible = false;1353} else {1354// Linked locally, and we must also check public/private, etc.1355is_accessible = check_klass_accessibility(accessor, k);1356}1357if (!is_accessible) {1358return NULL;1359}1360return k;1361}13621363// It is known to be accessible, since it was found in the constant pool.1364is_accessible = true;1365return klass;1366}13671368// ------------------------------------------------------------------1369// Get a klass from the constant pool.1370Klass* JVMCIRuntime::get_klass_by_index(const constantPoolHandle& cpool,1371int index,1372bool& is_accessible,1373Klass* accessor) {1374ResourceMark rm;1375Klass* result = get_klass_by_index_impl(cpool, index, is_accessible, accessor);1376return result;1377}13781379// ------------------------------------------------------------------1380// Implementation of get_field_by_index.1381//1382// Implementation note: the results of field lookups are cached1383// in the accessor klass.1384void JVMCIRuntime::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc,1385int index) {1386JVMCI_EXCEPTION_CONTEXT;13871388assert(klass->is_linked(), "must be linked before using its constant-pool");13891390constantPoolHandle cpool(thread, klass->constants());13911392// Get the field's name, signature, and type.1393Symbol* name = cpool->name_ref_at(index);13941395int nt_index = cpool->name_and_type_ref_index_at(index);1396int sig_index = cpool->signature_ref_index_at(nt_index);1397Symbol* signature = cpool->symbol_at(sig_index);13981399// Get the field's declared holder.1400int holder_index = cpool->klass_ref_index_at(index);1401bool holder_is_accessible;1402Klass* declared_holder = get_klass_by_index(cpool, holder_index,1403holder_is_accessible,1404klass);14051406// The declared holder of this field may not have been loaded.1407// Bail out with partial field information.1408if (!holder_is_accessible) {1409return;1410}141114121413// Perform the field lookup.1414Klass* canonical_holder =1415InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc);1416if (canonical_holder == NULL) {1417return;1418}14191420assert(canonical_holder == field_desc.field_holder(), "just checking");1421}14221423// ------------------------------------------------------------------1424// Get a field by index from a klass's constant pool.1425void JVMCIRuntime::get_field_by_index(InstanceKlass* accessor, fieldDescriptor& fd, int index) {1426ResourceMark rm;1427return get_field_by_index_impl(accessor, fd, index);1428}14291430// ------------------------------------------------------------------1431// Perform an appropriate method lookup based on accessor, holder,1432// name, signature, and bytecode.1433Method* JVMCIRuntime::lookup_method(InstanceKlass* accessor,1434Klass* holder,1435Symbol* name,1436Symbol* sig,1437Bytecodes::Code bc,1438constantTag tag) {1439// Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl().1440assert(check_klass_accessibility(accessor, holder), "holder not accessible");14411442LinkInfo link_info(holder, name, sig, accessor,1443LinkInfo::AccessCheck::required,1444LinkInfo::LoaderConstraintCheck::required,1445tag);1446switch (bc) {1447case Bytecodes::_invokestatic:1448return LinkResolver::resolve_static_call_or_null(link_info);1449case Bytecodes::_invokespecial:1450return LinkResolver::resolve_special_call_or_null(link_info);1451case Bytecodes::_invokeinterface:1452return LinkResolver::linktime_resolve_interface_method_or_null(link_info);1453case Bytecodes::_invokevirtual:1454return LinkResolver::linktime_resolve_virtual_method_or_null(link_info);1455default:1456fatal("Unhandled bytecode: %s", Bytecodes::name(bc));1457return NULL; // silence compiler warnings1458}1459}146014611462// ------------------------------------------------------------------1463Method* JVMCIRuntime::get_method_by_index_impl(const constantPoolHandle& cpool,1464int index, Bytecodes::Code bc,1465InstanceKlass* accessor) {1466if (bc == Bytecodes::_invokedynamic) {1467ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);1468bool is_resolved = !cpce->is_f1_null();1469if (is_resolved) {1470// Get the invoker Method* from the constant pool.1471// (The appendix argument, if any, will be noted in the method's signature.)1472Method* adapter = cpce->f1_as_method();1473return adapter;1474}14751476return NULL;1477}14781479int holder_index = cpool->klass_ref_index_at(index);1480bool holder_is_accessible;1481Klass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);14821483// Get the method's name and signature.1484Symbol* name_sym = cpool->name_ref_at(index);1485Symbol* sig_sym = cpool->signature_ref_at(index);14861487if (cpool->has_preresolution()1488|| ((holder == vmClasses::MethodHandle_klass() || holder == vmClasses::VarHandle_klass()) &&1489MethodHandles::is_signature_polymorphic_name(holder, name_sym))) {1490// Short-circuit lookups for JSR 292-related call sites.1491// That is, do not rely only on name-based lookups, because they may fail1492// if the names are not resolvable in the boot class loader (7056328).1493switch (bc) {1494case Bytecodes::_invokevirtual:1495case Bytecodes::_invokeinterface:1496case Bytecodes::_invokespecial:1497case Bytecodes::_invokestatic:1498{1499Method* m = ConstantPool::method_at_if_loaded(cpool, index);1500if (m != NULL) {1501return m;1502}1503}1504break;1505default:1506break;1507}1508}15091510if (holder_is_accessible) { // Our declared holder is loaded.1511constantTag tag = cpool->tag_ref_at(index);1512Method* m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag);1513if (m != NULL) {1514// We found the method.1515return m;1516}1517}15181519// Either the declared holder was not loaded, or the method could1520// not be found.15211522return NULL;1523}15241525// ------------------------------------------------------------------1526InstanceKlass* JVMCIRuntime::get_instance_klass_for_declared_method_holder(Klass* method_holder) {1527// For the case of <array>.clone(), the method holder can be an ArrayKlass*1528// instead of an InstanceKlass*. For that case simply pretend that the1529// declared holder is Object.clone since that's where the call will bottom out.1530if (method_holder->is_instance_klass()) {1531return InstanceKlass::cast(method_holder);1532} else if (method_holder->is_array_klass()) {1533return vmClasses::Object_klass();1534} else {1535ShouldNotReachHere();1536}1537return NULL;1538}153915401541// ------------------------------------------------------------------1542Method* JVMCIRuntime::get_method_by_index(const constantPoolHandle& cpool,1543int index, Bytecodes::Code bc,1544InstanceKlass* accessor) {1545ResourceMark rm;1546return get_method_by_index_impl(cpool, index, bc, accessor);1547}15481549// ------------------------------------------------------------------1550// Check for changes to the system dictionary during compilation1551// class loads, evolution, breakpoints1552JVMCI::CodeInstallResult JVMCIRuntime::validate_compile_task_dependencies(Dependencies* dependencies, JVMCICompileState* compile_state, char** failure_detail) {1553// If JVMTI capabilities were enabled during compile, the compilation is invalidated.1554if (compile_state != NULL && compile_state->jvmti_state_changed()) {1555*failure_detail = (char*) "Jvmti state change during compilation invalidated dependencies";1556return JVMCI::dependencies_failed;1557}15581559CompileTask* task = compile_state == NULL ? NULL : compile_state->task();1560Dependencies::DepType result = dependencies->validate_dependencies(task, failure_detail);1561if (result == Dependencies::end_marker) {1562return JVMCI::ok;1563}15641565return JVMCI::dependencies_failed;1566}15671568void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& method, int entry_bci) {1569JVMCI_EXCEPTION_CONTEXT15701571JVMCICompileState* compile_state = JVMCIENV->compile_state();15721573bool is_osr = entry_bci != InvocationEntryBci;1574if (compiler->is_bootstrapping() && is_osr) {1575// no OSR compilations during bootstrap - the compiler is just too slow at this point,1576// and we know that there are no endless loops1577compile_state->set_failure(true, "No OSR during bootstrap");1578return;1579}1580if (JVMCI::in_shutdown()) {1581compile_state->set_failure(false, "Avoiding compilation during shutdown");1582return;1583}15841585HandleMark hm(thread);1586JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);1587if (JVMCIENV->has_pending_exception()) {1588fatal_exception(JVMCIENV, "Exception during HotSpotJVMCIRuntime initialization");1589}1590JVMCIObject jvmci_method = JVMCIENV->get_jvmci_method(method, JVMCIENV);1591if (JVMCIENV->has_pending_exception()) {1592JVMCIENV->describe_pending_exception(true);1593compile_state->set_failure(false, "exception getting JVMCI wrapper method");1594return;1595}15961597JVMCIObject result_object = JVMCIENV->call_HotSpotJVMCIRuntime_compileMethod(receiver, jvmci_method, entry_bci,1598(jlong) compile_state, compile_state->task()->compile_id());1599if (!JVMCIENV->has_pending_exception()) {1600if (result_object.is_non_null()) {1601JVMCIObject failure_message = JVMCIENV->get_HotSpotCompilationRequestResult_failureMessage(result_object);1602if (failure_message.is_non_null()) {1603// Copy failure reason into resource memory first ...1604const char* failure_reason = JVMCIENV->as_utf8_string(failure_message);1605// ... and then into the C heap.1606failure_reason = os::strdup(failure_reason, mtJVMCI);1607bool retryable = JVMCIENV->get_HotSpotCompilationRequestResult_retry(result_object) != 0;1608compile_state->set_failure(retryable, failure_reason, true);1609} else {1610if (compile_state->task()->code() == NULL) {1611compile_state->set_failure(true, "no nmethod produced");1612} else {1613compile_state->task()->set_num_inlined_bytecodes(JVMCIENV->get_HotSpotCompilationRequestResult_inlinedBytecodes(result_object));1614compiler->inc_methods_compiled();1615}1616}1617} else {1618assert(false, "JVMCICompiler.compileMethod should always return non-null");1619}1620} else {1621// An uncaught exception here implies failure during compiler initialization.1622// The only sensible thing to do here is to exit the VM.1623fatal_exception(JVMCIENV, "Exception during JVMCI compiler initialization");1624}1625if (compiler->is_bootstrapping()) {1626compiler->set_bootstrap_compilation_request_handled();1627}1628}16291630bool JVMCIRuntime::is_gc_supported(JVMCIEnv* JVMCIENV, CollectedHeap::Name name) {1631JVMCI_EXCEPTION_CONTEXT16321633JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);1634if (JVMCIENV->has_pending_exception()) {1635fatal_exception(JVMCIENV, "Exception during HotSpotJVMCIRuntime initialization");1636}1637return JVMCIENV->call_HotSpotJVMCIRuntime_isGCSupported(receiver, (int) name);1638}16391640// ------------------------------------------------------------------1641JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,1642const methodHandle& method,1643nmethod*& nm,1644int entry_bci,1645CodeOffsets* offsets,1646int orig_pc_offset,1647CodeBuffer* code_buffer,1648int frame_words,1649OopMapSet* oop_map_set,1650ExceptionHandlerTable* handler_table,1651ImplicitExceptionTable* implicit_exception_table,1652AbstractCompiler* compiler,1653DebugInformationRecorder* debug_info,1654Dependencies* dependencies,1655int compile_id,1656bool has_unsafe_access,1657bool has_wide_vector,1658JVMCIObject compiled_code,1659JVMCIObject nmethod_mirror,1660FailedSpeculation** failed_speculations,1661char* speculations,1662int speculations_len) {1663JVMCI_EXCEPTION_CONTEXT;1664nm = NULL;1665int comp_level = CompLevel_full_optimization;1666char* failure_detail = NULL;16671668bool install_default = JVMCIENV->get_HotSpotNmethod_isDefault(nmethod_mirror) != 0;1669assert(JVMCIENV->isa_HotSpotNmethod(nmethod_mirror), "must be");1670JVMCIObject name = JVMCIENV->get_InstalledCode_name(nmethod_mirror);1671const char* nmethod_mirror_name = name.is_null() ? NULL : JVMCIENV->as_utf8_string(name);1672int nmethod_mirror_index;1673if (!install_default) {1674// Reserve or initialize mirror slot in the oops table.1675OopRecorder* oop_recorder = debug_info->oop_recorder();1676nmethod_mirror_index = oop_recorder->allocate_oop_index(nmethod_mirror.is_hotspot() ? nmethod_mirror.as_jobject() : NULL);1677} else {1678// A default HotSpotNmethod mirror is never tracked by the nmethod1679nmethod_mirror_index = -1;1680}16811682JVMCI::CodeInstallResult result(JVMCI::ok);16831684// We require method counters to store some method state (max compilation levels) required by the compilation policy.1685if (method->get_method_counters(THREAD) == NULL) {1686result = JVMCI::cache_full;1687failure_detail = (char*) "can't create method counters";1688}16891690if (result == JVMCI::ok) {1691// To prevent compile queue updates.1692MutexLocker locker(THREAD, MethodCompileQueue_lock);16931694// Prevent SystemDictionary::add_to_hierarchy from running1695// and invalidating our dependencies until we install this method.1696MutexLocker ml(Compile_lock);16971698// Encode the dependencies now, so we can check them right away.1699dependencies->encode_content_bytes();17001701// Record the dependencies for the current compile in the log1702if (LogCompilation) {1703for (Dependencies::DepStream deps(dependencies); deps.next(); ) {1704deps.log_dependency();1705}1706}17071708// Check for {class loads, evolution, breakpoints} during compilation1709result = validate_compile_task_dependencies(dependencies, JVMCIENV->compile_state(), &failure_detail);1710if (result != JVMCI::ok) {1711// While not a true deoptimization, it is a preemptive decompile.1712MethodData* mdp = method()->method_data();1713if (mdp != NULL) {1714mdp->inc_decompile_count();1715#ifdef ASSERT1716if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {1717ResourceMark m;1718tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());1719}1720#endif1721}17221723// All buffers in the CodeBuffer are allocated in the CodeCache.1724// If the code buffer is created on each compile attempt1725// as in C2, then it must be freed.1726//code_buffer->free_blob();1727} else {1728nm = nmethod::new_nmethod(method,1729compile_id,1730entry_bci,1731offsets,1732orig_pc_offset,1733debug_info, dependencies, code_buffer,1734frame_words, oop_map_set,1735handler_table, implicit_exception_table,1736compiler, comp_level, GrowableArrayView<RuntimeStub*>::EMPTY,1737speculations, speculations_len,1738nmethod_mirror_index, nmethod_mirror_name, failed_speculations);173917401741// Free codeBlobs1742if (nm == NULL) {1743// The CodeCache is full. Print out warning and disable compilation.1744{1745MutexUnlocker ml(Compile_lock);1746MutexUnlocker locker(MethodCompileQueue_lock);1747CompileBroker::handle_full_code_cache(CodeCache::get_code_blob_type(comp_level));1748}1749} else {1750nm->set_has_unsafe_access(has_unsafe_access);1751nm->set_has_wide_vectors(has_wide_vector);17521753// Record successful registration.1754// (Put nm into the task handle *before* publishing to the Java heap.)1755if (JVMCIENV->compile_state() != NULL) {1756JVMCIENV->compile_state()->task()->set_code(nm);1757}17581759JVMCINMethodData* data = nm->jvmci_nmethod_data();1760assert(data != NULL, "must be");1761if (install_default) {1762assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm, /* phantom_ref */ false) == NULL, "must be");1763if (entry_bci == InvocationEntryBci) {1764// If there is an old version we're done with it1765CompiledMethod* old = method->code();1766if (TraceMethodReplacement && old != NULL) {1767ResourceMark rm;1768char *method_name = method->name_and_sig_as_C_string();1769tty->print_cr("Replacing method %s", method_name);1770}1771if (old != NULL ) {1772old->make_not_entrant();1773}17741775LogTarget(Info, nmethod, install) lt;1776if (lt.is_enabled()) {1777ResourceMark rm;1778char *method_name = method->name_and_sig_as_C_string();1779lt.print("Installing method (%d) %s [entry point: %p]",1780comp_level, method_name, nm->entry_point());1781}1782// Allow the code to be executed1783MutexLocker ml(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);1784if (nm->make_in_use()) {1785method->set_code(method, nm);1786}1787} else {1788LogTarget(Info, nmethod, install) lt;1789if (lt.is_enabled()) {1790ResourceMark rm;1791char *method_name = method->name_and_sig_as_C_string();1792lt.print("Installing osr method (%d) %s @ %d",1793comp_level, method_name, entry_bci);1794}1795MutexLocker ml(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);1796if (nm->make_in_use()) {1797InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);1798}1799}1800} else {1801assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm, /* phantom_ref */ false) == HotSpotJVMCI::resolve(nmethod_mirror), "must be");1802}1803}1804result = nm != NULL ? JVMCI::ok :JVMCI::cache_full;1805}1806}18071808// String creation must be done outside lock1809if (failure_detail != NULL) {1810// A failure to allocate the string is silently ignored.1811JVMCIObject message = JVMCIENV->create_string(failure_detail, JVMCIENV);1812JVMCIENV->set_HotSpotCompiledNmethod_installationFailureMessage(compiled_code, message);1813}18141815// JVMTI -- compiled method notification (must be done outside lock)1816if (nm != NULL) {1817nm->post_compiled_method_load_event();1818}18191820return result;1821}182218231824