/*
 * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "compiler/compilerOracle.hpp"
#include "compiler/compileTask.hpp"
#include "jvm_io.h"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/os.hpp"
#include "jvmci/jniAccessMark.inline.hpp"
#include "jvmci/jvmciCompiler.hpp"
#include "jvmci/jvmciRuntime.hpp"

jbyte* JVMCIEnv::_serialized_saved_properties = nullptr;
int JVMCIEnv::_serialized_saved_properties_len = 0;

JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler):
  _task(task),
  _compiler(compiler),
  _retryable(true),
  _failure_reason(nullptr),
  _failure_reason_on_C_heap(false) {
  // Get Jvmti capabilities under lock to get consistent values.
  MutexLocker mu(JvmtiThreadState_lock);
  _jvmti_redefinition_count             = JvmtiExport::redefinition_count();
  _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;
  _target_method_is_old                 = _task != nullptr && _task->method()->is_old();
  if (task->is_blocking()) {
    task->set_blocking_jvmci_compile_state(this);
  }
}

void JVMCICompileState::set_failure(bool retryable, const char* reason, bool reason_on_C_heap) {
  if (_failure_reason != nullptr && _failure_reason_on_C_heap) {
      os::free((void*) _failure_reason);
  }
  _failure_reason = reason;
  _failure_reason_on_C_heap = reason_on_C_heap;
  _retryable = retryable;
}

void JVMCICompileState::notify_libjvmci_oome() {
  const char* msg = "Out of memory initializing libjvmci or attaching it to the current thread";
  set_failure(true, msg);
  _compiler->on_upcall(msg);
}

// Update global JVMCI compilation ticks after 512 thread-local JVMCI compilation ticks.
// This mitigates the overhead of the atomic operation used for the global update.
#define THREAD_TICKS_PER_GLOBAL_TICKS (2 << 9)
#define THREAD_TICKS_PER_GLOBAL_TICKS_MASK (THREAD_TICKS_PER_GLOBAL_TICKS - 1)

void JVMCICompileState::inc_compilation_ticks() {
  if ((++_compilation_ticks & THREAD_TICKS_PER_GLOBAL_TICKS_MASK) == 0) {
    _compiler->inc_global_compilation_ticks();
  }
}

bool JVMCICompileState::jvmti_state_changed() const {
  // Some classes were redefined
  if (jvmti_redefinition_count() != JvmtiExport::redefinition_count()) {
    return true;
  }
  if (!jvmti_can_access_local_variables() &&
      JvmtiExport::can_access_local_variables()) {
    return true;
  }
  if (!jvmti_can_hotswap_or_post_breakpoint() &&
      JvmtiExport::can_hotswap_or_post_breakpoint()) {
    return true;
  }
  if (!jvmti_can_post_on_exceptions() &&
      JvmtiExport::can_post_on_exceptions()) {
    return true;
  }
  if (!jvmti_can_pop_frame() &&
      JvmtiExport::can_pop_frame()) {
    return true;
  }
  return false;
}

jbyte* JVMCIEnv::get_serialized_saved_properties(int& props_len, TRAPS) {
  jbyte* props = _serialized_saved_properties;
  if (props == nullptr) {
    // load VMSupport
    Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport();
    Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK_NULL);

    InstanceKlass* ik = InstanceKlass::cast(k);
    if (ik->should_be_initialized()) {
      ik->initialize(CHECK_NULL);
    }

    // invoke the serializeSavedPropertiesToByteArray method
    JavaValue result(T_OBJECT);
    JavaCallArguments args;

    Symbol* signature = vmSymbols::void_byte_array_signature();
    JavaCalls::call_static(&result,
                           ik,
                           vmSymbols::serializeSavedPropertiesToByteArray_name(),
                           signature,
                           &args,
                           CHECK_NULL);

    oop res = result.get_oop();
    assert(res->is_typeArray(), "must be");
    assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be");
    typeArrayOop ba = typeArrayOop(res);
    props_len = ba->length();

    // Copy serialized saved properties from HotSpot object into C heap
    props = NEW_C_HEAP_ARRAY(jbyte, props_len, mtJVMCI);
    memcpy(props, ba->byte_at_addr(0), props_len);

    _serialized_saved_properties_len = props_len;
    _serialized_saved_properties = props;
  } else {
    props_len = _serialized_saved_properties_len;
  }
  return props;
}

void JVMCIEnv::copy_saved_properties(jbyte* properties, int properties_len, JVMCI_TRAPS) {
  assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image");
  JavaThread* thread = JavaThread::current(); // For exception macros.

  // Copy native buffer into shared library object
  JVMCIPrimitiveArray buf = new_byteArray(properties_len, this);
  if (has_pending_exception()) {
    _runtime->fatal_exception(JVMCIENV, "Error in copy_saved_properties");
  }
  copy_bytes_from(properties, buf, 0, properties_len);
  if (has_pending_exception()) {
    _runtime->fatal_exception(JVMCIENV, "Error in copy_saved_properties");
  }

  // Initialize saved properties in shared library
  jclass servicesClass = JNIJVMCI::Services::clazz();
  jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method();
  bool exception = false;
  {
    JNIAccessMark jni(this, thread);
    jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject());
    exception = jni()->ExceptionCheck();
  }
  if (exception) {
    _runtime->fatal_exception(JVMCIENV, "Error calling jdk.vm.ci.services.Services.initializeSavedProperties");
  }
}

void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, bool jni_enomem_is_fatal) {
  assert(thread != nullptr, "npe");
  _env = nullptr;
  _pop_frame_on_close = false;
  _detach_on_close = false;
  if (!UseJVMCINativeLibrary) {
    // In HotSpot mode, JNI isn't used at all.
    _runtime = JVMCI::java_runtime();
    _is_hotspot = true;
    return;
  }

  if (parent_env != nullptr) {
    // 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.
    _is_hotspot = thread->jni_environment() == parent_env;
    if (_is_hotspot) {
      // Select the Java runtime
      _runtime = JVMCI::java_runtime();
      return;
    }
    _runtime = thread->libjvmci_runtime();
    assert(_runtime != nullptr, "npe");
    _env = parent_env;
    return;
  }

  // Running in JVMCI shared library mode so ensure the shared library
  // is loaded and initialized and get a shared library JNIEnv
  _is_hotspot = false;

  _runtime = JVMCI::compiler_runtime(thread);
  int create_JavaVM_err = JNI_OK;
  _env = _runtime->init_shared_library_javavm(&create_JavaVM_err);
  if (_env != nullptr) {
    // Creating the JVMCI shared library VM also attaches the current thread
    _detach_on_close = true;
  } else if (create_JavaVM_err != JNI_OK) {
    if (!jni_enomem_is_fatal && create_JavaVM_err == JNI_ENOMEM) {
      _jni_enomem = true;
      return;
    } else {
      fatal("JNI_CreateJavaVM failed with return value %d", create_JavaVM_err);
    }
  } else {
    _runtime->GetEnv(thread, (void**)&parent_env, JNI_VERSION_1_2);
    if (parent_env != nullptr) {
      // Even though there's a parent JNI env, there's no guarantee
      // it was opened by a JVMCIEnv scope and thus may not have
      // pushed a local JNI frame. As such, we use a new JNI local
      // frame in this scope to ensure local JNI refs are collected
      // in a timely manner after leaving this scope.
      _env = parent_env;
    } else {
      ResourceMark rm; // Thread name is resource allocated
      JavaVMAttachArgs attach_args;
      attach_args.version = JNI_VERSION_1_2;
      attach_args.name = const_cast<char*>(thread->name());
      attach_args.group = nullptr;
      jint attach_result = _runtime->AttachCurrentThread(thread, (void**) &_env, &attach_args);
      if (attach_result == JNI_OK) {
        _detach_on_close = true;
      } else if (!jni_enomem_is_fatal && attach_result == JNI_ENOMEM) {
        _env = nullptr;
        _jni_enomem = true;
        return;
      } else {
        fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
      }
    }
  }

  assert(_env != nullptr, "missing env");
  assert(_throw_to_caller == false, "must be");

  JNIAccessMark jni(this, thread);
  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::fatal_exception(this, message);
  }
  _pop_frame_on_close = true;
}

JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
    _throw_to_caller(false), _file(file), _line(line), _jni_enomem(false), _compile_state(compile_state) {
  // In case of JNI_ENOMEM, there's a good chance a subsequent attempt to create libjvmci or attach to it
  // might succeed. Other errors most likely indicate a non-recoverable error in the JVMCI runtime.
  bool jni_enomem_is_fatal = false;
  init_env_mode_runtime(thread, nullptr, jni_enomem_is_fatal);
  if (_jni_enomem) {
    compile_state->set_failure(true, "Out of memory while attaching JVMCI compiler to current thread");
  }
}

JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
    _throw_to_caller(false), _file(file), _line(line), _jni_enomem(false), _compile_state(nullptr) {
  init_env_mode_runtime(thread, nullptr);
}

JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
    _throw_to_caller(true), _file(file), _line(line), _jni_enomem(false), _compile_state(nullptr) {
  init_env_mode_runtime(thread, parent_env);
  assert(_env == nullptr || parent_env == _env, "mismatched JNIEnvironment");
}

void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fatal, const char* file, int line) {
  _compile_state = nullptr;
  _throw_to_caller = false;
  _file = file;
  _line = line;
  _jni_enomem = false;
  if (is_hotspot) {
    _env = nullptr;
    _pop_frame_on_close = false;
    _detach_on_close = false;
    _is_hotspot = true;
    _runtime = JVMCI::java_runtime();
  } else {
    init_env_mode_runtime(thread, nullptr, jni_enomem_is_fatal);
  }
}

// Prints a pending exception (if any) and its stack trace to st.
// Also partially logs the stack trace to the JVMCI event log.
void JVMCIEnv::describe_pending_exception(outputStream* st) {
  ResourceMark rm;
  char* stack_trace = nullptr;
  if (pending_exception_as_string(nullptr, (const char**) &stack_trace)) {
    st->print_raw_cr(stack_trace);

    // Use up to half the lines of the JVMCI event log to
    // show the stack trace.
    char* cursor = stack_trace;
    int line = 0;
    const int max_lines = LogEventsBufferEntries / 2;
    char* last_line = nullptr;
    while (*cursor != '\0') {
      char* eol = strchr(cursor, '\n');
      if (eol == nullptr) {
        if (line == max_lines - 1) {
          last_line = cursor;
        } else if (line < max_lines) {
          JVMCI_event_1("%s", cursor);
        }
        cursor = cursor + strlen(cursor);
      } else {
        *eol = '\0';
        if (line == max_lines - 1) {
          last_line = cursor;
        } else if (line < max_lines) {
          JVMCI_event_1("%s", cursor);
        }
        cursor = eol + 1;
      }
      line++;
    }
    if (last_line != nullptr) {
      if (line > max_lines) {
        JVMCI_event_1("%s [elided %d more stack trace lines]", last_line, line - max_lines);
      } else {
        JVMCI_event_1("%s", last_line);
      }
    }
  }
}

bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char** stack_trace) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  JVMCIObject to_string_obj;
  JVMCIObject stack_trace_obj;
  bool had_nested_exception = false;
  if (!is_hotspot()) {
    JNIAccessMark jni(this, THREAD);
    jthrowable ex = jni()->ExceptionOccurred();
    if (ex != nullptr) {
      jni()->ExceptionClear();
      jobjectArray pair = (jobjectArray) jni()->CallStaticObjectMethod(
        JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
        JNIJVMCI::HotSpotJVMCIRuntime::exceptionToString_method(),
        ex, to_string != nullptr, stack_trace != nullptr);
      if (jni()->ExceptionCheck()) {
        // As last resort, dump nested exception
        jni()->ExceptionDescribe();
        had_nested_exception = true;
      } else {
        guarantee(pair != nullptr, "pair is null");
        int len = jni()->GetArrayLength(pair);
        guarantee(len == 2, "bad len is %d", len);
        if (to_string != nullptr) {
          to_string_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 0), false);
        }
        if (stack_trace != nullptr) {
          stack_trace_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 1), false);
        }
      }
    } else {
      return false;
    }
  } else {
    if (HAS_PENDING_EXCEPTION) {
      Handle exception(THREAD, PENDING_EXCEPTION);
      CLEAR_PENDING_EXCEPTION;
      JavaCallArguments jargs;
      jargs.push_oop(exception);
      jargs.push_int(to_string != nullptr);
      jargs.push_int(stack_trace != nullptr);
      JavaValue result(T_OBJECT);
      JavaCalls::call_static(&result,
                              HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
                              vmSymbols::exceptionToString_name(),
                              vmSymbols::exceptionToString_signature(), &jargs, THREAD);
      if (HAS_PENDING_EXCEPTION) {
        Handle nested_exception(THREAD, PENDING_EXCEPTION);
        CLEAR_PENDING_EXCEPTION;
        java_lang_Throwable::print_stack_trace(nested_exception, tty);
        // Clear and ignore any exceptions raised during printing
        CLEAR_PENDING_EXCEPTION;
        had_nested_exception = true;
      } else {
        oop pair = result.get_oop();
        guarantee(pair->is_objArray(), "must be");
        objArrayOop pair_arr = objArrayOop(pair);
        int len = pair_arr->length();
        guarantee(len == 2, "bad len is %d", len);
        if (to_string != nullptr) {
          to_string_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(0));
        }
        if (stack_trace != nullptr) {
          stack_trace_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(1));
        }
      }
    } else {
      return false;
    }
  }
  if (had_nested_exception) {
    if (to_string != nullptr) {
      *to_string = "nested exception occurred converting exception to string";
    }
    if (stack_trace != nullptr) {
      *stack_trace = "nested exception occurred converting exception stack to string";
    }
  } else {
    if (to_string_obj.is_non_null()) {
      *to_string = as_utf8_string(to_string_obj);
    }
    if (stack_trace_obj.is_non_null()) {
      *stack_trace = as_utf8_string(stack_trace_obj);
    }
  }
  return true;
}


// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
class ExceptionTranslation: public StackObj {
 protected:
  enum DecodeFormat {
    _encoded_ok        = 0, // exception was successfully encoded into buffer
    _buffer_alloc_fail = 1, // native memory for buffer could not be allocated
    _encode_oome_fail  = 2, // OutOfMemoryError thrown during encoding
    _encode_fail       = 3  // some other problem occured during encoding. If buffer != 0,
                            // buffer contains a `struct { u4 len; char[len] desc}`
                            // describing the problem
  };

  JVMCIEnv*  _from_env; // Source of translation. Can be null.
  JVMCIEnv*  _to_env;   // Destination of translation. Never null.

  ExceptionTranslation(JVMCIEnv* from_env, JVMCIEnv* to_env) : _from_env(from_env), _to_env(to_env) {}

  // Encodes the exception in `_from_env` into `buffer`.
  // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
  // and the encoding was written to `buffer` otherwise returns -N.
  virtual int encode(JavaThread* THREAD, jlong buffer, int buffer_size) = 0;

  // Decodes the exception in `buffer` in `_to_env` and throws it.
  virtual void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) = 0;

 public:
  void doit(JavaThread* THREAD) {
    int buffer_size = 2048;
    while (true) {
      ResourceMark rm;
      jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jbyte, buffer_size);
      if (buffer == 0L) {
        JVMCI_event_1("error translating exception: translation buffer allocation failed");
        decode(THREAD, _buffer_alloc_fail, 0L);
        return;
      }
      int res = encode(THREAD, buffer, buffer_size);
      if (_to_env->has_pending_exception()) {
        // Propagate pending exception
        return;
      }
      if (res < 0) {
        int required_buffer_size = -res;
        if (required_buffer_size > buffer_size) {
          buffer_size = required_buffer_size;
        }
      } else {
        decode(THREAD, _encoded_ok, buffer);
        if (!_to_env->has_pending_exception()) {
          _to_env->throw_InternalError("decodeAndThrowThrowable should have thrown an exception");
        }
        return;
      }
    }
  }
};

// Translates an exception on the HotSpot heap to an exception on the shared library heap.
class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
 private:
  const Handle& _throwable;

  bool handle_pending_exception(JavaThread* THREAD, jlong buffer, int buffer_size) {
    if (HAS_PENDING_EXCEPTION) {
      Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
      Symbol *ex_name = throwable->klass()->name();
      CLEAR_PENDING_EXCEPTION;
      if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) {
        JVMCI_event_1("error translating exception: OutOfMemoryError");
        decode(THREAD, _encode_oome_fail, 0L);
      } else {
        char* char_buffer = (char*) buffer + 4;
        stringStream st(char_buffer, (size_t) buffer_size - 4);
        java_lang_Throwable::print_stack_trace(throwable, &st);
        u4 len = (u4) st.size();
        *((u4*) buffer) = len;
        JVMCI_event_1("error translating exception: %s", char_buffer);
        decode(THREAD, _encode_fail, buffer);
      }
      return true;
    }
    return false;
  }

  int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
    Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD);
    if (handle_pending_exception(THREAD, buffer, buffer_size)) {
      return 0;
    }
    JavaCallArguments jargs;
    jargs.push_oop(_throwable);
    jargs.push_long(buffer);
    jargs.push_int(buffer_size);
    JavaValue result(T_INT);
    JavaCalls::call_static(&result,
                            vmSupport,
                            vmSymbols::encodeThrowable_name(),
                            vmSymbols::encodeThrowable_signature(), &jargs, THREAD);
    if (handle_pending_exception(THREAD, buffer, buffer_size)) {
      return 0;
    }
    return result.get_jint();
  }

  void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) {
    JNIAccessMark jni(_to_env, THREAD);
    jni()->CallStaticVoidMethod(JNIJVMCI::VMSupport::clazz(),
                                JNIJVMCI::VMSupport::decodeAndThrowThrowable_method(),
                                format, buffer, false);
  }
 public:
  HotSpotToSharedLibraryExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) :
    ExceptionTranslation(hotspot_env, jni_env), _throwable(throwable) {}
};

// Translates an exception on the shared library heap to an exception on the HotSpot heap.
class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
 private:
  jthrowable _throwable;

  int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
    JNIAccessMark jni(_from_env, THREAD);
    int res = jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(),
                                      JNIJVMCI::VMSupport::encodeThrowable_method(),
                                      _throwable, buffer, buffer_size);
    if (jni()->ExceptionCheck()) {
      // Cannot get name of exception thrown as that can raise another exception.
      jni()->ExceptionClear();
      JVMCI_event_1("error translating exception: unknown error");
      decode(THREAD, _encode_fail, 0L);
      return 0;
    }
    return res;
  }

  void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) {
    Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, CHECK);
    JavaCallArguments jargs;
    jargs.push_int(format);
    jargs.push_long(buffer);
    jargs.push_int(true);
    JavaValue result(T_VOID);
    JavaCalls::call_static(&result,
                            vmSupport,
                            vmSymbols::decodeAndThrowThrowable_name(),
                            vmSymbols::decodeAndThrowThrowable_signature(), &jargs, THREAD);
  }
 public:
  SharedLibraryToHotSpotExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, jthrowable throwable) :
    ExceptionTranslation(jni_env, hotspot_env), _throwable(throwable) {}
};

void JVMCIEnv::translate_to_jni_exception(JavaThread* THREAD, const Handle& throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
  HotSpotToSharedLibraryExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD);
}

void JVMCIEnv::translate_from_jni_exception(JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
  SharedLibraryToHotSpotExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD);
}

jboolean JVMCIEnv::transfer_pending_exception_to_jni(JavaThread* THREAD, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
  if (HAS_PENDING_EXCEPTION) {
    Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
    CLEAR_PENDING_EXCEPTION;
    translate_to_jni_exception(THREAD, throwable, hotspot_env, jni_env);
    return true;
  }
  return false;
}

jboolean JVMCIEnv::transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer_env) {
  if (is_hotspot()) {
    return transfer_pending_exception_to_jni(THREAD, this, peer_env);
  }
  jthrowable ex = nullptr;
  {
    JNIAccessMark jni(this, THREAD);
    ex = jni()->ExceptionOccurred();
    if (ex != nullptr) {
      jni()->ExceptionClear();
    }
  }
  if (ex != nullptr) {
    translate_from_jni_exception(THREAD, ex, peer_env, this);
    return true;
  }
  return false;
}

JVMCIEnv::~JVMCIEnv() {
  if (_jni_enomem) {
    return;
  }
  if (_throw_to_caller) {
    if (is_hotspot()) {
      // Nothing to do
    } else {
      Thread* thread = Thread::current();
      if (thread->is_Java_thread()) {
        JavaThread* THREAD = JavaThread::cast(thread); // For exception macros.
        if (HAS_PENDING_EXCEPTION) {
          Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
          CLEAR_PENDING_EXCEPTION;
          translate_to_jni_exception(THREAD, throwable, nullptr, this);
        }
      }
    }
  } else {
    if (_pop_frame_on_close) {
      // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
      JNIAccessMark jni(this);
      jni()->PopLocalFrame(nullptr);
    }

    if (has_pending_exception()) {
      char message[256];
      jio_snprintf(message, 256, "Uncaught exception exiting %s JVMCIEnv scope entered at %s:%d",
          is_hotspot() ? "HotSpot" : "libjvmci", _file, _line);
      JVMCIRuntime::fatal_exception(this, message);
    }

    if (_detach_on_close) {
      _runtime->DetachCurrentThread(JavaThread::current());
    }
  }
}

jboolean JVMCIEnv::has_pending_exception() {
  if (is_hotspot()) {
    JavaThread* THREAD = JavaThread::current(); // For exception macros.
    return HAS_PENDING_EXCEPTION;
  } else {
    JNIAccessMark jni(this);
    return jni()->ExceptionCheck();
  }
}

void JVMCIEnv::clear_pending_exception() {
  if (is_hotspot()) {
    JavaThread* THREAD = JavaThread::current(); // For exception macros.
    CLEAR_PENDING_EXCEPTION;
  } else {
    JNIAccessMark jni(this);
    jni()->ExceptionClear();
  }
}

int JVMCIEnv::get_length(JVMCIArray array) {
  if (is_hotspot()) {
    return HotSpotJVMCI::resolve(array)->length();
  } else {
    JNIAccessMark jni(this);
    return jni()->GetArrayLength(get_jarray(array));
  }
}

JVMCIObject JVMCIEnv::get_object_at(JVMCIObjectArray array, int index) {
  if (is_hotspot()) {
    oop result = HotSpotJVMCI::resolve(array)->obj_at(index);
    return wrap(result);
  } else {
    JNIAccessMark jni(this);
    jobject result = jni()->GetObjectArrayElement(get_jobjectArray(array), index);
    return wrap(result);
  }
}

void JVMCIEnv::put_object_at(JVMCIObjectArray array, int index, JVMCIObject value) {
  if (is_hotspot()) {
    HotSpotJVMCI::resolve(array)->obj_at_put(index, HotSpotJVMCI::resolve(value));
  } else {
    JNIAccessMark jni(this);
    jni()->SetObjectArrayElement(get_jobjectArray(array), index, get_jobject(value));
  }
}

jboolean JVMCIEnv::get_bool_at(JVMCIPrimitiveArray array, int index) {
  if (is_hotspot()) {
    return HotSpotJVMCI::resolve(array)->bool_at(index);
  } else {
    JNIAccessMark jni(this);
    jboolean result;
    jni()->GetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &result);
    return result;
  }
}
void JVMCIEnv::put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value) {
  if (is_hotspot()) {
    HotSpotJVMCI::resolve(array)->bool_at_put(index, value);
  } else {
    JNIAccessMark jni(this);
    jni()->SetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &value);
  }
}

jbyte JVMCIEnv::get_byte_at(JVMCIPrimitiveArray array, int index) {
  if (is_hotspot()) {
    return HotSpotJVMCI::resolve(array)->byte_at(index);
  } else {
    JNIAccessMark jni(this);
    jbyte result;
    jni()->GetByteArrayRegion(array.as_jbyteArray(), index, 1, &result);
    return result;
  }
}
void JVMCIEnv::put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value) {
  if (is_hotspot()) {
    HotSpotJVMCI::resolve(array)->byte_at_put(index, value);
  } else {
    JNIAccessMark jni(this);
    jni()->SetByteArrayRegion(array.as_jbyteArray(), index, 1, &value);
  }
}

jint JVMCIEnv::get_int_at(JVMCIPrimitiveArray array, int index) {
  if (is_hotspot()) {
    return HotSpotJVMCI::resolve(array)->int_at(index);
  } else {
    JNIAccessMark jni(this);
    jint result;
    jni()->GetIntArrayRegion(array.as_jintArray(), index, 1, &result);
    return result;
  }
}
void JVMCIEnv::put_int_at(JVMCIPrimitiveArray array, int index, jint value) {
  if (is_hotspot()) {
    HotSpotJVMCI::resolve(array)->int_at_put(index, value);
  } else {
    JNIAccessMark jni(this);
    jni()->SetIntArrayRegion(array.as_jintArray(), index, 1, &value);
  }
}

jlong JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) {
  if (is_hotspot()) {
    return HotSpotJVMCI::resolve(array)->long_at(index);
  } else {
    JNIAccessMark jni(this);
    jlong result;
    jni()->GetLongArrayRegion(array.as_jlongArray(), index, 1, &result);
    return result;
  }
}
void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
  if (is_hotspot()) {
    HotSpotJVMCI::resolve(array)->long_at_put(index, value);
  } else {
    JNIAccessMark jni(this);
    jni()->SetLongArrayRegion(array.as_jlongArray(), index, 1, &value);
  }
}

void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
  if (length == 0) {
    return;
  }
  if (is_hotspot()) {
    memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
  } else {
    JNIAccessMark jni(this);
    jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
  }
}
void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
  if (length == 0) {
    return;
  }
  if (is_hotspot()) {
    memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
  } else {
    JNIAccessMark jni(this);
    jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
  }
}

void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
  if (length == 0) {
    return;
  }
  if (is_hotspot()) {
    memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
  } else {
    JNIAccessMark jni(this);
    jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
  }
}

jboolean JVMCIEnv::is_boxing_object(BasicType type, JVMCIObject object) {
  if (is_hotspot()) {
    return java_lang_boxing_object::is_instance(HotSpotJVMCI::resolve(object), type);
  } else {
    JNIAccessMark jni(this);
    return jni()->IsInstanceOf(get_jobject(object), JNIJVMCI::box_class(type));
  }
}

// Get the primitive value from a Java boxing object.  It's hard error to
// pass a non-primitive BasicType.
jvalue JVMCIEnv::get_boxed_value(BasicType type, JVMCIObject object) {
  jvalue result;
  if (is_hotspot()) {
    if (java_lang_boxing_object::get_value(HotSpotJVMCI::resolve(object), &result) == T_ILLEGAL) {
      ShouldNotReachHere();
    }
  } else {
    JNIAccessMark jni(this);
    jfieldID field = JNIJVMCI::box_field(type);
    switch (type) {
      case T_BOOLEAN: result.z = jni()->GetBooleanField(get_jobject(object), field); break;
      case T_BYTE:    result.b = jni()->GetByteField(get_jobject(object), field); break;
      case T_SHORT:   result.s = jni()->GetShortField(get_jobject(object), field); break;
      case T_CHAR:    result.c = jni()->GetCharField(get_jobject(object), field); break;
      case T_INT:     result.i = jni()->GetIntField(get_jobject(object), field); break;
      case T_LONG:    result.j = jni()->GetLongField(get_jobject(object), field); break;
      case T_FLOAT:   result.f = jni()->GetFloatField(get_jobject(object), field); break;
      case T_DOUBLE:  result.d = jni()->GetDoubleField(get_jobject(object), field); break;
      default:
        ShouldNotReachHere();
    }
  }
  return result;
}

// Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
BasicType JVMCIEnv::get_box_type(JVMCIObject object) {
  if (is_hotspot()) {
    return java_lang_boxing_object::basic_type(HotSpotJVMCI::resolve(object));
  } else {
    JNIAccessMark jni(this);
    jclass clazz = jni()->GetObjectClass(get_jobject(object));
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BOOLEAN))) return T_BOOLEAN;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BYTE))) return T_BYTE;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_SHORT))) return T_SHORT;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_CHAR))) return T_CHAR;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_INT))) return T_INT;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_LONG))) return T_LONG;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_FLOAT))) return T_FLOAT;
    if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_DOUBLE))) return T_DOUBLE;
    return T_ILLEGAL;
  }
}

// Create a boxing object of the appropriate primitive type.
JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) {
  switch (type) {
    case T_BOOLEAN:
    case T_BYTE:
    case T_CHAR:
    case T_SHORT:
    case T_INT:
    case T_LONG:
    case T_FLOAT:
    case T_DOUBLE:
      break;
    default:
      JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject());
  }
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
    return HotSpotJVMCI::wrap(box);
  } else {
    JNIAccessMark jni(this, THREAD);
    jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
    assert(box != nullptr, "");
    return wrap(box);
  }
}

const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
  if (is_hotspot()) {
    return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
  } else {
    JNIAccessMark jni(this);
    jstring jstr = str.as_jstring();
    int length = jni()->GetStringLength(jstr);
    int utf8_length = jni()->GetStringUTFLength(jstr);
    char* result = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
    jni()->GetStringUTFRegion(jstr, 0, length, result);
    return result;
  }
}

#define DO_THROW(name)                             \
void JVMCIEnv::throw_##name(const char* msg) {     \
  if (is_hotspot()) {                              \
    JavaThread* THREAD = JavaThread::current();    \
    THROW_MSG(HotSpotJVMCI::name::symbol(), msg);  \
  } else {                                         \
    JNIAccessMark jni(this);                       \
    jni()->ThrowNew(JNIJVMCI::name::clazz(), msg); \
  }                                                \
}

DO_THROW(InternalError)
DO_THROW(ArrayIndexOutOfBoundsException)
DO_THROW(IllegalStateException)
DO_THROW(NullPointerException)
DO_THROW(IllegalArgumentException)
DO_THROW(InvalidInstalledCodeException)
DO_THROW(UnsatisfiedLinkError)
DO_THROW(UnsupportedOperationException)
DO_THROW(OutOfMemoryError)
DO_THROW(ClassNotFoundException)

#undef DO_THROW

void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) {
  const int max_msg_size = 1024;
  va_list ap;
  va_start(ap, format);
  char msg[max_msg_size];
  os::vsnprintf(msg, max_msg_size, format, ap);
  va_end(ap);
  JavaThread* THREAD = JavaThread::current();
  if (is_hotspot()) {
    Handle h_loader = Handle();
    Handle h_protection_domain = Handle();
    Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain);
  } else {
    JNIAccessMark jni(this, THREAD);
    jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
  }
}

jboolean JVMCIEnv::call_HotSpotJVMCIRuntime_isGCSupported (JVMCIObject runtime, jint gcIdentifier) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    JavaCallArguments jargs;
    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
    jargs.push_int(gcIdentifier);
    JavaValue result(T_BOOLEAN);
    JavaCalls::call_special(&result,
                            HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
                            vmSymbols::isGCSupported_name(),
                            vmSymbols::int_bool_signature(), &jargs, CHECK_0);
    return result.get_jboolean();
  } else {
    JNIAccessMark jni(this, THREAD);
    jboolean result = jni()->CallNonvirtualBooleanMethod(runtime.as_jobject(),
                                                     JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
                                                     JNIJVMCI::HotSpotJVMCIRuntime::isGCSupported_method(),
                                                     gcIdentifier);
    if (jni()->ExceptionCheck()) {
      return false;
    }
    return result;
  }
}

JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
                                                              jlong compile_state, int id) {
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  if (is_hotspot()) {
    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(result.get_oop());
  } else {
    JNIAccessMark jni(this, THREAD);
    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);
  }
}

void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  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::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK);
  } else {
    JNIAccessMark jni(this, THREAD);
    jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method());

  }
}

void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  HandleMark hm(THREAD);
  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, THREAD);
    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(tty);
  }
}

JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  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(result.get_oop());
  } else {
    JNIAccessMark jni(this, THREAD);
    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 = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  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(result.get_oop());
  } else {
    JNIAccessMark jni(this, THREAD);
    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 = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  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(result.get_oop());
  } else {
    JNIAccessMark jni(this, THREAD);
    jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method());
    if (jni()->ExceptionCheck()) {
      return JVMCIObject();
    }
    return wrap(result);
  }
}

void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCIEnv* JVMCIENV) {
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  if (is_hotspot()) {
    JavaCallArguments jargs;
    jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
    JavaValue result(T_VOID);
    JavaCalls::call_static(&result,
                           HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
                           vmSymbols::postTranslation_name(),
                           vmSymbols::object_void_signature(), &jargs, CHECK);
  } else {
    JNIAccessMark jni(this, THREAD);
    jni()->CallStaticVoidMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
                                JNIJVMCI::HotSpotJVMCIRuntime::postTranslation_method(),
                                object.as_jobject());
  }
}

JVMCIObject JVMCIEnv::call_JavaConstant_forPrimitive(jchar type_char, jlong value, JVMCI_TRAPS) {
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  if (is_hotspot()) {
    JavaCallArguments jargs;
    jargs.push_int(type_char);
    jargs.push_long(value);
    JavaValue result(T_OBJECT);
    JavaCalls::call_static(&result,
                           HotSpotJVMCI::JavaConstant::klass(),
                           vmSymbols::forPrimitive_name(),
                           vmSymbols::forPrimitive_signature(), &jargs, CHECK_(JVMCIObject()));
    return wrap(result.get_oop());
  } else {
    JNIAccessMark jni(this, THREAD);
    jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
                                                             JNIJVMCI::JavaConstant::forPrimitive_method(),
                                                             type_char, 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(const methodHandle& method, int bci, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  Symbol* file_name_sym;
  int line_number;
  java_lang_StackTraceElement::decode(method, bci, file_name_sym, line_number, CHECK_(JVMCIObject()));

  Symbol* method_name_sym = method->name();
  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 != nullptr) {
      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, THREAD);
    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 = nullptr;
    if (file_name_sym != nullptr) {
      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(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) {
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.

  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, THREAD);
    jobject nameStr = name == nullptr ? nullptr : 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()));
  }
}

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());
  }
}

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() == nullptr) {
    return method_object;
  }
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  JVMCIKlassHandle holder_klass(THREAD, method->method_holder());
  JVMCIObject holder = get_jvmci_type(holder_klass, JVMCI_CHECK_(JVMCIObject()));

  CompilerOracle::tag_blackhole_if_possible(method);

  jmetadata handle = _runtime->allocate_handle(method);
  jboolean exception = false;
  if (is_hotspot()) {
    JavaValue result(T_OBJECT);
    JavaCallArguments args;
    args.push_long((jlong) handle);
    args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(holder)));
    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(result.get_oop());
    }
  } else {
    JNIAccessMark jni(this, THREAD);
    method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
                                                                  JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
                                                                 (jlong) handle, holder.as_jobject()));
    exception = jni()->ExceptionCheck();
  }

  if (exception) {
    _runtime->release_handle(handle);
    return JVMCIObject();
  }

  assert(asMethod(method_object) == method(), "must be");
  if (get_HotSpotResolvedJavaMethodImpl_methodHandle(method_object) != (jlong) handle) {
    _runtime->release_handle(handle);
  }
  assert(!method_object.is_null(), "must be");
  return method_object;
}

JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) {
  JVMCIObject type;
  if (klass.is_null()) {
    return type;
  }

  guarantee(klass->is_klass(), "must be valid klass");
  guarantee(klass->is_loader_alive(), "klass must be alive");

  jlong pointer = (jlong) klass();
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  jboolean exception = false;
  if (is_hotspot()) {
    JavaValue result(T_OBJECT);
    JavaCallArguments args;
    args.push_long(pointer);
    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(result.get_oop());
    }
  } else {
    JNIAccessMark jni(this, THREAD);

    HandleMark hm(THREAD);
    type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(),
                                                        JNIJVMCI::HotSpotResolvedObjectTypeImpl_fromMetaspace_method(),
                                                        pointer));
    exception = jni()->ExceptionCheck();
  }
  if (exception) {
    return JVMCIObject();
  }

  assert(type.is_non_null(), "must have result");
  return type;
}

JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) {
  JVMCIObject cp_object;
  jmetadata handle = _runtime->allocate_handle(cp);
  jboolean exception = false;
  JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
  if (is_hotspot()) {
    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(result.get_oop());
    }
  } else {
    JNIAccessMark jni(this, THREAD);
    cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(),
                                                             JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(),
                                                             (jlong) handle));
    exception = jni()->ExceptionCheck();
  }

  if (exception) {
    _runtime->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_constantPoolHandle(cp_object) == (jlong) handle, "must use same handle");
  return cp_object;
}

JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject()));
    return wrap(result);
  } else {
    JNIAccessMark jni(this, THREAD);
    jbooleanArray result = jni()->NewBooleanArray(length);
    return wrap(result);
  }
}

JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject()));
    return wrap(result);
  } else {
    JNIAccessMark jni(this, THREAD);
    jbyteArray result = jni()->NewByteArray(length);
    return wrap(result);
  }
}

JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    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, THREAD);
    jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), nullptr);
    return wrap(result);
  }
}

JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject()));
    return wrap(result);
  } else {
    JNIAccessMark jni(this, THREAD);
    jintArray result = jni()->NewIntArray(length);
    return wrap(result);
  }
}

JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject()));
    return wrap(result);
  } else {
    JNIAccessMark jni(this, THREAD);
    jlongArray result = jni()->NewLongArray(length);
    return wrap(result);
  }
}

JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    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, THREAD);
    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) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    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, THREAD);
    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) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    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, THREAD);
    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(); // For exception macros.
    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(); // For exception macros.
    HotSpotJVMCI::JVMCIError::klass()->initialize(CHECK_(JVMCIObject()));
    oop obj = HotSpotJVMCI::JVMCIError::klass()->allocate_instance(CHECK_(JVMCIObject()));
    return wrap(obj);
  } else {
    ShouldNotReachHere();
    return JVMCIObject();
  }
}

JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    HotSpotJVMCI::FieldInfo::klass()->initialize(CHECK_(JVMCIObject()));
    oop obj = HotSpotJVMCI::FieldInfo::klass()->allocate_instance(CHECK_(JVMCIObject()));
    Handle obj_h(THREAD, obj);
    HotSpotJVMCI::FieldInfo::set_nameIndex(JVMCIENV, obj_h(), (jint)fieldinfo->name_index());
    HotSpotJVMCI::FieldInfo::set_signatureIndex(JVMCIENV, obj_h(), (jint)fieldinfo->signature_index());
    HotSpotJVMCI::FieldInfo::set_offset(JVMCIENV, obj_h(), (jint)fieldinfo->offset());
    HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_int());
    HotSpotJVMCI::FieldInfo::set_internalFlags(JVMCIENV, obj_h(), (jint)fieldinfo->field_flags().as_uint());
    HotSpotJVMCI::FieldInfo::set_initializerIndex(JVMCIENV, obj_h(), (jint)fieldinfo->initializer_index());
    return wrap(obj_h());
  } else {
    JNIAccessMark jni(this, THREAD);
    jobject result = jni()->NewObject(JNIJVMCI::FieldInfo::clazz(),
                                      JNIJVMCI::FieldInfo::constructor(),
                                      (jint)fieldinfo->name_index(),
                                      (jint)fieldinfo->signature_index(),
                                      (jint)fieldinfo->offset(),
                                      (jint)fieldinfo->access_flags().as_int(),
                                      (jint)fieldinfo->field_flags().as_uint(),
                                      (jint)fieldinfo->initializer_index());

    return wrap(result);
  }
}

JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  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_oop_handle(obj);
    JNIAccessMark jni(this, THREAD);
    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(); // For exception macros.
  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 if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
    jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
    if (object_handle == 0L) {
      JVMCI_THROW_MSG_(NullPointerException, "Foreign object reference has been cleared", Handle());
    }
    oop result = resolve_oop_handle(object_handle);
    if (result == nullptr) {
      JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly null", Handle());
    }
    return Handle(THREAD, result);
  } else {
    JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
  }
}

JVMCIObject JVMCIEnv::wrap(jobject object) {
  return JVMCIObject::create(object, is_hotspot());
}

jlong JVMCIEnv::make_oop_handle(const Handle& obj) {
  assert(!obj.is_null(), "should only create handle for non-null oops");
  return _runtime->make_oop_handle(obj);
}

oop JVMCIEnv::resolve_oop_handle(jlong oopHandle) {
  assert(oopHandle != 0, "should be a valid handle");
  oop obj = NativeAccess<>::oop_load(reinterpret_cast<oop*>(oopHandle));
  if (obj != nullptr) {
    guarantee(oopDesc::is_oop_or_null(obj), "invalid oop: " INTPTR_FORMAT, p2i((oopDesc*) obj));
  }
  return obj;
}

JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) {
  JavaThread* THREAD = JavaThread::current(); // For exception macros.
  if (is_hotspot()) {
    Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject()));
    return HotSpotJVMCI::wrap(result());
  } else {
    jobject result;
    jboolean exception = false;
    {
      JNIAccessMark jni(this, THREAD);
      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::typeCharToBasicType(jchar ch, JVMCI_TRAPS) {
  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 type char: %c", ch);
  }
}

BasicType JVMCIEnv::kindToBasicType(JVMCIObject kind, JVMCI_TRAPS) {
  if (kind.is_null()) {
    JVMCI_THROW_(NullPointerException, T_ILLEGAL);
  }
  jchar ch = get_JavaKind_typeChar(kind);
  BasicType bt = typeCharToBasicType(ch, JVMCI_CHECK_(T_ILLEGAL));
  return bt;
}

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_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, bool deoptimize, JVMCI_TRAPS) {
  if (mirror.is_null()) {
    JVMCI_THROW(NullPointerException);
  }

  nmethod* nm = JVMCIENV->get_nmethod(mirror);
  if (nm == nullptr) {
    // Nothing to do
    return;
  }

  Thread* current = Thread::current();
  if (!mirror.is_hotspot() && !current->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");
  }

  if (!deoptimize) {
    // Prevent future executions of the nmethod but let current executions complete.
    nm->make_not_entrant();

    // Do not clear the address field here as the Java code may still
    // want to later call this method with deoptimize == true. That requires
    // the address field to still be pointing at the nmethod.
   } else {
    // Deoptimize the nmethod immediately.
    DeoptimizationScope deopt_scope;
    deopt_scope.mark(nm);
    nm->make_not_entrant();
    nm->make_deoptimized();
    deopt_scope.deoptimize_marked();

    // 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_klassPointer(obj);
}

Method* JVMCIEnv::asMethod(JVMCIObject obj) {
  Method** methodHandle = (Method**) get_HotSpotResolvedJavaMethodImpl_methodHandle(obj);
  return *methodHandle;
}

ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) {
  ConstantPool** constantPoolHandle = (ConstantPool**) get_HotSpotConstantPool_constantPoolHandle(obj);
  return *constantPoolHandle;
}

MethodData* JVMCIEnv::asMethodData(JVMCIObject obj) {
  return (MethodData*) get_HotSpotMethodData_methodDataPointer(obj);
}

// Lookup an nmethod with a matching base and compile id
nmethod* JVMCIEnv::lookup_nmethod(address code, jlong compile_id_snapshot) {
  if (code == nullptr) {
    return nullptr;
  }

  CodeBlob* cb = CodeCache::find_blob(code);
  if (cb == (CodeBlob*) code) {
    nmethod* nm = cb->as_nmethod_or_null();
    if (nm != nullptr && (compile_id_snapshot == 0 || nm->compile_id() == compile_id_snapshot)) {
      return nm;
    }
  }
  return nullptr;
}


CodeBlob* JVMCIEnv::get_code_blob(JVMCIObject obj) {
  address code = (address) get_InstalledCode_address(obj);
  if (code == nullptr) {
    return nullptr;
  }
  if (isa_HotSpotNmethod(obj)) {
    jlong compile_id_snapshot = get_HotSpotNmethod_compileIdSnapshot(obj);
    nmethod* nm = lookup_nmethod(code, compile_id_snapshot);
    if (nm != nullptr && compile_id_snapshot != 0L && 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);
      // Refetch the nmethod since the previous call will be a safepoint in libjvmci
      nm = lookup_nmethod(code, compile_id_snapshot);
    }

    if (nm == nullptr) {
      // The HotSpotNmethod was pointing at some nmethod but the nmethod is no longer valid, so
      // clear the InstalledCode fields of this HotSpotNmethod so that it no longer refers to a
      // nmethod in the code cache.
      set_InstalledCode_address(obj, 0);
      set_InstalledCode_entryPoint(obj, 0);
      set_HotSpotInstalledCode_codeStart(obj, 0);
    }
    return nm;
  }

  CodeBlob* cb = (CodeBlob*) code;
  assert(!cb->is_nmethod(), "unexpected nmethod");
  return cb;
}

nmethod* JVMCIEnv::get_nmethod(JVMCIObject obj) {
  CodeBlob* cb = get_code_blob(obj);
  if (cb != nullptr) {
    return cb->as_nmethod_or_null();
  }
  return nullptr;
}

// 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()) {                                                                                              \
      JavaThread* THREAD = JavaThread::current(); /* For exception macros. */ \
      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(), nullptr);                    \
      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
