Path: blob/master/src/hotspot/share/jvmci/jvmciRuntime.hpp
40950 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#ifndef SHARE_JVMCI_JVMCIRUNTIME_HPP24#define SHARE_JVMCI_JVMCIRUNTIME_HPP2526#include "jvm_io.h"27#include "code/nmethod.hpp"28#include "gc/shared/collectedHeap.hpp"29#include "jvmci/jvmci.hpp"30#include "jvmci/jvmciExceptions.hpp"31#include "jvmci/jvmciObject.hpp"32#include "utilities/linkedlist.hpp"33#if INCLUDE_G1GC34#include "gc/g1/g1CardTable.hpp"35#endif // INCLUDE_G1GC3637class JVMCIEnv;38class JVMCICompiler;39class JVMCICompileState;40class MetadataHandles;4142// Encapsulates the JVMCI metadata for an nmethod.43// JVMCINMethodData objects are inlined into nmethods44// at nmethod::_jvmci_data_offset.45class JVMCINMethodData {46friend class JVMCIVMStructs;47// Index for the HotSpotNmethod mirror in the nmethod's oops table.48// This is -1 if there is no mirror in the oops table.49int _nmethod_mirror_index;5051// Is HotSpotNmethod.name non-null? If so, the value is52// embedded in the end of this object.53bool _has_name;5455// Address of the failed speculations list to which a speculation56// is appended when it causes a deoptimization.57FailedSpeculation** _failed_speculations;5859// A speculation id is a length (low 5 bits) and an index into60// a jbyte array (i.e. 31 bits for a positive Java int).61enum {62// Keep in sync with HotSpotSpeculationEncoding.63SPECULATION_LENGTH_BITS = 5,64SPECULATION_LENGTH_MASK = (1 << SPECULATION_LENGTH_BITS) - 165};6667public:68// Computes the size of a JVMCINMethodData object69static int compute_size(const char* nmethod_mirror_name) {70int size = sizeof(JVMCINMethodData);71if (nmethod_mirror_name != NULL) {72size += (int) strlen(nmethod_mirror_name) + 1;73}74return size;75}7677void initialize(int nmethod_mirror_index,78const char* name,79FailedSpeculation** failed_speculations);8081// Adds `speculation` to the failed speculations list.82void add_failed_speculation(nmethod* nm, jlong speculation);8384// Gets the JVMCI name of the nmethod (which may be NULL).85const char* name() { return _has_name ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : NULL; }8687// Clears the HotSpotNmethod.address field in the mirror. If nm88// is dead, the HotSpotNmethod.entryPoint field is also cleared.89void invalidate_nmethod_mirror(nmethod* nm);9091// Gets the mirror from nm's oops table.92oop get_nmethod_mirror(nmethod* nm, bool phantom_ref);9394// Sets the mirror in nm's oops table.95void set_nmethod_mirror(nmethod* nm, oop mirror);9697// Clears the mirror in nm's oops table.98void clear_nmethod_mirror(nmethod* nm);99};100101// A top level class that represents an initialized JVMCI runtime.102// There is one instance of this class per HotSpotJVMCIRuntime object.103class JVMCIRuntime: public CHeapObj<mtJVMCI> {104friend class JVMCI;105public:106// Constants describing whether JVMCI wants to be able to adjust the compilation107// level selected for a method by the VM compilation policy and if so, based on108// what information about the method being schedule for compilation.109enum CompLevelAdjustment {110none = 0, // no adjustment111by_holder = 1, // adjust based on declaring class of method112by_full_signature = 2 // adjust based on declaring class, name and signature of method113};114115private:116117enum InitState {118uninitialized,119being_initialized,120fully_initialized121};122123// Initialization state of this JVMCIRuntime.124InitState _init_state;125126// A wrapper for a VM scoped JNI global handle (i.e. JVMCIEnv::make_global)127// to a HotSpotJVMCIRuntime instance. This JNI global handle must never128// be explicitly destroyed as it can be accessed in a racy way during129// JVMCI shutdown. Furthermore, it will be reclaimed when130// the VM or shared library JavaVM managing the handle dies.131JVMCIObject _HotSpotJVMCIRuntime_instance;132133// Result of calling JNI_CreateJavaVM in the JVMCI shared library.134// Must only be modified under JVMCI_lock.135volatile JavaVM* _shared_library_javavm;136137// The HotSpot heap based runtime will have an id of -1 and the138// JVMCI shared library runtime will have an id of 0.139int _id;140141// Handles to Metadata objects.142MetadataHandles* _metadata_handles;143144JVMCIObject create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS);145146// Implementation methods for loading and constant pool access.147static Klass* get_klass_by_name_impl(Klass*& accessing_klass,148const constantPoolHandle& cpool,149Symbol* klass_name,150bool require_local);151static Klass* get_klass_by_index_impl(const constantPoolHandle& cpool,152int klass_index,153bool& is_accessible,154Klass* loading_klass);155static void get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd,156int field_index);157static Method* get_method_by_index_impl(const constantPoolHandle& cpool,158int method_index, Bytecodes::Code bc,159InstanceKlass* loading_klass);160161// Helper methods162static bool check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass);163static Method* lookup_method(InstanceKlass* accessor,164Klass* holder,165Symbol* name,166Symbol* sig,167Bytecodes::Code bc,168constantTag tag);169170public:171JVMCIRuntime(int id);172173int id() const { return _id; }174175// Ensures that a JVMCI shared library JavaVM exists for this runtime.176// If the JavaVM was created by this call, then the thread-local JNI177// interface pointer for the JavaVM is returned otherwise NULL is returned.178JNIEnv* init_shared_library_javavm();179180// Determines if the JVMCI shared library JavaVM exists for this runtime.181bool has_shared_library_javavm() { return _shared_library_javavm != NULL; }182183// Copies info about the JVMCI shared library JavaVM associated with this184// runtime into `info` as follows:185// {186// javaVM, // the {@code JavaVM*} value187// javaVM->functions->reserved0,188// javaVM->functions->reserved1,189// javaVM->functions->reserved2190// }191void init_JavaVM_info(jlongArray info, JVMCI_TRAPS);192193// Wrappers for calling Invocation Interface functions on the194// JVMCI shared library JavaVM associated with this runtime.195// These wrappers ensure all required thread state transitions are performed.196jint AttachCurrentThread(JavaThread* thread, void **penv, void *args);197jint AttachCurrentThreadAsDaemon(JavaThread* thread, void **penv, void *args);198jint DetachCurrentThread(JavaThread* thread);199jint GetEnv(JavaThread* thread, void **penv, jint version);200201// Compute offsets and construct any state required before executing JVMCI code.202void initialize(JVMCIEnv* jvmciEnv);203204// Allocation and management of JNI global object handles205// whose lifetime is scoped by this JVMCIRuntime. The lifetime206// of these handles is the same as the JVMCI shared library JavaVM207// associated with this JVMCIRuntime. These JNI handles are208// used when creating a IndirectHotSpotObjectConstantImpl in the209// shared library JavaVM.210jobject make_global(const Handle& obj);211void destroy_global(jobject handle);212bool is_global_handle(jobject handle);213214// Allocation and management of metadata handles.215jmetadata allocate_handle(const methodHandle& handle);216jmetadata allocate_handle(const constantPoolHandle& handle);217void release_handle(jmetadata handle);218219// Gets the HotSpotJVMCIRuntime instance for this runtime,220// initializing it first if necessary.221JVMCIObject get_HotSpotJVMCIRuntime(JVMCI_TRAPS);222223bool is_HotSpotJVMCIRuntime_initialized() {224return _HotSpotJVMCIRuntime_instance.is_non_null();225}226227// Gets the current HotSpotJVMCIRuntime instance for this runtime which228// may be a "null" JVMCIObject value.229JVMCIObject probe_HotSpotJVMCIRuntime() {230return _HotSpotJVMCIRuntime_instance;231}232233// Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()234void initialize_JVMCI(JVMCI_TRAPS);235236// Explicitly initialize HotSpotJVMCIRuntime itself237void initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS);238239void call_getCompiler(TRAPS);240241// Shuts down this runtime by calling HotSpotJVMCIRuntime.shutdown().242void shutdown();243244void bootstrap_finished(TRAPS);245246// Look up a klass by name from a particular class loader (the accessor's).247// If require_local, result must be defined in that class loader, or NULL.248// If !require_local, a result from remote class loader may be reported,249// if sufficient class loader constraints exist such that initiating250// a class loading request from the given loader is bound to return251// the class defined in the remote loader (or throw an error).252//253// Return an unloaded klass if !require_local and no class at all is found.254//255// The CI treats a klass as loaded if it is consistently defined in256// another loader, even if it hasn't yet been loaded in all loaders257// that could potentially see it via delegation.258static Klass* get_klass_by_name(Klass* accessing_klass,259Symbol* klass_name,260bool require_local);261262// Constant pool access.263static Klass* get_klass_by_index(const constantPoolHandle& cpool,264int klass_index,265bool& is_accessible,266Klass* loading_klass);267static void get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd,268int field_index);269static Method* get_method_by_index(const constantPoolHandle& cpool,270int method_index, Bytecodes::Code bc,271InstanceKlass* loading_klass);272273// converts the Klass* representing the holder of a method into a274// InstanceKlass*. This is needed since the holder of a method in275// the bytecodes could be an array type. Basically this converts276// array types into java/lang/Object and other types stay as they are.277static InstanceKlass* get_instance_klass_for_declared_method_holder(Klass* klass);278279// Helper routine for determining the validity of a compilation280// with respect to concurrent class loading.281static JVMCI::CodeInstallResult validate_compile_task_dependencies(Dependencies* target, JVMCICompileState* task, char** failure_detail);282283// Compiles `target` with the JVMCI compiler.284void compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& target, int entry_bci);285286// Determines if the GC identified by `name` is supported by the JVMCI compiler.287bool is_gc_supported(JVMCIEnv* JVMCIENV, CollectedHeap::Name name);288289// Register the result of a compilation.290JVMCI::CodeInstallResult register_method(JVMCIEnv* JVMCIENV,291const methodHandle& target,292nmethod*& nm,293int entry_bci,294CodeOffsets* offsets,295int orig_pc_offset,296CodeBuffer* code_buffer,297int frame_words,298OopMapSet* oop_map_set,299ExceptionHandlerTable* handler_table,300ImplicitExceptionTable* implicit_exception_table,301AbstractCompiler* compiler,302DebugInformationRecorder* debug_info,303Dependencies* dependencies,304int compile_id,305bool has_unsafe_access,306bool has_wide_vector,307JVMCIObject compiled_code,308JVMCIObject nmethod_mirror,309FailedSpeculation** failed_speculations,310char* speculations,311int speculations_len);312313// Reports an unexpected exception and exits the VM with a fatal error.314static void fatal_exception(JVMCIEnv* JVMCIENV, const char* message);315316static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear);317318#define CHECK_EXIT THREAD); \319if (HAS_PENDING_EXCEPTION) { \320char buf[256]; \321jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \322JVMCIRuntime::fatal_exception(NULL, buf); \323return; \324} \325(void)(0326327#define CHECK_EXIT_(v) THREAD); \328if (HAS_PENDING_EXCEPTION) { \329char buf[256]; \330jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \331JVMCIRuntime::fatal_exception(NULL, buf); \332return v; \333} \334(void)(0335336#define JVMCI_CHECK_EXIT JVMCIENV); \337if (JVMCIENV->has_pending_exception()) { \338char buf[256]; \339jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \340JVMCIRuntime::fatal_exception(JVMCIENV, buf); \341return; \342} \343(void)(0344345#define JVMCI_CHECK_EXIT_(result) JVMCIENV); \346if (JVMCIENV->has_pending_exception()) { \347char buf[256]; \348jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \349JVMCIRuntime::fatal_exception(JVMCIENV, buf); \350return result; \351} \352(void)(0353354static BasicType kindToBasicType(const Handle& kind, TRAPS);355356static void new_instance_common(JavaThread* current, Klass* klass, bool null_on_fail);357static void new_array_common(JavaThread* current, Klass* klass, jint length, bool null_on_fail);358static void new_multi_array_common(JavaThread* current, Klass* klass, int rank, jint* dims, bool null_on_fail);359static void dynamic_new_array_common(JavaThread* current, oopDesc* element_mirror, jint length, bool null_on_fail);360static void dynamic_new_instance_common(JavaThread* current, oopDesc* type_mirror, bool null_on_fail);361362// The following routines are called from compiled JVMCI code363364// When allocation fails, these stubs:365// 1. Exercise -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError handling and also366// post a JVMTI_EVENT_RESOURCE_EXHAUSTED event if the failure is an OutOfMemroyError367// 2. Return NULL with a pending exception.368// Compiled code must ensure these stubs are not called twice for the same allocation369// site due to the non-repeatable side effects in the case of OOME.370static void new_instance(JavaThread* current, Klass* klass) { new_instance_common(current, klass, false); }371static void new_array(JavaThread* current, Klass* klass, jint length) { new_array_common(current, klass, length, false); }372static void new_multi_array(JavaThread* current, Klass* klass, int rank, jint* dims) { new_multi_array_common(current, klass, rank, dims, false); }373static void dynamic_new_array(JavaThread* current, oopDesc* element_mirror, jint length) { dynamic_new_array_common(current, element_mirror, length, false); }374static void dynamic_new_instance(JavaThread* current, oopDesc* type_mirror) { dynamic_new_instance_common(current, type_mirror, false); }375376// When allocation fails, these stubs return NULL and have no pending exception. Compiled code377// can use these stubs if a failed allocation will be retried (e.g., by deoptimizing and378// re-executing in the interpreter).379static void new_instance_or_null(JavaThread* thread, Klass* klass) { new_instance_common(thread, klass, true); }380static void new_array_or_null(JavaThread* thread, Klass* klass, jint length) { new_array_common(thread, klass, length, true); }381static void new_multi_array_or_null(JavaThread* thread, Klass* klass, int rank, jint* dims) { new_multi_array_common(thread, klass, rank, dims, true); }382static void dynamic_new_array_or_null(JavaThread* thread, oopDesc* element_mirror, jint length) { dynamic_new_array_common(thread, element_mirror, length, true); }383static void dynamic_new_instance_or_null(JavaThread* thread, oopDesc* type_mirror) { dynamic_new_instance_common(thread, type_mirror, true); }384385static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);386static jint identity_hash_code(JavaThread* current, oopDesc* obj);387static address exception_handler_for_pc(JavaThread* current);388static void monitorenter(JavaThread* current, oopDesc* obj, BasicLock* lock);389static void monitorexit (JavaThread* current, oopDesc* obj, BasicLock* lock);390static jboolean object_notify(JavaThread* current, oopDesc* obj);391static jboolean object_notifyAll(JavaThread* current, oopDesc* obj);392static void vm_error(JavaThread* current, jlong where, jlong format, jlong value);393static oopDesc* load_and_clear_exception(JavaThread* thread);394static void log_printf(JavaThread* thread, const char* format, jlong v1, jlong v2, jlong v3);395static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);396// Print the passed in object, optionally followed by a newline. If397// as_string is true and the object is a java.lang.String then it398// printed as a string, otherwise the type of the object is printed399// followed by its address.400static void log_object(JavaThread* thread, oopDesc* object, bool as_string, bool newline);401#if INCLUDE_G1GC402using CardValue = G1CardTable::CardValue;403static void write_barrier_pre(JavaThread* thread, oopDesc* obj);404static void write_barrier_post(JavaThread* thread, volatile CardValue* card);405#endif406static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);407408// used to throw exceptions from compiled JVMCI code409static int throw_and_post_jvmti_exception(JavaThread* current, const char* exception, const char* message);410// helper methods to throw exception with complex messages411static int throw_klass_external_name_exception(JavaThread* current, const char* exception, Klass* klass);412static int throw_class_cast_exception(JavaThread* current, const char* exception, Klass* caster_klass, Klass* target_klass);413414// A helper to allow invocation of an arbitrary Java method. For simplicity the method is415// restricted to a static method that takes at most one argument. For calling convention416// simplicty all types are passed by being converted into a jlong417static jlong invoke_static_method_one_arg(JavaThread* current, Method* method, jlong argument);418419// Test only function420static jint test_deoptimize_call_int(JavaThread* current, int value);421};422#endif // SHARE_JVMCI_JVMCIRUNTIME_HPP423424425