src/hotspot/share/jvmci/jvmciEnv.cpp
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File open Cdiff src/hotspot/share/jvmci/jvmciEnv.cpp

src/hotspot/share/jvmci/jvmciEnv.cpp

Print this page

        

*** 23,77 **** */ #include "precompiled.hpp" #include "jvmci/jvmciEnv.hpp" #include "classfile/javaAssertions.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" #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 "utilities/dtrace.hpp" #include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciJavaClasses.hpp" ! JVMCIEnv::JVMCIEnv(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) ! { // 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; _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables() ? 1 : 0; _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0; _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0; } ! bool JVMCIEnv::jvmti_state_changed() const { if (!jvmti_can_access_local_variables() && JvmtiExport::can_access_local_variables()) { return true; } if (!jvmti_can_hotswap_or_post_breakpoint() && --- 23,76 ---- */ #include "precompiled.hpp" #include "jvmci/jvmciEnv.hpp" #include "classfile/javaAssertions.hpp" + #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.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/universe.hpp" #include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" ! #include "runtime/javaCalls.hpp" #include "utilities/dtrace.hpp" #include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciJavaClasses.hpp" ! #include <string.h> ! ! 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) { // 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; _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables() ? 1 : 0; _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0; _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0; } ! bool JVMCICompileState::jvmti_state_changed() const { if (!jvmti_can_access_local_variables() && JvmtiExport::can_access_local_variables()) { return true; } if (!jvmti_can_hotswap_or_post_breakpoint() &&
*** 87,620 **** return true; } 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(); } - if (!accessing_klass->is_instance_klass()) { - return true; } ! 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); } } ! // 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); } } ! 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; } } } } ! return found_klass; } ! // ------------------------------------------------------------------ ! Klass* JVMCIEnv::get_klass_by_name(Klass* accessing_klass, ! Symbol* klass_name, ! bool require_local) { 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; } else { ! // Linked locally, and we must also check public/private, etc. ! is_accessible = check_klass_accessibility(accessor, k); } - if (!is_accessible) { - return NULL; } ! return k; } ! // It is known to be accessible, since it was found in the constant pool. ! is_accessible = true; ! return klass; } ! // ------------------------------------------------------------------ ! // 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); } ! // ------------------------------------------------------------------ ! // 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; } - // Perform the field lookup. - Klass* canonical_holder = - InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc); - if (canonical_holder == NULL) { - return; } ! assert(canonical_holder == field_desc.field_holder(), "just checking"); } ! // ------------------------------------------------------------------ ! // 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); } ! // ------------------------------------------------------------------ ! // 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; } ! // ------------------------------------------------------------------ ! 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); } ! return NULL; } ! 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; } } ! break; ! default: ! break; } } ! 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; } } ! // Either the declared holder was not loaded, or the method could ! // not be found. ! return NULL; } ! // ------------------------------------------------------------------ ! InstanceKlass* JVMCIEnv::get_instance_klass_for_declared_method_holder(Klass* method_holder) { ! // For the case of <array>.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(); } else { ! ShouldNotReachHere(); } - return NULL; } ! // ------------------------------------------------------------------ ! 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); } ! // ------------------------------------------------------------------ ! // 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(); } } ! // 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 } ! // 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(); ! } 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); ! ! // 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); ! } ! ! 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; } } ! // 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()); } ! // JVMTI -- compiled method notification (must be done outside lock) ! if (nm != NULL) { ! nm->post_compiled_method_load_event(); ! 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); } } ! return result; } --- 86,1406 ---- return true; } return false; } ! 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"); } } ! // 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"); } } ! 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; + } ! 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; } } + + // 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); + } } + } + + 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); ! } ! } ! ! // 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; ! 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 { ! 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); } } ! } ! } 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); ! } ! } } ! 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); ! } } ! 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; + } + } + 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); ! } } ! 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); ! } ! } ! ! 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); ! } ! } ! ! 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); ! } } ! ! 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); ! } } ! 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); + } + } ! 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); + } + } ! 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(); } } ! 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(); + + 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); ! } ! } ! 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())); ! } } ! 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())); } } + 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 { + JNIAccessMark jni(this); + return wrap(jni()->NewWeakGlobalRef(object.as_jobject())); + } + } ! void JVMCIEnv::destroy_local(JVMCIObject object) { ! if (is_hotspot()) { ! JNIHandles::destroy_local(object.as_jobject()); ! } else { ! JNIAccessMark jni(this); ! jni()->DeleteLocalRef(object.as_jobject()); ! } } ! void JVMCIEnv::destroy_global(JVMCIObject object) { ! if (is_hotspot()) { ! JNIHandles::destroy_global(object.as_jobject()); ! } else { ! JNIAccessMark jni(this); ! jni()->DeleteGlobalRef(object.as_jobject()); ! } ! } ! ! 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); ! } ! } ! 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); ! if (HAS_PENDING_EXCEPTION) { ! exception = true; ! } else { ! type = wrap((oop)result.get_jobject()); } ! } else { ! JNIAccessMark jni(this); ! ! 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(); } ! ! 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; ! } ! ! 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; ! } ! ! 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; ! } ! } ! ! 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()); ! } ! ! ! 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
src/hotspot/share/jvmci/jvmciEnv.cpp
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File