src/hotspot/share/jvmci/jvmciEnv.cpp
changeset 54669 ad45b3802d4e
parent 53430 ccfd4e614bb8
child 54732 2d012a75d35c
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp	Wed May 01 12:31:29 2019 -0700
@@ -23,44 +23,22 @@
  */
 
 #include "precompiled.hpp"
-#include "jvmci/jvmciEnv.hpp"
-#include "classfile/javaAssertions.hpp"
-#include "classfile/systemDictionary.hpp"
-#include "classfile/vmSymbols.hpp"
+#include "classfile/stringTable.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 "oops/typeArrayOop.inline.hpp"
+#include "runtime/jniHandles.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "jvmci/jniAccessMark.inline.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
 
-JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter):
+JVMCICompileState::JVMCICompileState(CompileTask* task, int system_dictionary_modification_counter):
   _task(task),
   _system_dictionary_modification_counter(system_dictionary_modification_counter),
   _retryable(true),
   _failure_reason(NULL),
-  _failure_reason_on_C_heap(false)
-{
+  _failure_reason_on_C_heap(false) {
   // Get Jvmti capabilities under lock to get consistent values.
   MutexLocker mu(JvmtiThreadState_lock);
   _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0;
@@ -69,7 +47,7 @@
   _jvmti_can_pop_frame                  = JvmtiExport::can_pop_frame() ? 1 : 0;
 }
 
-bool JVMCIEnv::jvmti_state_changed() const {
+bool JVMCICompileState::jvmti_state_changed() const {
   if (!jvmti_can_access_local_variables() &&
       JvmtiExport::can_access_local_variables()) {
     return true;
@@ -89,532 +67,1587 @@
   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;
-  }
+JavaVM* JVMCIEnv::_shared_library_javavm = NULL;
+void* JVMCIEnv::_shared_library_handle = NULL;
+char* JVMCIEnv::_shared_library_path = NULL;
 
-  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;
-}
+void JVMCIEnv::copy_saved_properties() {
+  assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image");
+
+  JavaThread* THREAD = JavaThread::current();
 
-// ------------------------------------------------------------------
-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);
+  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");
   }
-
-  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);
+  InstanceKlass* ik = InstanceKlass::cast(k);
+  if (ik->should_be_initialized()) {
+    ik->initialize(THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services");
     }
   }
 
-  // If 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 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");
+  }
+}
 
-    // 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);
+JNIEnv* JVMCIEnv::attach_shared_library() {
+  if (_shared_library_javavm == NULL) {
+    MutexLocker locker(JVMCI_lock);
+    if (_shared_library_javavm == NULL) {
+
+      char path[JVM_MAXPATHLEN];
+      char ebuf[1024];
+      if (JVMCILibPath != NULL) {
+        if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) {
+          vm_exit_during_initialization("Unable to create JVMCI shared library path from -XX:JVMCILibPath value", JVMCILibPath);
+        }
+      } else {
+        if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) {
+          vm_exit_during_initialization("Unable to create path to JVMCI shared library");
+        }
+      }
+
+      void* handle = os::dll_load(path, ebuf, sizeof ebuf);
+      if (handle == NULL) {
+        vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf);
+      }
+      _shared_library_handle = handle;
+      _shared_library_path = strdup(path);
+      jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
+      typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);
+
+      JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(handle, "JNI_CreateJavaVM"));
+      JNIEnv* env;
+      if (JNI_CreateJavaVM == NULL) {
+        vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", path);
+      }
+
+      ResourceMark rm;
+      JavaVMInitArgs vm_args;
+      vm_args.version = JNI_VERSION_1_2;
+      vm_args.ignoreUnrecognized = JNI_TRUE;
+      vm_args.options = NULL;
+      vm_args.nOptions = 0;
+
+      JavaVM* the_javavm = NULL;
+      int result = (*JNI_CreateJavaVM)(&the_javavm, (void**) &env, &vm_args);
+      if (result == JNI_OK) {
+        guarantee(env != NULL, "missing env");
+        _shared_library_javavm = the_javavm;
+        return env;
+      } else {
+        vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), path);
+      }
     }
   }
+  JNIEnv* env;
+  if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) {
+    guarantee(env != NULL, "missing env");
+    return env;
+  }
+  fatal("Error attaching current thread to JVMCI shared library JNI interface");
+  return NULL;
+}
 
-  if (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;
-        }
-      }
+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;
     }
   }
 
-  return found_klass;
+  // 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");
 }
 
-// ------------------------------------------------------------------
-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);
+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);
+  }
 }
 
-// ------------------------------------------------------------------
-// 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);
+// 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, const 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");
   }
 
-  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;
+  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 {
-      // Linked locally, and we must also check public/private, etc.
-      is_accessible = check_klass_accessibility(accessor, k);
+      if (Thread::current()->is_Java_thread()) {
+        JavaThread* THREAD = JavaThread::current();
+        if (HAS_PENDING_EXCEPTION) {
+          Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
+          CLEAR_PENDING_EXCEPTION;
+          translate_hotspot_exception_to_jni_exception(THREAD, throwable);
+        }
+      }
     }
