--- old/src/hotspot/share/jvmci/jvmciEnv.cpp 2019-03-28 11:22:48.000000000 -0700 +++ new/src/hotspot/share/jvmci/jvmciEnv.cpp 2019-03-28 11:22:48.000000000 -0700 @@ -25,42 +25,41 @@ #include "precompiled.hpp" #include "jvmci/jvmciEnv.hpp" #include "classfile/javaAssertions.hpp" +#include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" -#include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/scopeDesc.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compileLog.hpp" #include "compiler/compilerOracle.hpp" +#ifdef INCLUDE_ALL_GCS +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" +#endif #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" -#include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "oops/constantPool.inline.hpp" -#include "oops/cpCache.inline.hpp" -#include "oops/method.inline.hpp" #include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" -#include "runtime/fieldDescriptor.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" -#include "runtime/sweeper.hpp" +#include "runtime/javaCalls.hpp" #include "utilities/dtrace.hpp" #include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciJavaClasses.hpp" -JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter): +#include + +JVMCICompileState::JVMCICompileState(CompileTask* task, int system_dictionary_modification_counter): _task(task), _system_dictionary_modification_counter(system_dictionary_modification_counter), _retryable(true), _failure_reason(NULL), - _failure_reason_on_C_heap(false) -{ + _failure_reason_on_C_heap(false) { // Get Jvmti capabilities under lock to get consistent values. MutexLocker mu(JvmtiThreadState_lock); _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0; @@ -69,7 +68,7 @@ _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0; } -bool JVMCIEnv::jvmti_state_changed() const { +bool JVMCICompileState::jvmti_state_changed() const { if (!jvmti_can_access_local_variables() && JvmtiExport::can_access_local_variables()) { return true; @@ -89,532 +88,1319 @@ return false; } -// ------------------------------------------------------------------ -// Note: the logic of this method should mirror the logic of -// constantPoolOopDesc::verify_constant_pool_resolve. -bool JVMCIEnv::check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass) { - if (accessing_klass->is_objArray_klass()) { - accessing_klass = ObjArrayKlass::cast(accessing_klass)->bottom_klass(); +JavaVM* JVMCIEnv::_shared_library_javavm = NULL; +void* JVMCIEnv::_shared_library_handle = NULL; +char* JVMCIEnv::_shared_library_path = NULL; + +void JVMCIEnv::copy_saved_properties() { + assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image"); + + JavaThread* THREAD = JavaThread::current(); + + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_services_Services(), Handle(), Handle(), true, THREAD); + if (HAS_PENDING_EXCEPTION) { + JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services"); + } + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->should_be_initialized()) { + ik->initialize(THREAD); + if (HAS_PENDING_EXCEPTION) { + JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services"); + } } - if (!accessing_klass->is_instance_klass()) { - return true; + + // Get the serialized saved properties from HotSpot + TempNewSymbol serializeSavedProperties = SymbolTable::new_symbol("serializeSavedProperties", CHECK_EXIT); + JavaValue result(T_OBJECT); + JavaCallArguments args; + JavaCalls::call_static(&result, ik, serializeSavedProperties, vmSymbols::serializePropertiesToByteArray_signature(), &args, THREAD); + if (HAS_PENDING_EXCEPTION) { + JVMCIRuntime::exit_on_pending_exception(NULL, "Error calling jdk.vm.ci.services.Services.serializeSavedProperties"); + } + oop res = (oop) result.get_jobject(); + assert(res->is_typeArray(), "must be"); + assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be"); + typeArrayOop ba = typeArrayOop(res); + int serialized_properties_len = ba->length(); + + // Copy serialized saved properties from HotSpot object into native buffer + jbyte* serialized_properties = NEW_RESOURCE_ARRAY(jbyte, serialized_properties_len); + memcpy(serialized_properties, ba->byte_at_addr(0), serialized_properties_len); + + // Copy native buffer into shared library object + JVMCIPrimitiveArray buf = new_byteArray(serialized_properties_len, this); + if (has_pending_exception()) { + describe_pending_exception(true); + fatal("Error in copy_saved_properties"); + } + copy_bytes_from(serialized_properties, buf, 0, serialized_properties_len); + if (has_pending_exception()) { + describe_pending_exception(true); + fatal("Error in copy_saved_properties"); + } + + // Initialize saved properties in shared library + jclass servicesClass = JNIJVMCI::Services::clazz(); + jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method(); + JNIAccessMark jni(this); + jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject()); + if (jni()->ExceptionCheck()) { + jni()->ExceptionDescribe(); + fatal("Error calling jdk.vm.ci.services.Services.initializeSavedProperties"); } +} - if (resolved_klass->is_objArray_klass()) { - // Find the element klass, if this is an array. - resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass(); - } - if (resolved_klass->is_instance_klass()) { - Reflection::VerifyClassAccessResults result = - Reflection::verify_class_access(accessing_klass, InstanceKlass::cast(resolved_klass), true); - return result == Reflection::ACCESS_OK; - } - return true; -} - -// ------------------------------------------------------------------ -Klass* JVMCIEnv::get_klass_by_name_impl(Klass* accessing_klass, - const constantPoolHandle& cpool, - Symbol* sym, - bool require_local) { - JVMCI_EXCEPTION_CONTEXT; - - // Now we need to check the SystemDictionary - if (sym->char_at(0) == 'L' && - sym->char_at(sym->utf8_length()-1) == ';') { - // This is a name from a signature. Strip off the trimmings. - // Call recursive to keep scope of strippedsym. - TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1, - sym->utf8_length()-2, - CHECK_NULL); - return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local); - } - - Handle loader(THREAD, (oop)NULL); - Handle domain(THREAD, (oop)NULL); - if (accessing_klass != NULL) { - loader = Handle(THREAD, accessing_klass->class_loader()); - domain = Handle(THREAD, accessing_klass->protection_domain()); - } - - Klass* found_klass = NULL; - { - ttyUnlocker ttyul; // release tty lock to avoid ordering problems - MutexLocker ml(Compile_lock); - if (!require_local) { - found_klass = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_NULL); - } else { - found_klass = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_NULL); +JNIEnv* JVMCIEnv::attach_shared_library() { + if (_shared_library_javavm == NULL) { + MutexLocker locker(JVMCI_lock); + if (_shared_library_javavm == NULL) { + + char path[JVM_MAXPATHLEN]; + char ebuf[1024]; + if (JVMCILibPath != NULL) { + if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) { + vm_exit_during_initialization("Unable to create JVMCI shared library path from -XX:JVMCILibPath value", JVMCILibPath); + } + } else { + if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) { + vm_exit_during_initialization("Unable to create path to JVMCI shared library"); + } + } + + void* handle = os::dll_load(path, ebuf, sizeof ebuf); + if (handle == NULL) { + vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf); + } + _shared_library_handle = handle; + _shared_library_path = strdup(path); + jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args); + typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args); + + JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(handle, "JNI_CreateJavaVM")); + JNIEnv* env; + if (JNI_CreateJavaVM == NULL) { + vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", path); + } + + ResourceMark rm; + JavaVMInitArgs vm_args; + vm_args.version = JNI_VERSION_1_2; + vm_args.ignoreUnrecognized = JNI_TRUE; + vm_args.options = NULL; + vm_args.nOptions = 0; + + JavaVM* the_javavm = NULL; + int result = (*JNI_CreateJavaVM)(&the_javavm, (void**) &env, &vm_args); + if (result == JNI_OK) { + guarantee(env != NULL, "missing env"); + _shared_library_javavm = the_javavm; + return env; + } else { + vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), path); + } } } + JNIEnv* env; + if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) { + guarantee(env != NULL, "missing env"); + return env; + } + fatal("Error attaching current thread to JVMCI shared library JNI interface"); + return NULL; +} - // If we fail to find an array klass, look again for its element type. - // The element type may be available either locally or via constraints. - // In either case, if we can find the element type in the system dictionary, - // we must build an array type around it. The CI requires array klasses - // to be loaded if their element klasses are loaded, except when memory - // is exhausted. - if (sym->char_at(0) == '[' && - (sym->char_at(1) == '[' || sym->char_at(1) == 'L')) { - // We have an unloaded array. - // Build it on the fly if the element class exists. - TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1, - sym->utf8_length()-1, - CHECK_NULL); - - // Get element Klass recursively. - Klass* elem_klass = - get_klass_by_name_impl(accessing_klass, - cpool, - elem_sym, - require_local); - if (elem_klass != NULL) { - // Now make an array for it - return elem_klass->array_klass(THREAD); +void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) { + // By default there is only one runtime which is the compiler runtime. + _runtime = JVMCI::compiler_runtime(); + if (!UseJVMCINativeLibrary) { + // In HotSpot mode, JNI isn't used at all. + _is_hotspot = true; + _env = NULL; + return; + } + + if (parent_env != NULL) { + // If the parent JNI environment is non-null then figure out whether it + // is a HotSpot or shared library JNIEnv and set the state appropriately. + JavaThread* thread = JavaThread::current(); + if (thread->jni_environment() == parent_env) { + // Select the Java runtime + _runtime = JVMCI::java_runtime(); + _is_hotspot = true; + _env = NULL; + return; } } - if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) { - // Look inside the constant pool for pre-resolved class entries. - for (int i = cpool->length() - 1; i >= 1; i--) { - if (cpool->tag_at(i).is_klass()) { - Klass* kls = cpool->resolved_klass_at(i); - if (kls->name() == sym) { - return kls; - } - } + // Running in JVMCI shared library mode so get a shared library JNIEnv + _is_hotspot = false; + _env = attach_shared_library(); + assert(parent_env == NULL || _env == parent_env, "must be"); + + if (parent_env == NULL) { + // There is no parent shared library JNI env so push + // a JNI local frame to release all local handles in + // this JVMCIEnv scope when it's closed. + assert(_throw_to_caller == false, "must be"); + JNIAccessMark jni(this); + jint result = _env->PushLocalFrame(32); + if (result != JNI_OK) { + char message[256]; + jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line); + JVMCIRuntime::exit_on_pending_exception(this, message); } } +} - return found_klass; +JVMCIEnv::JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line): + _throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) { + init_env_mode_runtime(NULL); +} + +JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line): + _throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) { + init_env_mode_runtime(NULL); +} + +JVMCIEnv::JVMCIEnv(JNIEnv* parent_env, const char* file, int line): + _throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) { + init_env_mode_runtime(parent_env); + assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment"); +} + +void JVMCIEnv::init(bool is_hotspot, const char* file, int line) { + _compile_state = NULL; + _throw_to_caller = false; + _file = file; + _line = line; + if (is_hotspot) { + _env = NULL; + _is_hotspot = true; + _runtime = JVMCI::java_runtime(); + } else { + init_env_mode_runtime(NULL); + } } -// ------------------------------------------------------------------ -Klass* JVMCIEnv::get_klass_by_name(Klass* accessing_klass, - Symbol* klass_name, - bool require_local) { +// Prints a pending exception (if any) and its stack trace. +void JVMCIEnv::describe_pending_exception(bool clear) { + if (!is_hotspot()) { + JNIAccessMark jni(this); + if (jni()->ExceptionCheck()) { + jthrowable ex = !clear ? jni()->ExceptionOccurred() : NULL; + jni()->ExceptionDescribe(); + if (ex != NULL) { + jni()->Throw(ex); + } + } + } else { + Thread* THREAD = Thread::current(); + if (HAS_PENDING_EXCEPTION) { + JVMCIRuntime::describe_pending_hotspot_exception((JavaThread*) THREAD, clear); + } + } +} + +void JVMCIEnv::translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, Handle throwable) { + assert(!is_hotspot(), "must_be"); + // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets + // may not have been called. + Klass* runtimeKlass = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime(), true, CHECK); + JavaCallArguments jargs; + jargs.push_oop(throwable); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + runtimeKlass, + vmSymbols::encodeThrowable_name(), + vmSymbols::encodeThrowable_signature(), &jargs, THREAD); + if (HAS_PENDING_EXCEPTION) { + JVMCIRuntime::exit_on_pending_exception(this, "HotSpotJVMCIRuntime.encodeThrowable should not throw an exception"); + } + + oop encoded_throwable_string = (oop) result.get_jobject(); + ResourceMark rm; - constantPoolHandle cpool; - return get_klass_by_name_impl(accessing_klass, - cpool, - klass_name, - require_local); -} - -// ------------------------------------------------------------------ -// Implementation of get_klass_by_index. -Klass* JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool, - int index, - bool& is_accessible, - Klass* accessor) { - JVMCI_EXCEPTION_CONTEXT; - Klass* klass = ConstantPool::klass_at_if_loaded(cpool, index); - Symbol* klass_name = NULL; - if (klass == NULL) { - klass_name = cpool->klass_name_at(index); - } - - if (klass == NULL) { - // Not found in constant pool. Use the name to do the lookup. - Klass* k = get_klass_by_name_impl(accessor, - cpool, - klass_name, - false); - // Calculate accessibility the hard way. - if (k == NULL) { - is_accessible = false; - } else if (k->class_loader() != accessor->class_loader() && - get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) { - // Loaded only remotely. Not linked yet. - is_accessible = false; + const char* encoded_throwable_chars = java_lang_String::as_utf8_string(encoded_throwable_string); + + JNIAccessMark jni(this); + jobject jni_encoded_throwable_string = jni()->NewStringUTF(encoded_throwable_chars); + jthrowable jni_throwable = (jthrowable) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method(), + jni_encoded_throwable_string); + jni()->Throw(jni_throwable); +} + +JVMCIEnv::~JVMCIEnv() { + if (_throw_to_caller) { + if (is_hotspot()) { + // Nothing to do } else { - // Linked locally, and we must also check public/private, etc. - is_accessible = check_klass_accessibility(accessor, k); + if (Thread::current()->is_Java_thread()) { + JavaThread* THREAD = JavaThread::current(); + if (HAS_PENDING_EXCEPTION) { + Handle throwable = Handle(THREAD, PENDING_EXCEPTION); + CLEAR_PENDING_EXCEPTION; + translate_hotspot_exception_to_jni_exception(THREAD, throwable); + } + } } - if (!is_accessible) { - return NULL; + } else { + if (!is_hotspot()) { + // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope. + JNIAccessMark jni(this); + jni()->PopLocalFrame(NULL); + } + + if (has_pending_exception()) { + char message[256]; + jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line); + JVMCIRuntime::exit_on_pending_exception(this, message); } - return k; } +} - // It is known to be accessible, since it was found in the constant pool. - is_accessible = true; - return klass; +JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci, + jlong compile_state, int id) { + if (is_hotspot()) { + Thread* THREAD = Thread::current(); + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method))); + jargs.push_int(entry_bci); + jargs.push_long(compile_state); + jargs.push_int(id); + JavaValue result(T_OBJECT); + JavaCalls::call_special(&result, + HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), + vmSymbols::compileMethod_name(), + vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(), + JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(), + method.as_jobject(), entry_bci, compile_state, id); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); + } } -// ------------------------------------------------------------------ -// Get a klass from the constant pool. -Klass* JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool, - int index, - bool& is_accessible, - Klass* accessor) { - ResourceMark rm; - return get_klass_by_index_impl(cpool, index, is_accessible, accessor); +int JVMCIEnv::call_HotSpotJVMCIRuntime_adjustCompilationLevel (JVMCIObject runtime, InstanceKlass* declaringClass, + JVMCIObject name, JVMCIObject signature, bool is_osr, int level, JVMCI_TRAPS) { + if (is_hotspot()) { + Thread* THREAD = Thread::current(); + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); + jargs.push_oop(Handle(THREAD, declaringClass->java_mirror())); + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(name))); + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(signature))); + jargs.push_int(is_osr); + jargs.push_int(level); + JavaValue result(T_INT); + JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::adjustCompilationLevel_name(), vmSymbols::adjustCompilationLevel_signature(), &jargs, THREAD); + return result.get_jint(); + } else { + JVMCIObject declaringClassName = create_string(declaringClass->external_name(), JVMCI_CHECK_(0)); + int result; + { + JNIAccessMark jni(this); + result = jni()->CallNonvirtualIntMethod(runtime.as_jobject(), + JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::adjustCompilationLevel_method(), + get_jobject(declaringClassName), get_jobject(name), get_jobject(signature), is_osr, level); + } + return result; + } } -// ------------------------------------------------------------------ -// Implementation of get_field_by_index. -// -// Implementation note: the results of field lookups are cached -// in the accessor klass. -void JVMCIEnv::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc, - int index) { - JVMCI_EXCEPTION_CONTEXT; - - assert(klass->is_linked(), "must be linked before using its constant-pool"); - - constantPoolHandle cpool(thread, klass->constants()); - - // Get the field's name, signature, and type. - Symbol* name = cpool->name_ref_at(index); - - int nt_index = cpool->name_and_type_ref_index_at(index); - int sig_index = cpool->signature_ref_index_at(nt_index); - Symbol* signature = cpool->symbol_at(sig_index); - - // Get the field's declared holder. - int holder_index = cpool->klass_ref_index_at(index); - bool holder_is_accessible; - Klass* declared_holder = get_klass_by_index(cpool, holder_index, - holder_is_accessible, - klass); - - // The declared holder of this field may not have been loaded. - // Bail out with partial field information. - if (!holder_is_accessible) { - return; +void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) { + if (is_hotspot()) { + Thread* THREAD = Thread::current(); + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); + JavaValue result(T_VOID); + JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK); + } else { + JNIAccessMark jni(this); + jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method()); + } +} +void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) { + HandleMark hm; + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); + JavaValue result(T_VOID); + JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD); + } else { + JNIAccessMark jni(this); + jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method()); + } + if (has_pending_exception()) { + // This should never happen as HotSpotJVMCIRuntime.shutdown() should + // handle all exceptions. + describe_pending_exception(true); + } +} - // Perform the field lookup. - Klass* canonical_holder = - InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc); - if (canonical_holder == NULL) { - return; +JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method()); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); } +} - assert(canonical_holder == field_desc.field_holder(), "just checking"); +JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method()); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); + } } -// ------------------------------------------------------------------ -// Get a field by index from a klass's constant pool. -void JVMCIEnv::get_field_by_index(InstanceKlass* accessor, fieldDescriptor& fd, int index) { - ResourceMark rm; - return get_field_by_index_impl(accessor, fd, index); +JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); + JavaValue result(T_OBJECT); + JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method()); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); + } } -// ------------------------------------------------------------------ -// Perform an appropriate method lookup based on accessor, holder, -// name, signature, and bytecode. -methodHandle JVMCIEnv::lookup_method(InstanceKlass* accessor, - Klass* holder, - Symbol* name, - Symbol* sig, - Bytecodes::Code bc, - constantTag tag) { - // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl(). - assert(check_klass_accessibility(accessor, holder), "holder not accessible"); - - methodHandle dest_method; - LinkInfo link_info(holder, name, sig, accessor, LinkInfo::needs_access_check, tag); - switch (bc) { - case Bytecodes::_invokestatic: - dest_method = - LinkResolver::resolve_static_call_or_null(link_info); - break; - case Bytecodes::_invokespecial: - dest_method = - LinkResolver::resolve_special_call_or_null(link_info); - break; - case Bytecodes::_invokeinterface: - dest_method = - LinkResolver::linktime_resolve_interface_method_or_null(link_info); - break; - case Bytecodes::_invokevirtual: - dest_method = - LinkResolver::linktime_resolve_virtual_method_or_null(link_info); - break; - default: ShouldNotReachHere(); - } - - return dest_method; + +JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object))); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), + vmSymbols::callToString_name(), + vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), + JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(), + object.as_jobject()); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); + } } -// ------------------------------------------------------------------ -methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool, - int index, Bytecodes::Code bc, - InstanceKlass* accessor) { - if (bc == Bytecodes::_invokedynamic) { - ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index); - bool is_resolved = !cpce->is_f1_null(); - if (is_resolved) { - // Get the invoker Method* from the constant pool. - // (The appendix argument, if any, will be noted in the method's signature.) - Method* adapter = cpce->f1_as_method(); - return methodHandle(adapter); +JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_int(kind); + jargs.push_long(value); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + HotSpotJVMCI::PrimitiveConstant::klass(), + vmSymbols::forTypeChar_name(), + vmSymbols::forTypeChar_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::PrimitiveConstant::clazz(), + JNIJVMCI::PrimitiveConstant::forTypeChar_method(), + kind, value); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); } + return wrap(result); + } +} - return NULL; +JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_float(value); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + HotSpotJVMCI::JavaConstant::klass(), + vmSymbols::forFloat_name(), + vmSymbols::forFloat_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(), + JNIJVMCI::JavaConstant::forFloat_method(), + value); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); } +} - int holder_index = cpool->klass_ref_index_at(index); - bool holder_is_accessible; - Klass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); - - // Get the method's name and signature. - Symbol* name_sym = cpool->name_ref_at(index); - Symbol* sig_sym = cpool->signature_ref_at(index); - - if (cpool->has_preresolution() - || ((holder == SystemDictionary::MethodHandle_klass() || holder == SystemDictionary::VarHandle_klass()) && - MethodHandles::is_signature_polymorphic_name(holder, name_sym))) { - // Short-circuit lookups for JSR 292-related call sites. - // That is, do not rely only on name-based lookups, because they may fail - // if the names are not resolvable in the boot class loader (7056328). - switch (bc) { - case Bytecodes::_invokevirtual: - case Bytecodes::_invokeinterface: - case Bytecodes::_invokespecial: - case Bytecodes::_invokestatic: - { - Method* m = ConstantPool::method_at_if_loaded(cpool, index); - if (m != NULL) { - return m; - } +JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + JavaCallArguments jargs; + jargs.push_double(value); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, + HotSpotJVMCI::JavaConstant::klass(), + vmSymbols::forDouble_name(), + vmSymbols::forDouble_signature(), &jargs, CHECK_(JVMCIObject())); + return wrap((oop) result.get_jobject()); + } else { + JNIAccessMark jni(this); + jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(), + JNIJVMCI::JavaConstant::forDouble_method(), + value); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + return wrap(result); + } +} + +JVMCIObject JVMCIEnv::get_jvmci_primitive_type(BasicType type) { + JVMCIObjectArray primitives = get_HotSpotResolvedPrimitiveType_primitives(); + JVMCIObject result = get_object_at(primitives, type); + return result; +} + +JVMCIObject JVMCIEnv::new_StackTraceElement(methodHandle method, int bci, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); + Symbol* method_name_sym; + Symbol* file_name_sym; + int line_number; + Handle mirror (THREAD, method->method_holder()->java_mirror()); + java_lang_StackTraceElement::decode(mirror, method, bci, method_name_sym, file_name_sym, line_number); + + InstanceKlass* holder = method->method_holder(); + const char* declaring_class_str = holder->external_name(); + + if (is_hotspot()) { + HotSpotJVMCI::StackTraceElement::klass()->initialize(CHECK_(JVMCIObject())); + oop objOop = HotSpotJVMCI::StackTraceElement::klass()->allocate_instance(CHECK_(JVMCIObject())); + Handle obj = Handle(THREAD, objOop); + + oop declaring_class = StringTable::intern((char*) declaring_class_str, CHECK_(JVMCIObject())); + HotSpotJVMCI::StackTraceElement::set_declaringClass(this, obj(), declaring_class); + + oop method_name = StringTable::intern(method_name_sym, CHECK_(JVMCIObject())); + HotSpotJVMCI::StackTraceElement::set_methodName(this, obj(), method_name); + + if (file_name_sym != NULL) { + oop file_name = StringTable::intern(file_name_sym, CHECK_(JVMCIObject())); + HotSpotJVMCI::StackTraceElement::set_fileName(this, obj(), file_name); + } + HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number); + return wrap(obj()); + } else { + JNIAccessMark jni(this); + jobject declaring_class = jni()->NewStringUTF(declaring_class_str); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + jobject method_name = jni()->NewStringUTF(method_name_sym->as_C_string()); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + jobject file_name = NULL; + if (file_name != NULL) { + file_name = jni()->NewStringUTF(file_name_sym->as_C_string()); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); } - break; - default: - break; } + + jobject result = jni()->NewObject(JNIJVMCI::StackTraceElement::clazz(), + JNIJVMCI::StackTraceElement::constructor(), + declaring_class, method_name, file_name, line_number); + return wrap(result); } +} + +JVMCIObject JVMCIEnv::new_HotSpotNmethod(methodHandle method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); - if (holder_is_accessible) { // Our declared holder is loaded. - constantTag tag = cpool->tag_ref_at(index); - methodHandle m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag); - if (!m.is_null()) { - // We found the method. - return m; + JVMCIObject methodObject = get_jvmci_method(method(), JVMCI_CHECK_(JVMCIObject())); + + if (is_hotspot()) { + InstanceKlass* ik = InstanceKlass::cast(HotSpotJVMCI::HotSpotNmethod::klass()); + if (ik->should_be_initialized()) { + ik->initialize(CHECK_(JVMCIObject())); } + oop obj = ik->allocate_instance(CHECK_(JVMCIObject())); + Handle obj_h(THREAD, obj); + Handle nameStr = java_lang_String::create_from_str(name, CHECK_(JVMCIObject())); + + // Call constructor + JavaCallArguments jargs; + jargs.push_oop(obj_h); + jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(methodObject))); + jargs.push_oop(nameStr); + jargs.push_int(isDefault); + jargs.push_long(compileId); + JavaValue result(T_VOID); + JavaCalls::call_special(&result, ik, + vmSymbols::object_initializer_name(), + vmSymbols::method_string_bool_long_signature(), + &jargs, CHECK_(JVMCIObject())); + return wrap(obj_h()); + } else { + JNIAccessMark jni(this); + jobject nameStr = name == NULL ? NULL : jni()->NewStringUTF(name); + if (jni()->ExceptionCheck()) { + return JVMCIObject(); + } + + jobject result = jni()->NewObject(JNIJVMCI::HotSpotNmethod::clazz(), + JNIJVMCI::HotSpotNmethod::constructor(), + methodObject.as_jobject(), nameStr, isDefault); + return wrap(result); } +} - // Either the declared holder was not loaded, or the method could - // not be found. +JVMCIObject JVMCIEnv::make_local(JVMCIObject object) { + if (object.is_null()) { + return JVMCIObject(); + } + if (is_hotspot()) { + return wrap(JNIHandles::make_local(HotSpotJVMCI::resolve(object))); + } else { + JNIAccessMark jni(this); + return wrap(jni()->NewLocalRef(object.as_jobject())); + } +} - return NULL; +JVMCIObject JVMCIEnv::make_global(JVMCIObject object) { + if (object.is_null()) { + return JVMCIObject(); + } + if (is_hotspot()) { + return wrap(JNIHandles::make_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object)))); + } else { + JNIAccessMark jni(this); + return wrap(jni()->NewGlobalRef(object.as_jobject())); + } } -// ------------------------------------------------------------------ -InstanceKlass* JVMCIEnv::get_instance_klass_for_declared_method_holder(Klass* method_holder) { - // For the case of .clone(), the method holder can be an ArrayKlass* - // instead of an InstanceKlass*. For that case simply pretend that the - // declared holder is Object.clone since that's where the call will bottom out. - if (method_holder->is_instance_klass()) { - return InstanceKlass::cast(method_holder); - } else if (method_holder->is_array_klass()) { - return SystemDictionary::Object_klass(); +JVMCIObject JVMCIEnv::make_weak(JVMCIObject object) { + if (object.is_null()) { + return JVMCIObject(); + } + if (is_hotspot()) { + return wrap(JNIHandles::make_weak_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object)))); } else { - ShouldNotReachHere(); + JNIAccessMark jni(this); + return wrap(jni()->NewWeakGlobalRef(object.as_jobject())); } - return NULL; } +void JVMCIEnv::destroy_local(JVMCIObject object) { + if (is_hotspot()) { + JNIHandles::destroy_local(object.as_jobject()); + } else { + JNIAccessMark jni(this); + jni()->DeleteLocalRef(object.as_jobject()); + } +} -// ------------------------------------------------------------------ -methodHandle JVMCIEnv::get_method_by_index(const constantPoolHandle& cpool, - int index, Bytecodes::Code bc, - InstanceKlass* accessor) { - ResourceMark rm; - return get_method_by_index_impl(cpool, index, bc, accessor); +void JVMCIEnv::destroy_global(JVMCIObject object) { + if (is_hotspot()) { + JNIHandles::destroy_global(object.as_jobject()); + } else { + JNIAccessMark jni(this); + jni()->DeleteGlobalRef(object.as_jobject()); + } } -// ------------------------------------------------------------------ -// Check for changes to the system dictionary during compilation -// class loads, evolution, breakpoints -JVMCIEnv::CodeInstallResult JVMCIEnv::validate_compile_task_dependencies(Dependencies* dependencies, Handle compiled_code, - JVMCIEnv* env, char** failure_detail) { - // If JVMTI capabilities were enabled during compile, the compilation is invalidated. - if (env != NULL && env->jvmti_state_changed()) { - *failure_detail = (char*) "Jvmti state change during compilation invalidated dependencies"; - return JVMCIEnv::dependencies_failed; - } - - // Dependencies must be checked when the system dictionary changes - // or if we don't know whether it has changed (i.e., env == NULL). - bool counter_changed = env == NULL || env->_system_dictionary_modification_counter != SystemDictionary::number_of_modifications(); - CompileTask* task = env == NULL ? NULL : env->task(); - Dependencies::DepType result = dependencies->validate_dependencies(task, counter_changed, failure_detail); - if (result == Dependencies::end_marker) { - return JVMCIEnv::ok; - } - - if (!Dependencies::is_klass_type(result) || counter_changed) { - return JVMCIEnv::dependencies_failed; - } - // The dependencies were invalid at the time of installation - // without any intervening modification of the system - // dictionary. That means they were invalidly constructed. - return JVMCIEnv::dependencies_invalid; -} - -// ------------------------------------------------------------------ -JVMCIEnv::CodeInstallResult JVMCIEnv::register_method( - const methodHandle& method, - nmethod*& nm, - int entry_bci, - CodeOffsets* offsets, - int orig_pc_offset, - CodeBuffer* code_buffer, - int frame_words, - OopMapSet* oop_map_set, - ExceptionHandlerTable* handler_table, - AbstractCompiler* compiler, - DebugInformationRecorder* debug_info, - Dependencies* dependencies, - JVMCIEnv* env, - int compile_id, - bool has_unsafe_access, - bool has_wide_vector, - Handle installed_code, - Handle compiled_code, - Handle speculation_log) { - JVMCI_EXCEPTION_CONTEXT; - nm = NULL; - int comp_level = CompLevel_full_optimization; - char* failure_detail = NULL; - JVMCIEnv::CodeInstallResult result; - { - // To prevent compile queue updates. - MutexLocker locker(MethodCompileQueue_lock, THREAD); - - // Prevent SystemDictionary::add_to_hierarchy from running - // and invalidating our dependencies until we install this method. - MutexLocker ml(Compile_lock); - - // Encode the dependencies now, so we can check them right away. - dependencies->encode_content_bytes(); - - // Record the dependencies for the current compile in the log - if (LogCompilation) { - for (Dependencies::DepStream deps(dependencies); deps.next(); ) { - deps.log_dependency(); - } +void JVMCIEnv::destroy_weak(JVMCIObject object) { + if (is_hotspot()) { + JNIHandles::destroy_weak_global(object.as_jweak()); + } else { + JNIAccessMark jni(this); + jni()->DeleteWeakGlobalRef(object.as_jweak()); + } +} + +const char* JVMCIEnv::klass_name(JVMCIObject object) { + if (is_hotspot()) { + return HotSpotJVMCI::resolve(object)->klass()->signature_name(); + } else { + JVMCIObject name; + { + JNIAccessMark jni(this); + jclass jcl = jni()->GetObjectClass(object.as_jobject()); + jobject result = jni()->CallObjectMethod(jcl, JNIJVMCI::Class_getName_method()); + name = JVMCIObject::create(result, is_hotspot()); } + return as_utf8_string(name); + } +} - // Check for {class loads, evolution, breakpoints} during compilation - result = validate_compile_task_dependencies(dependencies, compiled_code, env, &failure_detail); - if (result != JVMCIEnv::ok) { - // While not a true deoptimization, it is a preemptive decompile. - MethodData* mdp = method()->method_data(); - if (mdp != NULL) { - mdp->inc_decompile_count(); -#ifdef ASSERT - if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) { - ResourceMark m; - tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string()); - } -#endif - } +JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) { + JVMCIObject method_object; + if (method() == NULL) { + return method_object; + } + + Thread* THREAD = Thread::current(); + jmetadata handle = JVMCI::allocate_handle(method); + jboolean exception = false; + if (is_hotspot()) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_long((jlong) handle); + JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass(), + vmSymbols::fromMetaspace_name(), + vmSymbols::method_fromMetaspace_signature(), &args, THREAD); + if (HAS_PENDING_EXCEPTION) { + exception = true; + } else { + method_object = wrap((oop)result.get_jobject()); + } + } else { + JNIAccessMark jni(this); + method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(), + JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(), + (jlong) handle)); + exception = jni()->ExceptionCheck(); + } + + if (exception) { + JVMCI::release_handle(handle); + return JVMCIObject(); + } + + assert(asMethod(method_object) == method(), "must be"); + if (get_HotSpotResolvedJavaMethodImpl_metadataHandle(method_object) != (jlong) handle) { + JVMCI::release_handle(handle); + } + assert(!method_object.is_null(), "must be"); + return method_object; +} + +JVMCIObject JVMCIEnv::get_jvmci_type(JVMCIKlassHandle& klass, JVMCI_TRAPS) { + JVMCIObject type; + if (klass.is_null()) { + return type; + } +#ifdef INCLUDE_ALL_GCS + if (UseG1GC) { + // The klass might have come from a weak location so enqueue + // the Class to make sure it's noticed by G1 + G1SATBCardTableModRefBS::enqueue(klass()->java_mirror()); + } +#endif // Klass* don't require tracking as Metadata* + + jlong pointer = (jlong) klass(); + JavaThread* THREAD = JavaThread::current(); + JVMCIObject signature = create_string(klass->signature_name(), JVMCI_CHECK_(JVMCIObject())); + jboolean exception = false; + if (is_hotspot()) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_long(pointer); + args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(signature))); + JavaCalls::call_static(&result, + HotSpotJVMCI::HotSpotResolvedObjectTypeImpl::klass(), + vmSymbols::fromMetaspace_name(), + vmSymbols::klass_fromMetaspace_signature(), &args, THREAD); - // All buffers in the CodeBuffer are allocated in the CodeCache. - // If the code buffer is created on each compile attempt - // as in C2, then it must be freed. - //code_buffer->free_blob(); + if (HAS_PENDING_EXCEPTION) { + exception = true; } else { - ImplicitExceptionTable implicit_tbl; - nm = nmethod::new_nmethod(method, - compile_id, - entry_bci, - offsets, - orig_pc_offset, - debug_info, dependencies, code_buffer, - frame_words, oop_map_set, - handler_table, &implicit_tbl, - compiler, comp_level, - JNIHandles::make_weak_global(installed_code), - JNIHandles::make_weak_global(speculation_log)); - - // Free codeBlobs - //code_buffer->free_blob(); - if (nm == NULL) { - // The CodeCache is full. Print out warning and disable compilation. - { - MutexUnlocker ml(Compile_lock); - MutexUnlocker locker(MethodCompileQueue_lock); - CompileBroker::handle_full_code_cache(CodeCache::get_code_blob_type(comp_level)); - } - } else { - nm->set_has_unsafe_access(has_unsafe_access); - nm->set_has_wide_vectors(has_wide_vector); + type = wrap((oop)result.get_jobject()); + } + } else { + JNIAccessMark jni(this); - // Record successful registration. - // (Put nm into the task handle *before* publishing to the Java heap.) - CompileTask* task = env == NULL ? NULL : env->task(); - if (task != NULL) { - task->set_code(nm); - } + HandleMark hm(THREAD); + type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(), + JNIJVMCI::HotSpotResolvedObjectTypeImpl_fromMetaspace_method(), + pointer, signature.as_jstring())); + exception = jni()->ExceptionCheck(); + } + if (exception) { + return JVMCIObject(); + } - if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) { - if (entry_bci == InvocationEntryBci) { - if (TieredCompilation) { - // If there is an old version we're done with it - CompiledMethod* old = method->code(); - if (TraceMethodReplacement && old != NULL) { - ResourceMark rm; - char *method_name = method->name_and_sig_as_C_string(); - tty->print_cr("Replacing method %s", method_name); - } - if (old != NULL ) { - old->make_not_entrant(); - } - } - if (TraceNMethodInstalls) { - ResourceMark rm; - char *method_name = method->name_and_sig_as_C_string(); - ttyLocker ttyl; - tty->print_cr("Installing method (%d) %s [entry point: %p]", - comp_level, - method_name, nm->entry_point()); - } - // Allow the code to be executed - method->set_code(method, nm); - } else { - if (TraceNMethodInstalls ) { - ResourceMark rm; - char *method_name = method->name_and_sig_as_C_string(); - ttyLocker ttyl; - tty->print_cr("Installing osr method (%d) %s @ %d", - comp_level, - method_name, - entry_bci); - } - InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm); - } - } - nm->make_in_use(); - } - result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full; + assert(type.is_non_null(), "must have result"); + return type; +} + +JVMCIObject JVMCIEnv::get_jvmci_constant_pool(constantPoolHandle cp, JVMCI_TRAPS) { + JVMCIObject cp_object; + jmetadata handle = JVMCI::allocate_handle(cp); + jboolean exception = false; + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_long((jlong) handle); + JavaCalls::call_static(&result, + HotSpotJVMCI::HotSpotConstantPool::klass(), + vmSymbols::fromMetaspace_name(), + vmSymbols::constantPool_fromMetaspace_signature(), &args, THREAD); + if (HAS_PENDING_EXCEPTION) { + exception = true; + } else { + cp_object = wrap((oop)result.get_jobject()); + } + } else { + JNIAccessMark jni(this); + cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(), + JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(), + (jlong) handle)); + exception = jni()->ExceptionCheck(); + } + + if (exception) { + JVMCI::release_handle(handle); + return JVMCIObject(); + } + + assert(!cp_object.is_null(), "must be"); + // Constant pools aren't cached so this is always a newly created object using the handle + assert(get_HotSpotConstantPool_metadataHandle(cp_object) == (jlong) handle, "must use same handle"); + return cp_object; +} + +JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject())); + return wrap(result); + } else { + JNIAccessMark jni(this); + jbooleanArray result = jni()->NewBooleanArray(length); + return wrap(result); + } +} + +JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject())); + return wrap(result); + } else { + JNIAccessMark jni(this); + jbyteArray result = jni()->NewByteArray(length); + return wrap(result); + } +} + +JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlassObj ())->array_klass(CHECK_(JVMCIObject())); + objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject())); + return wrap(result); + } else { + JNIAccessMark jni(this); + jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), NULL); + return wrap(result); + } +} + +JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject())); + return wrap(result); + } else { + JNIAccessMark jni(this); + jintArray result = jni()->NewIntArray(length); + return wrap(result); + } +} + +JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject())); + return wrap(result); + } else { + JNIAccessMark jni(this); + jlongArray result = jni()->NewLongArray(length); + return wrap(result); + } +} + +JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject())); + oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject())); + HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name)); + HotSpotJVMCI::VMField::set_type(this, obj, HotSpotJVMCI::resolve(type)); + HotSpotJVMCI::VMField::set_offset(this, obj, offset); + HotSpotJVMCI::VMField::set_address(this, obj, address); + HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value)); + return wrap(obj); + } else { + JNIAccessMark jni(this); + jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(), + JNIJVMCI::VMField::constructor(), + get_jobject(name), get_jobject(type), offset, address, get_jobject(value)); + return wrap(result); + } +} + +JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject())); + oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject())); + HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name)); + HotSpotJVMCI::VMFlag::set_type(this, obj, HotSpotJVMCI::resolve(type)); + HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value)); + return wrap(obj); + } else { + JNIAccessMark jni(this); + jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(), + JNIJVMCI::VMFlag::constructor(), + get_jobject(name), get_jobject(type), get_jobject(value)); + return wrap(result); + } +} + +JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject())); + oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject())); + HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass)); + HotSpotJVMCI::VMIntrinsicMethod::set_name(this, obj, HotSpotJVMCI::resolve(name)); + HotSpotJVMCI::VMIntrinsicMethod::set_descriptor(this, obj, HotSpotJVMCI::resolve(descriptor)); + HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id); + return wrap(obj); + } else { + JNIAccessMark jni(this); + jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(), + JNIJVMCI::VMIntrinsicMethod::constructor(), + get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id); + return wrap(result); + } +} + +JVMCIObject JVMCIEnv::new_HotSpotStackFrameReference(JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_(JVMCIObject())); + oop obj = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance(CHECK_(JVMCIObject())); + return wrap(obj); + } else { + ShouldNotReachHere(); + return JVMCIObject(); + } +} +JVMCIObject JVMCIEnv::new_JVMCIError(JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + HotSpotJVMCI::JVMCIError::klass()->initialize(CHECK_(JVMCIObject())); + oop obj = HotSpotJVMCI::JVMCIError::klass()->allocate_instance(CHECK_(JVMCIObject())); + return wrap(obj); + } else { + ShouldNotReachHere(); + return JVMCIObject(); + } +} + + +JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) { + JavaThread* THREAD = JavaThread::current(); + Handle obj = Handle(THREAD, objOop); + if (obj.is_null()) { + return JVMCIObject(); + } + if (is_hotspot()) { + HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->initialize(CHECK_(JVMCIObject())); + oop constant = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->allocate_instance(CHECK_(JVMCIObject())); + HotSpotJVMCI::DirectHotSpotObjectConstantImpl::set_object(this, constant, obj()); + HotSpotJVMCI::HotSpotObjectConstantImpl::set_compressed(this, constant, compressed); + return wrap(constant); + } else { + jlong handle = make_handle(obj); + JNIAccessMark jni(this); + jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(), + JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(), + handle, compressed, dont_register); + return wrap(result); + } +} + + +Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) { + if (constant.is_null()) { + return Handle(); + } + JavaThread* THREAD = JavaThread::current(); + if (is_hotspot()) { + assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type"); + oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant)); + return Handle(THREAD, obj); + } else { + assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type"); + jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant); + oop result = resolve_handle(object_handle); + if (result == NULL) { + JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle()); } + return Handle(THREAD, result); } +} + +JVMCIObject JVMCIEnv::wrap(jobject object) { + return JVMCIObject::create(object, is_hotspot()); +} + +jlong JVMCIEnv::make_handle(Handle obj) { + assert(!obj.is_null(), "should only create handle for non-NULL oops"); + jobject handle = JVMCI::make_global(obj); + return (jlong) handle; +} - // String creation must be done outside lock - if (failure_detail != NULL) { - // A failure to allocate the string is silently ignored. - Handle message = java_lang_String::create_from_str(failure_detail, THREAD); - HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message()); +oop JVMCIEnv::resolve_handle(jlong objectHandle) { + assert(objectHandle != 0, "should be a valid handle"); + oop obj = *((oopDesc**)objectHandle); + if (obj != NULL) { + oopDesc::verify(obj); } + return obj; +} - // JVMTI -- compiled method notification (must be done outside lock) - if (nm != NULL) { - nm->post_compiled_method_load_event(); +JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) { + if (is_hotspot()) { + JavaThread* THREAD = JavaThread::current(); + Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject())); + return HotSpotJVMCI::wrap(result()); + } else { + jobject result; + jboolean exception = false; + { + JNIAccessMark jni(this); + result = jni()->NewStringUTF(str); + exception = jni()->ExceptionCheck(); + } + return wrap(result); + } +} + +bool JVMCIEnv::equals(JVMCIObject a, JVMCIObject b) { + if (is_hotspot()) { + return HotSpotJVMCI::resolve(a) == HotSpotJVMCI::resolve(b); + } else { + JNIAccessMark jni(this); + return jni()->IsSameObject(a.as_jobject(), b.as_jobject()) != 0; + } +} - if (env == NULL) { - // This compile didn't come through the CompileBroker so perform the printing here - DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler); - nm->maybe_print_nmethod(directive); - DirectivesStack::release(directive); +BasicType JVMCIEnv::kindToBasicType(JVMCIObject kind, JVMCI_TRAPS) { + if (kind.is_null()) { + JVMCI_THROW_(NullPointerException, T_ILLEGAL); + } + jchar ch = get_JavaKind_typeChar(kind); + switch(ch) { + case 'Z': return T_BOOLEAN; + case 'B': return T_BYTE; + case 'S': return T_SHORT; + case 'C': return T_CHAR; + case 'I': return T_INT; + case 'F': return T_FLOAT; + case 'J': return T_LONG; + case 'D': return T_DOUBLE; + case 'A': return T_OBJECT; + case '-': return T_ILLEGAL; + default: + JVMCI_ERROR_(T_ILLEGAL, "unexpected Kind: %c", ch); + } +} + +void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS) { + // Ensure that all updates to the InstalledCode fields are consistent. + if (get_InstalledCode_address(installed_code) != 0) { + JVMCI_THROW_MSG(InternalError, "InstalledCode instance already in use"); + } + if (!isa_HotSpotInstalledCode(installed_code)) { + JVMCI_THROW_MSG(InternalError, "InstalledCode instance must be a subclass of HotSpotInstalledCode"); + } + + // Ignore the version which can stay at 0 + if (cb->is_nmethod()) { + nmethod* nm = cb->as_nmethod_or_null(); + if (!nm->is_alive()) { + JVMCI_THROW_MSG(InternalError, "nmethod has been reclaimed"); } + if (nm->is_in_use()) { + set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_entry_point()); + } + } else { + set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin()); } + set_InstalledCode_address(installed_code, (jlong) cb); + set_HotSpotInstalledCode_size(installed_code, cb->size()); + set_HotSpotInstalledCode_codeStart(installed_code, (jlong) cb->code_begin()); + set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size()); +} - return result; + +void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS) { + if (mirror.is_null()) { + JVMCI_THROW(NullPointerException); + } + + jlong nativeMethod = get_InstalledCode_address(mirror); + nmethod* nm = JVMCIENV->asNmethod(mirror); + if (nm == NULL) { + // Nothing to do + return; + } + + Thread* THREAD = Thread::current(); + if (!mirror.is_hotspot() && !THREAD->is_Java_thread()) { + // Calling back into native might cause the execution to block, so only allow this when calling + // from a JavaThread, which is the normal case anyway. + JVMCI_THROW_MSG(IllegalArgumentException, + "Cannot invalidate HotSpotNmethod object in shared library VM heap from non-JavaThread"); + } + + nmethodLocker nml(nm); + if (nm->is_alive()) { + // Invalidating the HotSpotNmethod means we want the nmethod + // to be deoptimized. + nm->mark_for_deoptimization(); + VM_Deoptimize op; + VMThread::execute(&op); + } + + // A HotSpotNmethod instance can only reference a single nmethod + // during its lifetime so simply clear it here. + set_InstalledCode_address(mirror, 0); +} + +Klass* JVMCIEnv::asKlass(JVMCIObject obj) { + return (Klass*) get_HotSpotResolvedObjectTypeImpl_metadataPointer(obj); +} + +Method* JVMCIEnv::asMethod(JVMCIObject obj) { + Method** metadataHandle = (Method**) get_HotSpotResolvedJavaMethodImpl_metadataHandle(obj); + return *metadataHandle; } + +ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) { + ConstantPool** metadataHandle = (ConstantPool**) get_HotSpotConstantPool_metadataHandle(obj); + return *metadataHandle; +} + + +CodeBlob* JVMCIEnv::asCodeBlob(JVMCIObject obj) { + address code = (address) get_InstalledCode_address(obj); + if (code == NULL) { + return NULL; + } + if (isa_HotSpotNmethod(obj)) { + jlong compile_id_snapshot = get_HotSpotNmethod_compileIdSnapshot(obj); + if (compile_id_snapshot != 0L) { + // A HotSpotNMethod not in an nmethod's oops table so look up + // the nmethod and then update the fields based on its state. + CodeBlob* cb = CodeCache::find_blob_unsafe(code); + if (cb == (CodeBlob*) code) { + // Found a live CodeBlob with the same address, make sure it's the same nmethod + nmethod* nm = cb->as_nmethod_or_null(); + if (nm != NULL && nm->compile_id() == compile_id_snapshot) { + if (!nm->is_alive()) { + // Break the links from the mirror to the nmethod + set_InstalledCode_address(obj, 0); + set_InstalledCode_entryPoint(obj, 0); + } else if (nm->is_not_entrant()) { + // Zero the entry point so that the nmethod + // cannot be invoked by the mirror but can + // still be deoptimized. + set_InstalledCode_entryPoint(obj, 0); + } + return cb; + } + } + // Clear the InstalledCode fields of this HotSpotNmethod + // that no longer refers to an nmethod in the code cache. + set_InstalledCode_address(obj, 0); + set_InstalledCode_entryPoint(obj, 0); + return NULL; + } + } + return (CodeBlob*) code; +} + + +// Generate implementations for the initialize, new, isa, get and set methods for all the types and +// fields declared in the JVMCI_CLASSES_DO macro. + +#define START_CLASS(className, fullClassName) \ + void JVMCIEnv::className##_initialize(JVMCI_TRAPS) { \ + if (is_hotspot()) { \ + HotSpotJVMCI::className::initialize(JVMCI_CHECK); \ + } else { \ + JNIJVMCI::className::initialize(JVMCI_CHECK); \ + } \ + } \ + JVMCIObjectArray JVMCIEnv::new_##className##_array(int length, JVMCI_TRAPS) { \ + if (is_hotspot()) { \ + Thread* THREAD = Thread::current(); \ + objArrayOop array = oopFactory::new_objArray(HotSpotJVMCI::className::klass(), length, CHECK_(JVMCIObject())); \ + return (JVMCIObjectArray) wrap(array); \ + } else { \ + JNIAccessMark jni(this); \ + jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::className::clazz(), NULL); \ + return wrap(result); \ + } \ + } \ + bool JVMCIEnv::isa_##className(JVMCIObject object) { \ + if (is_hotspot()) { \ + return HotSpotJVMCI::className::is_instance(this, object); \ + } else { \ + return JNIJVMCI::className::is_instance(this, object); \ + } \ + } + +#define END_CLASS + +#define FIELD(className, name, type, accessor, cast) \ + type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \ + if (is_hotspot()) { \ + return HotSpotJVMCI::className::get_##name(this, obj); \ + } else { \ + return JNIJVMCI::className::get_##name(this, obj); \ + } \ + } \ + void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \ + if (is_hotspot()) { \ + HotSpotJVMCI::className::set_##name(this, obj, x); \ + } else { \ + JNIJVMCI::className::set_##name(this, obj, x); \ + } \ + } + +#define EMPTY_CAST +#define CHAR_FIELD(className, name) FIELD(className, name, jchar, Char, EMPTY_CAST) +#define INT_FIELD(className, name) FIELD(className, name, jint, Int, EMPTY_CAST) +#define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, Boolean, EMPTY_CAST) +#define LONG_FIELD(className, name) FIELD(className, name, jlong, Long, EMPTY_CAST) +#define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, Float, EMPTY_CAST) + +#define OBJECT_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST) +#define OBJECTARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray)) +#define PRIMARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray)) + +#define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject)) +#define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray)) + +#define OOPISH_FIELD(className, name, type, accessor, cast) \ + type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \ + if (is_hotspot()) { \ + return HotSpotJVMCI::className::get_##name(this, obj); \ + } else { \ + return JNIJVMCI::className::get_##name(this, obj); \ + } \ + } \ + void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \ + if (is_hotspot()) { \ + HotSpotJVMCI::className::set_##name(this, obj, x); \ + } else { \ + JNIJVMCI::className::set_##name(this, obj, x); \ + } \ + } + +#define STATIC_OOPISH_FIELD(className, name, type, accessor, cast) \ + type JVMCIEnv::get_##className##_##name() { \ + if (is_hotspot()) { \ + return HotSpotJVMCI::className::get_##name(this); \ + } else { \ + return JNIJVMCI::className::get_##name(this); \ + } \ + } \ + void JVMCIEnv::set_##className##_##name(type x) { \ + if (is_hotspot()) { \ + HotSpotJVMCI::className::set_##name(this, x); \ + } else { \ + JNIJVMCI::className::set_##name(this, x); \ + } \ + } + +#define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast) \ + type JVMCIEnv::get_##className##_##name() { \ + if (is_hotspot()) { \ + return HotSpotJVMCI::className::get_##name(this); \ + } else { \ + return JNIJVMCI::className::get_##name(this); \ + } \ + } \ + void JVMCIEnv::set_##className##_##name(type x) { \ + if (is_hotspot()) { \ + HotSpotJVMCI::className::set_##name(this, x); \ + } else { \ + JNIJVMCI::className::set_##name(this, x); \ + } \ + } +#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST) +#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST) +#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) +#define CONSTRUCTOR(className, signature) + +JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR) + +#undef START_CLASS +#undef END_CLASS +#undef METHOD +#undef CONSTRUCTOR +#undef FIELD +#undef CHAR_FIELD +#undef INT_FIELD +#undef BOOLEAN_FIELD +#undef LONG_FIELD +#undef FLOAT_FIELD +#undef OBJECT_FIELD +#undef PRIMARRAY_FIELD +#undef OBJECTARRAY_FIELD +#undef STATIC_OOPISH_FIELD +#undef STATIC_OBJECT_FIELD +#undef STATIC_OBJECTARRAY_FIELD +#undef STATIC_INT_FIELD +#undef STATIC_BOOLEAN_FIELD +#undef EMPTY_CAST