-    if (!is_accessible) {
-      return NULL;
+  } else {
+    if (!is_hotspot()) {
+      // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
+      JNIAccessMark jni(this);
+      jni()->PopLocalFrame(NULL);
+    }
+
+    if (has_pending_exception()) {
+      char message[256];
+      jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
+      JVMCIRuntime::exit_on_pending_exception(this, message);
     }
-    return k;
+  }
+}
+
+jboolean JVMCIEnv::has_pending_exception() {
+  if (is_hotspot()) {
+    Thread* THREAD = Thread::current();
+    return HAS_PENDING_EXCEPTION;
+  } else {
+    JNIAccessMark jni(this);
+    return jni()->ExceptionCheck();
   }
+}
+
+void JVMCIEnv::clear_pending_exception() {
+  if (is_hotspot()) {
+    Thread* THREAD = Thread::current();
+    CLEAR_PENDING_EXCEPTION;
+  } else {
+    JNIAccessMark jni(this);
+    jni()->ExceptionClear();
+  }
+}
 
-  // It is known to be accessible, since it was found in the constant pool.
-  is_accessible = true;
-  return klass;
+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));
+  }
 }
 
-// ------------------------------------------------------------------
-// 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);
+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);
+  }
+}
+
+long 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, int size_in_bytes) {
+  if (size_in_bytes == 0) {
+    return;
+  }
+  if (is_hotspot()) {
+    memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), size_in_bytes);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, size_in_bytes, dest);
+  }
+}
+void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes) {
+  if (size_in_bytes == 0) {
+    return;
+  }
+  if (is_hotspot()) {
+    memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, size_in_bytes);
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, size_in_bytes, src);
+  }
 }
 
-// ------------------------------------------------------------------
-// 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;
+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;
+  }
+}
 
-  assert(klass->is_linked(), "must be linked before using its constant-pool");
+// 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());
+  }
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
+    return HotSpotJVMCI::wrap(box);
+  } else {
+    JNIAccessMark jni(this);
+    jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
+    assert(box != NULL, "");
+    return wrap(box);
+  }
+}
 
-  constantPoolHandle cpool(thread, klass->constants());
+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);
+    int length = jni()->GetStringLength(str.as_jstring());
+    char* result = NEW_RESOURCE_ARRAY(char, length + 1);
+    jni()->GetStringUTFRegion(str.as_jstring(), 0, length, result);
+    return result;
+  }
+}
 
-  // Get the field's name, signature, and type.
-  Symbol* name  = cpool->name_ref_at(index);
+char* JVMCIEnv::as_utf8_string(JVMCIObject str, char* buf, int buflen) {
+  if (is_hotspot()) {
+    return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str), buf, buflen);
+  } else {
+    JNIAccessMark jni(this);
+    int length = jni()->GetStringLength(str.as_jstring());
+    if (length >= buflen) {
+      length = buflen;
+    }
+    jni()->GetStringUTFRegion(str.as_jstring(), 0, length, buf);
+    return buf;
+  }
+}
+
+#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)
+
+#undef DO_THROW
 
-  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);
+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];
+  vsnprintf(msg, max_msg_size, format, ap);
+  msg[max_msg_size-1] = '\0';
+  va_end(ap);
+  if (is_hotspot()) {
+    JavaThread* THREAD = JavaThread::current();
+    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);
+    jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
+  }
+}
+
+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);
+  }
+}
+
+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());
+
+  }
+}
 
-  // 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);
+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);
+  }
+}
 
-  // The declared holder of this field may not have been loaded.
-  // Bail out with partial field information.
-  if (!holder_is_accessible) {
-    return;
+JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
+  JavaThread* THREAD = JavaThread::current();
+  if (is_hotspot()) {
+    JavaCallArguments jargs;
+    JavaValue result(T_OBJECT);
+    JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject()));
+    return wrap((oop) result.get_jobject());
+  } else {
+    JNIAccessMark jni(this);
+    jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method());
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return wrap(result);
   }
+}
+
+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);
+  }
+}
 
 
-  // Perform the field lookup.
-  Klass*  canonical_holder =
-    InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc);
-  if (canonical_holder == NULL) {
-    return;
+JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_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);
   }
-
-  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);
+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(const 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();
+      }
     }
 
-    return NULL;
+    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 = 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;
   }
 
-  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);
+  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();
+  }
 
-  // Get the method's name and signature.
-  Symbol* name_sym = cpool->name_ref_at(index);
-  Symbol* sig_sym  = cpool->signature_ref_at(index);
+  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(const 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*
 
-  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;
+  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(const 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();
   }
 
-  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;
-    }
+  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);
   }
+}
 
-  // Either the declared holder was not loaded, or the method could
-  // not be found.
+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);
+  }
+}
 
-  return NULL;
+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);
+  }
 }
 
-// ------------------------------------------------------------------
-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();
+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();
   }
-  return NULL;
+}
+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();
+  }
 }
 
 
-// ------------------------------------------------------------------
-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);
+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(const 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;
+  }
 }
 
-// ------------------------------------------------------------------
-// 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;
+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");
   }
 
-  // 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;
+  // 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);
   }
 
-  if (!Dependencies::is_klass_type(result) || counter_changed) {
-    return JVMCIEnv::dependencies_failed;
+  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");
   }
-  // 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;
+
+  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;
 }
 
-// ------------------------------------------------------------------
-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);
+ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) {
+  ConstantPool** metadataHandle = (ConstantPool**) get_HotSpotConstantPool_metadataHandle(obj);
+  return *metadataHandle;
+}
 
-    // 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);
+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;
         }
-
-        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;
+      // 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;
+}
 
-  // 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());
+
+// 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);                 \
+    }                                                                \
   }
 
-  // JVMTI -- compiled method notification (must be done outside lock)
-  if (nm != NULL) {
-    nm->post_compiled_method_load_event();
+#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))
 
-    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);
-    }
+#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);                  \
+    }                                                                 \
   }
 
-  return result;
-}
+#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