8220623: [JVMCI] Update JVMCI to support JVMCI based Compiler compiled into shared library
authorkvn
Wed, 01 May 2019 12:31:29 -0700
changeset 54669 ad45b3802d4e
parent 54668 0bda2308eded
child 54670 a38438fcbbd2
8220623: [JVMCI] Update JVMCI to support JVMCI based Compiler compiled into shared library Reviewed-by: dnsimon, never, stefank, rehn, neliasso, dholmes, kbarrett, coleenp
make/autoconf/hotspot.m4
src/hotspot/.mx.jvmci/suite.py
src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp
src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp
src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp
src/hotspot/share/aot/aotCompiledMethod.cpp
src/hotspot/share/aot/aotLoader.cpp
src/hotspot/share/classfile/javaClasses.cpp
src/hotspot/share/classfile/javaClasses.hpp
src/hotspot/share/classfile/metadataOnStackMark.cpp
src/hotspot/share/classfile/systemDictionary.cpp
src/hotspot/share/classfile/systemDictionary.hpp
src/hotspot/share/classfile/vmSymbols.hpp
src/hotspot/share/code/nmethod.cpp
src/hotspot/share/code/nmethod.hpp
src/hotspot/share/compiler/abstractCompiler.hpp
src/hotspot/share/compiler/compileBroker.cpp
src/hotspot/share/compiler/compileTask.cpp
src/hotspot/share/compiler/compilerDefinitions.cpp
src/hotspot/share/compiler/disassembler.cpp
src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp
src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp
src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp
src/hotspot/share/gc/g1/g1RootProcessor.cpp
src/hotspot/share/gc/g1/g1RootProcessor.hpp
src/hotspot/share/gc/parallel/pcTasks.cpp
src/hotspot/share/gc/parallel/pcTasks.hpp
src/hotspot/share/gc/parallel/psMarkSweep.cpp
src/hotspot/share/gc/parallel/psParallelCompact.cpp
src/hotspot/share/gc/parallel/psScavenge.cpp
src/hotspot/share/gc/parallel/psTasks.cpp
src/hotspot/share/gc/parallel/psTasks.hpp
src/hotspot/share/gc/serial/genMarkSweep.cpp
src/hotspot/share/gc/shared/genCollectedHeap.cpp
src/hotspot/share/gc/shared/genCollectedHeap.hpp
src/hotspot/share/gc/shared/parallelCleaning.cpp
src/hotspot/share/gc/shared/parallelCleaning.hpp
src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp
src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp
src/hotspot/share/jvmci/jniAccessMark.inline.hpp
src/hotspot/share/jvmci/jvmci.cpp
src/hotspot/share/jvmci/jvmci.hpp
src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
src/hotspot/share/jvmci/jvmciCodeInstaller.hpp
src/hotspot/share/jvmci/jvmciCompiler.cpp
src/hotspot/share/jvmci/jvmciCompiler.hpp
src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
src/hotspot/share/jvmci/jvmciEnv.cpp
src/hotspot/share/jvmci/jvmciEnv.hpp
src/hotspot/share/jvmci/jvmciExceptions.hpp
src/hotspot/share/jvmci/jvmciJavaClasses.cpp
src/hotspot/share/jvmci/jvmciJavaClasses.hpp
src/hotspot/share/jvmci/jvmciObject.hpp
src/hotspot/share/jvmci/jvmciRuntime.cpp
src/hotspot/share/jvmci/jvmciRuntime.hpp
src/hotspot/share/jvmci/jvmci_globals.cpp
src/hotspot/share/jvmci/jvmci_globals.hpp
src/hotspot/share/jvmci/metadataHandleBlock.cpp
src/hotspot/share/jvmci/metadataHandleBlock.hpp
src/hotspot/share/jvmci/systemDictionary_jvmci.hpp
src/hotspot/share/jvmci/vmStructs_jvmci.cpp
src/hotspot/share/jvmci/vmSymbols_jvmci.hpp
src/hotspot/share/memory/allocation.hpp
src/hotspot/share/oops/method.cpp
src/hotspot/share/oops/methodData.cpp
src/hotspot/share/oops/methodData.hpp
src/hotspot/share/opto/chaitin.cpp
src/hotspot/share/prims/jni.cpp
src/hotspot/share/prims/jvmtiTagMap.cpp
src/hotspot/share/prims/nativeLookup.hpp
src/hotspot/share/runtime/arguments.cpp
src/hotspot/share/runtime/deoptimization.cpp
src/hotspot/share/runtime/frame.cpp
src/hotspot/share/runtime/init.cpp
src/hotspot/share/runtime/java.cpp
src/hotspot/share/runtime/javaCalls.cpp
src/hotspot/share/runtime/mutexLocker.cpp
src/hotspot/share/runtime/mutexLocker.hpp
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/runtime/thread.hpp
src/hotspot/share/runtime/tieredThresholdPolicy.cpp
src/hotspot/share/runtime/vmOperations.cpp
src/java.base/share/classes/module-info.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/NativeImageReinitialize.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Cleaner.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJDKReflection.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIUnsupportedOperationError.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationEncoding.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceHandleObject.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceObject.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMEntryPoint.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/VMEntryPoint.java
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java
test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java
test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java
test/hotspot/jtreg/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java
test/hotspot/jtreg/compiler/jvmci/errors/CodeInstallerTest.java
test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java
test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotSpeculationLog.java
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestSpeculationLog.java
test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java
--- a/make/autoconf/hotspot.m4	Wed May 01 12:41:26 2019 -0400
+++ b/make/autoconf/hotspot.m4	Wed May 01 12:31:29 2019 -0700
@@ -392,9 +392,8 @@
     JVM_FEATURES_jvmci=""
     INCLUDE_JVMCI="false"
   else
-    # Only enable jvmci on x86_64, sparcv9 and aarch64
+    # Only enable jvmci on x86_64 and aarch64
     if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \
-       test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \
        test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then
       AC_MSG_RESULT([yes])
       JVM_FEATURES_jvmci="jvmci"
--- a/src/hotspot/.mx.jvmci/suite.py	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/.mx.jvmci/suite.py	Wed May 01 12:31:29 2019 -0700
@@ -56,6 +56,9 @@
     "jdk.vm.ci.common" : {
       "subDir" : "../jdk.internal.vm.ci/share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : [
+        "jdk.vm.ci.services",
+      ],
       "checkstyle" : "jdk.vm.ci.services",
       "javaCompliance" : "9+",
       "workingSets" : "API,JVMCI",
@@ -258,9 +261,11 @@
       "subDir" : "../../test/hotspot/jtreg/compiler/jvmci",
       "dependencies" : [
         "jdk.vm.ci.runtime.test",
+        "jdk.vm.ci.hotspot.test",
       ],
       "distDependencies" : [
         "JVMCI_API",
+        "JVMCI_HOTSPOT",
       ],
       "exclude" : ["mx:JUNIT"],
     },
--- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -30,7 +30,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "vmreg_aarch64.inline.hpp"
 
-jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS) {
   if (inst->is_call() || inst->is_jump() || inst->is_blr()) {
     return pc_offset + NativeCall::instruction_size;
   } else if (inst->is_general_jump()) {
@@ -43,12 +43,12 @@
   }
 }
 
-void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
 #ifdef ASSERT
   {
     NativeInstruction *insn = nativeInstruction_at(pc);
-    if (HotSpotObjectConstantImpl::compressed(constant)) {
+    if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
       // Mov narrow constant: movz n << 16, movk
       assert(Instruction_aarch64::extract(insn->encoding(), 31, 21) == 0b11010010101 &&
              nativeInstruction_at(pc+4)->is_movk(), "wrong insn in patch");
@@ -59,7 +59,7 @@
     }
   }
 #endif // ASSERT
-  Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+  Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK);
   jobject value = JNIHandles::make_local(obj());
   MacroAssembler::patch_oop(pc, (address)obj());
   int oop_index = _oop_recorder->find_index(value);
@@ -67,21 +67,21 @@
   _instructions->relocate(pc, rspec);
 }
 
-void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
-    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK);
+  if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
+    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     MacroAssembler::patch_narrow_klass(pc, narrowOop);
     TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
   } else {
     NativeMovConstReg* move = nativeMovConstReg_at(pc);
-    void* reference = record_metadata_reference(_instructions, pc, constant, CHECK);
+    void* reference = record_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     move->set_data((intptr_t) reference);
     TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
   }
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
   NativeInstruction* inst = nativeInstruction_at(pc);
   if (inst->is_adr_aligned() || inst->is_ldr_literal()
@@ -94,7 +94,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
   address pc = (address) inst;
   if (inst->is_call()) {
     NativeCall* call = nativeCall_at(pc);
@@ -118,12 +118,12 @@
   TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
 }
 
-void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, Handle hotspot_method, jint pc_offset, TRAPS) {
+void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) {
 #ifdef ASSERT
   Method* method = NULL;
   // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method());
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(hotspot_method)) {
+    method = JVMCIENV->asMethod(hotspot_method);
   }
 #endif
   switch (_next_call_type) {
@@ -157,7 +157,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
   switch (mark) {
     case POLL_NEAR:
       JVMCI_ERROR("unimplemented");
@@ -178,7 +178,7 @@
 }
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
-VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
   if (jvmci_reg < RegisterImpl::number_of_registers) {
     return as_Register(jvmci_reg)->as_VMReg();
   } else {
--- a/src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/cpu/sparc/jvmciCodeInstaller_sparc.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -31,7 +31,7 @@
 #include "utilities/align.hpp"
 #include "vmreg_sparc.inline.hpp"
 
-jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS) {
   if (inst->is_call() || inst->is_jump()) {
     return pc_offset + NativeCall::instruction_size;
   } else if (inst->is_call_reg()) {
@@ -44,11 +44,11 @@
   }
 }
 
-void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+  Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK);
   jobject value = JNIHandles::make_local(obj());
-  if (HotSpotObjectConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
     int oop_index = _oop_recorder->find_index(value);
     RelocationHolder rspec = oop_Relocation::spec(oop_index);
     _instructions->relocate(pc, rspec, 1);
@@ -64,22 +64,22 @@
   }
 }
 
-void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
     NativeMovConstReg32* move = nativeMovConstReg32_at(pc);
-    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK);
+    narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     move->set_data((intptr_t)narrowOop);
     TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
   } else {
     NativeMovConstReg* move = nativeMovConstReg_at(pc);
-    void* reference = record_metadata_reference(_instructions, pc, constant, CHECK);
+    void* reference = record_metadata_reference(_instructions, pc, constant, JVMCI_CHECK);
     move->set_data((intptr_t)reference);
     TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
   }
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
   NativeInstruction* inst = nativeInstruction_at(pc);
   NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
@@ -100,7 +100,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
   address pc = (address) inst;
   if (inst->is_call()) {
     NativeCall* call = nativeCall_at(pc);
@@ -116,12 +116,12 @@
   TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
 }
 
-void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, Handle hotspot_method, jint pc_offset, TRAPS) {
+void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) {
 #ifdef ASSERT
   Method* method = NULL;
   // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method());
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(hotspot_method)) {
+    method = JVMCIENV->asMethod(hotspot_method);
   }
 #endif
   switch (_next_call_type) {
@@ -155,7 +155,7 @@
   }
 }
 
-void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
   switch (mark) {
     case POLL_NEAR:
       JVMCI_ERROR("unimplemented");
@@ -176,7 +176,7 @@
 }
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
-VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
   // JVMCI Registers are numbered as follows:
   //   0..31: Thirty-two General Purpose registers (CPU Registers)
   //   32..63: Thirty-two single precision float registers
--- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -37,7 +37,7 @@
 #include "code/vmreg.hpp"
 #include "vmreg_x86.inline.hpp"
 
-jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS) {
   if (inst->is_call() || inst->is_jump()) {
     assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
     return (pc_offset + NativeCall::instruction_size);
@@ -54,7 +54,7 @@
     return (offset);
   } else if (inst->is_call_reg()) {
     // the inlined vtable stub contains a "call register" instruction
-    assert(method.not_null(), "only valid for virtual calls");
+    assert(method.is_non_null(), "only valid for virtual calls");
     return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
   } else if (inst->is_cond_jump()) {
     address pc = (address) (inst);
@@ -64,11 +64,12 @@
   }
 }
 
-void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+  Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK);
+  Thread* THREAD = Thread::current();
   jobject value = JNIHandles::make_local(obj());
-  if (HotSpotObjectConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
 #ifdef _LP64
     address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
     int oop_index = _oop_recorder->find_index(value);
@@ -85,24 +86,24 @@
   }
 }
 
-void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
-  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+  if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
 #ifdef _LP64
     address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
-    *((narrowKlass*) operand) = record_narrow_metadata_reference(_instructions, operand, constant, CHECK);
+    *((narrowKlass*) operand) = record_narrow_metadata_reference(_instructions, operand, constant, JVMCI_CHECK);
     TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
 #else
     JVMCI_ERROR("compressed Klass* on 32bit");
 #endif
   } else {
     address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
-    *((void**) operand) = record_metadata_reference(_instructions, operand, constant, CHECK);
+    *((void**) operand) = record_metadata_reference(_instructions, operand, constant, JVMCI_CHECK);
     TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
   }
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
   address pc = _instructions->start() + pc_offset;
 
   address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
@@ -117,7 +118,7 @@
   TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
 }
 
-void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
   address pc = (address) inst;
   if (inst->is_call()) {
     // NOTE: for call without a mov, the offset must fit a 32-bit immediate
@@ -145,12 +146,12 @@
   TRACE_jvmci_3("relocating (foreign call)  at " PTR_FORMAT, p2i(inst));
 }
 
-void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, Handle hotspot_method, jint pc_offset, TRAPS) {
+void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) {
 #ifdef ASSERT
   Method* method = NULL;
   // we need to check, this might also be an unresolved method
-  if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    method = getMethodFromHotSpotMethod(hotspot_method());
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(hotspot_method)) {
+    method = JVMCIENV->asMethod(hotspot_method);
   }
 #endif
   switch (_next_call_type) {
@@ -199,7 +200,7 @@
 }
 
 
-void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
+void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
   switch (mark) {
     case POLL_NEAR: {
       relocate_poll_near(pc);
@@ -229,7 +230,7 @@
 }
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
-VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
   if (jvmci_reg < RegisterImpl::number_of_registers) {
     return as_Register(jvmci_reg)->as_VMReg();
   } else {
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Wed May 01 12:31:29 2019 -0700
@@ -32,8 +32,6 @@
 #include "compiler/compilerOracle.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "jvmci/compilerRuntime.hpp"
-#include "jvmci/jvmciRuntime.hpp"
 #include "oops/method.inline.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
--- a/src/hotspot/share/aot/aotLoader.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/aot/aotLoader.cpp	Wed May 01 12:31:29 2019 -0700
@@ -26,8 +26,8 @@
 
 #include "aot/aotCodeHeap.hpp"
 #include "aot/aotLoader.inline.hpp"
-#include "jvmci/jvmciRuntime.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/os.inline.hpp"
--- a/src/hotspot/share/classfile/javaClasses.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Wed May 01 12:31:29 2019 -0700
@@ -2607,6 +2607,45 @@
   }
 }
 
+#if INCLUDE_JVMCI
+void java_lang_StackTraceElement::decode(Handle mirror, methodHandle method, int bci, Symbol*& methodname, Symbol*& filename, int& line_number) {
+  int method_id = method->orig_method_idnum();
+  int cpref = method->name_index();
+  decode(mirror, method_id, method->constants()->version(), bci, cpref, methodname, filename, line_number);
+}
+
+void java_lang_StackTraceElement::decode(Handle mirror, int method_id, int version, int bci, int cpref, Symbol*& methodname, Symbol*& filename, int& line_number) {
+  // Fill in class name
+  InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
+  Method* method = holder->method_with_orig_idnum(method_id, version);
+
+  // The method can be NULL if the requested class version is gone
+  Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
+
+  // Fill in method name
+  methodname = sym;
+
+  if (!version_matches(method, version)) {
+    // If the method was redefined, accurate line number information isn't available
+    filename = NULL;
+    line_number = -1;
+  } else {
+    // Fill in source file name and line number.
+    // Use a specific ik version as a holder since the mirror might
+    // refer to a version that is now obsolete and no longer accessible
+    // via the previous versions list.
+    holder = holder->get_klass_version(version);
+    assert(holder != NULL, "sanity check");
+    Symbol* source = holder->source_file_name();
+    if (ShowHiddenFrames && source == NULL) {
+      source = vmSymbols::unknown_class_name();
+    }
+    filename = source;
+    line_number = Backtrace::get_line_number(method, bci);
+  }
+}
+#endif // INCLUDE_JVMCI
+
 Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) {
   HandleMark hm(THREAD);
   Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
--- a/src/hotspot/share/classfile/javaClasses.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Wed May 01 12:31:29 2019 -0700
@@ -1368,6 +1368,11 @@
   static void compute_offsets();
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
 
+#if INCLUDE_JVMCI
+  static void decode(Handle mirror, int method, int version, int bci, int cpref, Symbol*& methodName, Symbol*& fileName, int& lineNumber);
+  static void decode(Handle mirror, methodHandle method, int bci, Symbol*& methodName, Symbol*& fileName, int& lineNumber);
+#endif
+
   // Debugging
   friend class JavaClasses;
 };
--- a/src/hotspot/share/classfile/metadataOnStackMark.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/classfile/metadataOnStackMark.cpp	Wed May 01 12:31:29 2019 -0700
@@ -33,7 +33,7 @@
 #include "services/threadService.hpp"
 #include "utilities/chunkedList.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmci.hpp"
 #endif
 
 MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
@@ -73,7 +73,7 @@
     JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
     ThreadService::metadata_do(Metadata::mark_on_stack);
 #if INCLUDE_JVMCI
-    JVMCIRuntime::metadata_do(Metadata::mark_on_stack);
+    JVMCI::metadata_do(Metadata::mark_on_stack);
 #endif
   }
 }
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Wed May 01 12:31:29 2019 -0700
@@ -86,9 +86,6 @@
 #if INCLUDE_CDS
 #include "classfile/systemDictionaryShared.hpp"
 #endif
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 #if INCLUDE_JFR
 #include "jfr/jfr.hpp"
 #endif
@@ -1922,13 +1919,6 @@
   Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
   InstanceKlass** klassp = &_well_known_klasses[id];
 
-
-#if INCLUDE_JVMCI
-  if (id >= FIRST_JVMCI_WKID) {
-    assert(EnableJVMCI, "resolve JVMCI classes only when EnableJVMCI is true");
-  }
-#endif
-
   if ((*klassp) == NULL) {
     Klass* k = resolve_or_fail(symbol, true, CHECK_0);
     (*klassp) = InstanceKlass::cast(k);
@@ -2017,7 +2007,7 @@
   WKID jsr292_group_end   = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
   resolve_wk_klasses_until(jsr292_group_start, scan, CHECK);
   resolve_wk_klasses_through(jsr292_group_end, scan, CHECK);
-  WKID last = NOT_JVMCI(WKID_LIMIT) JVMCI_ONLY(FIRST_JVMCI_WKID);
+  WKID last = WKID_LIMIT;
   resolve_wk_klasses_until(last, scan, CHECK);
 
   _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Wed May 01 12:31:29 2019 -0700
@@ -26,7 +26,6 @@
 #define SHARE_CLASSFILE_SYSTEMDICTIONARY_HPP
 
 #include "classfile/classLoaderData.hpp"
-#include "jvmci/systemDictionary_jvmci.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/java.hpp"
@@ -215,9 +214,6 @@
   do_klass(Integer_klass,                               java_lang_Integer                                     ) \
   do_klass(Long_klass,                                  java_lang_Long                                        ) \
                                                                                                                 \
-  /* JVMCI classes. These are loaded on-demand. */                                                              \
-  JVMCI_WK_KLASSES_DO(do_klass)                                                                                 \
-                                                                                                                \
   /*end*/
 
 
@@ -236,11 +232,6 @@
 
     WKID_LIMIT,
 
-#if INCLUDE_JVMCI
-    FIRST_JVMCI_WKID = WK_KLASS_ENUM_NAME(JVMCI_klass),
-    LAST_JVMCI_WKID  = WK_KLASS_ENUM_NAME(Value_klass),
-#endif
-
     FIRST_WKID = NO_WKID + 1
   };
 
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Wed May 01 12:31:29 2019 -0700
@@ -358,8 +358,7 @@
   template(destroyed_name,                            "destroyed")                                \
   template(nthreads_name,                             "nthreads")                                 \
   template(ngroups_name,                              "ngroups")                                  \
-  template(shutdown_method_name,                      "shutdown")                                 \
-  template(bootstrapFinished_method_name,             "bootstrapFinished")                        \
+  template(shutdown_name,                             "shutdown")                                 \
   template(finalize_method_name,                      "finalize")                                 \
   template(reference_lock_name,                       "lock")                                     \
   template(reference_discovered_name,                 "discovered")                               \
--- a/src/hotspot/share/code/nmethod.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/code/nmethod.cpp	Wed May 01 12:31:29 2019 -0700
@@ -64,7 +64,7 @@
 #include "utilities/resourceHash.hpp"
 #include "utilities/xmlstream.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
 #endif
 
 #ifdef DTRACE_ENABLED
@@ -112,6 +112,10 @@
   int dependencies_size;
   int handler_table_size;
   int nul_chk_table_size;
+#if INCLUDE_JVMCI
+  int speculations_size;
+  int jvmci_data_size;
+#endif
   int oops_size;
   int metadata_size;
 
@@ -129,6 +133,10 @@
     dependencies_size   += nm->dependencies_size();
     handler_table_size  += nm->handler_table_size();
     nul_chk_table_size  += nm->nul_chk_table_size();
+#if INCLUDE_JVMCI
+    speculations_size   += nm->speculations_size();
+    jvmci_data_size     += nm->jvmci_data_size();
+#endif
   }
   void print_nmethod_stats(const char* name) {
     if (nmethod_count == 0)  return;
@@ -146,6 +154,10 @@
     if (dependencies_size != 0)   tty->print_cr(" dependencies   = %d", dependencies_size);
     if (handler_table_size != 0)  tty->print_cr(" handler table  = %d", handler_table_size);
     if (nul_chk_table_size != 0)  tty->print_cr(" nul chk table  = %d", nul_chk_table_size);
+#if INCLUDE_JVMCI
+    if (speculations_size != 0)   tty->print_cr(" speculations   = %d", speculations_size);
+    if (jvmci_data_size != 0)     tty->print_cr(" JVMCI data     = %d", jvmci_data_size);
+#endif
   }
 };
 
@@ -426,11 +438,6 @@
 #if INCLUDE_RTM_OPT
   _rtm_state               = NoRTM;
 #endif
-#if INCLUDE_JVMCI
-  _jvmci_installed_code   = NULL;
-  _speculation_log        = NULL;
-  _jvmci_installed_code_triggers_invalidation = false;
-#endif
 }
 
 nmethod* nmethod::new_native_nmethod(const methodHandle& method,
@@ -483,8 +490,11 @@
   AbstractCompiler* compiler,
   int comp_level
 #if INCLUDE_JVMCI
-  , jweak installed_code,
-  jweak speculationLog
+  , char* speculations,
+  int speculations_len,
+  int nmethod_mirror_index,
+  const char* nmethod_mirror_name,
+  FailedSpeculation** failed_speculations
 #endif
 )
 {
@@ -493,12 +503,19 @@
   // create nmethod
   nmethod* nm = NULL;
   { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+#if INCLUDE_JVMCI
+    int jvmci_data_size = !compiler->is_jvmci() ? 0 : JVMCINMethodData::compute_size(nmethod_mirror_name);
+#endif
     int nmethod_size =
       CodeBlob::allocation_size(code_buffer, sizeof(nmethod))
       + adjust_pcs_size(debug_info->pcs_size())
       + align_up((int)dependencies->size_in_bytes(), oopSize)
       + align_up(handler_table->size_in_bytes()    , oopSize)
       + align_up(nul_chk_table->size_in_bytes()    , oopSize)
+#if INCLUDE_JVMCI
+      + align_up(speculations_len                  , oopSize)
+      + align_up(jvmci_data_size                   , oopSize)
+#endif
       + align_up(debug_info->data_size()           , oopSize);
 
     nm = new (nmethod_size, comp_level)
@@ -510,12 +527,19 @@
             compiler,
             comp_level
 #if INCLUDE_JVMCI
-            , installed_code,
-            speculationLog
+            , speculations,
+            speculations_len,
+            jvmci_data_size
 #endif
             );
 
     if (nm != NULL) {
+#if INCLUDE_JVMCI
+      if (compiler->is_jvmci()) {
+        // Initialize the JVMCINMethodData object inlined into nm
+        nm->jvmci_nmethod_data()->initialize(nmethod_mirror_index, nmethod_mirror_name, failed_speculations);
+      }
+#endif
       // To make dependency checking during class loading fast, record
       // the nmethod dependencies in the classes it is dependent on.
       // This allows the dependency checking code to simply walk the
@@ -591,7 +615,13 @@
     _dependencies_offset     = _scopes_pcs_offset;
     _handler_table_offset    = _dependencies_offset;
     _nul_chk_table_offset    = _handler_table_offset;
+#if INCLUDE_JVMCI
+    _speculations_offset     = _nul_chk_table_offset;
+    _jvmci_data_offset       = _speculations_offset;
+    _nmethod_end_offset      = _jvmci_data_offset;
+#else
     _nmethod_end_offset      = _nul_chk_table_offset;
+#endif
     _compile_id              = compile_id;
     _comp_level              = CompLevel_none;
     _entry_point             = code_begin()          + offsets->value(CodeOffsets::Entry);
@@ -667,8 +697,9 @@
   AbstractCompiler* compiler,
   int comp_level
 #if INCLUDE_JVMCI
-  , jweak installed_code,
-  jweak speculation_log
+  , char* speculations,
+  int speculations_len,
+  int jvmci_data_size
 #endif
   )
   : CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
@@ -697,15 +728,6 @@
     set_ctable_begin(header_begin() + _consts_offset);
 
 #if INCLUDE_JVMCI
-    _jvmci_installed_code = installed_code;
-    _speculation_log = speculation_log;
-    oop obj = JNIHandles::resolve(installed_code);
-    if (obj == NULL || (obj->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(obj))) {
-      _jvmci_installed_code_triggers_invalidation = false;
-    } else {
-      _jvmci_installed_code_triggers_invalidation = true;
-    }
-
     if (compiler->is_jvmci()) {
       // JVMCI might not produce any stub sections
       if (offsets->value(CodeOffsets::Exceptions) != -1) {
@@ -735,10 +757,10 @@
       _deopt_mh_handler_begin  = (address) this + _stub_offset          + offsets->value(CodeOffsets::DeoptMH);
     } else {
       _deopt_mh_handler_begin  = NULL;
+    }
 #if INCLUDE_JVMCI
     }
 #endif
-    }
     if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
       _unwind_handler_offset = code_offset()         + offsets->value(CodeOffsets::UnwindHandler);
     } else {
@@ -753,7 +775,13 @@
     _dependencies_offset     = _scopes_pcs_offset    + adjust_pcs_size(debug_info->pcs_size());
     _handler_table_offset    = _dependencies_offset  + align_up((int)dependencies->size_in_bytes (), oopSize);
     _nul_chk_table_offset    = _handler_table_offset + align_up(handler_table->size_in_bytes(), oopSize);
+#if INCLUDE_JVMCI
+    _speculations_offset     = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize);
+    _jvmci_data_offset       = _speculations_offset  + align_up(speculations_len, oopSize);
+    _nmethod_end_offset      = _jvmci_data_offset    + align_up(jvmci_data_size, oopSize);
+#else
     _nmethod_end_offset      = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize);
+#endif
     _entry_point             = code_begin()          + offsets->value(CodeOffsets::Entry);
     _verified_entry_point    = code_begin()          + offsets->value(CodeOffsets::Verified_Entry);
     _osr_entry_point         = code_begin()          + offsets->value(CodeOffsets::OSR_Entry);
@@ -779,6 +807,13 @@
     handler_table->copy_to(this);
     nul_chk_table->copy_to(this);
 
+#if INCLUDE_JVMCI
+    // Copy speculations to nmethod
+    if (speculations_size() != 0) {
+      memcpy(speculations_begin(), speculations, speculations_len);
+    }
+#endif
+
     // we use the information of entry points to find out if a method is
     // static or non static
     assert(compiler->is_c2() || compiler->is_jvmci() ||
@@ -798,13 +833,14 @@
     log->print(" level='%d'", comp_level());
   }
 #if INCLUDE_JVMCI
-    char buffer[O_BUFLEN];
-    char* jvmci_name = jvmci_installed_code_name(buffer, O_BUFLEN);
+  if (jvmci_nmethod_data() != NULL) {
+    const char* jvmci_name = jvmci_nmethod_data()->name();
     if (jvmci_name != NULL) {
-      log->print(" jvmci_installed_code_name='");
+      log->print(" jvmci_mirror_name='");
       log->text("%s", jvmci_name);
       log->print("'");
     }
+  }
 #endif
 }
 
@@ -1115,13 +1151,6 @@
   // Log the unloading.
   log_state_change();
 
-#if INCLUDE_JVMCI
-  // The method can only be unloaded after the pointer to the installed code
-  // Java wrapper is no longer alive. Here we need to clear out this weak
-  // reference to the dead object.
-  maybe_invalidate_installed_code();
-#endif
-
   // The Method* is gone at this point
   assert(_method == NULL, "Tautology");
 
@@ -1134,6 +1163,15 @@
   // concurrent nmethod unloading. Therefore, there is no need for
   // acquire on the loader side.
   OrderAccess::release_store(&_state, (signed char)unloaded);
+
+#if INCLUDE_JVMCI
+  // Clear the link between this nmethod and a HotSpotNmethod mirror
+  JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
+  if (nmethod_data != NULL) {
+    nmethod_data->invalidate_nmethod_mirror(this);
+    nmethod_data->clear_nmethod_mirror(this);
+  }
+#endif
 }
 
 void nmethod::invalidate_osr_method() {
@@ -1265,13 +1303,18 @@
     // Log the transition once
     log_state_change();
 
-    // Invalidate while holding the patching lock
-    JVMCI_ONLY(maybe_invalidate_installed_code());
-
     // Remove nmethod from method.
     unlink_from_method(false /* already owns Patching_lock */);
   } // leave critical region under Patching_lock
 
+#if INCLUDE_JVMCI
+  // Invalidate can't occur while holding the Patching lock
+  JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
+  if (nmethod_data != NULL) {
+    nmethod_data->invalidate_nmethod_mirror(this);
+  }
+#endif
+
 #ifdef ASSERT
   if (is_osr_method() && method() != NULL) {
     // Make sure osr nmethod is invalidated, i.e. not on the list
@@ -1297,6 +1340,14 @@
       flush_dependencies(/*delete_immediately*/true);
     }
 
+#if INCLUDE_JVMCI
+    // Now that the nmethod has been unregistered, it's
+    // safe to clear the HotSpotNmethod mirror oop.
+    if (nmethod_data != NULL) {
+      nmethod_data->clear_nmethod_mirror(this);
+    }
+#endif
+
     // Clear ICStubs to prevent back patching stubs of zombie or flushed
     // nmethods during the next safepoint (see ICStub::finalize), as well
     // as to free up CompiledICHolder resources.
@@ -1324,7 +1375,7 @@
     assert(state == not_entrant, "other cases may need to be handled differently");
   }
 
-  if (TraceCreateZombies) {
+  if (TraceCreateZombies && state == zombie) {
     ResourceMark m;
     tty->print_cr("nmethod <" INTPTR_FORMAT "> %s code made %s", p2i(this), this->method() ? this->method()->name_and_sig_as_C_string() : "null", (state == not_entrant) ? "not entrant" : "zombie");
   }
@@ -1362,11 +1413,6 @@
     ec = next;
   }
 
-#if INCLUDE_JVMCI
-  assert(_jvmci_installed_code == NULL, "should have been nulled out when transitioned to zombie");
-  assert(_speculation_log == NULL, "should have been nulled out when transitioned to zombie");
-#endif
-
   Universe::heap()->flush_nmethod(this);
 
   CodeBlob::flush();
@@ -1660,17 +1706,6 @@
   if (is_unloading()) {
     make_unloaded();
   } else {
-#if INCLUDE_JVMCI
-    if (_jvmci_installed_code != NULL) {
-      if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
-        if (_jvmci_installed_code_triggers_invalidation) {
-          make_not_entrant();
-        }
-        clear_jvmci_installed_code();
-      }
-    }
-#endif
-
     guarantee(unload_nmethod_caches(unloading_occurred),
               "Should not need transition stubs");
   }
@@ -2066,7 +2101,7 @@
   if (cm->is_aot()) return;  // FIXME: Revisit once _lock_count is added to aot_method
   nmethod* nm = cm->as_nmethod();
   Atomic::inc(&nm->_lock_count);
-  assert(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method");
+  assert(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method: %p", nm);
 }
 
 void nmethodLocker::unlock_nmethod(CompiledMethod* cm) {
@@ -2275,6 +2310,16 @@
                                               p2i(nul_chk_table_begin()),
                                               p2i(nul_chk_table_end()),
                                               nul_chk_table_size());
+#if INCLUDE_JVMCI
+  if (speculations_size () > 0) tty->print_cr(" speculations   [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
+                                              p2i(speculations_begin()),
+                                              p2i(speculations_end()),
+                                              speculations_size());
+  if (jvmci_data_size   () > 0) tty->print_cr(" JVMCI data     [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
+                                              p2i(jvmci_data_begin()),
+                                              p2i(jvmci_data_end()),
+                                              jvmci_data_size());
+#endif
 }
 
 #ifndef PRODUCT
@@ -2857,115 +2902,18 @@
 #endif // !PRODUCT
 
 #if INCLUDE_JVMCI
-void nmethod::clear_jvmci_installed_code() {
-  assert_locked_or_safepoint(Patching_lock);
-  if (_jvmci_installed_code != NULL) {
-    JNIHandles::destroy_weak_global(_jvmci_installed_code);
-    _jvmci_installed_code = NULL;
-  }
-}
-
-void nmethod::clear_speculation_log() {
-  assert_locked_or_safepoint(Patching_lock);
-  if (_speculation_log != NULL) {
-    JNIHandles::destroy_weak_global(_speculation_log);
-    _speculation_log = NULL;
-  }
-}
-
-void nmethod::maybe_invalidate_installed_code() {
-  if (!is_compiled_by_jvmci()) {
-    return;
-  }
-
-  assert(Patching_lock->is_locked() ||
-         SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
-  oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
-  if (installed_code != NULL) {
-    // Update the values in the InstalledCode instance if it still refers to this nmethod
-    nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
-    if (nm == this) {
-      if (!is_alive() || is_unloading()) {
-        // Break the link between nmethod and InstalledCode such that the nmethod
-        // can subsequently be flushed safely.  The link must be maintained while
-        // the method could have live activations since invalidateInstalledCode
-        // might want to invalidate all existing activations.
-        InstalledCode::set_address(installed_code, 0);
-        InstalledCode::set_entryPoint(installed_code, 0);
-      } else if (is_not_entrant()) {
-        // Remove the entry point so any invocation will fail but keep
-        // the address link around that so that existing activations can
-        // be invalidated.
-        InstalledCode::set_entryPoint(installed_code, 0);
-      }
-    }
-  }
-  if (!is_alive() || is_unloading()) {
-    // Clear these out after the nmethod has been unregistered and any
-    // updates to the InstalledCode instance have been performed.
-    clear_jvmci_installed_code();
-    clear_speculation_log();
+void nmethod::update_speculation(JavaThread* thread) {
+  jlong speculation = thread->pending_failed_speculation();
+  if (speculation != 0) {
+    guarantee(jvmci_nmethod_data() != NULL, "failed speculation in nmethod without failed speculation list");
+    jvmci_nmethod_data()->add_failed_speculation(this, speculation);
+    thread->set_pending_failed_speculation(0);
   }
 }
 
-void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
-  if (installedCode() == NULL) {
-    THROW(vmSymbols::java_lang_NullPointerException());
-  }
-  jlong nativeMethod = InstalledCode::address(installedCode);
-  nmethod* nm = (nmethod*)nativeMethod;
-  if (nm == NULL) {
-    // Nothing to do
-    return;
-  }
-
-  nmethodLocker nml(nm);
-#ifdef ASSERT
-  {
-    MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-    // This relationship can only be checked safely under a lock
-    assert(!nm->is_alive() || nm->is_unloading() || nm->jvmci_installed_code() == installedCode(), "sanity check");
-  }
-#endif
-
-  if (nm->is_alive()) {
-    // Invalidating the InstalledCode means we want the nmethod
-    // to be deoptimized.
-    nm->mark_for_deoptimization();
-    VM_Deoptimize op;
-    VMThread::execute(&op);
-  }
-
-  // Multiple threads could reach this point so we now need to
-  // lock and re-check the link to the nmethod so that only one
-  // thread clears it.
-  MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-  if (InstalledCode::address(installedCode) == nativeMethod) {
-      InstalledCode::set_address(installedCode, 0);
-  }
-}
-
-oop nmethod::jvmci_installed_code() {
-  return JNIHandles::resolve(_jvmci_installed_code);
-}
-
-oop nmethod::speculation_log() {
-  return JNIHandles::resolve(_speculation_log);
-}
-
-char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) const {
-  if (!this->is_compiled_by_jvmci()) {
-    return NULL;
-  }
-  oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
-  if (installed_code != NULL) {
-    oop installed_code_name = NULL;
-    if (installed_code->is_a(InstalledCode::klass())) {
-      installed_code_name = InstalledCode::name(installed_code);
-    }
-    if (installed_code_name != NULL) {
-      return java_lang_String::as_utf8_string(installed_code_name, buf, (int)buflen);
-    }
+const char* nmethod::jvmci_name() {
+  if (jvmci_nmethod_data() != NULL) {
+    return jvmci_nmethod_data()->name();
   }
   return NULL;
 }
--- a/src/hotspot/share/code/nmethod.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/code/nmethod.hpp	Wed May 01 12:31:29 2019 -0700
@@ -51,37 +51,28 @@
 //  - handler entry point array
 //  [Implicit Null Pointer exception table]
 //  - implicit null table array
+//  [Speculations]
+//  - encoded speculations array
+//  [JVMCINMethodData]
+//  - meta data for JVMCI compiled nmethod
+
+#if INCLUDE_JVMCI
+class FailedSpeculation;
+class JVMCINMethodData;
+#endif
 
 class nmethod : public CompiledMethod {
   friend class VMStructs;
   friend class JVMCIVMStructs;
   friend class NMethodSweeper;
   friend class CodeCache;  // scavengable oops
+  friend class JVMCINMethodData;
  private:
 
   // Shared fields for all nmethod's
   int       _entry_bci;        // != InvocationEntryBci if this nmethod is an on-stack replacement method
   jmethodID _jmethod_id;       // Cache of method()->jmethod_id()
 
-#if INCLUDE_JVMCI
-  // A weak reference to an InstalledCode object associated with
-  // this nmethod.
-  jweak     _jvmci_installed_code;
-
-  // A weak reference to a SpeculationLog object associated with
-  // this nmethod.
-  jweak     _speculation_log;
-
-  // Determines whether this nmethod is unloaded when the
-  // referent in _jvmci_installed_code is cleared. This
-  // will be false if the referent is initialized to a
-  // HotSpotNMethod object whose isDefault field is true.
-  // That is, installed code other than a "default"
-  // HotSpotNMethod causes nmethod unloading.
-  // This field is ignored once _jvmci_installed_code is NULL.
-  bool _jvmci_installed_code_triggers_invalidation;
-#endif
-
   // To support simple linked-list chaining of nmethods:
   nmethod*  _osr_link;         // from InstanceKlass::osr_nmethods_head
 
@@ -107,6 +98,10 @@
   int _dependencies_offset;
   int _handler_table_offset;
   int _nul_chk_table_offset;
+#if INCLUDE_JVMCI
+  int _speculations_offset;
+  int _jvmci_data_offset;
+#endif
   int _nmethod_end_offset;
 
   int code_offset() const { return (address) code_begin() - header_begin(); }
@@ -207,8 +202,9 @@
           AbstractCompiler* compiler,
           int comp_level
 #if INCLUDE_JVMCI
-          , jweak installed_code,
-          jweak speculation_log
+          , char* speculations,
+          int speculations_len,
+          int jvmci_data_size
 #endif
           );
 
@@ -251,8 +247,11 @@
                               AbstractCompiler* compiler,
                               int comp_level
 #if INCLUDE_JVMCI
-                              , jweak installed_code = NULL,
-                              jweak speculation_log = NULL
+                              , char* speculations = NULL,
+                              int speculations_len = 0,
+                              int nmethod_mirror_index = -1,
+                              const char* nmethod_mirror_name = NULL,
+                              FailedSpeculation** failed_speculations = NULL
 #endif
   );
 
@@ -299,12 +298,24 @@
   address handler_table_begin   () const          { return           header_begin() + _handler_table_offset ; }
   address handler_table_end     () const          { return           header_begin() + _nul_chk_table_offset ; }
   address nul_chk_table_begin   () const          { return           header_begin() + _nul_chk_table_offset ; }
+#if INCLUDE_JVMCI
+  address nul_chk_table_end     () const          { return           header_begin() + _speculations_offset  ; }
+  address speculations_begin    () const          { return           header_begin() + _speculations_offset  ; }
+  address speculations_end      () const          { return           header_begin() + _jvmci_data_offset   ; }
+  address jvmci_data_begin      () const          { return           header_begin() + _jvmci_data_offset    ; }
+  address jvmci_data_end        () const          { return           header_begin() + _nmethod_end_offset   ; }
+#else
   address nul_chk_table_end     () const          { return           header_begin() + _nmethod_end_offset   ; }
+#endif
 
   // Sizes
   int oops_size         () const                  { return (address)  oops_end         () - (address)  oops_begin         (); }
   int metadata_size     () const                  { return (address)  metadata_end     () - (address)  metadata_begin     (); }
   int dependencies_size () const                  { return            dependencies_end () -            dependencies_begin (); }
+#if INCLUDE_JVMCI
+  int speculations_size () const                  { return            speculations_end () -            speculations_begin (); }
+  int jvmci_data_size   () const                  { return            jvmci_data_end   () -            jvmci_data_begin   (); }
+#endif
 
   int     oops_count() const { assert(oops_size() % oopSize == 0, "");  return (oops_size() / oopSize) + 1; }
   int metadata_count() const { assert(metadata_size() % wordSize == 0, ""); return (metadata_size() / wordSize) + 1; }
@@ -446,39 +457,19 @@
   void set_method(Method* method) { _method = method; }
 
 #if INCLUDE_JVMCI
-  // Gets the InstalledCode object associated with this nmethod
-  // which may be NULL if this nmethod was not compiled by JVMCI
-  // or the weak reference has been cleared.
-  oop jvmci_installed_code();
+  // Gets the JVMCI name of this nmethod.
+  const char* jvmci_name();
 
-  // Copies the value of the name field in the InstalledCode
-  // object (if any) associated with this nmethod into buf.
-  // Returns the value of buf if it was updated otherwise NULL.
-  char* jvmci_installed_code_name(char* buf, size_t buflen) const;
-
-  // Updates the state of the InstalledCode (if any) associated with
-  // this nmethod based on the current value of _state.
-  void maybe_invalidate_installed_code();
+  // Records the pending failed speculation in the
+  // JVMCI speculation log associated with this nmethod.
+  void update_speculation(JavaThread* thread);
 
-  // Deoptimizes the nmethod (if any) in the address field of a given
-  // InstalledCode object. The address field is zeroed upon return.
-  static void invalidate_installed_code(Handle installed_code, TRAPS);
-
-  // Gets the SpeculationLog object associated with this nmethod
-  // which may be NULL if this nmethod was not compiled by JVMCI
-  // or the weak reference has been cleared.
-  oop speculation_log();
-
- private:
-  // Deletes the weak reference (if any) to the InstalledCode object
-  // associated with this nmethod.
-  void clear_jvmci_installed_code();
-
-  // Deletes the weak reference (if any) to the SpeculationLog object
-  // associated with this nmethod.
-  void clear_speculation_log();
-
- public:
+  // Gets the data specific to a JVMCI compiled method.
+  // This returns a non-NULL value iff this nmethod was
+  // compiled by the JVMCI compiler.
+  JVMCINMethodData* jvmci_nmethod_data() const {
+    return jvmci_data_size() == 0 ? NULL : (JVMCINMethodData*) jvmci_data_begin();
+  }
 #endif
 
  public:
--- a/src/hotspot/share/compiler/abstractCompiler.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/compiler/abstractCompiler.hpp	Wed May 01 12:31:29 2019 -0700
@@ -154,9 +154,6 @@
   const bool is_jvmci()                          { return _type == compiler_jvmci; }
   const CompilerType type()                      { return _type; }
 
-  // Extra tests to identify trivial methods for the tiered compilation policy.
-  virtual bool is_trivial(Method* method) { return false; }
-
   // Customization
   virtual void initialize () = 0;
 
--- a/src/hotspot/share/compiler/compileBroker.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Wed May 01 12:31:29 2019 -0700
@@ -68,9 +68,8 @@
 #include "c1/c1_Compiler.hpp"
 #endif
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
+#include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
 #include "runtime/vframe.hpp"
 #endif
 #ifdef COMPILER2
@@ -1064,36 +1063,34 @@
     }
 
 #if INCLUDE_JVMCI
-    if (UseJVMCICompiler) {
-      if (blocking) {
-        // Don't allow blocking compiles for requests triggered by JVMCI.
-        if (thread->is_Compiler_thread()) {
-          blocking = false;
-        }
+    if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) {
+      // Don't allow blocking compiles for requests triggered by JVMCI.
+      if (thread->is_Compiler_thread()) {
+        blocking = false;
+      }
 
-        // Don't allow blocking compiles if inside a class initializer or while performing class loading
-        vframeStream vfst((JavaThread*) thread);
-        for (; !vfst.at_end(); vfst.next()) {
-          if (vfst.method()->is_static_initializer() ||
-              (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
-                  vfst.method()->name() == vmSymbols::loadClass_name())) {
-            blocking = false;
-            break;
-          }
+      // Don't allow blocking compiles if inside a class initializer or while performing class loading
+      vframeStream vfst((JavaThread*) thread);
+      for (; !vfst.at_end(); vfst.next()) {
+        if (vfst.method()->is_static_initializer() ||
+            (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
+                vfst.method()->name() == vmSymbols::loadClass_name())) {
+          blocking = false;
+          break;
         }
+      }
 
-        // Don't allow blocking compilation requests to JVMCI
-        // if JVMCI itself is not yet initialized
-        if (!JVMCIRuntime::is_HotSpotJVMCIRuntime_initialized() && compiler(comp_level)->is_jvmci()) {
-          blocking = false;
-        }
+      // Don't allow blocking compilation requests to JVMCI
+      // if JVMCI itself is not yet initialized
+      if (!JVMCI::is_compiler_initialized() && compiler(comp_level)->is_jvmci()) {
+        blocking = false;
+      }
 
-        // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
-        // to avoid deadlock between compiler thread(s) and threads run at shutdown
-        // such as the DestroyJavaVM thread.
-        if (JVMCIRuntime::shutdown_called()) {
-          blocking = false;
-        }
+      // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
+      // to avoid deadlock between compiler thread(s) and threads run at shutdown
+      // such as the DestroyJavaVM thread.
+      if (JVMCI::shutdown_called()) {
+        blocking = false;
       }
     }
 #endif // INCLUDE_JVMCI
@@ -1193,7 +1190,7 @@
   }
 
 #if INCLUDE_JVMCI
-  if (comp->is_jvmci() && !JVMCIRuntime::can_initialize_JVMCI()) {
+  if (comp->is_jvmci() && !JVMCI::can_initialize_JVMCI()) {
     return NULL;
   }
 #endif
@@ -2061,20 +2058,24 @@
 
     // Skip redefined methods
     if (target_handle->is_old()) {
-        failure_reason = "redefined method";
-        retry_message = "not retryable";
-        compilable = ciEnv::MethodCompilable_never;
+      failure_reason = "redefined method";
+      retry_message = "not retryable";
+      compilable = ciEnv::MethodCompilable_never;
     } else {
-        JVMCIEnv env(task, system_dictionary_modification_counter);
-        methodHandle method(thread, target_handle);
-        jvmci->compile_method(method, osr_bci, &env);
+      JVMCICompileState compile_state(task, system_dictionary_modification_counter);
+      JVMCIEnv env(&compile_state, __FILE__, __LINE__);
+      methodHandle method(thread, target_handle);
+      env.runtime()->compile_method(&env, jvmci, method, osr_bci);
 
-        failure_reason = env.failure_reason();
-        failure_reason_on_C_heap = env.failure_reason_on_C_heap();
-        if (!env.retryable()) {
-          retry_message = "not retryable";
-          compilable = ciEnv::MethodCompilable_not_at_tier;
-        }
+      failure_reason = compile_state.failure_reason();
+      failure_reason_on_C_heap = compile_state.failure_reason_on_C_heap();
+      if (!compile_state.retryable()) {
+        retry_message = "not retryable";
+        compilable = ciEnv::MethodCompilable_not_at_tier;
+      }
+      if (task->code() == NULL) {
+        assert(failure_reason != NULL, "must specify failure_reason");
+      }
     }
     post_compile(thread, task, task->code() != NULL, NULL, compilable, failure_reason);
     if (event.should_commit()) {
--- a/src/hotspot/share/compiler/compileTask.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/compiler/compileTask.cpp	Wed May 01 12:31:29 2019 -0700
@@ -396,6 +396,7 @@
   ResourceMark rm(thread);
 
   if (!_is_success) {
+    assert(_failure_reason != NULL, "missing");
     const char* reason = _failure_reason != NULL ? _failure_reason : "unknown";
     log->elem("failure reason='%s'", reason);
   }
--- a/src/hotspot/share/compiler/compilerDefinitions.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/compiler/compilerDefinitions.cpp	Wed May 01 12:31:29 2019 -0700
@@ -253,22 +253,6 @@
     if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
       FLAG_SET_DEFAULT(TypeProfileWidth, 8);
     }
-    if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
-      FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
-    }
-    // JVMCI needs values not less than defaults
-    if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
-      FLAG_SET_DEFAULT(ReservedCodeCacheSize, MAX2(64*M, ReservedCodeCacheSize));
-    }
-    if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
-      FLAG_SET_DEFAULT(InitialCodeCacheSize, MAX2(16*M, InitialCodeCacheSize));
-    }
-    if (FLAG_IS_DEFAULT(MetaspaceSize)) {
-      FLAG_SET_DEFAULT(MetaspaceSize, MIN2(MAX2(12*M, MetaspaceSize), MaxMetaspaceSize));
-    }
-    if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
-      FLAG_SET_DEFAULT(NewSizeThreadIncrease, MAX2(4*K, NewSizeThreadIncrease));
-    }
     if (TieredStopAtLevel != CompLevel_full_optimization) {
       // Currently JVMCI compiler can only work at the full optimization level
       warning("forcing TieredStopAtLevel to full optimization because JVMCI is enabled");
@@ -277,7 +261,43 @@
     if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
       FLAG_SET_DEFAULT(TypeProfileLevel, 0);
     }
-  }
+
+    if (UseJVMCINativeLibrary) {
+      // SVM compiled code requires more stack space
+      if (FLAG_IS_DEFAULT(CompilerThreadStackSize)) {
+        // Duplicate logic in the implementations of os::create_thread
+        // so that we can then double the computed stack size. Once
+        // the stack size requirements of SVM are better understood,
+        // this logic can be pushed down into os::create_thread.
+        int stack_size = CompilerThreadStackSize;
+        if (stack_size == 0) {
+          stack_size = VMThreadStackSize;
+        }
+        if (stack_size != 0) {
+          FLAG_SET_DEFAULT(CompilerThreadStackSize, stack_size * 2);
+        }
+      }
+    } else {
+      // Adjust the on stack replacement percentage to avoid early
+      // OSR compilations while JVMCI itself is warming up
+      if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+        FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
+      }
+      // JVMCI needs values not less than defaults
+      if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+        FLAG_SET_DEFAULT(ReservedCodeCacheSize, MAX2(64*M, ReservedCodeCacheSize));
+      }
+      if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+        FLAG_SET_DEFAULT(InitialCodeCacheSize, MAX2(16*M, InitialCodeCacheSize));
+      }
+      if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+        FLAG_SET_DEFAULT(MetaspaceSize, MIN2(MAX2(12*M, MetaspaceSize), MaxMetaspaceSize));
+      }
+      if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
+        FLAG_SET_DEFAULT(NewSizeThreadIncrease, MAX2(4*K, NewSizeThreadIncrease));
+      }
+    } // !UseJVMCINativeLibrary
+  } // UseJVMCICompiler
 }
 #endif // INCLUDE_JVMCI
 
@@ -392,6 +412,8 @@
   // Check that JVMCI compiler supports selested GC.
   // Should be done after GCConfig::initialize() was called.
   JVMCIGlobals::check_jvmci_supported_gc();
+
+  // Do JVMCI specific settings
   set_jvmci_specific_flags();
 #endif
 
--- a/src/hotspot/share/compiler/disassembler.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/compiler/disassembler.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -672,8 +672,7 @@
   nm->method()->signature()->print_symbol_on(env.output());
 #if INCLUDE_JVMCI
   {
-    char buffer[O_BUFLEN];
-    char* jvmciName = nm->jvmci_installed_code_name(buffer, O_BUFLEN);
+    const char* jvmciName = nm->jvmci_name();
     if (jvmciName != NULL) {
       env.output()->print(" (%s)", jvmciName);
     }
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Wed May 01 12:31:29 2019 -0700
@@ -82,6 +82,9 @@
 #include "services/runtimeService.hpp"
 #include "utilities/align.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 // statics
 CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
@@ -5258,6 +5261,9 @@
 
       // Prune dead klasses from subklass/sibling/implementor lists.
       Klass::clean_weak_klass_links(purged_class);
+
+      // Clean JVMCI metadata handles.
+      JVMCI_ONLY(JVMCI::do_unloading(purged_class));
     }
   }
 
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Wed May 01 12:31:29 2019 -0700
@@ -60,9 +60,8 @@
   _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms):");
   _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms):");
   _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms):");
-#if INCLUDE_AOT
-  _gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "AOT Root Scan (ms):");
-#endif
+  AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "AOT Root Scan (ms):");)
+  JVMCI_ONLY(_gc_par_phases[JVMCIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMCI Root Scan (ms):");)
   _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):");
   _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):");
   _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):");
@@ -527,9 +526,8 @@
       "SystemDictionaryRoots",
       "CLDGRoots",
       "JVMTIRoots",
-#if INCLUDE_AOT
-      "AOTCodeRoots",
-#endif
+      AOT_ONLY("AOTCodeRoots" COMMA)
+      JVMCI_ONLY("JVMCIRoots" COMMA)
       "CMRefRoots",
       "WaitForStrongCLD",
       "WeakCLDRoots",
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Wed May 01 12:31:29 2019 -0700
@@ -55,9 +55,8 @@
     SystemDictionaryRoots,
     CLDGRoots,
     JVMTIRoots,
-#if INCLUDE_AOT
-    AOTCodeRoots,
-#endif
+    AOT_ONLY(AOTCodeRoots COMMA)
+    JVMCI_ONLY(JVMCIRoots COMMA)
     CMRefRoots,
     WaitForStrongCLD,
     WeakCLDRoots,
--- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Wed May 01 12:31:29 2019 -0700
@@ -43,6 +43,9 @@
 #include "runtime/mutex.hpp"
 #include "services/management.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 void G1RootProcessor::worker_has_discovered_all_strong_classes() {
   assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
@@ -267,6 +270,15 @@
   }
 #endif
 
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JVMCIRoots, worker_i);
+    if (_process_strong_tasks.try_claim_task(G1RP_PS_JVMCI_oops_do)) {
+      JVMCI::oops_do(strong_roots);
+    }
+  }
+#endif
+
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i);
     if (_process_strong_tasks.try_claim_task(G1RP_PS_SystemDictionary_oops_do)) {
--- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Wed May 01 12:31:29 2019 -0700
@@ -63,7 +63,8 @@
     G1RP_PS_ClassLoaderDataGraph_oops_do,
     G1RP_PS_jvmti_oops_do,
     G1RP_PS_CodeCache_oops_do,
-    G1RP_PS_aot_oops_do,
+    AOT_ONLY(G1RP_PS_aot_oops_do COMMA)
+    JVMCI_ONLY(G1RP_PS_JVMCI_oops_do COMMA)
     G1RP_PS_filter_satb_buffers,
     G1RP_PS_refProcessor_oops_do,
     // Leave this one last.
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -46,6 +46,9 @@
 #include "runtime/vmThread.hpp"
 #include "services/management.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 //
 // ThreadRootsMarkingTask
@@ -121,6 +124,12 @@
       AOTLoader::oops_do(&mark_and_push_closure);
       break;
 
+#if INCLUDE_JVMCI
+    case jvmci:
+      JVMCI::oops_do(&mark_and_push_closure);
+      break;
+#endif
+
     default:
       fatal("Unknown root type");
   }
--- a/src/hotspot/share/gc/parallel/pcTasks.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/pcTasks.hpp	Wed May 01 12:31:29 2019 -0700
@@ -98,6 +98,7 @@
     system_dictionary     = 7,
     class_loader_data     = 8,
     code_cache            = 9
+    JVMCI_ONLY(COMMA jvmci = 10)
   };
  private:
   RootType _root_type;
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Wed May 01 12:31:29 2019 -0700
@@ -62,6 +62,9 @@
 #include "utilities/align.hpp"
 #include "utilities/events.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 elapsedTimer        PSMarkSweep::_accumulated_time;
 jlong               PSMarkSweep::_time_of_last_gc   = 0;
@@ -524,7 +527,8 @@
     ClassLoaderDataGraph::always_strong_cld_do(follow_cld_closure());
     // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
     //ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
-    AOTLoader::oops_do(mark_and_push_closure());
+    AOT_ONLY(AOTLoader::oops_do(mark_and_push_closure());)
+    JVMCI_ONLY(JVMCI::oops_do(mark_and_push_closure());)
   }
 
   // Flush marking stack.
@@ -562,6 +566,9 @@
 
     // Prune dead klasses from subklass/sibling/implementor lists.
     Klass::clean_weak_klass_links(purged_class);
+
+    // Clean JVMCI metadata handles.
+    JVMCI_ONLY(JVMCI::do_unloading(purged_class));
   }
 
   _gc_tracer->report_object_count_after_gc(is_alive_closure());
@@ -615,7 +622,10 @@
 
   CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
-  AOTLoader::oops_do(adjust_pointer_closure());
+  AOT_ONLY(AOTLoader::oops_do(adjust_pointer_closure());)
+
+  JVMCI_ONLY(JVMCI::oops_do(adjust_pointer_closure());)
+
   ref_processor()->weak_oops_do(adjust_pointer_closure());
   PSScavenge::reference_processor()->weak_oops_do(adjust_pointer_closure());
 
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Wed May 01 12:31:29 2019 -0700
@@ -77,6 +77,9 @@
 #include "utilities/formatBuffer.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 #include <math.h>
 
@@ -2123,6 +2126,7 @@
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::class_loader_data));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));
+    JVMCI_ONLY(q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmci));)
 
     if (active_gc_threads > 1) {
       for (uint j = 0; j < active_gc_threads; j++) {
@@ -2176,6 +2180,9 @@
 
     // Prune dead klasses from subklass/sibling/implementor lists.
     Klass::clean_weak_klass_links(purged_class);
+
+    // Clean JVMCI metadata handles.
+    JVMCI_ONLY(JVMCI::do_unloading(purged_class));
   }
 
   _gc_tracer.report_object_count_after_gc(is_alive_closure());
@@ -2207,7 +2214,10 @@
 
   CodeBlobToOopClosure adjust_from_blobs(&oop_closure, CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
-  AOTLoader::oops_do(&oop_closure);
+  AOT_ONLY(AOTLoader::oops_do(&oop_closure);)
+
+  JVMCI_ONLY(JVMCI::oops_do(&oop_closure);)
+
   ref_processor()->weak_oops_do(&oop_closure);
   // Roots were visited so references into the young gen in roots
   // may have been scanned.  Process them also.
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Wed May 01 12:31:29 2019 -0700
@@ -379,6 +379,7 @@
       q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::class_loader_data));
       q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti));
       q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache));
+      JVMCI_ONLY(q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmci));)
 
       TaskTerminator terminator(active_workers,
                                 (TaskQueueSetSuper*) promotion_manager->stack_array_depth());
--- a/src/hotspot/share/gc/parallel/psTasks.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psTasks.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -44,6 +44,9 @@
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/management.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 //
 // ScavengeRootsTask
@@ -95,7 +98,6 @@
       JvmtiExport::oops_do(&roots_closure);
       break;
 
-
     case code_cache:
       {
         MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
@@ -104,6 +106,12 @@
       }
       break;
 
+#if INCLUDE_JVMCI
+    case jvmci:
+      JVMCI::oops_do(&roots_closure);
+      break;
+#endif
+
     default:
       fatal("Unknown root type");
   }
--- a/src/hotspot/share/gc/parallel/psTasks.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psTasks.hpp	Wed May 01 12:31:29 2019 -0700
@@ -61,6 +61,7 @@
     management            = 7,
     jvmti                 = 8,
     code_cache            = 9
+    JVMCI_ONLY(COMMA jvmci = 10)
   };
  private:
   RootType _root_type;
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp	Wed May 01 12:31:29 2019 -0700
@@ -56,6 +56,9 @@
 #include "utilities/copy.hpp"
 #include "utilities/events.hpp"
 #include "utilities/stack.inline.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_softrefs) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
@@ -233,6 +236,9 @@
 
     // Prune dead klasses from subklass/sibling/implementor lists.
     Klass::clean_weak_klass_links(purged_class);
+
+    // Clean JVMCI metadata handles.
+    JVMCI_ONLY(JVMCI::do_unloading(purged_class));
   }
 
   gc_tracer()->report_object_count_after_gc(&is_alive);
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Wed May 01 12:31:29 2019 -0700
@@ -69,6 +69,9 @@
 #include "utilities/macros.hpp"
 #include "utilities/stack.inline.hpp"
 #include "utilities/vmError.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy,
                                    Generation::Name young,
@@ -857,10 +860,16 @@
   if (_process_strong_tasks->try_claim_task(GCH_PS_jvmti_oops_do)) {
     JvmtiExport::oops_do(strong_roots);
   }
+#if INCLUDE_AOT
   if (UseAOT && _process_strong_tasks->try_claim_task(GCH_PS_aot_oops_do)) {
     AOTLoader::oops_do(strong_roots);
   }
-
+#endif
+#if INCLUDE_JVMCI
+  if (EnableJVMCI && _process_strong_tasks->try_claim_task(GCH_PS_jvmci_oops_do)) {
+    JVMCI::oops_do(strong_roots);
+  }
+#endif
   if (_process_strong_tasks->try_claim_task(GCH_PS_SystemDictionary_oops_do)) {
     SystemDictionary::oops_do(strong_roots);
   }
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Wed May 01 12:31:29 2019 -0700
@@ -117,7 +117,8 @@
     GCH_PS_ClassLoaderDataGraph_oops_do,
     GCH_PS_jvmti_oops_do,
     GCH_PS_CodeCache_oops_do,
-    GCH_PS_aot_oops_do,
+    AOT_ONLY(GCH_PS_aot_oops_do COMMA)
+    JVMCI_ONLY(GCH_PS_jvmci_oops_do COMMA)
     GCH_PS_younger_gens,
     // Leave this one last.
     GCH_PS_NumElements
--- a/src/hotspot/share/gc/shared/parallelCleaning.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp	Wed May 01 12:31:29 2019 -0700
@@ -30,6 +30,9 @@
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "logging/log.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 StringDedupCleaningTask::StringDedupCleaningTask(BoolObjectClosure* is_alive,
                                                  OopClosure* keep_alive,
@@ -158,6 +161,27 @@
   }
 }
 
+#if INCLUDE_JVMCI
+JVMCICleaningTask::JVMCICleaningTask() :
+  _cleaning_claimed(0) {
+}
+
+bool JVMCICleaningTask::claim_cleaning_task() {
+  if (_cleaning_claimed) {
+    return false;
+  }
+
+  return Atomic::cmpxchg(1, &_cleaning_claimed, 0) == 0;
+}
+
+void JVMCICleaningTask::work(bool unloading_occurred) {
+  // One worker will clean JVMCI metadata handles.
+  if (unloading_occurred && EnableJVMCI && claim_cleaning_task()) {
+    JVMCI::do_unloading(unloading_occurred);
+  }
+}
+#endif // INCLUDE_JVMCI
+
 ParallelCleaningTask::ParallelCleaningTask(BoolObjectClosure* is_alive,
                                            uint num_workers,
                                            bool unloading_occurred,
@@ -166,11 +190,16 @@
   _unloading_occurred(unloading_occurred),
   _string_dedup_task(is_alive, NULL, resize_dedup_table),
   _code_cache_task(num_workers, is_alive, unloading_occurred),
+  JVMCI_ONLY(_jvmci_cleaning_task() COMMA)
   _klass_cleaning_task() {
 }
 
 // The parallel work done by all worker threads.
 void ParallelCleaningTask::work(uint worker_id) {
+  // Clean JVMCI metadata handles.
+  // Execute this task first because it is serial task.
+  JVMCI_ONLY(_jvmci_cleaning_task.work(_unloading_occurred);)
+
   // Do first pass of code cache cleaning.
   _code_cache_task.work(worker_id);
 
--- a/src/hotspot/share/gc/shared/parallelCleaning.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/gc/shared/parallelCleaning.hpp	Wed May 01 12:31:29 2019 -0700
@@ -87,6 +87,20 @@
   void work();
 };
 
+#if INCLUDE_JVMCI
+class JVMCICleaningTask : public StackObj {
+  volatile int       _cleaning_claimed;
+
+public:
+  JVMCICleaningTask();
+  // Clean JVMCI metadata handles.
+  void work(bool unloading_occurred);
+
+private:
+  bool claim_cleaning_task();
+};
+#endif
+
 // Do cleanup of some weakly held data in the same parallel task.
 // Assumes a non-moving context.
 class ParallelCleaningTask : public AbstractGangTask {
@@ -94,6 +108,9 @@
   bool                    _unloading_occurred;
   StringDedupCleaningTask _string_dedup_task;
   CodeCacheUnloadingTask  _code_cache_task;
+#if INCLUDE_JVMCI
+  JVMCICleaningTask       _jvmci_cleaning_task;
+#endif
   KlassCleaningTask       _klass_cleaning_task;
 
 public:
--- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -40,6 +40,9 @@
 #include "runtime/thread.hpp"
 #include "services/management.hpp"
 #include "utilities/align.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 RootSetClosure::RootSetClosure(EdgeQueue* edge_queue) :
   _edge_queue(edge_queue) {
@@ -104,4 +107,5 @@
   Management::oops_do(closure);
   StringTable::oops_do(closure);
   AOTLoader::oops_do(closure);
+  JVMCI_ONLY(JVMCI::oops_do(closure);)
 }
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -40,6 +40,9 @@
 #include "runtime/vframe_hp.hpp"
 #include "services/management.hpp"
 #include "utilities/growableArray.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 class ReferenceLocateClosure : public OopClosure {
  protected:
@@ -102,6 +105,7 @@
   bool do_management_roots();
   bool do_string_table_roots();
   bool do_aot_loader_roots();
+  JVMCI_ONLY(bool do_jvmci_roots();)
 
   bool do_roots();
 
@@ -188,6 +192,15 @@
   return rcl.complete();
 }
 
+#if INCLUDE_JVMCI
+bool ReferenceToRootClosure::do_jvmci_roots() {
+  assert(!complete(), "invariant");
+  ReferenceLocateClosure rcl(_callback, OldObjectRoot::_jvmci, OldObjectRoot::_type_undetermined, NULL);
+  JVMCI::oops_do(&rcl);
+  return rcl.complete();
+}
+#endif
+
 bool ReferenceToRootClosure::do_roots() {
   assert(!complete(), "invariant");
   assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
@@ -238,6 +251,13 @@
     return true;
   }
 
+#if INCLUDE_JVMCI
+  if (do_jvmci_roots()) {
+   _complete = true;
+    return true;
+  }
+#endif
+
   return false;
 }
 
--- a/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jfr/leakprofiler/utilities/rootType.hpp	Wed May 01 12:31:29 2019 -0700
@@ -43,6 +43,7 @@
     _code_cache,
     _string_table,
     _aot,
+    JVMCI_ONLY(_jvmci COMMA)
     _number_of_systems
   };
 
@@ -81,6 +82,10 @@
         return "String Table";
       case _aot:
         return "AOT";
+#if INCLUDE_JVMCI
+      case _jvmci:
+        return "JVMCI";
+#endif
       default:
         ShouldNotReachHere();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jniAccessMark.inline.hpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+#ifndef SHARE_JVMCI_JNIACCESSMARK_INLINE_HPP
+#define SHARE_JVMCI_JNIACCESSMARK_INLINE_HPP
+
+#include "jvmci/jvmciEnv.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
+
+// Wrapper for a JNI call into the JVMCI shared library.
+// This performs a ThreadToNativeFromVM transition so that the VM
+// will not be blocked if the call takes a long time (e.g., due
+// to a GC in the shared library).
+class JNIAccessMark : public StackObj {
+ private:
+  ThreadToNativeFromVM ttnfv;
+  HandleMark hm;
+  JNIEnv* _env;
+ public:
+  inline JNIAccessMark(JVMCIEnv* jvmci_env) :
+    ttnfv(JavaThread::current()), hm(JavaThread::current()) {
+    _env = jvmci_env->_env;
+  }
+  JNIEnv* env() const { return _env; }
+  JNIEnv* operator () () const { return _env; }
+};
+
+#endif // SHARE_JVMCI_JNIACCESSMARK_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmci.cpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2019, 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/systemDictionary.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/oopStorage.inline.hpp"
+#include "jvmci/jvmci.hpp"
+#include "jvmci/jvmci_globals.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/metadataHandleBlock.hpp"
+
+OopStorage* JVMCI::_object_handles = NULL;
+MetadataHandleBlock* JVMCI::_metadata_handles = NULL;
+JVMCIRuntime* JVMCI::_compiler_runtime = NULL;
+JVMCIRuntime* JVMCI::_java_runtime = NULL;
+
+bool JVMCI::can_initialize_JVMCI() {
+  // Initializing JVMCI requires the module system to be initialized past phase 3.
+  // The JVMCI API itself isn't available until phase 2 and ServiceLoader (which
+  // JVMCI initialization requires) isn't usable until after phase 3. Testing
+  // whether the system loader is initialized satisfies all these invariants.
+  if (SystemDictionary::java_system_loader() == NULL) {
+    return false;
+  }
+  assert(Universe::is_module_initialized(), "must be");
+  return true;
+}
+
+void JVMCI::initialize_compiler(TRAPS) {
+  if (JVMCILibDumpJNIConfig) {
+    JNIJVMCI::initialize_ids(NULL);
+    ShouldNotReachHere();
+  }
+
+  JVMCI::compiler_runtime()->call_getCompiler(CHECK);
+}
+
+void JVMCI::initialize_globals() {
+  _object_handles = new OopStorage("JVMCI Global Oop Handles",
+                                   JVMCIGlobalAlloc_lock,
+                                   JVMCIGlobalActive_lock);
+  _metadata_handles = MetadataHandleBlock::allocate_block();
+  if (UseJVMCINativeLibrary) {
+    // There are two runtimes.
+    _compiler_runtime = new JVMCIRuntime();
+    _java_runtime = new JVMCIRuntime();
+  } else {
+    // There is only a single runtime
+    _java_runtime = _compiler_runtime = new JVMCIRuntime();
+  }
+}
+
+OopStorage* JVMCI::object_handles() {
+  assert(_object_handles != NULL, "Uninitialized");
+  return _object_handles;
+}
+
+jobject JVMCI::make_global(const Handle& obj) {
+  assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
+  assert(oopDesc::is_oop(obj()), "not an oop");
+  oop* ptr = object_handles()->allocate();
+  jobject res = NULL;
+  if (ptr != NULL) {
+    assert(*ptr == NULL, "invariant");
+    NativeAccess<>::oop_store(ptr, obj());
+    res = reinterpret_cast<jobject>(ptr);
+  } else {
+    vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
+                          "Cannot create JVMCI oop handle");
+  }
+  return res;
+}
+
+bool JVMCI::is_global_handle(jobject handle) {
+  const oop* ptr = reinterpret_cast<oop*>(handle);
+  return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;
+}
+
+jmetadata JVMCI::allocate_handle(const methodHandle& handle) {
+  assert(_metadata_handles != NULL, "uninitialized");
+  MutexLocker ml(JVMCI_lock);
+  return _metadata_handles->allocate_handle(handle);
+}
+
+jmetadata JVMCI::allocate_handle(const constantPoolHandle& handle) {
+  assert(_metadata_handles != NULL, "uninitialized");
+  MutexLocker ml(JVMCI_lock);
+  return _metadata_handles->allocate_handle(handle);
+}
+
+void JVMCI::release_handle(jmetadata handle) {
+  MutexLocker ml(JVMCI_lock);
+  _metadata_handles->chain_free_list(handle);
+}
+
+void JVMCI::oops_do(OopClosure* f) {
+  if (_object_handles != NULL) {
+    _object_handles->oops_do(f);
+  }
+}
+
+void JVMCI::metadata_do(void f(Metadata*)) {
+  if (_metadata_handles != NULL) {
+    _metadata_handles->metadata_do(f);
+  }
+}
+
+void JVMCI::do_unloading(bool unloading_occurred) {
+  if (_metadata_handles != NULL && unloading_occurred) {
+    _metadata_handles->do_unloading();
+  }
+}
+
+bool JVMCI::is_compiler_initialized() {
+  return compiler_runtime()->is_HotSpotJVMCIRuntime_initialized();
+}
+
+void JVMCI::shutdown() {
+  if (compiler_runtime() != NULL) {
+    compiler_runtime()->shutdown();
+  }
+}
+
+bool JVMCI::shutdown_called() {
+  if (compiler_runtime() != NULL) {
+    return compiler_runtime()->shutdown_called();
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmci.hpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017, 2019, 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.
+ */
+
+#ifndef SHARE_JVMCI_JVMCI_HPP
+#define SHARE_JVMCI_JVMCI_HPP
+
+#include "compiler/compilerDefinitions.hpp"
+#include "utilities/exceptions.hpp"
+
+class BoolObjectClosure;
+class constantPoolHandle;
+class JavaThread;
+class JVMCIEnv;
+class JVMCIRuntime;
+class Metadata;
+class MetadataHandleBlock;
+class OopClosure;
+class OopStorage;
+
+struct _jmetadata;
+typedef struct _jmetadata *jmetadata;
+
+class JVMCI : public AllStatic {
+  friend class JVMCIRuntime;
+  friend class JVMCIEnv;
+
+ private:
+  // Handles to objects in the HotSpot heap.
+  static OopStorage* _object_handles;
+
+  static OopStorage* object_handles();
+
+  // Handles to Metadata objects.
+  static MetadataHandleBlock* _metadata_handles;
+
+  // Access to the HotSpotJVMCIRuntime used by the CompileBroker.
+  static JVMCIRuntime* _compiler_runtime;
+
+  // Access to the HotSpotJVMCIRuntime used by Java code running on the
+  // HotSpot heap. It will be the same as _compiler_runtime if
+  // UseJVMCINativeLibrary is false
+  static JVMCIRuntime* _java_runtime;
+
+ public:
+  enum CodeInstallResult {
+     ok,
+     dependencies_failed,
+     dependencies_invalid,
+     cache_full,
+     code_too_large
+  };
+
+  static void do_unloading(bool unloading_occurred);
+
+  static void metadata_do(void f(Metadata*));
+
+  static void oops_do(OopClosure* f);
+
+  static void shutdown();
+
+  static bool shutdown_called();
+
+  static bool is_compiler_initialized();
+
+  /**
+   * Determines if the VM is sufficiently booted to initialize JVMCI.
+   */
+  static bool can_initialize_JVMCI();
+
+  static void initialize_globals();
+
+  static void initialize_compiler(TRAPS);
+
+  static jobject make_global(const Handle& obj);
+  static bool is_global_handle(jobject handle);
+
+  static jmetadata allocate_handle(const methodHandle& handle);
+  static jmetadata allocate_handle(const constantPoolHandle& handle);
+
+  static void release_handle(jmetadata handle);
+
+  static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; }
+  static JVMCIRuntime* java_runtime()     { return _java_runtime; }
+};
+
+#endif // SHARE_JVMCI_JVMCI_HPP
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Wed May 01 12:31:29 2019 -0700
@@ -22,28 +22,13 @@
  */
 
 #include "precompiled.hpp"
-#include "asm/register.hpp"
-#include "classfile/vmSymbols.hpp"
 #include "code/compiledIC.hpp"
-#include "code/vmreg.inline.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/disassembler.hpp"
-#include "jvmci/jvmciEnv.hpp"
-#include "jvmci/jvmciCompiler.hpp"
 #include "jvmci/jvmciCodeInstaller.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "memory/allocation.inline.hpp"
-#include "oops/arrayOop.inline.hpp"
-#include "oops/oop.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
-#include "oops/typeArrayOop.inline.hpp"
-#include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/javaCalls.hpp"
 #include "runtime/jniHandles.inline.hpp"
-#include "runtime/safepointMechanism.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/align.hpp"
 
@@ -51,30 +36,25 @@
 // Allocate them with new so they are never destroyed (otherwise, a
 // forced exit could destroy these objects while they are still in
 // use).
-ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
-ConstantIntValue*      CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
-ConstantIntValue*      CodeInstaller::_int_0_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue((jint)0);
-ConstantIntValue*      CodeInstaller::_int_1_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
-ConstantIntValue*      CodeInstaller::_int_2_scope_value =  new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
-LocationValue*         CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
+ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtJVMCI) ConstantOopWriteValue(NULL);
+ConstantIntValue*      CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue(-1);
+ConstantIntValue*      CodeInstaller::_int_0_scope_value =  new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue((jint)0);
+ConstantIntValue*      CodeInstaller::_int_1_scope_value =  new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue(1);
+ConstantIntValue*      CodeInstaller::_int_2_scope_value =  new (ResourceObj::C_HEAP, mtJVMCI) ConstantIntValue(2);
+LocationValue*         CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtJVMCI) LocationValue(Location());
 
-Method* getMethodFromHotSpotMethod(oop hotspot_method) {
-  assert(hotspot_method != NULL && hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass()), "sanity");
-  return CompilerToVM::asMethod(hotspot_method);
-}
-
-VMReg getVMRegFromLocation(Handle location, int total_frame_size, TRAPS) {
+VMReg CodeInstaller::getVMRegFromLocation(JVMCIObject location, int total_frame_size, JVMCI_TRAPS) {
   if (location.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
 
-  Handle reg(THREAD, code_Location::reg(location));
-  jint offset = code_Location::offset(location);
+  JVMCIObject reg = jvmci_env()->get_code_Location_reg(location);
+  jint offset = jvmci_env()->get_code_Location_offset(location);
 
-  if (reg.not_null()) {
+  if (reg.is_non_null()) {
     // register
-    jint number = code_Register::number(reg);
-    VMReg vmReg = CodeInstaller::get_hotspot_reg(number, CHECK_NULL);
+    jint number = jvmci_env()->get_code_Register_number(reg);
+    VMReg vmReg = CodeInstaller::get_hotspot_reg(number, JVMCI_CHECK_NULL);
     if (offset % 4 == 0) {
       return vmReg->next(offset / 4);
     } else {
@@ -102,71 +82,45 @@
   }
 }
 
-objArrayOop CodeInstaller::sites() {
-  return (objArrayOop) JNIHandles::resolve(_sites_handle);
-}
-
-arrayOop CodeInstaller::code() {
-  return (arrayOop) JNIHandles::resolve(_code_handle);
-}
-
-arrayOop CodeInstaller::data_section() {
-  return (arrayOop) JNIHandles::resolve(_data_section_handle);
-}
-
-objArrayOop CodeInstaller::data_section_patches() {
-  return (objArrayOop) JNIHandles::resolve(_data_section_patches_handle);
-}
-
-#ifndef PRODUCT
-objArrayOop CodeInstaller::comments() {
-  return (objArrayOop) JNIHandles::resolve(_comments_handle);
-}
-#endif
-
-oop CodeInstaller::word_kind() {
-  return JNIHandles::resolve(_word_kind_handle);
-}
-
 // creates a HotSpot oop map out of the byte arrays provided by DebugInfo
-OopMap* CodeInstaller::create_oop_map(Handle debug_info, TRAPS) {
-  Handle reference_map(THREAD, DebugInfo::referenceMap(debug_info));
+OopMap* CodeInstaller::create_oop_map(JVMCIObject debug_info, JVMCI_TRAPS) {
+  JVMCIObject reference_map = jvmci_env()->get_DebugInfo_referenceMap(debug_info);
   if (reference_map.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (!reference_map->is_a(HotSpotReferenceMap::klass())) {
-    JVMCI_ERROR_NULL("unknown reference map: %s", reference_map->klass()->signature_name());
+  if (!jvmci_env()->isa_HotSpotReferenceMap(reference_map)) {
+    JVMCI_ERROR_NULL("unknown reference map: %s", jvmci_env()->klass_name(reference_map));
   }
-  if (!_has_wide_vector && SharedRuntime::is_wide_vector(HotSpotReferenceMap::maxRegisterSize(reference_map))) {
+  if (!_has_wide_vector && SharedRuntime::is_wide_vector(jvmci_env()->get_HotSpotReferenceMap_maxRegisterSize(reference_map))) {
     if (SharedRuntime::polling_page_vectors_safepoint_handler_blob() == NULL) {
       JVMCI_ERROR_NULL("JVMCI is producing code using vectors larger than the runtime supports");
     }
     _has_wide_vector = true;
   }
   OopMap* map = new OopMap(_total_frame_size, _parameter_count);
-  objArrayHandle objects(THREAD, HotSpotReferenceMap::objects(reference_map));
-  objArrayHandle derivedBase(THREAD, HotSpotReferenceMap::derivedBase(reference_map));
-  typeArrayHandle sizeInBytes(THREAD, HotSpotReferenceMap::sizeInBytes(reference_map));
+  JVMCIObjectArray objects = jvmci_env()->get_HotSpotReferenceMap_objects(reference_map);
+  JVMCIObjectArray derivedBase = jvmci_env()->get_HotSpotReferenceMap_derivedBase(reference_map);
+  JVMCIPrimitiveArray sizeInBytes = jvmci_env()->get_HotSpotReferenceMap_sizeInBytes(reference_map);
   if (objects.is_null() || derivedBase.is_null() || sizeInBytes.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (objects->length() != derivedBase->length() || objects->length() != sizeInBytes->length()) {
-    JVMCI_ERROR_NULL("arrays in reference map have different sizes: %d %d %d", objects->length(), derivedBase->length(), sizeInBytes->length());
+  if (JVMCIENV->get_length(objects) != JVMCIENV->get_length(derivedBase) || JVMCIENV->get_length(objects) != JVMCIENV->get_length(sizeInBytes)) {
+    JVMCI_ERROR_NULL("arrays in reference map have different sizes: %d %d %d", JVMCIENV->get_length(objects), JVMCIENV->get_length(derivedBase), JVMCIENV->get_length(sizeInBytes));
   }
-  for (int i = 0; i < objects->length(); i++) {
-    Handle location(THREAD, objects->obj_at(i));
-    Handle baseLocation(THREAD, derivedBase->obj_at(i));
-    int bytes = sizeInBytes->int_at(i);
+  for (int i = 0; i < JVMCIENV->get_length(objects); i++) {
+    JVMCIObject location = JVMCIENV->get_object_at(objects, i);
+    JVMCIObject baseLocation = JVMCIENV->get_object_at(derivedBase, i);
+    jint bytes = JVMCIENV->get_int_at(sizeInBytes, i);
 
-    VMReg vmReg = getVMRegFromLocation(location, _total_frame_size, CHECK_NULL);
-    if (baseLocation.not_null()) {
+    VMReg vmReg = getVMRegFromLocation(location, _total_frame_size, JVMCI_CHECK_NULL);
+    if (baseLocation.is_non_null()) {
       // derived oop
 #ifdef _LP64
       if (bytes == 8) {
 #else
       if (bytes == 4) {
 #endif
-        VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size, CHECK_NULL);
+        VMReg baseReg = getVMRegFromLocation(baseLocation, _total_frame_size, JVMCI_CHECK_NULL);
         map->set_derived_oop(vmReg, baseReg);
       } else {
         JVMCI_ERROR_NULL("invalid derived oop size in ReferenceMap: %d", bytes);
@@ -187,16 +141,16 @@
     }
   }
 
-  Handle callee_save_info(THREAD, (oop) DebugInfo::calleeSaveInfo(debug_info));
-  if (callee_save_info.not_null()) {
-    objArrayHandle registers(THREAD, RegisterSaveLayout::registers(callee_save_info));
-    typeArrayHandle slots(THREAD, RegisterSaveLayout::slots(callee_save_info));
-    for (jint i = 0; i < slots->length(); i++) {
-      Handle jvmci_reg (THREAD, registers->obj_at(i));
-      jint jvmci_reg_number = code_Register::number(jvmci_reg);
-      VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number, CHECK_NULL);
+  JVMCIObject callee_save_info = jvmci_env()->get_DebugInfo_calleeSaveInfo(debug_info);
+  if (callee_save_info.is_non_null()) {
+    JVMCIObjectArray registers = jvmci_env()->get_RegisterSaveLayout_registers(callee_save_info);
+    JVMCIPrimitiveArray slots = jvmci_env()->get_RegisterSaveLayout_slots(callee_save_info);
+    for (jint i = 0; i < JVMCIENV->get_length(slots); i++) {
+      JVMCIObject jvmci_reg = JVMCIENV->get_object_at(registers, i);
+      jint jvmci_reg_number = jvmci_env()->get_code_Register_number(jvmci_reg);
+      VMReg hotspot_reg = CodeInstaller::get_hotspot_reg(jvmci_reg_number, JVMCI_CHECK_NULL);
       // HotSpot stack slots are 4 bytes
-      jint jvmci_slot = slots->int_at(i);
+      jint jvmci_slot = JVMCIENV->get_int_at(slots, i);
       jint hotspot_slot = jvmci_slot * VMRegImpl::slots_per_word;
       VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot);
       map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg);
@@ -211,7 +165,8 @@
 }
 
 #if INCLUDE_AOT
-AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
+AOTOopRecorder::AOTOopRecorder(CodeInstaller* code_inst, Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) {
+  _code_inst = code_inst;
   _meta_refs = new GrowableArray<jobject>();
 }
 
@@ -225,6 +180,7 @@
 
 int AOTOopRecorder::find_index(Metadata* h) {
   JavaThread* THREAD = JavaThread::current();
+  JVMCIEnv* JVMCIENV = _code_inst->jvmci_env();
   int oldCount = metadata_count();
   int index =  this->OopRecorder::find_index(h);
   int newCount = metadata_count();
@@ -237,18 +193,18 @@
   vmassert(index + 1 == newCount, "must be last");
 
   JVMCIKlassHandle klass(THREAD);
-  oop result = NULL;
+  JVMCIObject result;
   guarantee(h != NULL,
             "If DebugInformationRecorder::describe_scope passes NULL oldCount == newCount must hold.");
   if (h->is_klass()) {
     klass = (Klass*) h;
-    result = CompilerToVM::get_jvmci_type(klass, CATCH);
+    result = JVMCIENV->get_jvmci_type(klass, JVMCI_CATCH);
   } else if (h->is_method()) {
     Method* method = (Method*) h;
     methodHandle mh(method);
-    result = CompilerToVM::get_jvmci_method(method, CATCH);
+    result = JVMCIENV->get_jvmci_method(method, JVMCI_CATCH);
   }
-  jobject ref = JNIHandles::make_local(THREAD, result);
+  jobject ref = JVMCIENV->get_jobject(result);
   record_meta_ref(ref, index);
 
   return index;
@@ -272,43 +228,43 @@
 }
 #endif // INCLUDE_AOT
 
-void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
+void* CodeInstaller::record_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS) {
   /*
    * This method needs to return a raw (untyped) pointer, since the value of a pointer to the base
    * class is in general not equal to the pointer of the subclass. When patching metaspace pointers,
    * the compiler expects a direct pointer to the subclass (Klass* or Method*), not a pointer to the
    * base class (Metadata* or MetaspaceObj*).
    */
-  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
-  if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
-    Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
-    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass));
+  JVMCIObject obj = jvmci_env()->get_HotSpotMetaspaceConstantImpl_metaspaceObject(constant);
+  if (jvmci_env()->isa_HotSpotResolvedObjectTypeImpl(obj)) {
+    Klass* klass = JVMCIENV->asKlass(obj);
+    assert(!jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass));
     int index = _oop_recorder->find_index(klass);
     section->relocate(dest, metadata_Relocation::spec(index));
     TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
     return klass;
-  } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
-    Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj);
-    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method));
+  } else if (jvmci_env()->isa_HotSpotResolvedJavaMethodImpl(obj)) {
+    Method* method = jvmci_env()->asMethod(obj);
+    assert(!jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method));
     int index = _oop_recorder->find_index(method);
     section->relocate(dest, metadata_Relocation::spec(index));
     TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string());
     return method;
   } else {
-    JVMCI_ERROR_NULL("unexpected metadata reference for constant of type %s", obj->klass()->signature_name());
+    JVMCI_ERROR_NULL("unexpected metadata reference for constant of type %s", jvmci_env()->klass_name(obj));
   }
 }
 
 #ifdef _LP64
-narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS) {
-  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
-  assert(HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected uncompressed pointer");
+narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS) {
+  JVMCIObject obj = jvmci_env()->get_HotSpotMetaspaceConstantImpl_metaspaceObject(constant);
+  assert(jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected uncompressed pointer");
 
-  if (!obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
-    JVMCI_ERROR_0("unexpected compressed pointer of type %s", obj->klass()->signature_name());
+  if (!jvmci_env()->isa_HotSpotResolvedObjectTypeImpl(obj)) {
+    JVMCI_ERROR_0("unexpected compressed pointer of type %s", jvmci_env()->klass_name(obj));
   }
 
-  Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
+  Klass* klass = JVMCIENV->asKlass(obj);
   int index = _oop_recorder->find_index(klass);
   section->relocate(dest, metadata_Relocation::spec(index));
   TRACE_jvmci_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
@@ -316,34 +272,34 @@
 }
 #endif
 
-Location::Type CodeInstaller::get_oop_type(Thread* thread, Handle value) {
-  Handle valueKind(thread, Value::valueKind(value));
-  Handle platformKind(thread, ValueKind::platformKind(valueKind));
+Location::Type CodeInstaller::get_oop_type(JVMCIObject value) {
+  JVMCIObject valueKind = jvmci_env()->get_Value_valueKind(value);
+  JVMCIObject platformKind = jvmci_env()->get_ValueKind_platformKind(valueKind);
 
-  if (platformKind == word_kind()) {
+  if (jvmci_env()->equals(platformKind, word_kind())) {
     return Location::oop;
   } else {
     return Location::narrowoop;
   }
 }
 
-ScopeValue* CodeInstaller::get_scope_value(Handle value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, TRAPS) {
+ScopeValue* CodeInstaller::get_scope_value(JVMCIObject value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, JVMCI_TRAPS) {
   second = NULL;
   if (value.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
-  } else if (value == Value::ILLEGAL()) {
+    JVMCI_THROW_NULL(NullPointerException);
+  } else if (JVMCIENV->equals(value, jvmci_env()->get_Value_ILLEGAL())) {
     if (type != T_ILLEGAL) {
       JVMCI_ERROR_NULL("unexpected illegal value, expected %s", basictype_to_str(type));
     }
     return _illegal_value;
-  } else if (value->is_a(RegisterValue::klass())) {
-    Handle reg(THREAD, RegisterValue::reg(value));
-    jint number = code_Register::number(reg);
-    VMReg hotspotRegister = get_hotspot_reg(number, CHECK_NULL);
+  } else if (jvmci_env()->isa_RegisterValue(value)) {
+    JVMCIObject reg = jvmci_env()->get_RegisterValue_reg(value);
+    jint number = jvmci_env()->get_code_Register_number(reg);
+    VMReg hotspotRegister = get_hotspot_reg(number, JVMCI_CHECK_NULL);
     if (is_general_purpose_reg(hotspotRegister)) {
       Location::Type locationType;
       if (type == T_OBJECT) {
-        locationType = get_oop_type(THREAD, value);
+        locationType = get_oop_type(value);
       } else if (type == T_LONG) {
         locationType = Location::lng;
       } else if (type == T_INT || type == T_FLOAT || type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) {
@@ -372,15 +328,15 @@
       }
       return value;
     }
-  } else if (value->is_a(StackSlot::klass())) {
-    jint offset = StackSlot::offset(value);
-    if (StackSlot::addFrameSize(value)) {
+  } else if (jvmci_env()->isa_StackSlot(value)) {
+    jint offset = jvmci_env()->get_StackSlot_offset(value);
+    if (jvmci_env()->get_StackSlot_addFrameSize(value)) {
       offset += _total_frame_size;
     }
 
     Location::Type locationType;
     if (type == T_OBJECT) {
-      locationType = get_oop_type(THREAD, value);
+      locationType = get_oop_type(value);
     } else if (type == T_LONG) {
       locationType = Location::lng;
     } else if (type == T_DOUBLE) {
@@ -395,19 +351,18 @@
       second = value;
     }
     return value;
-  } else if (value->is_a(JavaConstant::klass())) {
-    if (value->is_a(PrimitiveConstant::klass())) {
-      if (value->is_a(RawConstant::klass())) {
-        jlong prim = PrimitiveConstant::primitive(value);
+  } else if (jvmci_env()->isa_JavaConstant(value)) {
+    if (jvmci_env()->isa_PrimitiveConstant(value)) {
+      if (jvmci_env()->isa_RawConstant(value)) {
+        jlong prim = jvmci_env()->get_PrimitiveConstant_primitive(value);
         return new ConstantLongValue(prim);
       } else {
-        Handle primitive_constant_kind(THREAD, PrimitiveConstant::kind(value));
-        BasicType constantType = JVMCIRuntime::kindToBasicType(primitive_constant_kind, CHECK_NULL);
+        BasicType constantType = jvmci_env()->kindToBasicType(jvmci_env()->get_PrimitiveConstant_kind(value), JVMCI_CHECK_NULL);
         if (type != constantType) {
           JVMCI_ERROR_NULL("primitive constant type doesn't match, expected %s but got %s", basictype_to_str(type), basictype_to_str(constantType));
         }
         if (type == T_INT || type == T_FLOAT) {
-          jint prim = (jint)PrimitiveConstant::primitive(value);
+          jint prim = (jint)jvmci_env()->get_PrimitiveConstant_primitive(value);
           switch (prim) {
             case -1: return _int_m1_scope_value;
             case  0: return _int_0_scope_value;
@@ -416,33 +371,33 @@
             default: return new ConstantIntValue(prim);
           }
         } else if (type == T_LONG || type == T_DOUBLE) {
-          jlong prim = PrimitiveConstant::primitive(value);
+          jlong prim = jvmci_env()->get_PrimitiveConstant_primitive(value);
           second = _int_1_scope_value;
           return new ConstantLongValue(prim);
         } else {
           JVMCI_ERROR_NULL("unexpected primitive constant type %s", basictype_to_str(type));
         }
       }
-    } else if (value->is_a(NullConstant::klass()) || value->is_a(HotSpotCompressedNullConstant::klass())) {
+    } else if (jvmci_env()->isa_NullConstant(value) || jvmci_env()->isa_HotSpotCompressedNullConstant(value)) {
       if (type == T_OBJECT) {
         return _oop_null_scope_value;
       } else {
         JVMCI_ERROR_NULL("unexpected null constant, expected %s", basictype_to_str(type));
       }
-    } else if (value->is_a(HotSpotObjectConstantImpl::klass())) {
+    } else if (jvmci_env()->isa_HotSpotObjectConstantImpl(value)) {
       if (type == T_OBJECT) {
-        oop obj = HotSpotObjectConstantImpl::object(value);
+        Handle obj = jvmci_env()->asConstant(value, JVMCI_CHECK_NULL);
         if (obj == NULL) {
           JVMCI_ERROR_NULL("null value must be in NullConstant");
         }
-        return new ConstantOopWriteValue(JNIHandles::make_local(obj));
+        return new ConstantOopWriteValue(JNIHandles::make_local(obj()));
       } else {
         JVMCI_ERROR_NULL("unexpected object constant, expected %s", basictype_to_str(type));
       }
     }
-  } else if (value->is_a(VirtualObject::klass())) {
+  } else if (jvmci_env()->isa_VirtualObject(value)) {
     if (type == T_OBJECT) {
-      int id = VirtualObject::id(value);
+      int id = jvmci_env()->get_VirtualObject_id(value);
       if (0 <= id && id < objects->length()) {
         ScopeValue* object = objects->at(id);
         if (object != NULL) {
@@ -455,26 +410,22 @@
     }
   }
 
-  JVMCI_ERROR_NULL("unexpected value in scope: %s", value->klass()->signature_name())
+  JVMCI_ERROR_NULL("unexpected value in scope: %s", jvmci_env()->klass_name(value))
 }
 
-void CodeInstaller::record_object_value(ObjectValue* sv, Handle value, GrowableArray<ScopeValue*>* objects, TRAPS) {
-  // Might want a HandleMark here.
-  Handle type(THREAD, VirtualObject::type(value));
-  int id = VirtualObject::id(value);
-  oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
-  Klass* klass = java_lang_Class::as_Klass(javaMirror);
+void CodeInstaller::record_object_value(ObjectValue* sv, JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS) {
+  JVMCIObject type = jvmci_env()->get_VirtualObject_type(value);
+  int id = jvmci_env()->get_VirtualObject_id(value);
+  Klass* klass = JVMCIENV->asKlass(type);
   bool isLongArray = klass == Universe::longArrayKlassObj();
 
-  objArrayHandle values(THREAD, VirtualObject::values(value));
-  objArrayHandle slotKinds(THREAD, VirtualObject::slotKinds(value));
-  for (jint i = 0; i < values->length(); i++) {
-    HandleMark hm(THREAD);
+  JVMCIObjectArray values = jvmci_env()->get_VirtualObject_values(value);
+  JVMCIObjectArray slotKinds = jvmci_env()->get_VirtualObject_slotKinds(value);
+  for (jint i = 0; i < JVMCIENV->get_length(values); i++) {
     ScopeValue* cur_second = NULL;
-    Handle object(THREAD, values->obj_at(i));
-    Handle slot_kind (THREAD, slotKinds->obj_at(i));
-    BasicType type = JVMCIRuntime::kindToBasicType(slot_kind, CHECK);
-    ScopeValue* value = get_scope_value(object, type, objects, cur_second, CHECK);
+    JVMCIObject object = JVMCIENV->get_object_at(values, i);
+    BasicType type = jvmci_env()->kindToBasicType(JVMCIENV->get_object_at(slotKinds, i), JVMCI_CHECK);
+    ScopeValue* value = get_scope_value(object, type, objects, cur_second, JVMCI_CHECK);
 
     if (isLongArray && cur_second == NULL) {
       // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
@@ -490,68 +441,65 @@
   }
 }
 
-MonitorValue* CodeInstaller::get_monitor_value(Handle value, GrowableArray<ScopeValue*>* objects, TRAPS) {
+MonitorValue* CodeInstaller::get_monitor_value(JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS) {
   if (value.is_null()) {
-    THROW_NULL(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (!value->is_a(StackLockValue::klass())) {
-    JVMCI_ERROR_NULL("Monitors must be of type StackLockValue, got %s", value->klass()->signature_name());
+  if (!jvmci_env()->isa_StackLockValue(value)) {
+    JVMCI_ERROR_NULL("Monitors must be of type StackLockValue, got %s", jvmci_env()->klass_name(value));
   }
 
   ScopeValue* second = NULL;
-  Handle stack_lock_owner(THREAD, StackLockValue::owner(value));
-  ScopeValue* owner_value = get_scope_value(stack_lock_owner, T_OBJECT, objects, second, CHECK_NULL);
+  ScopeValue* owner_value = get_scope_value(jvmci_env()->get_StackLockValue_owner(value), T_OBJECT, objects, second, JVMCI_CHECK_NULL);
   assert(second == NULL, "monitor cannot occupy two stack slots");
 
-  Handle stack_lock_slot(THREAD, StackLockValue::slot(value));
-  ScopeValue* lock_data_value = get_scope_value(stack_lock_slot, T_LONG, objects, second, CHECK_NULL);
+  ScopeValue* lock_data_value = get_scope_value(jvmci_env()->get_StackLockValue_slot(value), T_LONG, objects, second, JVMCI_CHECK_NULL);
   assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots");
   assert(lock_data_value->is_location(), "invalid monitor location");
   Location lock_data_loc = ((LocationValue*)lock_data_value)->location();
 
   bool eliminated = false;
-  if (StackLockValue::eliminated(value)) {
+  if (jvmci_env()->get_StackLockValue_eliminated(value)) {
     eliminated = true;
   }
 
   return new MonitorValue(owner_value, lock_data_loc, eliminated);
 }
 
-void CodeInstaller::initialize_dependencies(oop compiled_code, OopRecorder* recorder, TRAPS) {
+void CodeInstaller::initialize_dependencies(JVMCIObject compiled_code, OopRecorder* oop_recorder, JVMCI_TRAPS) {
   JavaThread* thread = JavaThread::current();
-  assert(THREAD == thread, "");
   CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL;
-  _oop_recorder = recorder;
+  _oop_recorder = oop_recorder;
   _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL);
-  objArrayHandle assumptions(THREAD, HotSpotCompiledCode::assumptions(compiled_code));
-  if (!assumptions.is_null()) {
-    int length = assumptions->length();
+  JVMCIObjectArray assumptions = jvmci_env()->get_HotSpotCompiledCode_assumptions(compiled_code);
+  if (assumptions.is_non_null()) {
+    int length = JVMCIENV->get_length(assumptions);
     for (int i = 0; i < length; ++i) {
-      Handle assumption(THREAD, assumptions->obj_at(i));
-      if (!assumption.is_null()) {
-        if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) {
-          assumption_NoFinalizableSubclass(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
-          assumption_ConcreteSubtype(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_LeafType::klass()) {
-          assumption_LeafType(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
-          assumption_ConcreteMethod(THREAD, assumption);
-        } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
-          assumption_CallSiteTargetValue(THREAD, assumption);
+      JVMCIObject assumption = JVMCIENV->get_object_at(assumptions, i);
+      if (assumption.is_non_null()) {
+        if (jvmci_env()->isa_Assumptions_NoFinalizableSubclass(assumption)) {
+          assumption_NoFinalizableSubclass(assumption);
+        } else if (jvmci_env()->isa_Assumptions_ConcreteSubtype(assumption)) {
+          assumption_ConcreteSubtype(assumption);
+        } else if (jvmci_env()->isa_Assumptions_LeafType(assumption)) {
+          assumption_LeafType(assumption);
+        } else if (jvmci_env()->isa_Assumptions_ConcreteMethod(assumption)) {
+          assumption_ConcreteMethod(assumption);
+        } else if (jvmci_env()->isa_Assumptions_CallSiteTargetValue(assumption)) {
+          assumption_CallSiteTargetValue(assumption, JVMCI_CHECK);
         } else {
-          JVMCI_ERROR("unexpected Assumption subclass %s", assumption->klass()->signature_name());
+          JVMCI_ERROR("unexpected Assumption subclass %s", jvmci_env()->klass_name(assumption));
         }
       }
     }
   }
   if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
-    objArrayHandle methods(THREAD, HotSpotCompiledCode::methods(compiled_code));
-    if (!methods.is_null()) {
-      int length = methods->length();
+    JVMCIObjectArray methods = jvmci_env()->get_HotSpotCompiledCode_methods(compiled_code);
+    if (methods.is_non_null()) {
+      int length = JVMCIENV->get_length(methods);
       for (int i = 0; i < length; ++i) {
-        Handle method_handle(THREAD, methods->obj_at(i));
-        methodHandle method = getMethodFromHotSpotMethod(method_handle());
+        JVMCIObject method_handle = JVMCIENV->get_object_at(methods, i);
+        methodHandle method = jvmci_env()->asMethod(method_handle);
         _dependencies->assert_evol_method(method());
       }
     }
@@ -581,16 +529,16 @@
   assert(_buffer == NULL, "can only be used once");
   assert(_size == 0, "can only be used once");
   if (bytes >= RelocBuffer::stack_size) {
-    _buffer = NEW_C_HEAP_ARRAY(char, bytes, mtInternal);
+    _buffer = NEW_C_HEAP_ARRAY(char, bytes, mtJVMCI);
   }
   _size = bytes;
 }
 
-JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS) {
+JVMCI::CodeInstallResult CodeInstaller::gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS) {
+  assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
   CodeBuffer buffer("JVMCI Compiler CodeBuffer for Metadata");
-  jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
-  AOTOopRecorder* recorder = new AOTOopRecorder(&_arena, true);
-  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder, CHECK_OK);
+  AOTOopRecorder* recorder = new AOTOopRecorder(this, &_arena, true);
+  initialize_dependencies(compiled_code, recorder, JVMCI_CHECK_OK);
 
   metadata.set_oop_recorder(recorder);
 
@@ -599,9 +547,9 @@
   _constants = buffer.consts();
   buffer.set_immutable_PIC(_immutable_pic_compilation);
 
-  initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
-  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, false, CHECK_OK);
-  if (result != JVMCIEnv::ok) {
+  initialize_fields(target, compiled_code, JVMCI_CHECK_OK);
+  JVMCI::CodeInstallResult result = initialize_buffer(buffer, false, JVMCI_CHECK_OK);
+  if (result != JVMCI::ok) {
     return result;
   }
 
@@ -618,16 +566,24 @@
   reloc_buffer->ensure_size(buffer.total_relocation_size());
   size_t size = (size_t) buffer.copy_relocations_to(reloc_buffer->begin(), (CodeBuffer::csize_t) reloc_buffer->size(), true);
   reloc_buffer->set_size(size);
-  return JVMCIEnv::ok;
+  return JVMCI::ok;
 }
 #endif // INCLUDE_AOT
 
 // constructor used to create a method
-JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS) {
+JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
+    JVMCIObject target,
+    JVMCIObject compiled_code,
+    CodeBlob*& cb,
+    JVMCIObject installed_code,
+    FailedSpeculation** failed_speculations,
+    char* speculations,
+    int speculations_len,
+    JVMCI_TRAPS) {
+
   CodeBuffer buffer("JVMCI Compiler CodeBuffer");
-  jobject compiled_code_obj = JNIHandles::make_local(compiled_code());
   OopRecorder* recorder = new OopRecorder(&_arena, true);
-  initialize_dependencies(JNIHandles::resolve(compiled_code_obj), recorder, CHECK_OK);
+  initialize_dependencies(compiled_code, recorder, JVMCI_CHECK_OK);
 
   // Get instructions and constants CodeSections early because we need it.
   _instructions = buffer.insts();
@@ -636,44 +592,55 @@
   buffer.set_immutable_PIC(_immutable_pic_compilation);
 #endif
 
-  initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
-  JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, true, CHECK_OK);
-  if (result != JVMCIEnv::ok) {
+  initialize_fields(target, compiled_code, JVMCI_CHECK_OK);
+  JVMCI::CodeInstallResult result = initialize_buffer(buffer, true, JVMCI_CHECK_OK);
+  if (result != JVMCI::ok) {
     return result;
   }
 
   int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
 
-  if (!compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
-    oop stubName = HotSpotCompiledCode::name(compiled_code_obj);
-    if (stubName == NULL) {
+  if (!jvmci_env()->isa_HotSpotCompiledNmethod(compiled_code)) {
+    JVMCIObject stubName = jvmci_env()->get_HotSpotCompiledCode_name(compiled_code);
+    if (stubName.is_null()) {
       JVMCI_ERROR_OK("stub should have a name");
     }
-    char* name = strdup(java_lang_String::as_utf8_string(stubName));
+    char* name = strdup(jvmci_env()->as_utf8_string(stubName));
     cb = RuntimeStub::new_runtime_stub(name,
                                        &buffer,
                                        CodeOffsets::frame_never_safe,
                                        stack_slots,
                                        _debug_recorder->_oopmaps,
                                        false);
-    result = JVMCIEnv::ok;
+    result = JVMCI::ok;
   } else {
-    nmethod* nm = NULL;
-    methodHandle method = getMethodFromHotSpotMethod(HotSpotCompiledNmethod::method(compiled_code));
-    jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code);
-    jint id = HotSpotCompiledNmethod::id(compiled_code);
-    bool has_unsafe_access = HotSpotCompiledNmethod::hasUnsafeAccess(compiled_code) == JNI_TRUE;
-    JVMCIEnv* env = (JVMCIEnv*) (address) HotSpotCompiledNmethod::jvmciEnv(compiled_code);
+    JVMCICompileState* compile_state = (JVMCICompileState*) (address) jvmci_env()->get_HotSpotCompiledNmethod_compileState(compiled_code);
+    if (compile_state != NULL) {
+      jvmci_env()->set_compile_state(compile_state);
+    }
+
+    methodHandle method = jvmci_env()->asMethod(jvmci_env()->get_HotSpotCompiledNmethod_method(compiled_code));
+    jint entry_bci = jvmci_env()->get_HotSpotCompiledNmethod_entryBCI(compiled_code);
+    bool has_unsafe_access = jvmci_env()->get_HotSpotCompiledNmethod_hasUnsafeAccess(compiled_code) == JNI_TRUE;
+    jint id = jvmci_env()->get_HotSpotCompiledNmethod_id(compiled_code);
     if (id == -1) {
       // Make sure a valid compile_id is associated with every compile
       id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci);
+      jvmci_env()->set_HotSpotCompiledNmethod_id(compiled_code, id);
     }
-    result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer,
-                                       stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-                                       compiler, _debug_recorder, _dependencies, env, id,
-                                       has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
+    if (!jvmci_env()->isa_HotSpotNmethod(installed_code)) {
+      JVMCI_THROW_MSG_(IllegalArgumentException, "InstalledCode object must be a HotSpotNmethod when installing a HotSpotCompiledNmethod", JVMCI::ok);
+    }
+
+    JVMCIObject mirror = installed_code;
+    nmethod* nm = NULL;
+    result = runtime()->register_method(jvmci_env(), method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer,
+                                        stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+                                        compiler, _debug_recorder, _dependencies, id,
+                                        has_unsafe_access, _has_wide_vector, compiled_code, mirror,
+                                        failed_speculations, speculations, speculations_len);
     cb = nm->as_codeblob_or_null();
-    if (nm != NULL && env == NULL) {
+    if (nm != NULL && compile_state == NULL) {
       DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
       bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
       if (!printnmethods && (PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers)) {
@@ -690,10 +657,10 @@
   return result;
 }
 
-void CodeInstaller::initialize_fields(oop target, oop compiled_code, TRAPS) {
-  if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) {
-    Handle hotspotJavaMethod(THREAD, HotSpotCompiledNmethod::method(compiled_code));
-    methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod());
+void CodeInstaller::initialize_fields(JVMCIObject target, JVMCIObject compiled_code, JVMCI_TRAPS) {
+  if (jvmci_env()->isa_HotSpotCompiledNmethod(compiled_code)) {
+    JVMCIObject hotspotJavaMethod = jvmci_env()->get_HotSpotCompiledNmethod_method(compiled_code);
+    methodHandle method = jvmci_env()->asMethod(hotspotJavaMethod);
     _parameter_count = method->size_of_parameters();
     TRACE_jvmci_2("installing code for %s", method->name_and_sig_as_C_string());
   } else {
@@ -701,18 +668,18 @@
     // Only used in OopMap constructor for non-product builds
     _parameter_count = 0;
   }
-  _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code));
+  _sites_handle = jvmci_env()->get_HotSpotCompiledCode_sites(compiled_code);
 
-  _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code));
-  _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code);
-  _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code);
+  _code_handle = jvmci_env()->get_HotSpotCompiledCode_targetCode(compiled_code);
+  _code_size = jvmci_env()->get_HotSpotCompiledCode_targetCodeSize(compiled_code);
+  _total_frame_size = jvmci_env()->get_HotSpotCompiledCode_totalFrameSize(compiled_code);
 
-  oop deoptRescueSlot = HotSpotCompiledCode::deoptRescueSlot(compiled_code);
-  if (deoptRescueSlot == NULL) {
+  JVMCIObject deoptRescueSlot = jvmci_env()->get_HotSpotCompiledCode_deoptRescueSlot(compiled_code);
+  if (deoptRescueSlot.is_null()) {
     _orig_pc_offset = -1;
   } else {
-    _orig_pc_offset = StackSlot::offset(deoptRescueSlot);
-    if (StackSlot::addFrameSize(deoptRescueSlot)) {
+    _orig_pc_offset = jvmci_env()->get_StackSlot_offset(deoptRescueSlot);
+    if (jvmci_env()->get_StackSlot_addFrameSize(deoptRescueSlot)) {
       _orig_pc_offset += _total_frame_size;
     }
     if (_orig_pc_offset < 0) {
@@ -721,62 +688,61 @@
   }
 
   // Pre-calculate the constants section size.  This is required for PC-relative addressing.
-  _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code));
-  if ((_constants->alignment() % HotSpotCompiledCode::dataSectionAlignment(compiled_code)) != 0) {
-    JVMCI_ERROR("invalid data section alignment: %d", HotSpotCompiledCode::dataSectionAlignment(compiled_code));
+  _data_section_handle = jvmci_env()->get_HotSpotCompiledCode_dataSection(compiled_code);
+  if ((_constants->alignment() % jvmci_env()->get_HotSpotCompiledCode_dataSectionAlignment(compiled_code)) != 0) {
+    JVMCI_ERROR("invalid data section alignment: %d", jvmci_env()->get_HotSpotCompiledCode_dataSectionAlignment(compiled_code));
   }
-  _constants_size = data_section()->length();
+  _constants_size = JVMCIENV->get_length(data_section());
 
-  _data_section_patches_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSectionPatches(compiled_code));
+  _data_section_patches_handle = jvmci_env()->get_HotSpotCompiledCode_dataSectionPatches(compiled_code);
 
 #ifndef PRODUCT
-  _comments_handle = JNIHandles::make_local(HotSpotCompiledCode::comments(compiled_code));
+  _comments_handle = jvmci_env()->get_HotSpotCompiledCode_comments(compiled_code);
 #endif
 
   _next_call_type = INVOKE_INVALID;
 
   _has_wide_vector = false;
 
-  oop arch = TargetDescription::arch(target);
-  _word_kind_handle = JNIHandles::make_local(Architecture::wordKind(arch));
+  JVMCIObject arch = jvmci_env()->get_TargetDescription_arch(target);
+  _word_kind_handle = jvmci_env()->get_Architecture_wordKind(arch);
 }
 
-int CodeInstaller::estimate_stubs_size(TRAPS) {
+int CodeInstaller::estimate_stubs_size(JVMCI_TRAPS) {
   // Estimate the number of static and aot call stubs that might be emitted.
   int static_call_stubs = 0;
   int aot_call_stubs = 0;
   int trampoline_stubs = 0;
-  objArrayOop sites = this->sites();
-  for (int i = 0; i < sites->length(); i++) {
-    oop site = sites->obj_at(i);
-    if (site != NULL) {
-      if (site->is_a(site_Mark::klass())) {
-        oop id_obj = site_Mark::id(site);
-        if (id_obj != NULL) {
-          if (!java_lang_boxing_object::is_instance(id_obj, T_INT)) {
-            JVMCI_ERROR_0("expected Integer id, got %s", id_obj->klass()->signature_name());
+  JVMCIObjectArray sites = this->sites();
+  for (int i = 0; i < JVMCIENV->get_length(sites); i++) {
+    JVMCIObject site = JVMCIENV->get_object_at(sites, i);
+    if (!site.is_null()) {
+      if (jvmci_env()->isa_site_Mark(site)) {
+        JVMCIObject id_obj = jvmci_env()->get_site_Mark_id(site);
+        if (id_obj.is_non_null()) {
+          if (!jvmci_env()->is_boxing_object(T_INT, id_obj)) {
+            JVMCI_ERROR_0("expected Integer id, got %s", jvmci_env()->klass_name(id_obj));
           }
-          jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+          jint id = jvmci_env()->get_boxed_value(T_INT, id_obj).i;
           switch (id) {
-          case INVOKEINTERFACE:
-          case INVOKEVIRTUAL:
-            trampoline_stubs++;
-            break;
-          case INVOKESTATIC:
-          case INVOKESPECIAL:
-            static_call_stubs++;
-            trampoline_stubs++;
-            break;
-          default:
-            break;
+            case INVOKEINTERFACE:
+            case INVOKEVIRTUAL:
+              trampoline_stubs++;
+              break;
+            case INVOKESTATIC:
+            case INVOKESPECIAL:
+              static_call_stubs++;
+              trampoline_stubs++;
+              break;
+            default:
+              break;
           }
         }
       }
 #if INCLUDE_AOT
-      if (UseAOT && site->is_a(site_Call::klass())) {
-        oop target = site_Call::target(site);
-        InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
-        if (!target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+      if (UseAOT && jvmci_env()->isa_site_Call(site)) {
+        JVMCIObject target = jvmci_env()-> get_site_Call_target(site);
+        if (!jvmci_env()->isa_HotSpotForeignCallTarget(target)) {
           // Add far aot trampolines.
           aot_call_stubs++;
         }
@@ -793,25 +759,25 @@
 }
 
 // perform data and call relocation on the CodeBuffer
-JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS) {
+JVMCI::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, JVMCI_TRAPS) {
   HandleMark hm;
-  objArrayHandle sites(THREAD, this->sites());
-  int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
+  JVMCIObjectArray sites = this->sites();
+  int locs_buffer_size = JVMCIENV->get_length(sites) * (relocInfo::length_limit + sizeof(relocInfo));
 
   // Allocate enough space in the stub section for the static call
   // stubs.  Stubs have extra relocs but they are managed by the stub
   // section itself so they don't need to be accounted for in the
   // locs_buffer above.
-  int stubs_size = estimate_stubs_size(CHECK_OK);
+  int stubs_size = estimate_stubs_size(JVMCI_CHECK_OK);
   int total_size = align_up(_code_size, buffer.insts()->alignment()) + align_up(_constants_size, buffer.consts()->alignment()) + align_up(stubs_size, buffer.stubs()->alignment());
 
   if (check_size && total_size > JVMCINMethodSizeLimit) {
-    return JVMCIEnv::code_too_large;
+    return JVMCI::code_too_large;
   }
 
   buffer.initialize(total_size, locs_buffer_size);
   if (buffer.blob() == NULL) {
-    return JVMCIEnv::cache_full;
+    return JVMCI::cache_full;
   }
   buffer.initialize_stubs_size(stubs_size);
   buffer.initialize_consts_size(_constants_size);
@@ -823,49 +789,49 @@
 
   // copy the constant data into the newly created CodeBuffer
   address end_data = _constants->start() + _constants_size;
-  memcpy(_constants->start(), data_section()->base(T_BYTE), _constants_size);
+  JVMCIENV->copy_bytes_to(data_section(), (jbyte*) _constants->start(), 0, _constants_size);
   _constants->set_end(end_data);
 
   // copy the code into the newly created CodeBuffer
   address end_pc = _instructions->start() + _code_size;
   guarantee(_instructions->allocates2(end_pc), "initialize should have reserved enough space for all the code");
-  memcpy(_instructions->start(), code()->base(T_BYTE), _code_size);
+  JVMCIENV->copy_bytes_to(code(), (jbyte*) _instructions->start(), 0, _code_size);
   _instructions->set_end(end_pc);
 
-  for (int i = 0; i < data_section_patches()->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle patch(THREAD, data_section_patches()->obj_at(i));
+  for (int i = 0; i < JVMCIENV->get_length(data_section_patches()); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject patch = JVMCIENV->get_object_at(data_section_patches(), i);
     if (patch.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
-    Handle reference(THREAD, site_DataPatch::reference(patch));
+    JVMCIObject reference = jvmci_env()->get_site_DataPatch_reference(patch);
     if (reference.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
-    if (!reference->is_a(site_ConstantReference::klass())) {
-      JVMCI_ERROR_OK("invalid patch in data section: %s", reference->klass()->signature_name());
+    if (!jvmci_env()->isa_site_ConstantReference(reference)) {
+      JVMCI_ERROR_OK("invalid patch in data section: %s", jvmci_env()->klass_name(reference));
     }
-    Handle constant(THREAD, site_ConstantReference::constant(reference));
+    JVMCIObject constant = jvmci_env()->get_site_ConstantReference_constant(reference);
     if (constant.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
-    address dest = _constants->start() + site_Site::pcOffset(patch);
-    if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-      if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+    address dest = _constants->start() + jvmci_env()->get_site_Site_pcOffset(patch);
+    if (jvmci_env()->isa_HotSpotMetaspaceConstantImpl(constant)) {
+      if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) {
 #ifdef _LP64
-        *((narrowKlass*) dest) = record_narrow_metadata_reference(_constants, dest, constant, CHECK_OK);
+        *((narrowKlass*) dest) = record_narrow_metadata_reference(_constants, dest, constant, JVMCI_CHECK_OK);
 #else
         JVMCI_ERROR_OK("unexpected compressed Klass* in 32-bit mode");
 #endif
       } else {
-        *((void**) dest) = record_metadata_reference(_constants, dest, constant, CHECK_OK);
+        *((void**) dest) = record_metadata_reference(_constants, dest, constant, JVMCI_CHECK_OK);
       }
-    } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
-      Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant));
+    } else if (jvmci_env()->isa_HotSpotObjectConstantImpl(constant)) {
+      Handle obj = jvmci_env()->asConstant(constant, JVMCI_CHECK_OK);
       jobject value = JNIHandles::make_local(obj());
       int oop_index = _oop_recorder->find_index(value);
 
-      if (HotSpotObjectConstantImpl::compressed(constant)) {
+      if (jvmci_env()->get_HotSpotObjectConstantImpl_compressed(constant)) {
 #ifdef _LP64
         _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const);
 #else
@@ -875,46 +841,48 @@
         _constants->relocate(dest, oop_Relocation::spec(oop_index));
       }
     } else {
-      JVMCI_ERROR_OK("invalid constant in data section: %s", constant->klass()->signature_name());
+      JVMCI_ERROR_OK("invalid constant in data section: %s", jvmci_env()->klass_name(constant));
     }
   }
   jint last_pc_offset = -1;
-  for (int i = 0; i < sites->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle site(THREAD, sites->obj_at(i));
+  for (int i = 0; i < JVMCIENV->get_length(sites); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject site = JVMCIENV->get_object_at(sites, i);
     if (site.is_null()) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JVMCIEnv::ok);
+      JVMCI_THROW_(NullPointerException, JVMCI::ok);
     }
 
-    jint pc_offset = site_Site::pcOffset(site);
+    jint pc_offset = jvmci_env()->get_site_Site_pcOffset(site);
 
-    if (site->is_a(site_Call::klass())) {
+    if (jvmci_env()->isa_site_Call(site)) {
       TRACE_jvmci_4("call at %i", pc_offset);
-      site_Call(buffer, pc_offset, site, CHECK_OK);
-    } else if (site->is_a(site_Infopoint::klass())) {
+      site_Call(buffer, pc_offset, site, JVMCI_CHECK_OK);
+    } else if (jvmci_env()->isa_site_Infopoint(site)) {
       // three reasons for infopoints denote actual safepoints
-      oop reason = site_Infopoint::reason(site);
-      if (site_InfopointReason::SAFEPOINT() == reason || site_InfopointReason::CALL() == reason || site_InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+      JVMCIObject reason = jvmci_env()->get_site_Infopoint_reason(site);
+      if (JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_SAFEPOINT()) ||
+          JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_CALL()) ||
+          JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_IMPLICIT_EXCEPTION())) {
         TRACE_jvmci_4("safepoint at %i", pc_offset);
-        site_Safepoint(buffer, pc_offset, site, CHECK_OK);
+        site_Safepoint(buffer, pc_offset, site, JVMCI_CHECK_OK);
         if (_orig_pc_offset < 0) {
           JVMCI_ERROR_OK("method contains safepoint, but has no deopt rescue slot");
         }
       } else {
         TRACE_jvmci_4("infopoint at %i", pc_offset);
-        site_Infopoint(buffer, pc_offset, site, CHECK_OK);
+        site_Infopoint(buffer, pc_offset, site, JVMCI_CHECK_OK);
       }
-    } else if (site->is_a(site_DataPatch::klass())) {
+    } else if (jvmci_env()->isa_site_DataPatch(site)) {
       TRACE_jvmci_4("datapatch at %i", pc_offset);
-      site_DataPatch(buffer, pc_offset, site, CHECK_OK);
-    } else if (site->is_a(site_Mark::klass())) {
+      site_DataPatch(buffer, pc_offset, site, JVMCI_CHECK_OK);
+    } else if (jvmci_env()->isa_site_Mark(site)) {
       TRACE_jvmci_4("mark at %i", pc_offset);
-      site_Mark(buffer, pc_offset, site, CHECK_OK);
-    } else if (site->is_a(site_ExceptionHandler::klass())) {
+      site_Mark(buffer, pc_offset, site, JVMCI_CHECK_OK);
+    } else if (jvmci_env()->isa_site_ExceptionHandler(site)) {
       TRACE_jvmci_4("exceptionhandler at %i", pc_offset);
       site_ExceptionHandler(pc_offset, site);
     } else {
-      JVMCI_ERROR_OK("unexpected site subclass: %s", site->klass()->signature_name());
+      JVMCI_ERROR_OK("unexpected site subclass: %s", jvmci_env()->klass_name(site));
     }
     last_pc_offset = pc_offset;
 
@@ -926,61 +894,62 @@
   }
 
 #ifndef PRODUCT
-  if (comments() != NULL) {
-    for (int i = 0; i < comments()->length(); i++) {
-      oop comment = comments()->obj_at(i);
-      assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce");
-      jint offset = HotSpotCompiledCode_Comment::pcOffset(comment);
-      char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment));
+  if (comments().is_non_null()) {
+    for (int i = 0; i < JVMCIENV->get_length(comments()); i++) {
+      JVMCIObject comment = JVMCIENV->get_object_at(comments(), i);
+      assert(jvmci_env()->isa_HotSpotCompiledCode_Comment(comment), "cce");
+      jint offset = jvmci_env()->get_HotSpotCompiledCode_Comment_pcOffset(comment);
+      const char* text = jvmci_env()->as_utf8_string(jvmci_env()->get_HotSpotCompiledCode_Comment_text(comment));
       buffer.block_comment(offset, text);
     }
   }
 #endif
-  return JVMCIEnv::ok;
+  return JVMCI::ok;
 }
 
-void CodeInstaller::assumption_NoFinalizableSubclass(Thread* thread, Handle assumption) {
-  Handle receiverType_handle (thread, Assumptions_NoFinalizableSubclass::receiverType(assumption()));
-  Klass* receiverType = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(receiverType_handle));
+void CodeInstaller::assumption_NoFinalizableSubclass(JVMCIObject assumption) {
+  JVMCIObject receiverType_handle = jvmci_env()->get_Assumptions_NoFinalizableSubclass_receiverType(assumption);
+  Klass* receiverType = jvmci_env()->asKlass(receiverType_handle);
   _dependencies->assert_has_no_finalizable_subclasses(receiverType);
 }
 
-void CodeInstaller::assumption_ConcreteSubtype(Thread* thread, Handle assumption) {
-  Handle context_handle (thread, Assumptions_ConcreteSubtype::context(assumption()));
-  Handle subtype_handle (thread, Assumptions_ConcreteSubtype::subtype(assumption()));
-  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
-  Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle));
+void CodeInstaller::assumption_ConcreteSubtype(JVMCIObject assumption) {
+  JVMCIObject context_handle = jvmci_env()->get_Assumptions_ConcreteSubtype_context(assumption);
+  JVMCIObject subtype_handle = jvmci_env()->get_Assumptions_ConcreteSubtype_subtype(assumption);
+  Klass* context = jvmci_env()->asKlass(context_handle);
+  Klass* subtype = jvmci_env()->asKlass(subtype_handle);
 
   assert(context->is_abstract(), "");
   _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
 }
 
-void CodeInstaller::assumption_LeafType(Thread* thread, Handle assumption) {
-  Handle context_handle (thread, Assumptions_LeafType::context(assumption()));
-  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+void CodeInstaller::assumption_LeafType(JVMCIObject assumption) {
+  JVMCIObject context_handle = jvmci_env()->get_Assumptions_LeafType_context(assumption);
+  Klass* context = jvmci_env()->asKlass(context_handle);
 
   _dependencies->assert_leaf_type(context);
 }
 
-void CodeInstaller::assumption_ConcreteMethod(Thread* thread, Handle assumption) {
-  Handle impl_handle (thread, Assumptions_ConcreteMethod::impl(assumption()));
-  Handle context_handle (thread, Assumptions_ConcreteMethod::context(assumption()));
+void CodeInstaller::assumption_ConcreteMethod(JVMCIObject assumption) {
+  JVMCIObject impl_handle = jvmci_env()->get_Assumptions_ConcreteMethod_impl(assumption);
+  JVMCIObject context_handle = jvmci_env()->get_Assumptions_ConcreteMethod_context(assumption);
 
-  methodHandle impl = getMethodFromHotSpotMethod(impl_handle());
-  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+  methodHandle impl = jvmci_env()->asMethod(impl_handle);
+  Klass* context = jvmci_env()->asKlass(context_handle);
 
   _dependencies->assert_unique_concrete_method(context, impl());
 }
 
-void CodeInstaller::assumption_CallSiteTargetValue(Thread* thread, Handle assumption) {
-  Handle callSite(thread, HotSpotObjectConstantImpl::object(Assumptions_CallSiteTargetValue::callSite(assumption())));
-  Handle methodHandle(thread, HotSpotObjectConstantImpl::object(Assumptions_CallSiteTargetValue::methodHandle(assumption())));
-
+void CodeInstaller::assumption_CallSiteTargetValue(JVMCIObject assumption, JVMCI_TRAPS) {
+  JVMCIObject callSiteConstant = jvmci_env()->get_Assumptions_CallSiteTargetValue_callSite(assumption);
+  Handle callSite = jvmci_env()->asConstant(callSiteConstant, JVMCI_CHECK);
+  JVMCIObject methodConstant = jvmci_env()->get_Assumptions_CallSiteTargetValue_methodHandle(assumption);
+  Handle methodHandle = jvmci_env()->asConstant(methodConstant, JVMCI_CHECK);
   _dependencies->assert_call_site_target_value(callSite(), methodHandle());
 }
 
-void CodeInstaller::site_ExceptionHandler(jint pc_offset, Handle exc) {
-  jint handler_offset = site_ExceptionHandler::handlerPos(exc);
+void CodeInstaller::site_ExceptionHandler(jint pc_offset, JVMCIObject exc) {
+  jint handler_offset = jvmci_env()->get_site_ExceptionHandler_handlerPos(exc);
 
   // Subtable header
   _exception_handler_table.add_entry(HandlerTableEntry(1, pc_offset, 0));
@@ -1005,19 +974,20 @@
   return true;
 }
 
-GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(Handle debug_info, TRAPS) {
-  objArrayHandle virtualObjects(THREAD, DebugInfo::virtualObjectMapping(debug_info));
+GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(JVMCIObject debug_info, JVMCI_TRAPS) {
+  JVMCIObjectArray virtualObjects = jvmci_env()->get_DebugInfo_virtualObjectMapping(debug_info);
   if (virtualObjects.is_null()) {
     return NULL;
   }
-  GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(virtualObjects->length(), virtualObjects->length(), NULL);
+  GrowableArray<ScopeValue*>* objects = new GrowableArray<ScopeValue*>(JVMCIENV->get_length(virtualObjects), JVMCIENV->get_length(virtualObjects), NULL);
   // Create the unique ObjectValues
-  for (int i = 0; i < virtualObjects->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle value(THREAD, virtualObjects->obj_at(i));
-    int id = VirtualObject::id(value);
-    Handle type(THREAD, VirtualObject::type(value));
-    oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type);
+  for (int i = 0; i < JVMCIENV->get_length(virtualObjects); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject value = JVMCIENV->get_object_at(virtualObjects, i);
+    int id = jvmci_env()->get_VirtualObject_id(value);
+    JVMCIObject type = jvmci_env()->get_VirtualObject_type(value);
+    Klass* klass = jvmci_env()->asKlass(type);
+    oop javaMirror = klass->java_mirror();
     ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror)));
     if (id < 0 || id >= objects->length()) {
       JVMCI_ERROR_NULL("virtual object id %d out of bounds", id);
@@ -1029,18 +999,18 @@
   }
   // All the values which could be referenced by the VirtualObjects
   // exist, so now describe all the VirtualObjects themselves.
-  for (int i = 0; i < virtualObjects->length(); i++) {
-    HandleMark hm(THREAD);
-    Handle value(THREAD, virtualObjects->obj_at(i));
-    int id = VirtualObject::id(value);
-    record_object_value(objects->at(id)->as_ObjectValue(), value, objects, CHECK_NULL);
+  for (int i = 0; i < JVMCIENV->get_length(virtualObjects); i++) {
+    // HandleMark hm(THREAD);
+    JVMCIObject value = JVMCIENV->get_object_at(virtualObjects, i);
+    int id = jvmci_env()->get_VirtualObject_id(value);
+    record_object_value(objects->at(id)->as_ObjectValue(), value, objects, JVMCI_CHECK_NULL);
   }
   _debug_recorder->dump_object_pool(objects);
   return objects;
 }
 
-void CodeInstaller::record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS) {
-  Handle position(THREAD, DebugInfo::bytecodePosition(debug_info));
+void CodeInstaller::record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, bool return_oop, JVMCI_TRAPS) {
+  JVMCIObject position = jvmci_env()->get_DebugInfo_bytecodePosition(debug_info);
   if (position.is_null()) {
     // Stubs do not record scope info, just oop maps
     return;
@@ -1048,26 +1018,26 @@
 
   GrowableArray<ScopeValue*>* objectMapping;
   if (scope_mode == CodeInstaller::FullFrame) {
-    objectMapping = record_virtual_objects(debug_info, CHECK);
+    objectMapping = record_virtual_objects(debug_info, JVMCI_CHECK);
   } else {
     objectMapping = NULL;
   }
-  record_scope(pc_offset, position, scope_mode, objectMapping, return_oop, CHECK);
+  record_scope(pc_offset, position, scope_mode, objectMapping, return_oop, JVMCI_CHECK);
 }
 
 int CodeInstaller::map_jvmci_bci(int bci) {
   if (bci < 0) {
-    if (bci == BytecodeFrame::BEFORE_BCI()) {
+    if (bci == jvmci_env()->get_BytecodeFrame_BEFORE_BCI()) {
       return BeforeBci;
-    } else if (bci == BytecodeFrame::AFTER_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_AFTER_BCI()) {
       return AfterBci;
-    } else if (bci == BytecodeFrame::UNWIND_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_UNWIND_BCI()) {
       return UnwindBci;
-    } else if (bci == BytecodeFrame::AFTER_EXCEPTION_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_AFTER_EXCEPTION_BCI()) {
       return AfterExceptionBci;
-    } else if (bci == BytecodeFrame::UNKNOWN_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_UNKNOWN_BCI()) {
       return UnknownBci;
-    } else if (bci == BytecodeFrame::INVALID_FRAMESTATE_BCI()) {
+    } else if (bci == jvmci_env()->get_BytecodeFrame_INVALID_FRAMESTATE_BCI()) {
       return InvalidFrameStateBci;
     }
     ShouldNotReachHere();
@@ -1075,34 +1045,37 @@
   return bci;
 }
 
-void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS) {
-  Handle frame;
+void CodeInstaller::record_scope(jint pc_offset, JVMCIObject position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, JVMCI_TRAPS) {
+  JVMCIObject frame;
   if (scope_mode == CodeInstaller::FullFrame) {
-    if (!position->is_a(BytecodeFrame::klass())) {
+    if (!jvmci_env()->isa_BytecodeFrame(position)) {
       JVMCI_ERROR("Full frame expected for debug info at %i", pc_offset);
     }
     frame = position;
   }
-  Handle caller_frame (THREAD, BytecodePosition::caller(position));
-  if (caller_frame.not_null()) {
-    record_scope(pc_offset, caller_frame, scope_mode, objects, return_oop, CHECK);
+  JVMCIObject caller_frame = jvmci_env()->get_BytecodePosition_caller(position);
+  if (caller_frame.is_non_null()) {
+    record_scope(pc_offset, caller_frame, scope_mode, objects, return_oop, JVMCI_CHECK);
   }
 
-  Handle hotspot_method (THREAD, BytecodePosition::method(position));
-  Method* method = getMethodFromHotSpotMethod(hotspot_method());
-  jint bci = map_jvmci_bci(BytecodePosition::bci(position));
+  JVMCIObject hotspot_method = jvmci_env()->get_BytecodePosition_method(position);
+  Method* method = jvmci_env()->asMethod(hotspot_method);
+  jint bci = map_jvmci_bci(jvmci_env()->get_BytecodePosition_bci(position));
+  if (bci == jvmci_env()->get_BytecodeFrame_BEFORE_BCI()) {
+    bci = SynchronizationEntryBCI;
+  }
 
   TRACE_jvmci_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string());
 
   bool reexecute = false;
-  if (frame.not_null()) {
-    if (bci < 0) {
+  if (frame.is_non_null()) {
+    if (bci < 0){
        reexecute = false;
     } else {
       Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
       reexecute = bytecode_should_reexecute(code);
-      if (frame.not_null()) {
-        reexecute = (BytecodeFrame::duringCall(frame) == JNI_FALSE);
+      if (frame.is_non_null()) {
+        reexecute = (jvmci_env()->get_BytecodeFrame_duringCall(frame) == JNI_FALSE);
       }
     }
   }
@@ -1112,55 +1085,55 @@
   DebugToken* monitors_token = NULL;
   bool throw_exception = false;
 
-  if (frame.not_null()) {
-    jint local_count = BytecodeFrame::numLocals(frame);
-    jint expression_count = BytecodeFrame::numStack(frame);
-    jint monitor_count = BytecodeFrame::numLocks(frame);
-    objArrayHandle values(THREAD, BytecodeFrame::values(frame));
-    objArrayHandle slotKinds(THREAD, BytecodeFrame::slotKinds(frame));
+  if (frame.is_non_null()) {
+    jint local_count = jvmci_env()->get_BytecodeFrame_numLocals(frame);
+    jint expression_count = jvmci_env()->get_BytecodeFrame_numStack(frame);
+    jint monitor_count = jvmci_env()->get_BytecodeFrame_numLocks(frame);
+    JVMCIObjectArray values = jvmci_env()->get_BytecodeFrame_values(frame);
+    JVMCIObjectArray slotKinds = jvmci_env()->get_BytecodeFrame_slotKinds(frame);
 
     if (values.is_null() || slotKinds.is_null()) {
-      THROW(vmSymbols::java_lang_NullPointerException());
+      JVMCI_THROW(NullPointerException);
     }
-    if (local_count + expression_count + monitor_count != values->length()) {
-      JVMCI_ERROR("unexpected values length %d in scope (%d locals, %d expressions, %d monitors)", values->length(), local_count, expression_count, monitor_count);
+    if (local_count + expression_count + monitor_count != JVMCIENV->get_length(values)) {
+      JVMCI_ERROR("unexpected values length %d in scope (%d locals, %d expressions, %d monitors)", JVMCIENV->get_length(values), local_count, expression_count, monitor_count);
     }
-    if (local_count + expression_count != slotKinds->length()) {
-      JVMCI_ERROR("unexpected slotKinds length %d in scope (%d locals, %d expressions)", slotKinds->length(), local_count, expression_count);
+    if (local_count + expression_count != JVMCIENV->get_length(slotKinds)) {
+      JVMCI_ERROR("unexpected slotKinds length %d in scope (%d locals, %d expressions)", JVMCIENV->get_length(slotKinds), local_count, expression_count);
     }
 
     GrowableArray<ScopeValue*>* locals = local_count > 0 ? new GrowableArray<ScopeValue*> (local_count) : NULL;
     GrowableArray<ScopeValue*>* expressions = expression_count > 0 ? new GrowableArray<ScopeValue*> (expression_count) : NULL;
     GrowableArray<MonitorValue*>* monitors = monitor_count > 0 ? new GrowableArray<MonitorValue*> (monitor_count) : NULL;
 
-    TRACE_jvmci_2("Scope at bci %d with %d values", bci, values->length());
+    TRACE_jvmci_2("Scope at bci %d with %d values", bci, JVMCIENV->get_length(values));
     TRACE_jvmci_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count);
 
-    for (jint i = 0; i < values->length(); i++) {
-      HandleMark hm(THREAD);
+    for (jint i = 0; i < JVMCIENV->get_length(values); i++) {
+      // HandleMark hm(THREAD);
       ScopeValue* second = NULL;
-      Handle value(THREAD, values->obj_at(i));
+      JVMCIObject value = JVMCIENV->get_object_at(values, i);
       if (i < local_count) {
-        BasicType type = JVMCIRuntime::kindToBasicType(Handle(THREAD, slotKinds->obj_at(i)), CHECK);
-        ScopeValue* first = get_scope_value(value, type, objects, second, CHECK);
+        BasicType type = jvmci_env()->kindToBasicType(JVMCIENV->get_object_at(slotKinds, i), JVMCI_CHECK);
+        ScopeValue* first = get_scope_value(value, type, objects, second, JVMCI_CHECK);
         if (second != NULL) {
           locals->append(second);
         }
         locals->append(first);
       } else if (i < local_count + expression_count) {
-        BasicType type = JVMCIRuntime::kindToBasicType(Handle(THREAD, slotKinds->obj_at(i)), CHECK);
-        ScopeValue* first = get_scope_value(value, type, objects, second, CHECK);
+        BasicType type = jvmci_env()->kindToBasicType(JVMCIENV->get_object_at(slotKinds, i), JVMCI_CHECK);
+        ScopeValue* first = get_scope_value(value, type, objects, second, JVMCI_CHECK);
         if (second != NULL) {
           expressions->append(second);
         }
         expressions->append(first);
       } else {
-        MonitorValue *monitor = get_monitor_value(value, objects, CHECK);
+        MonitorValue *monitor = get_monitor_value(value, objects, JVMCI_CHECK);
         monitors->append(monitor);
       }
       if (second != NULL) {
         i++;
-        if (i >= values->length() || values->obj_at(i) != Value::ILLEGAL()) {
+        if (i >= JVMCIENV->get_length(values) || !JVMCIENV->equals(JVMCIENV->get_object_at(values, i), jvmci_env()->get_Value_ILLEGAL())) {
           JVMCI_ERROR("double-slot value not followed by Value.ILLEGAL");
         }
       }
@@ -1170,29 +1143,29 @@
     expressions_token = _debug_recorder->create_scope_values(expressions);
     monitors_token = _debug_recorder->create_monitor_values(monitors);
 
-    throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE;
+    throw_exception = jvmci_env()->get_BytecodeFrame_rethrowException(frame) == JNI_TRUE;
   }
 
   _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, return_oop,
                                   locals_token, expressions_token, monitors_token);
 }
 
-void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle debug_info (THREAD, site_Infopoint::debugInfo(site));
+void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject debug_info = jvmci_env()->get_site_Infopoint_debugInfo(site);
   if (debug_info.is_null()) {
     JVMCI_ERROR("debug info expected at safepoint at %i", pc_offset);
   }
 
   // address instruction = _instructions->start() + pc_offset;
   // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
-  OopMap *map = create_oop_map(debug_info, CHECK);
+  OopMap *map = create_oop_map(debug_info, JVMCI_CHECK);
   _debug_recorder->add_safepoint(pc_offset, map);
-  record_scope(pc_offset, debug_info, CodeInstaller::FullFrame, CHECK);
+  record_scope(pc_offset, debug_info, CodeInstaller::FullFrame, JVMCI_CHECK);
   _debug_recorder->end_safepoint(pc_offset);
 }
 
-void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle debug_info (THREAD, site_Infopoint::debugInfo(site));
+void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject debug_info = jvmci_env()->get_site_Infopoint_debugInfo(site);
   if (debug_info.is_null()) {
     JVMCI_ERROR("debug info expected at infopoint at %i", pc_offset);
   }
@@ -1202,53 +1175,51 @@
   // but DebugInformationRecorder doesn't have sufficient public API.
 
   _debug_recorder->add_non_safepoint(pc_offset);
-  record_scope(pc_offset, debug_info, CodeInstaller::BytecodePosition, CHECK);
+  record_scope(pc_offset, debug_info, CodeInstaller::BytecodePosition, JVMCI_CHECK);
   _debug_recorder->end_non_safepoint(pc_offset);
 }
 
-void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle target(THREAD, site_Call::target(site));
-  InstanceKlass* target_klass = InstanceKlass::cast(target->klass());
+void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject target = jvmci_env()->get_site_Call_target(site);
+  JVMCIObject hotspot_method; // JavaMethod
+  JVMCIObject foreign_call;
 
-  Handle hotspot_method; // JavaMethod
-  Handle foreign_call;
-
-  if (target_klass->is_subclass_of(SystemDictionary::HotSpotForeignCallTarget_klass())) {
+  if (jvmci_env()->isa_HotSpotForeignCallTarget(target)) {
     foreign_call = target;
   } else {
     hotspot_method = target;
   }
 
-  Handle debug_info (THREAD, site_Call::debugInfo(site));
+  JVMCIObject debug_info = jvmci_env()->get_site_Infopoint_debugInfo(site);
 
-  assert(hotspot_method.not_null() ^ foreign_call.not_null(), "Call site needs exactly one type");
+  assert(hotspot_method.is_non_null() ^ foreign_call.is_non_null(), "Call site needs exactly one type");
 
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
-  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method, CHECK);
+  jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method, JVMCI_CHECK);
 
-  if (debug_info.not_null()) {
-    OopMap *map = create_oop_map(debug_info, CHECK);
+  if (debug_info.is_non_null()) {
+    OopMap *map = create_oop_map(debug_info, JVMCI_CHECK);
     _debug_recorder->add_safepoint(next_pc_offset, map);
 
-    bool return_oop = hotspot_method.not_null() && getMethodFromHotSpotMethod(hotspot_method())->is_returning_oop();
+    bool return_oop = hotspot_method.is_non_null() && jvmci_env()->asMethod(hotspot_method)->is_returning_oop();
 
-    record_scope(next_pc_offset, debug_info, CodeInstaller::FullFrame, return_oop, CHECK);
+    record_scope(next_pc_offset, debug_info, CodeInstaller::FullFrame, return_oop, JVMCI_CHECK);
   }
 
-  if (foreign_call.not_null()) {
-    jlong foreign_call_destination = HotSpotForeignCallTarget::address(foreign_call);
+  if (foreign_call.is_non_null()) {
+    jlong foreign_call_destination = jvmci_env()->get_HotSpotForeignCallTarget_address(foreign_call);
     if (_immutable_pic_compilation) {
       // Use fake short distance during PIC compilation.
       foreign_call_destination = (jlong)(_instructions->start() + pc_offset);
     }
-    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, CHECK);
+    CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination, JVMCI_CHECK);
   } else { // method != NULL
     if (debug_info.is_null()) {
       JVMCI_ERROR("debug info expected at call at %i", pc_offset);
     }
 
     TRACE_jvmci_3("method call");
-    CodeInstaller::pd_relocate_JavaMethod(buffer, hotspot_method, pc_offset, CHECK);
+    CodeInstaller::pd_relocate_JavaMethod(buffer, hotspot_method, pc_offset, JVMCI_CHECK);
     if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) {
       // Need a static call stub for transitions from compiled to interpreted.
       CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset);
@@ -1261,57 +1232,67 @@
 
   _next_call_type = INVOKE_INVALID;
 
-  if (debug_info.not_null()) {
+  if (debug_info.is_non_null()) {
     _debug_recorder->end_safepoint(next_pc_offset);
   }
 }
 
-void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle reference(THREAD, site_DataPatch::reference(site));
+void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject reference = jvmci_env()->get_site_DataPatch_reference(site);
   if (reference.is_null()) {
-    THROW(vmSymbols::java_lang_NullPointerException());
-  } else if (reference->is_a(site_ConstantReference::klass())) {
-    Handle constant(THREAD, site_ConstantReference::constant(reference));
+    JVMCI_THROW(NullPointerException);
+  } else if (jvmci_env()->isa_site_ConstantReference(reference)) {
+    JVMCIObject constant = jvmci_env()->get_site_ConstantReference_constant(reference);
     if (constant.is_null()) {
-      THROW(vmSymbols::java_lang_NullPointerException());
-    } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
+      JVMCI_THROW(NullPointerException);
+    } else if (jvmci_env()->isa_DirectHotSpotObjectConstantImpl(constant)) {
+      if (!JVMCIENV->is_hotspot()) {
+        JVMCIObject string = JVMCIENV->call_HotSpotJVMCIRuntime_callToString(constant, JVMCI_CHECK);
+        const char* to_string = JVMCIENV->as_utf8_string(string);
+        JVMCI_THROW_MSG(IllegalArgumentException, err_msg("Direct object constant reached the backend: %s", to_string));
+      }
       if (!_immutable_pic_compilation) {
         // Do not patch during PIC compilation.
-        pd_patch_OopConstant(pc_offset, constant, CHECK);
+        pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
       }
-    } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
+    } else if (jvmci_env()->isa_IndirectHotSpotObjectConstantImpl(constant)) {
       if (!_immutable_pic_compilation) {
-        pd_patch_MetaspaceConstant(pc_offset, constant, CHECK);
+        // Do not patch during PIC compilation.
+        pd_patch_OopConstant(pc_offset, constant, JVMCI_CHECK);
+      }
+    } else if (jvmci_env()->isa_HotSpotMetaspaceConstantImpl(constant)) {
+      if (!_immutable_pic_compilation) {
+        pd_patch_MetaspaceConstant(pc_offset, constant, JVMCI_CHECK);
       }
 #if INCLUDE_AOT
-    } else if (constant->is_a(HotSpotSentinelConstant::klass())) {
+    } else if (jvmci_env()->isa_HotSpotSentinelConstant(constant)) {
       if (!_immutable_pic_compilation) {
-        JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", constant->klass()->signature_name());
+        JVMCI_ERROR("sentinel constant not supported for normal compiles: %s", jvmci_env()->klass_name(constant));
       }
 #endif
     } else {
-      JVMCI_ERROR("unknown constant type in data patch: %s", constant->klass()->signature_name());
+      JVMCI_ERROR("unknown constant type in data patch: %s", jvmci_env()->klass_name(constant));
     }
-  } else if (reference->is_a(site_DataSectionReference::klass())) {
-    int data_offset = site_DataSectionReference::offset(reference);
+  } else if (jvmci_env()->isa_site_DataSectionReference(reference)) {
+    int data_offset = jvmci_env()->get_site_DataSectionReference_offset(reference);
     if (0 <= data_offset && data_offset < _constants_size) {
-      pd_patch_DataSectionReference(pc_offset, data_offset, CHECK);
+      pd_patch_DataSectionReference(pc_offset, data_offset, JVMCI_CHECK);
     } else {
       JVMCI_ERROR("data offset 0x%X points outside data section (size 0x%X)", data_offset, _constants_size);
     }
   } else {
-    JVMCI_ERROR("unknown data patch type: %s", reference->klass()->signature_name());
+    JVMCI_ERROR("unknown data patch type: %s", jvmci_env()->klass_name(reference));
   }
 }
 
-void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS) {
-  Handle id_obj (THREAD, site_Mark::id(site));
+void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS) {
+  JVMCIObject id_obj = jvmci_env()->get_site_Mark_id(site);
 
-  if (id_obj.not_null()) {
-    if (!java_lang_boxing_object::is_instance(id_obj(), T_INT)) {
-      JVMCI_ERROR("expected Integer id, got %s", id_obj->klass()->signature_name());
+  if (id_obj.is_non_null()) {
+    if (!jvmci_env()->is_boxing_object(T_INT, id_obj)) {
+      JVMCI_ERROR("expected Integer id, got %s", jvmci_env()->klass_name(id_obj));
     }
-    jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT));
+    jint id = jvmci_env()->get_boxed_value(T_INT, id_obj).i;
 
     address pc = _instructions->start() + pc_offset;
 
@@ -1343,7 +1324,7 @@
       case POLL_FAR:
       case POLL_RETURN_NEAR:
       case POLL_RETURN_FAR:
-        pd_relocate_poll(pc, id, CHECK);
+        pd_relocate_poll(pc, id, JVMCI_CHECK);
         break;
       case CARD_TABLE_SHIFT:
       case CARD_TABLE_ADDRESS:
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Wed May 01 12:31:29 2019 -0700
@@ -24,9 +24,11 @@
 #ifndef SHARE_JVMCI_JVMCICODEINSTALLER_HPP
 #define SHARE_JVMCI_JVMCICODEINSTALLER_HPP
 
-#include "jvmci/jvmciCompiler.hpp"
+#include "code/debugInfoRec.hpp"
+#include "code/exceptionHandlerTable.hpp"
+#include "code/nativeInst.hpp"
+#include "jvmci/jvmci.hpp"
 #include "jvmci/jvmciEnv.hpp"
-#include "code/nativeInst.hpp"
 
 #if INCLUDE_AOT
 class RelocBuffer : public StackObj {
@@ -44,9 +46,11 @@
   char *_buffer;
 };
 
+class CodeInstaller;
+
 class AOTOopRecorder : public OopRecorder {
 public:
-  AOTOopRecorder(Arena* arena = NULL, bool deduplicate = false);
+  AOTOopRecorder(CodeInstaller* code_inst, Arena* arena = NULL, bool deduplicate = false);
 
   virtual int find_index(Metadata* h);
   virtual int find_index(jobject h);
@@ -57,7 +61,10 @@
   void record_meta_ref(jobject ref, int index);
 
   GrowableArray<jobject>* _meta_refs;
+
+  CodeInstaller* _code_inst;
 };
+#endif // INCLUDE_AOT
 
 class CodeMetadata {
 public:
@@ -71,9 +78,10 @@
   u_char* get_scopes_desc() const { return _scopes_desc; }
   int get_scopes_size() const { return _nr_scopes_desc; }
 
+#if INCLUDE_AOT
   RelocBuffer* get_reloc_buffer() { return &_reloc_buffer; }
-
   AOTOopRecorder* get_oop_recorder() { return _oop_recorder; }
+#endif
 
   ExceptionHandlerTable* get_exception_table() { return _exception_table; }
 
@@ -87,9 +95,11 @@
     _nr_scopes_desc = size;
   }
 
+#if INCLUDE_AOT
   void set_oop_recorder(AOTOopRecorder* recorder) {
     _oop_recorder = recorder;
   }
+#endif
 
   void set_exception_table(ExceptionHandlerTable* table) {
     _exception_table = table;
@@ -103,11 +113,12 @@
   u_char* _scopes_desc;
   int _nr_scopes_desc;
 
+#if INCLUDE_AOT
   RelocBuffer _reloc_buffer;
   AOTOopRecorder* _oop_recorder;
+#endif
   ExceptionHandlerTable* _exception_table;
 };
-#endif // INCLUDE_AOT
 
 /*
  * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod.
@@ -143,24 +154,26 @@
   };
 
   Arena         _arena;
+  JVMCIEnv*     _jvmci_env;
 
-  jobject       _data_section_handle;
-  jobject       _data_section_patches_handle;
-  jobject       _sites_handle;
+  JVMCIPrimitiveArray    _data_section_handle;
+  JVMCIObjectArray       _data_section_patches_handle;
+  JVMCIObjectArray       _sites_handle;
+#ifndef PRODUCT
+  JVMCIObjectArray       _comments_handle;
+#endif
+  JVMCIPrimitiveArray    _code_handle;
+  JVMCIObject            _word_kind_handle;
+
   CodeOffsets   _offsets;
 
-  jobject       _code_handle;
   jint          _code_size;
   jint          _total_frame_size;
   jint          _orig_pc_offset;
   jint          _parameter_count;
   jint          _constants_size;
-#ifndef PRODUCT
-  jobject       _comments_handle;
-#endif
 
   bool          _has_wide_vector;
-  jobject       _word_kind_handle;
 
   MarkId        _next_call_type;
   address       _invoke_mark_pc;
@@ -182,72 +195,84 @@
   static ConstantIntValue*    _int_2_scope_value;
   static LocationValue*       _illegal_value;
 
-  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS);
-  void pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS);
-  void pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS);
-  void pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS);
-  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS);
-  void pd_relocate_JavaMethod(CodeBuffer &cbuf, Handle method, jint pc_offset, TRAPS);
-  void pd_relocate_poll(address pc, jint mark, TRAPS);
+  jint pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS);
+  void pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS);
+  void pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS);
+  void pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS);
+  void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS);
+  void pd_relocate_JavaMethod(CodeBuffer &cbuf, JVMCIObject method, jint pc_offset, JVMCI_TRAPS);
+  void pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS);
 
-  objArrayOop sites();
-  arrayOop code();
-  arrayOop data_section();
-  objArrayOop data_section_patches();
+  JVMCIObjectArray sites()                { return _sites_handle; }
+  JVMCIPrimitiveArray code()              { return _code_handle; }
+  JVMCIPrimitiveArray  data_section()     { return _data_section_handle; }
+  JVMCIObjectArray data_section_patches() { return _data_section_patches_handle; }
 #ifndef PRODUCT
-  objArrayOop comments();
+  JVMCIObjectArray comments()             { return _comments_handle; }
 #endif
-
-  oop word_kind();
+  JVMCIObject word_kind()                 { return _word_kind_handle; }
 
 public:
 
-  CodeInstaller(bool immutable_pic_compilation) : _arena(mtCompiler), _immutable_pic_compilation(immutable_pic_compilation) {}
+  CodeInstaller(JVMCIEnv* jvmci_env, bool immutable_pic_compilation) : _arena(mtJVMCI), _jvmci_env(jvmci_env), _immutable_pic_compilation(immutable_pic_compilation) {}
 
 #if INCLUDE_AOT
-  JVMCIEnv::CodeInstallResult gather_metadata(Handle target, Handle compiled_code, CodeMetadata& metadata, TRAPS);
+  JVMCI::CodeInstallResult gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS);
 #endif
-  JVMCIEnv::CodeInstallResult install(JVMCICompiler* compiler, Handle target, Handle compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log, TRAPS);
+  JVMCI::CodeInstallResult install(JVMCICompiler* compiler,
+                                   JVMCIObject target,
+                                   JVMCIObject compiled_code,
+                                   CodeBlob*& cb,
+                                   JVMCIObject installed_code,
+                                   FailedSpeculation** failed_speculations,
+                                   char* speculations,
+                                   int speculations_len,
+                                   JVMCI_TRAPS);
+
+  JVMCIEnv* jvmci_env() { return _jvmci_env; }
+  JVMCIRuntime* runtime() { return _jvmci_env->runtime(); }
 
   static address runtime_call_target_address(oop runtime_call);
-  static VMReg get_hotspot_reg(jint jvmciRegisterNumber, TRAPS);
+  static VMReg get_hotspot_reg(jint jvmciRegisterNumber, JVMCI_TRAPS);
   static bool is_general_purpose_reg(VMReg hotspotRegister);
 
   const OopMapSet* oopMapSet() const { return _debug_recorder->_oopmaps; }
 
 protected:
-  Location::Type get_oop_type(Thread* thread, Handle value);
-  ScopeValue* get_scope_value(Handle value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, TRAPS);
-  MonitorValue* get_monitor_value(Handle value, GrowableArray<ScopeValue*>* objects, TRAPS);
+  Location::Type get_oop_type(JVMCIObject value);
+  ScopeValue* get_scope_value(JVMCIObject value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, JVMCI_TRAPS);
+  MonitorValue* get_monitor_value(JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS);
 
-  void* record_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS);
+  void* record_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS);
 #ifdef _LP64
-  narrowKlass record_narrow_metadata_reference(CodeSection* section, address dest, Handle constant, TRAPS);
+  narrowKlass record_narrow_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS);
 #endif
 
   // extract the fields of the HotSpotCompiledCode
-  void initialize_fields(oop target, oop target_method, TRAPS);
-  void initialize_dependencies(oop target_method, OopRecorder* oop_recorder, TRAPS);
+  void initialize_fields(JVMCIObject target, JVMCIObject compiled_code, JVMCI_TRAPS);
+  void initialize_dependencies(JVMCIObject compiled_code, OopRecorder* oop_recorder, JVMCI_TRAPS);
 
-  int estimate_stubs_size(TRAPS);
+  int estimate_stubs_size(JVMCI_TRAPS);
 
   // perform data and call relocation on the CodeBuffer
-  JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS);
+  JVMCI::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, JVMCI_TRAPS);
 
-  void assumption_NoFinalizableSubclass(Thread* thread, Handle assumption);
-  void assumption_ConcreteSubtype(Thread* thread, Handle assumption);
-  void assumption_LeafType(Thread* thread, Handle assumption);
-  void assumption_ConcreteMethod(Thread* thread, Handle assumption);
-  void assumption_CallSiteTargetValue(Thread* thread, Handle assumption);
+  void assumption_NoFinalizableSubclass(JVMCIObject assumption);
+  void assumption_ConcreteSubtype(JVMCIObject assumption);
+  void assumption_LeafType(JVMCIObject assumption);
+  void assumption_ConcreteMethod(JVMCIObject assumption);
+  void assumption_CallSiteTargetValue(JVMCIObject assumption, JVMCI_TRAPS);
 
-  void site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_DataPatch(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, TRAPS);
-  void site_ExceptionHandler(jint pc_offset, Handle site);
+  void site_Safepoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_Infopoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_DataPatch(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_Mark(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS);
+  void site_ExceptionHandler(jint pc_offset, JVMCIObject site);
 
-  OopMap* create_oop_map(Handle debug_info, TRAPS);
+  OopMap* create_oop_map(JVMCIObject debug_info, JVMCI_TRAPS);
+
+  VMReg getVMRegFromLocation(JVMCIObject location, int total_frame_size, JVMCI_TRAPS);
 
   /**
    * Specifies the level of detail to record for a scope.
@@ -260,23 +285,17 @@
   };
 
   int map_jvmci_bci(int bci);
-  void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS);
-  void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, TRAPS) {
-    record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, THREAD);
+
+  void record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, bool return_oop, JVMCI_TRAPS);
+  void record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, JVMCI_TRAPS) {
+    record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, JVMCIENV);
   }
-  void record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS);
-  void record_object_value(ObjectValue* sv, Handle value, GrowableArray<ScopeValue*>* objects, TRAPS);
+  void record_scope(jint pc_offset, JVMCIObject position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, JVMCI_TRAPS);
+  void record_object_value(ObjectValue* sv, JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS);
 
-  GrowableArray<ScopeValue*>* record_virtual_objects(Handle debug_info, TRAPS);
+  GrowableArray<ScopeValue*>* record_virtual_objects(JVMCIObject debug_info, JVMCI_TRAPS);
 
   int estimateStubSpace(int static_call_stubs);
 };
 
-/**
- * Gets the Method metaspace object from a HotSpotResolvedJavaMethodImpl Java object.
- */
-Method* getMethodFromHotSpotMethod(oop hotspot_method);
-
-
-
 #endif // SHARE_JVMCI_JVMCICODEINSTALLER_HPP
--- a/src/hotspot/share/jvmci/jvmciCompiler.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp	Wed May 01 12:31:29 2019 -0700
@@ -22,19 +22,10 @@
  */
 
 #include "precompiled.hpp"
-#include "jvm.h"
+#include "compiler/compileBroker.hpp"
 #include "classfile/moduleEntry.hpp"
-#include "memory/oopFactory.hpp"
-#include "memory/resourceArea.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/javaCalls.hpp"
-#include "runtime/handles.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-#include "jvmci/jvmciCompiler.hpp"
 #include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "runtime/compilationPolicy.hpp"
-#include "runtime/globals_extension.hpp"
 #include "runtime/handles.inline.hpp"
 
 JVMCICompiler* JVMCICompiler::_instance = NULL;
@@ -104,112 +95,39 @@
     tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methods_compiled);
   }
   _bootstrapping = false;
-  JVMCIRuntime::bootstrap_finished(CHECK);
+  JVMCI::compiler_runtime()->bootstrap_finished(CHECK);
 }
 
-#define CHECK_EXIT THREAD); \
-if (HAS_PENDING_EXCEPTION) { \
-  char buf[256]; \
-  jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
-  JVMCICompiler::exit_on_pending_exception(PENDING_EXCEPTION, buf); \
-  return; \
-} \
-(void)(0
-
-void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JVMCIEnv* env) {
-  JVMCI_EXCEPTION_CONTEXT
-
-  bool is_osr = entry_bci != InvocationEntryBci;
-  if (_bootstrapping && is_osr) {
-      // no OSR compilations during bootstrap - the compiler is just too slow at this point,
-      // and we know that there are no endless loops
-      env->set_failure(true, "No OSR during boostrap");
-      return;
+bool JVMCICompiler::force_comp_at_level_simple(Method *method) {
+  if (UseJVMCINativeLibrary) {
+    // This mechanism exists to force compilation of a JVMCI compiler by C1
+    // to reduces the compilation time spent on the JVMCI compiler itself. In
+    // +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled.
+    return false;
   }
 
-  JVMCIRuntime::initialize_well_known_classes(CHECK_EXIT);
-
-  HandleMark hm;
-  Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_EXIT);
-
-  JavaValue method_result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_long((jlong) (address) method());
-  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(),
-                         vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
-
-  JavaValue result(T_OBJECT);
-  if (!HAS_PENDING_EXCEPTION) {
-    JavaCallArguments args;
-    args.push_oop(receiver);
-    args.push_oop(Handle(THREAD, (oop)method_result.get_jobject()));
-    args.push_int(entry_bci);
-    args.push_long((jlong) (address) env);
-    args.push_int(env->task()->compile_id());
-    JavaCalls::call_special(&result, receiver->klass(),
-                            vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
+  if (_bootstrapping) {
+    // When bootstrapping, the JVMCI compiler can compile its own methods.
+    return false;
   }
 
-  // An uncaught exception was thrown during compilation.  Generally these
-  // should be handled by the Java code in some useful way but if they leak
-  // through to here report them instead of dying or silently ignoring them.
-  if (HAS_PENDING_EXCEPTION) {
-    Handle exception(THREAD, PENDING_EXCEPTION);
-    CLEAR_PENDING_EXCEPTION;
-
-    java_lang_Throwable::java_printStackTrace(exception, THREAD);
-    if (HAS_PENDING_EXCEPTION) {
-      CLEAR_PENDING_EXCEPTION;
-    }
-
-    env->set_failure(false, "unexpected exception thrown");
-  } else {
-    oop result_object = (oop) result.get_jobject();
-    if (result_object != NULL) {
-      oop failure_message = HotSpotCompilationRequestResult::failureMessage(result_object);
-      if (failure_message != NULL) {
-        // Copy failure reason into resource memory first ...
-        const char* failure_reason = java_lang_String::as_utf8_string(failure_message);
-        // ... and then into the C heap.
-        failure_reason = os::strdup(failure_reason, mtCompiler);
-        bool retryable = HotSpotCompilationRequestResult::retry(result_object) != 0;
-        env->set_failure(retryable, failure_reason, true);
-      } else {
-        if (env->task()->code() == NULL) {
-          env->set_failure(true, "no nmethod produced");
-        } else {
-          env->task()->set_num_inlined_bytecodes(HotSpotCompilationRequestResult::inlinedBytecodes(result_object));
-          Atomic::inc(&_methods_compiled);
+  JVMCIRuntime* runtime = JVMCI::compiler_runtime();
+  if (runtime != NULL && runtime->is_HotSpotJVMCIRuntime_initialized()) {
+    JavaThread* thread = JavaThread::current();
+    HandleMark hm(thread);
+    THREAD_JVMCIENV(thread);
+    JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(JVMCIENV);
+    objArrayHandle excludeModules(thread, HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(JVMCIENV, HotSpotJVMCI::resolve(receiver)));
+    if (excludeModules.not_null()) {
+      ModuleEntry* moduleEntry = method->method_holder()->module();
+      for (int i = 0; i < excludeModules->length(); i++) {
+        if (oopDesc::equals(excludeModules->obj_at(i), moduleEntry->module())) {
+          return true;
         }
       }
-    } else {
-      assert(false, "JVMCICompiler.compileMethod should always return non-null");
     }
   }
-  if (_bootstrapping) {
-    _bootstrap_compilation_request_handled = true;
-  }
-}
-
-void JVMCICompiler::exit_on_pending_exception(oop exception, const char* message) {
-  JavaThread* THREAD = JavaThread::current();
-  CLEAR_PENDING_EXCEPTION;
-
-  static volatile int report_error = 0;
-  if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) {
-    // Only report an error once
-    tty->print_raw_cr(message);
-    Handle ex(THREAD, exception);
-    java_lang_Throwable::java_printStackTrace(ex, THREAD);
-  } else {
-    // Allow error reporting thread to print the stack trace.  Windows
-    // doesn't allow uninterruptible wait for JavaThreads
-    const bool interruptible = true;
-    os::sleep(THREAD, 200, interruptible);
-  }
-
-  before_exit(THREAD);
-  vm_exit(-1);
+  return false;
 }
 
 // Compilation entry point for methods
@@ -227,33 +145,3 @@
   TRACE_jvmci_1("JVMCICompiler::print_timers");
   tty->print_cr("       JVMCI code install time:        %6.3f s",    _codeInstallTimer.seconds());
 }
-
-bool JVMCICompiler::force_comp_at_level_simple(Method *method) {
-  JVMCI_EXCEPTION_CONTEXT
-
-  if (_bootstrapping) {
-    // When bootstrapping, the JVMCI compiler can compile its own methods.
-    return false;
-  }
-
-  if (!JVMCIRuntime::is_HotSpotJVMCIRuntime_initialized()) {
-    // JVMCI cannot participate in compilation scheduling until
-    // JVMCI is initialized and indicates it wants to participate.
-    return false;
-  }
-  // Support for graal.CompileGraalWithC1Only
-  HandleMark hm(thread);
-  jobject runtime = JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject(CATCH);
-  objArrayHandle excludeFromJVMCICompilation(thread, HotSpotJVMCIRuntime::excludeFromJVMCICompilation(runtime));
-  if (excludeFromJVMCICompilation.is_null()) {
-    return false;
-  }
-  ModuleEntry *module = method->method_holder()->module();
-  for (int i = 0; i < excludeFromJVMCICompilation->length(); ++i) {
-    if (module->module() == excludeFromJVMCICompilation->obj_at(i)) {
-      return true;
-    }
-  }
-
-  return false;
-}
--- a/src/hotspot/share/jvmci/jvmciCompiler.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp	Wed May 01 12:31:29 2019 -0700
@@ -25,8 +25,6 @@
 #define SHARE_JVMCI_JVMCICOMPILER_HPP
 
 #include "compiler/abstractCompiler.hpp"
-#include "jvmci/jvmciEnv.hpp"
-#include "utilities/exceptions.hpp"
 
 class JVMCICompiler : public AbstractCompiler {
 private:
@@ -65,7 +63,7 @@
     return _instance;
   }
 
-  virtual const char* name() { return "JVMCI"; }
+  virtual const char* name() { return UseJVMCINativeLibrary ? "JVMCI-native" : "JVMCI"; }
 
   virtual bool supports_native()                 { return true; }
   virtual bool supports_osr   ()                 { return true; }
@@ -90,11 +88,13 @@
 
   bool is_bootstrapping() const { return _bootstrapping; }
 
+  void set_bootstrap_compilation_request_handled() {
+    _instance->_bootstrap_compilation_request_handled = true;
+  }
+
   // Compilation entry point for methods
   virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
 
-  void compile_method(const methodHandle& target, int entry_bci, JVMCIEnv* env);
-
   // Print compilation timers and statistics
   virtual void print_timers();
 
@@ -104,6 +104,10 @@
    */
   int methods_compiled() { return _methods_compiled; }
 
+  void inc_methods_compiled() {
+    Atomic::inc(&_methods_compiled);
+  }
+
   // Print compilation timers and statistics
   static void print_compilation_timers();
 
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Wed May 01 12:31:29 2019 -0700
@@ -22,25 +22,25 @@
  */
 
 #include "precompiled.hpp"
-#include "ci/ciUtilities.inline.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
 #include "code/scopeDesc.hpp"
-#include "interpreter/linkResolver.hpp"
-#include "memory/oopFactory.hpp"
-#include "oops/cpCache.inline.hpp"
-#include "oops/generateOopMap.hpp"
-#include "oops/method.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
-#include "oops/typeArrayOop.inline.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/disassembler.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "interpreter/bytecodeStream.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/jvmciCodeInstaller.hpp"
 #include "jvmci/jvmciRuntime.hpp"
+#include "memory/oopFactory.hpp"
+#include "oops/constantPool.inline.hpp"
+#include "oops/method.inline.hpp"
+#include "oops/typeArrayOop.inline.hpp"
+#include "prims/nativeLookup.hpp"
+#include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
-#include "runtime/flags/jvmFlag.hpp"
 #include "runtime/frame.inline.hpp"
-#include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/timerTrace.hpp"
@@ -87,38 +87,22 @@
   }
 }
 
-// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
-#define C2V_VMENTRY(result_type, name, signature) \
-  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
-  TRACE_jvmci_1("CompilerToVM::" #name); \
-  TRACE_CALL(result_type, jvmci_ ## name signature) \
-  JVMCI_VM_ENTRY_MARK; \
-
-#define C2V_END }
-
-oop CompilerToVM::get_jvmci_method(const methodHandle& method, TRAPS) {
-  if (method() != NULL) {
-    JavaValue result(T_OBJECT);
-    JavaCallArguments args;
-    args.push_long((jlong) (address) method());
-    JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_NULL);
+class JVMCITraceMark : public StackObj {
+  const char* _msg;
+ public:
+  JVMCITraceMark(const char* msg) {
+    _msg = msg;
+    if (JVMCITraceLevel >= 1) {
+      tty->print_cr(PTR_FORMAT " JVMCITrace-1: Enter %s", p2i(JavaThread::current()), _msg);
+    }
+  }
+  ~JVMCITraceMark() {
+    if (JVMCITraceLevel >= 1) {
+      tty->print_cr(PTR_FORMAT " JVMCITrace-1: Exit %s", p2i(JavaThread::current()), _msg);
+    }
+  }
+};
 
-    return (oop)result.get_jobject();
-  }
-  return NULL;
-}
-
-oop CompilerToVM::get_jvmci_type(JVMCIKlassHandle& klass, TRAPS) {
-  if (!klass.is_null()) {
-    JavaValue result(T_OBJECT);
-    JavaCallArguments args;
-    args.push_oop(Handle(THREAD, klass->java_mirror()));
-    JavaCalls::call_static(&result, SystemDictionary::HotSpotResolvedObjectTypeImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::klass_fromMetaspace_signature(), &args, CHECK_NULL);
-
-    return (oop)result.get_jobject();
-  }
-  return NULL;
-}
 
 Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
   assert(_index < _args->length(), "out of bounds");
@@ -127,22 +111,32 @@
   return Handle(Thread::current(), arg);
 }
 
-jobjectArray readConfiguration0(JNIEnv *env, TRAPS);
+// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
+#define C2V_VMENTRY(result_type, name, signature)        \
+  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+  JVMCITraceMark jtm("CompilerToVM::" #name);            \
+  TRACE_CALL(result_type, jvmci_ ## name signature)      \
+  JVMCI_VM_ENTRY_MARK;                                   \
+  ResourceMark rm;                                       \
+  JNI_JVMCIENV(env);
 
-C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
-   jobjectArray config = readConfiguration0(env, CHECK_NULL);
-   return config;
-C2V_END
+#define C2V_END }
+
+jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS);
 
-C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject c2vm, jobject name_handle))
-#define RETURN_BOXED_LONG(value) oop box; jvalue p; p.j = (jlong) (value); box = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
-#define RETURN_BOXED_DOUBLE(value) oop box; jvalue p; p.d = (jdouble) (value); box = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
-  Handle name(THREAD, JNIHandles::resolve(name_handle));
+C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv* env))
+  jobjectArray config = readConfiguration0(env, JVMCI_CHECK_NULL);
+  return config;
+}
+
+C2V_VMENTRY(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle))
+#define RETURN_BOXED_LONG(value) jvalue p; p.j = (jlong) (value); JVMCIObject box = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); return box.as_jobject();
+#define RETURN_BOXED_DOUBLE(value) jvalue p; p.d = (jdouble) (value); JVMCIObject box = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL); return box.as_jobject();
+  JVMCIObject name = JVMCIENV->wrap(name_handle);
   if (name.is_null()) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  ResourceMark rm;
-  const char* cstring = java_lang_String::as_utf8_string(name());
+  const char* cstring = JVMCIENV->as_utf8_string(name);
   JVMFlag* flag = JVMFlag::find_flag(cstring, strlen(cstring), /* allow_locked */ true, /* return_flag */ true);
   if (flag == NULL) {
     return c2vm;
@@ -150,11 +144,11 @@
   if (flag->is_bool()) {
     jvalue prim;
     prim.z = flag->get_bool();
-    oop box = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
-    return JNIHandles::make_local(THREAD, box);
+    JVMCIObject box = JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(box);
   } else if (flag->is_ccstr()) {
-    Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
-    return JNIHandles::make_local(THREAD, value());
+    JVMCIObject value = JVMCIENV->create_string(flag->get_ccstr(), JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(value);
   } else if (flag->is_intx()) {
     RETURN_BOXED_LONG(flag->get_intx());
   } else if (flag->is_int()) {
@@ -176,12 +170,25 @@
 #undef RETURN_BOXED_DOUBLE
 C2V_END
 
-C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  ResourceMark rm;
+C2V_VMENTRY(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address))
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  if (oop_address == 0) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Handle must be non-zero");
+  }
+  oop obj = *((oopDesc**) oop_address);
+  if (obj != NULL) {
+    oopDesc::verify(obj);
+  }
+  return JNIHandles::make_local(obj);
+C2V_END
+
+C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
 
   int code_size = method->code_size();
-  typeArrayOop reconstituted_code = oopFactory::new_byteArray(code_size, CHECK_NULL);
+  jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);
 
   guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
   // iterate over all bytecodes and replace non-Java bytecodes
@@ -193,9 +200,9 @@
     int len = s.instruction_size();
 
     // Restore original byte code.
-    reconstituted_code->byte_at_put(bci, (jbyte) (s.is_wide()? Bytecodes::_wide : code));
+    reconstituted_code[bci] =  (jbyte) (s.is_wide()? Bytecodes::_wide : code);
     if (len > 1) {
-      memcpy(reconstituted_code->byte_at_addr(bci + 1), s.bcp()+1, len-1);
+      memcpy(reconstituted_code + (bci + 1), s.bcp()+1, len-1);
     }
 
     if (len > 1) {
@@ -211,14 +218,14 @@
         case Bytecodes::_invokestatic:
         case Bytecodes::_invokeinterface:
         case Bytecodes::_invokehandle: {
-          int cp_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
-          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+          int cp_index = Bytes::get_native_u2((address) reconstituted_code + (bci + 1));
+          Bytes::put_Java_u2((address) reconstituted_code + (bci + 1), (u2) cp_index);
           break;
         }
 
         case Bytecodes::_invokedynamic: {
-          int cp_index = Bytes::get_native_u4((address) reconstituted_code->byte_at_addr(bci + 1));
-          Bytes::put_Java_u4((address) reconstituted_code->byte_at_addr(bci + 1), (u4) cp_index);
+          int cp_index = Bytes::get_native_u4((address) reconstituted_code + (bci + 1));
+          Bytes::put_Java_u4((address) reconstituted_code + (bci + 1), (u4) cp_index);
           break;
         }
 
@@ -229,18 +236,18 @@
       // Not all ldc byte code are rewritten.
       switch (raw_code) {
         case Bytecodes::_fast_aldc: {
-          int cpc_index = reconstituted_code->byte_at(bci + 1) & 0xff;
+          int cpc_index = reconstituted_code[bci + 1] & 0xff;
           int cp_index = method->constants()->object_to_cp_index(cpc_index);
           assert(cp_index < method->constants()->length(), "sanity check");
-          reconstituted_code->byte_at_put(bci + 1, (jbyte) cp_index);
+          reconstituted_code[bci + 1] = (jbyte) cp_index;
           break;
         }
 
         case Bytecodes::_fast_aldc_w: {
-          int cpc_index = Bytes::get_native_u2((address) reconstituted_code->byte_at_addr(bci + 1));
+          int cpc_index = Bytes::get_native_u2((address) reconstituted_code + (bci + 1));
           int cp_index = method->constants()->object_to_cp_index(cpc_index);
           assert(cp_index < method->constants()->length(), "sanity check");
-          Bytes::put_Java_u2((address) reconstituted_code->byte_at_addr(bci + 1), (u2) cp_index);
+          Bytes::put_Java_u2((address) reconstituted_code + (bci + 1), (u2) cp_index);
           break;
         }
 
@@ -250,25 +257,29 @@
     }
   }
 
-  return (jbyteArray) JNIHandles::make_local(THREAD, reconstituted_code);
+  JVMCIPrimitiveArray result = JVMCIENV->new_byteArray(code_size, JVMCI_CHECK_NULL);
+  JVMCIENV->copy_bytes_from(reconstituted_code, result, 0, code_size);
+  return JVMCIENV->get_jbyteArray(result);
 C2V_END
 
-C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return method->exception_table_length();
 C2V_END
 
-C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   if (method->exception_table_length() == 0) {
     return 0L;
   }
   return (jlong) (address) method->exception_table_start();
 C2V_END
 
-C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv *, jobject, jobject executable_handle))
+C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle))
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+
   oop executable = JNIHandles::resolve(executable_handle);
   oop mirror = NULL;
   int slot = 0;
@@ -283,89 +294,101 @@
   }
   Klass* holder = java_lang_Class::as_Klass(mirror);
   methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot);
-  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv *, jobject, jobject base, jlong offset))
+C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset))
   methodHandle method;
-  oop base_object = JNIHandles::resolve(base);
-  if (base_object == NULL) {
+  JVMCIObject base_object = JVMCIENV->wrap(base);
+  if (base_object.is_null()) {
     method = *((Method**)(offset));
-  } else if (base_object->is_a(SystemDictionary::ResolvedMethodName_klass())) {
-    method = (Method*) (intptr_t) base_object->long_field(offset);
-  } else if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-    method = *((Method**)(HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object) + offset));
-  } else {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Unexpected type: %s", base_object->klass()->external_name()));
+  } else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
+    Handle obj = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
+    if (obj->is_a(SystemDictionary::ResolvedMethodName_klass())) {
+      method = (Method*) (intptr_t) obj->long_field(offset);
+    } else {
+      JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected type: %s", obj->klass()->external_name()));
+    }
+  } else if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(base_object)) {
+    method = JVMCIENV->asMethod(base_object);
+  }
+  if (method.is_null()) {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected type: %s", JVMCIENV->klass_name(base_object)));
   }
   assert (method.is_null() || method->is_method(), "invalid read");
-  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject object_handle))
+C2V_VMENTRY(jobject, getConstantPool, (JNIEnv* env, jobject, jobject object_handle))
   constantPoolHandle cp;
-  oop object = JNIHandles::resolve(object_handle);
-  if (object == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+  JVMCIObject object = JVMCIENV->wrap(object_handle);
+  if (object.is_null()) {
+    JVMCI_THROW_NULL(NullPointerException);
   }
-  if (object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-    cp = CompilerToVM::asMethod(object)->constMethod()->constants();
-  } else if (object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-    cp = InstanceKlass::cast(CompilerToVM::asKlass(object))->constants();
+  if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(object)) {
+    cp = JVMCIENV->asMethod(object)->constMethod()->constants();
+  } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(object)) {
+    cp = InstanceKlass::cast(JVMCIENV->asKlass(object))->constants();
   } else {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Unexpected type: %s", object->klass()->external_name()));
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                err_msg("Unexpected type: %s", JVMCIENV->klass_name(object)));
   }
   assert(!cp.is_null(), "npe");
-  JavaValue method_result(T_OBJECT);
-  JavaCallArguments args;
-  args.push_long((jlong) (address) cp());
-  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
+
+  JVMCIObject result = JVMCIENV->get_jvmci_constant_pool(cp, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
+C2V_VMENTRY(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed))
   JVMCIKlassHandle klass(THREAD);
-  oop base_object = JNIHandles::resolve(base);
+  JVMCIObject base_object = JVMCIENV->wrap(base);
   jlong base_address = 0;
-  if (base_object != NULL && offset == oopDesc::klass_offset_in_bytes()) {
-    klass = base_object->klass();
+  if (base_object.is_non_null() && offset == oopDesc::klass_offset_in_bytes()) {
+    // klass = JVMCIENV->unhandle(base_object)->klass();
+    if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
+      Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
+      klass = base_oop->klass();
+    } else {
+      assert(false, "What types are we actually expecting here?");
+    }
   } else if (!compressed) {
-    if (base_object != NULL) {
-      if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-        base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
-      } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
-        base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
-      } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-        base_address = (jlong) CompilerToVM::asKlass(base_object);
-      } else if (base_object->is_a(SystemDictionary::Class_klass())) {
-        base_address = (jlong) (address) base_object;
-      } else {
-        THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-                    err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", base_object->klass()->external_name(), offset, compressed ? "true" : "false"));
+    if (base_object.is_non_null()) {
+      if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(base_object)) {
+        base_address = (intptr_t) JVMCIENV->asMethod(base_object);
+      } else if (JVMCIENV->isa_HotSpotConstantPool(base_object)) {
+        base_address = (intptr_t) JVMCIENV->asConstantPool(base_object);
+      } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
+        base_address = (intptr_t) JVMCIENV->asKlass(base_object);
+      } else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
+        Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
+        if (base_oop->is_a(SystemDictionary::Class_klass())) {
+          base_address = (jlong) (address) base_oop();
+        }
+      }
+      if (base_address == 0) {
+        JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                    err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", JVMCIENV->klass_name(base_object), offset, compressed ? "true" : "false"));
       }
     }
     klass = *((Klass**) (intptr_t) (base_address + offset));
   } else {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
                 err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s",
-                        base_object != NULL ? base_object->klass()->external_name() : "null",
+                        base_object.is_non_null() ? JVMCIENV->klass_name(base_object) : "null",
                         offset, compressed ? "true" : "false"));
   }
   assert (klass == NULL || klass->is_klass(), "invalid read");
-  oop result = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
-  ResourceMark rm;
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  Klass* holder = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
+  Klass* holder = JVMCIENV->asKlass(jvmci_type);
   if (holder->is_interface()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", holder->external_name()));
+    JVMCI_THROW_MSG_NULL(InternalError, err_msg("Interface %s should be handled in Java code", holder->external_name()));
   }
 
   methodHandle ucm;
@@ -373,12 +396,12 @@
     MutexLocker locker(Compile_lock);
     ucm = Dependencies::find_unique_concrete_method(holder, method());
   }
-  oop result = CompilerToVM::get_jvmci_method(ucm, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(ucm, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getImplementor, (JNIEnv *, jobject, jobject jvmci_type))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jobject, getImplementor, (JNIEnv* env, jobject, jobject jvmci_type))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_interface()) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
         err_msg("Expected interface type, got %s", klass->external_name()));
@@ -390,48 +413,55 @@
     MutexLocker locker(Compile_lock);
     handle = iklass->implementor();
   }
-  oop implementor = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, implementor);
+  JVMCIObject implementor = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(implementor);
 C2V_END
 
-C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return method->is_ignored_by_security_stack_walk();
 C2V_END
 
-C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, isCompilable,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   constantPoolHandle cp = method->constMethod()->constants();
   assert(!cp.is_null(), "npe");
   // don't inline method when constant pool contains a CONSTANT_Dynamic
   return !method->is_not_compilable(CompLevel_full_optimization) && !cp->has_dynamic_constant();
 C2V_END
 
-C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline();
 C2V_END
 
-C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return CompilerOracle::should_inline(method) || method->force_inline();
 C2V_END
 
-C2V_VMENTRY(jobject, lookupType, (JNIEnv*, jobject, jstring jname, jclass accessing_class, jboolean resolve))
-  ResourceMark rm;
-  Handle name(THREAD, JNIHandles::resolve(jname));
-  Symbol* class_name = java_lang_String::as_symbol(name(), CHECK_0);
-  if (java_lang_String::length(name()) <= 1) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
+C2V_VMENTRY(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jclass accessing_class, jboolean resolve))
+  JVMCIObject name = JVMCIENV->wrap(jname);
+  const char* str = JVMCIENV->as_utf8_string(name);
+  TempNewSymbol class_name = SymbolTable::new_symbol(str, CHECK_NULL);
+
+  if (class_name->utf8_length() <= 1) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
   }
 
   JVMCIKlassHandle resolved_klass(THREAD);
-  if (JNIHandles::resolve(accessing_class) == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+  Klass* accessing_klass = NULL;
+  Handle class_loader;
+  Handle protection_domain;
+  if (accessing_class != NULL) {
+    accessing_klass = JVMCIENV->asKlass(accessing_class);
+    class_loader = Handle(THREAD, accessing_klass->class_loader());
+    protection_domain = Handle(THREAD, accessing_klass->protection_domain());
+  } else {
+    // Use the System class loader
+    class_loader = Handle(THREAD, SystemDictionary::java_system_loader());
+    JVMCIENV->runtime()->initialize(JVMCIENV);
   }
-  Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class));
-  Handle class_loader(THREAD, accessing_klass->class_loader());
-  Handle protection_domain(THREAD, accessing_klass->protection_domain());
 
   if (resolve) {
     resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0);
@@ -464,135 +494,163 @@
       } else {
         resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(t))->array_klass(fd.dimension(), CHECK_0);
       }
+    } else {
+      resolved_klass = SystemDictionary::find(class_name, class_loader, protection_domain, CHECK_0);
     }
   }
-  oop result = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  if (mirror == NULL) {
+    return NULL;
+  }
+  JVMCIKlassHandle klass(THREAD);
+  klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
+  if (klass == NULL) {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException, "Primitive classes are unsupported");
+  }
+  JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+}
+
+C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop result = cp->resolve_constant_at(index, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result));
 C2V_END
 
-C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result));
 C2V_END
 
-C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->name_and_type_ref_index_at(index);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
-  Handle sym = java_lang_String::create_from_symbol(cp->name_ref_at(which), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, sym());
+C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
+  JVMCIObject sym = JVMCIENV->create_string(cp->name_ref_at(which), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(sym);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint which))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
-  Handle sym = java_lang_String::create_from_symbol(cp->signature_ref_at(which), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, sym());
+C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
+  JVMCIObject sym = JVMCIENV->create_string(cp->signature_ref_at(which), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(sym);
 C2V_END
 
-C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->klass_ref_index_at(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* klass = cp->klass_at(index, CHECK_NULL);
   JVMCIKlassHandle resolved_klass(THREAD, klass);
   if (resolved_klass->is_instance_klass()) {
     InstanceKlass::cast(resolved_klass())->link_class_or_fail(THREAD);
   }
-  oop jvmci_type = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, jvmci_type);
+  JVMCIObject klassObject = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(klassObject);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* loading_klass = cp->pool_holder();
   bool is_accessible = false;
-  JVMCIKlassHandle klass(THREAD, JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass));
+  JVMCIKlassHandle klass(THREAD, JVMCIRuntime::get_klass_by_index(cp, index, is_accessible, loading_klass));
   Symbol* symbol = NULL;
-  if (klass == NULL) {
-    symbol = cp->klass_name_at(index);
+  if (klass.is_null()) {
+    constantTag tag = cp->tag_at(index);
+    if (tag.is_klass()) {
+      // The klass has been inserted into the constant pool
+      // very recently.
+      klass = cp->resolved_klass_at(index);
+    } else if (tag.is_symbol()) {
+      symbol = cp->symbol_at(index);
+    } else {
+      assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag");
+      symbol = cp->klass_name_at(index);
+    }
   }
-  oop result_oop;
+  JVMCIObject result;
   if (!klass.is_null()) {
-    result_oop = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
+    result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
   } else {
-    Handle result = java_lang_String::create_from_symbol(symbol, CHECK_NULL);
-    result_oop = result();
+    result = JVMCIENV->create_string(symbol, JVMCI_CHECK_NULL);
   }
-  return JNIHandles::make_local(THREAD, result_oop);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
-  return JNIHandles::make_local(THREAD, appendix_oop);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(appendix_oop));
 C2V_END
 
-C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   InstanceKlass* pool_holder = cp->pool_holder();
   Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
-  methodHandle method = JVMCIEnv::get_method_by_index(cp, index, bc, pool_holder);
-  oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  methodHandle method = JVMCIRuntime::get_method_by_index(cp, index, bc, pool_holder);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->remap_instruction_operand_from_cache(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
-  ResourceMark rm;
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
   fieldDescriptor fd;
-  LinkInfo link_info(cp, index, (jvmci_method != NULL) ? CompilerToVM::asMethod(jvmci_method) : NULL, CHECK_0);
+  LinkInfo link_info(cp, index, (jvmci_method != NULL) ? JVMCIENV->asMethod(jvmci_method) : NULL, CHECK_0);
   LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0);
-  typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
-  if (info == NULL || info->length() != 3) {
+  JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
+  if (info.is_null() || JVMCIENV->get_length(info) != 3) {
     JVMCI_ERROR_NULL("info must not be null and have a length of 3");
   }
-  info->int_at_put(0, fd.access_flags().as_int());
-  info->int_at_put(1, fd.offset());
-  info->int_at_put(2, fd.index());
+  JVMCIENV->put_int_at(info, 0, fd.access_flags().as_int());
+  JVMCIENV->put_int_at(info, 1, fd.offset());
+  JVMCIENV->put_int_at(info, 2, fd.index());
   JVMCIKlassHandle handle(THREAD, fd.field_holder());
-  oop field_holder = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, field_holder);
+  JVMCIObject field_holder = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(field_holder);
 C2V_END
 
-C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv *, jobject, jobject jvmci_type, jobject jvmci_method))
-  ResourceMark rm;
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (klass->is_interface()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Interface %s should be handled in Java code", klass->external_name()));
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Interface %s should be handled in Java code", klass->external_name()));
   }
   if (!method->method_holder()->is_interface()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
+  }
+  if (!klass->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be instance klass", klass->external_name()));
   }
   if (!InstanceKlass::cast(klass)->is_linked()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be linked", klass->external_name()));
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be linked", klass->external_name()));
   }
   return LinkResolver::vtable_index_of_interface_method(klass, method);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
-  Klass* recv_klass = CompilerToVM::asKlass(receiver_jvmci_type);
-  Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type);
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jobject, resolveMethod, (JNIEnv* env, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
+  Klass* recv_klass = JVMCIENV->asKlass(receiver_jvmci_type);
+  Klass* caller_klass = JVMCIENV->asKlass(caller_jvmci_type);
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
 
   Klass* resolved     = method->method_holder();
   Symbol* h_name      = method->name();
@@ -632,27 +690,27 @@
     return NULL;
   }
 
-  oop result = CompilerToVM::get_jvmci_method(m, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(m, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_type))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   assert(klass != NULL, "method must not be called for primitive types");
   return Dependencies::find_finalizable_subclass(klass) != NULL;
 C2V_END
 
-C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv *, jobject, jobject jvmci_type))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type))
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_instance_klass()) {
     return NULL;
   }
   InstanceKlass* iklass = InstanceKlass::cast(klass);
-  oop result = CompilerToVM::get_jvmci_method(iklass->class_initializer(), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_method(iklass->class_initializer(), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv*, jobject, jlong addr))
+C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr))
   address target_addr = (address) addr;
   if (target_addr != 0x0) {
     int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
@@ -662,34 +720,47 @@
   return -1;
 C2V_END
 
-C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv *, jobject,  jobject jvmci_method))
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv* env, jobject,  jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
   method->set_not_c1_compilable();
   method->set_not_c2_compilable();
   method->set_dont_inline(true);
 C2V_END
 
-C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject installed_code, jobject speculation_log))
-  ResourceMark rm;
+C2V_VMENTRY(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject compiled_code,
+            jobject installed_code, jlong failed_speculations_address, jbyteArray speculations_obj))
   HandleMark hm;
   JNIHandleMark jni_hm;
 
-  Handle target_handle(THREAD, JNIHandles::resolve(target));
-  Handle compiled_code_handle(THREAD, JNIHandles::resolve(compiled_code));
+  JVMCIObject target_handle = JVMCIENV->wrap(target);
+  JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
   CodeBlob* cb = NULL;
-  Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code));
-  Handle speculation_log_handle(THREAD, JNIHandles::resolve(speculation_log));
+  JVMCIObject installed_code_handle = JVMCIENV->wrap(installed_code);
+  JVMCIPrimitiveArray speculations_handle = JVMCIENV->wrap(speculations_obj);
+
+  int speculations_len = JVMCIENV->get_length(speculations_handle);
+  char* speculations = NEW_RESOURCE_ARRAY(char, speculations_len);
+  JVMCIENV->copy_bytes_to(speculations_handle, (jbyte*) speculations, 0, speculations_len);
 
   JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR);
 
   TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
-  bool is_immutable_PIC = HotSpotCompiledCode::isImmutablePIC(compiled_code_handle) > 0;
-  CodeInstaller installer(is_immutable_PIC);
-  JVMCIEnv::CodeInstallResult result = installer.install(compiler, target_handle, compiled_code_handle, cb, installed_code_handle, speculation_log_handle, CHECK_0);
+  bool is_immutable_PIC = JVMCIENV->get_HotSpotCompiledCode_isImmutablePIC(compiled_code_handle) > 0;
+
+  CodeInstaller installer(JVMCIENV, is_immutable_PIC);
+  JVMCI::CodeInstallResult result = installer.install(compiler,
+      target_handle,
+      compiled_code_handle,
+      cb,
+      installed_code_handle,
+      (FailedSpeculation**)(address) failed_speculations_address,
+      speculations,
+      speculations_len,
+      JVMCI_CHECK_0);
 
   if (PrintCodeCacheOnCompilation) {
     stringStream s;
-    // Dump code cache  into a buffer before locking the tty,
+    // Dump code cache into a buffer before locking the tty,
     {
       MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
       CodeCache::print_summary(&s, false);
@@ -698,130 +769,115 @@
     tty->print_raw_cr(s.as_string());
   }
 
-  if (result != JVMCIEnv::ok) {
+  if (result != JVMCI::ok) {
     assert(cb == NULL, "should be");
   } else {
-    if (installed_code_handle.not_null()) {
-      assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
-      nmethod::invalidate_installed_code(installed_code_handle, CHECK_0);
-      {
-        // Ensure that all updates to the InstalledCode fields are consistent.
-        MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag);
-        InstalledCode::set_address(installed_code_handle, (jlong) cb);
-        InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
-        if (cb->is_nmethod()) {
-          InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->as_nmethod_or_null()->verified_entry_point());
-        } else {
-          InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->code_begin());
-        }
-        if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
-          HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
-          HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
-          HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
-        }
+    if (installed_code_handle.is_non_null()) {
+      if (cb->is_nmethod()) {
+        assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type");
+        // Clear the link to an old nmethod first
+        JVMCIObject nmethod_mirror = installed_code_handle;
+        JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK_0);
+      } else {
+        assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
       }
+      // Initialize the link to the new code blob
+      JVMCIENV->initialize_installed_code(installed_code_handle, cb, JVMCI_CHECK_0);
     }
   }
   return result;
 C2V_END
 
-C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject compiled_code, jobject metadata))
+C2V_VMENTRY(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata))
 #if INCLUDE_AOT
-  ResourceMark rm;
   HandleMark hm;
+  assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
 
-  Handle target_handle(THREAD, JNIHandles::resolve(target));
-  Handle compiled_code_handle(THREAD, JNIHandles::resolve(compiled_code));
-  Handle metadata_handle(THREAD, JNIHandles::resolve(metadata));
+  JVMCIObject target_handle = JVMCIENV->wrap(target);
+  JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
+  JVMCIObject metadata_handle = JVMCIENV->wrap(metadata);
 
   CodeMetadata code_metadata;
-  CodeBlob *cb = NULL;
-  CodeInstaller installer(true /* immutable PIC compilation */);
 
-  JVMCIEnv::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata, CHECK_0);
-  if (result != JVMCIEnv::ok) {
+  CodeInstaller installer(JVMCIENV, true /* immutable PIC compilation */);
+  JVMCI::CodeInstallResult result = installer.gather_metadata(target_handle, compiled_code_handle, code_metadata, JVMCI_CHECK_0);
+  if (result != JVMCI::ok) {
     return result;
   }
 
   if (code_metadata.get_nr_pc_desc() > 0) {
-    typeArrayHandle pcArrayOop = oopFactory::new_byteArray_handle(sizeof(PcDesc) * code_metadata.get_nr_pc_desc(), CHECK_(JVMCIEnv::cache_full));
-    memcpy(pcArrayOop->byte_at_addr(0), code_metadata.get_pc_desc(), sizeof(PcDesc) * code_metadata.get_nr_pc_desc());
-    HotSpotMetaData::set_pcDescBytes(metadata_handle, pcArrayOop());
+    int size = sizeof(PcDesc) * code_metadata.get_nr_pc_desc();
+    JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+    JVMCIENV->copy_bytes_from((jbyte*) code_metadata.get_pc_desc(), array, 0, size);
+    HotSpotJVMCI::HotSpotMetaData::set_pcDescBytes(JVMCIENV, metadata_handle, array);
   }
 
   if (code_metadata.get_scopes_size() > 0) {
-    typeArrayHandle scopesArrayOop = oopFactory::new_byteArray_handle(code_metadata.get_scopes_size(), CHECK_(JVMCIEnv::cache_full));
-    memcpy(scopesArrayOop->byte_at_addr(0), code_metadata.get_scopes_desc(), code_metadata.get_scopes_size());
-    HotSpotMetaData::set_scopesDescBytes(metadata_handle, scopesArrayOop());
+    int size = code_metadata.get_scopes_size();
+    JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+    JVMCIENV->copy_bytes_from((jbyte*) code_metadata.get_scopes_desc(), array, 0, size);
+    HotSpotJVMCI::HotSpotMetaData::set_scopesDescBytes(JVMCIENV, metadata_handle, array);
   }
 
   RelocBuffer* reloc_buffer = code_metadata.get_reloc_buffer();
-  typeArrayHandle relocArrayOop = oopFactory::new_byteArray_handle((int) reloc_buffer->size(), CHECK_(JVMCIEnv::cache_full));
-  if (reloc_buffer->size() > 0) {
-    memcpy(relocArrayOop->byte_at_addr(0), reloc_buffer->begin(), reloc_buffer->size());
-  }
-  HotSpotMetaData::set_relocBytes(metadata_handle, relocArrayOop());
+  int size = (int) reloc_buffer->size();
+  JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+  JVMCIENV->copy_bytes_from((jbyte*) reloc_buffer->begin(), array, 0, size);
+  HotSpotJVMCI::HotSpotMetaData::set_relocBytes(JVMCIENV, metadata_handle, array);
 
   const OopMapSet* oopMapSet = installer.oopMapSet();
   {
     ResourceMark mark;
     ImmutableOopMapBuilder builder(oopMapSet);
-    int oopmap_size = builder.heap_size();
-    typeArrayHandle oopMapArrayHandle = oopFactory::new_byteArray_handle(oopmap_size, CHECK_(JVMCIEnv::cache_full));
-    builder.generate_into((address) oopMapArrayHandle->byte_at_addr(0));
-    HotSpotMetaData::set_oopMaps(metadata_handle, oopMapArrayHandle());
+    int size = builder.heap_size();
+    JVMCIPrimitiveArray array = JVMCIENV->new_byteArray(size, JVMCI_CHECK_(JVMCI::cache_full));
+    builder.generate_into((address) HotSpotJVMCI::resolve(array)->byte_at_addr(0));
+    HotSpotJVMCI::HotSpotMetaData::set_oopMaps(JVMCIENV, metadata_handle, array);
   }
 
   AOTOopRecorder* recorder = code_metadata.get_oop_recorder();
 
   int nr_meta_refs = recorder->nr_meta_refs();
-  objArrayOop metadataArray = oopFactory::new_objectArray(nr_meta_refs, CHECK_(JVMCIEnv::cache_full));
-  objArrayHandle metadataArrayHandle(THREAD, metadataArray);
+  JVMCIObjectArray metadataArray = JVMCIENV->new_Object_array(nr_meta_refs, JVMCI_CHECK_(JVMCI::cache_full));
   for (int i = 0; i < nr_meta_refs; ++i) {
     jobject element = recorder->meta_element(i);
     if (element == NULL) {
-      return JVMCIEnv::cache_full;
+      return JVMCI::cache_full;
     }
-    metadataArrayHandle->obj_at_put(i, JNIHandles::resolve(element));
+    JVMCIENV->put_object_at(metadataArray, i, JVMCIENV->wrap(element));
   }
-  HotSpotMetaData::set_metadata(metadata_handle, metadataArrayHandle());
+  HotSpotJVMCI::HotSpotMetaData::set_metadata(JVMCIENV, metadata_handle, metadataArray);
 
   ExceptionHandlerTable* handler = code_metadata.get_exception_table();
   int table_size = handler->size_in_bytes();
-  typeArrayHandle exceptionArrayOop = oopFactory::new_byteArray_handle(table_size, CHECK_(JVMCIEnv::cache_full));
-
+  JVMCIPrimitiveArray exceptionArray = JVMCIENV->new_byteArray(table_size, JVMCI_CHECK_(JVMCI::cache_full));
   if (table_size > 0) {
-    handler->copy_bytes_to((address) exceptionArrayOop->byte_at_addr(0));
+    handler->copy_bytes_to((address) HotSpotJVMCI::resolve(exceptionArray)->byte_at_addr(0));
   }
-  HotSpotMetaData::set_exceptionBytes(metadata_handle, exceptionArrayOop());
+  HotSpotJVMCI::HotSpotMetaData::set_exceptionBytes(JVMCIENV, metadata_handle, exceptionArray);
 
   return result;
 #else
-  THROW_MSG_0(vmSymbols::java_lang_InternalError(), "unimplemented");
+  JVMCI_THROW_MSG_0(InternalError, "unimplemented");
 #endif
 C2V_END
 
-C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
+C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject))
   JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
   CompilerStatistics* stats = compiler->stats();
   stats->_standard.reset();
   stats->_osr.reset();
 C2V_END
 
-C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jobject installedCode))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode))
   HandleMark hm;
 
   if (installedCode == NULL) {
-    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "installedCode is null");
+    JVMCI_THROW_MSG_NULL(NullPointerException, "installedCode is null");
   }
 
-  jlong codeBlob = InstalledCode::address(installedCode);
-  if (codeBlob == 0L) {
-    return NULL;
-  }
-
-  CodeBlob* cb = (CodeBlob*) (address) codeBlob;
+  JVMCIObject installedCodeObject = JVMCIENV->wrap(installedCode);
+  CodeBlob* cb = JVMCIENV->asCodeBlob(installedCodeObject);
   if (cb == NULL) {
     return NULL;
   }
@@ -846,28 +902,32 @@
     return NULL;
   }
 
-  Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result());
+  JVMCIObject result = JVMCIENV->create_string(st.as_string(), JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv*, jobject, jobject jvmci_method, int bci))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv* env, jobject, jobject jvmci_method, int bci))
   HandleMark hm;
 
-  methodHandle method = CompilerToVM::asMethod(jvmci_method);
-  oop element = java_lang_StackTraceElement::create(method, bci, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, element);
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
+  JVMCIObject element = JVMCIENV->new_StackTraceElement(method, bci, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeInstalledCode, (JNIEnv*, jobject, jobject args, jobject hotspotInstalledCode))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod))
+  if (env != JavaThread::current()->jni_environment()) {
+    // The incoming arguments array would have to contain JavaConstants instead of regular objects
+    // and the return value would have to be wrapped as a JavaConstant.
+    JVMCI_THROW_MSG_NULL(InternalError, "Wrapping of arguments is currently unsupported");
+  }
+
   HandleMark hm;
 
-  jlong nmethodValue = InstalledCode::address(hotspotInstalledCode);
-  if (nmethodValue == 0L) {
-    THROW_NULL(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
+  JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
+  nmethod* nm = JVMCIENV->asNmethod(nmethod_mirror);
+  if (nm == NULL) {
+    JVMCI_THROW_NULL(InvalidInstalledCodeException);
   }
-  nmethod* nm = (nmethod*) (address) nmethodValue;
   methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
   JavaCallArguments jca(mh->size_of_parameters());
@@ -880,7 +940,7 @@
   if (jap.get_ret_type() == T_VOID) {
     return NULL;
   } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) {
-    return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
+    return JNIHandles::make_local((oop) result.get_jobject());
   } else {
     jvalue *value = (jvalue *) result.get_value_addr();
     // Narrow the value down if required (Important on big endian machines)
@@ -900,13 +960,13 @@
       default:
         break;
     }
-    oop o = java_lang_boxing_object::create(jap.get_ret_type(), value, CHECK_NULL);
-    return JNIHandles::make_local(THREAD, o);
+    JVMCIObject o = JVMCIENV->create_box(jap.get_ret_type(), value, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(o);
   }
 C2V_END
 
-C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv *, jobject, jobject jvmci_method))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (!method->has_linenumber_table()) {
     return NULL;
   }
@@ -917,38 +977,36 @@
   }
 
   CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
-  typeArrayOop result = oopFactory::new_longArray(2 * num_entries, CHECK_NULL);
+  JVMCIPrimitiveArray result = JVMCIENV->new_longArray(2 * num_entries, JVMCI_CHECK_NULL);
 
   int i = 0;
   jlong value;
   while (stream.read_pair()) {
     value = ((long) stream.bci());
-    result->long_at_put(i, value);
+    JVMCIENV->put_long_at(result, i, value);
     value = ((long) stream.line());
-    result->long_at_put(i + 1, value);
+    JVMCIENV->put_long_at(result, i + 1, value);
     i += 2;
   }
 
-  return (jlongArray) JNIHandles::make_local(THREAD, result);
+  return (jlongArray) JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (!method->has_localvariable_table()) {
     return 0;
   }
   return (jlong) (address) method->localvariable_table_start();
 C2V_END
 
-C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv *, jobject, jobject jvmci_method))
-  ResourceMark rm;
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   return method->localvariable_table_length();
 C2V_END
 
-C2V_VMENTRY(void, reprofile, (JNIEnv*, jobject, jobject jvmci_method))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, jobject jvmci_method))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   MethodCounters* mcs = method->method_counters();
   if (mcs != NULL) {
     mcs->clear_counters();
@@ -971,52 +1029,56 @@
 C2V_END
 
 
-C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code))
-  Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code));
-  nmethod::invalidate_installed_code(installed_code_handle, CHECK);
+C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod))
+  JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
+  JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK);
 C2V_END
 
-C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv*, jobject))
-  typeArrayOop arrayOop = oopFactory::new_longArray(JVMCICounterSize, CHECK_NULL);
-  JavaThread::collect_counters(arrayOop);
-  return (jlongArray) JNIHandles::make_local(THREAD, arrayOop);
+C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr))
+  oop ret = RawAccess<>::oop_load((oop*)(address)addr);
+  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(ret));
+ C2V_END
+
+C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv* env, jobject))
+  JVMCIPrimitiveArray array = JVMCIENV->new_longArray(JVMCICounterSize, JVMCI_CHECK_NULL);
+  JavaThread::collect_counters(JVMCIENV, array);
+  return (jlongArray) JVMCIENV->get_jobject(array);
 C2V_END
 
-C2V_VMENTRY(int, allocateCompileId, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci))
+C2V_VMENTRY(int, allocateCompileId, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci))
   HandleMark hm;
-  ResourceMark rm;
-  if (JNIHandles::resolve(jvmci_method) == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+  if (jvmci_method == NULL) {
+    JVMCI_THROW_0(NullPointerException);
   }
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   if (entry_bci >= method->code_size() || entry_bci < -1) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Unexpected bci %d", entry_bci));
+    JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Unexpected bci %d", entry_bci));
   }
   return CompileBroker::assign_compile_id_unlocked(THREAD, method, entry_bci);
 C2V_END
 
 
-C2V_VMENTRY(jboolean, isMature, (JNIEnv*, jobject, jlong metaspace_method_data))
-  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+C2V_VMENTRY(jboolean, isMature, (JNIEnv* env, jobject, jlong metaspace_method_data))
+  MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data);
   return mdo != NULL && mdo->is_mature();
 C2V_END
 
-C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv*, jobject, jobject jvmci_method, int entry_bci, int comp_level))
-  Method* method = CompilerToVM::asMethod(jvmci_method);
+C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci, int comp_level))
+  Method* method = JVMCIENV->asMethod(jvmci_method);
   return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
 C2V_END
 
-C2V_VMENTRY(jobject, getSymbol, (JNIEnv*, jobject, jlong symbol))
-  Handle sym = java_lang_String::create_from_symbol((Symbol*)(address)symbol, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, sym());
+C2V_VMENTRY(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol))
+  JVMCIObject sym = JVMCIENV->create_string((Symbol*)(address)symbol, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(sym);
 C2V_END
 
-bool matches(jobjectArray methods, Method* method) {
+bool matches(jobjectArray methods, Method* method, JVMCIEnv* JVMCIENV) {
   objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
 
   for (int i = 0; i < methods_oop->length(); i++) {
     oop resolved = methods_oop->obj_at(i);
-    if (resolved->is_a(HotSpotResolvedJavaMethodImpl::klass()) && CompilerToVM::asMethod(resolved) == method) {
+    if ((resolved->klass() == HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass()) && HotSpotJVMCI::asMethod(JVMCIENV, resolved) == method) {
       return true;
     }
   }
@@ -1037,18 +1099,21 @@
   JavaCalls::call(result, method, args, CHECK);
 }
 
-C2V_VMENTRY(jobject, iterateFrames, (JNIEnv*, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))
-  ResourceMark rm;
+C2V_VMENTRY(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))
 
   if (!thread->has_last_Java_frame()) {
     return NULL;
   }
   Handle visitor(THREAD, JNIHandles::resolve_non_null(visitor_handle));
-  Handle frame_reference = HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
-  HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
+
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "getNextStackFrame is only supported for HotSpot stack walking");
+  }
+
+  HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
+  Handle frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
 
   StackFrameStream fst(thread);
-
   jobjectArray methods = initial_methods;
 
   int frame_number = 0;
@@ -1062,7 +1127,7 @@
       if (vf->is_compiled_frame()) {
         // compiled method frame
         compiledVFrame* cvf = compiledVFrame::cast(vf);
-        if (methods == NULL || matches(methods, cvf->method())) {
+        if (methods == NULL || matches(methods, cvf->method(), JVMCIENV)) {
           if (initialSkip > 0) {
             initialSkip--;
           } else {
@@ -1096,29 +1161,29 @@
                   array->bool_at_put(i, true);
                 }
               }
-              HotSpotStackFrameReference::set_localIsVirtual(frame_reference, array());
+              HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), array());
             } else {
-              HotSpotStackFrameReference::set_localIsVirtual(frame_reference, NULL);
+              HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), NULL);
             }
 
             locals = cvf->locals();
-            HotSpotStackFrameReference::set_bci(frame_reference, cvf->bci());
-            oop method = CompilerToVM::get_jvmci_method(cvf->method(), CHECK_NULL);
-            HotSpotStackFrameReference::set_method(frame_reference, method);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_bci(JVMCIENV, frame_reference(), cvf->bci());
+            JVMCIObject method = JVMCIENV->get_jvmci_method(cvf->method(), JVMCI_CHECK_NULL);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_method(JVMCIENV, frame_reference(), JNIHandles::resolve(method.as_jobject()));
           }
         }
       } else if (vf->is_interpreted_frame()) {
         // interpreted method frame
         interpretedVFrame* ivf = interpretedVFrame::cast(vf);
-        if (methods == NULL || matches(methods, ivf->method())) {
+        if (methods == NULL || matches(methods, ivf->method(), JVMCIENV)) {
           if (initialSkip > 0) {
             initialSkip--;
           } else {
             locals = ivf->locals();
-            HotSpotStackFrameReference::set_bci(frame_reference, ivf->bci());
-            oop method = CompilerToVM::get_jvmci_method(ivf->method(), CHECK_NULL);
-            HotSpotStackFrameReference::set_method(frame_reference, method);
-            HotSpotStackFrameReference::set_localIsVirtual(frame_reference, NULL);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_bci(JVMCIENV, frame_reference(), ivf->bci());
+            JVMCIObject method = JVMCIENV->get_jvmci_method(ivf->method(), JVMCI_CHECK_NULL);
+            HotSpotJVMCI::HotSpotStackFrameReference::set_method(JVMCIENV, frame_reference(), JNIHandles::resolve(method.as_jobject()));
+            HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), NULL);
           }
         }
       }
@@ -1126,9 +1191,9 @@
       // locals != NULL means that we found a matching frame and result is already partially initialized
       if (locals != NULL) {
         methods = match_methods;
-        HotSpotStackFrameReference::set_compilerToVM(frame_reference, JNIHandles::resolve(compilerToVM));
-        HotSpotStackFrameReference::set_stackPointer(frame_reference, (jlong) fst.current()->sp());
-        HotSpotStackFrameReference::set_frameNumber(frame_reference, frame_number);
+        HotSpotJVMCI::HotSpotStackFrameReference::set_compilerToVM(JVMCIENV, frame_reference(), JNIHandles::resolve(compilerToVM));
+        HotSpotJVMCI::HotSpotStackFrameReference::set_stackPointer(JVMCIENV, frame_reference(), (jlong) fst.current()->sp());
+        HotSpotJVMCI::HotSpotStackFrameReference::set_frameNumber(JVMCIENV, frame_reference(), frame_number);
 
         // initialize the locals array
         objArrayOop array_oop = oopFactory::new_objectArray(locals->size(), CHECK_NULL);
@@ -1139,20 +1204,20 @@
             array->obj_at_put(i, locals->at(i)->get_obj()());
           }
         }
-        HotSpotStackFrameReference::set_locals(frame_reference, array());
-        HotSpotStackFrameReference::set_objectsMaterialized(frame_reference, JNI_FALSE);
+        HotSpotJVMCI::HotSpotStackFrameReference::set_locals(JVMCIENV, frame_reference(), array());
+        HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, frame_reference(), JNI_FALSE);
 
         JavaValue result(T_OBJECT);
         JavaCallArguments args(visitor);
         args.push_oop(frame_reference);
-        call_interface(&result, SystemDictionary::InspectedFrameVisitor_klass(), vmSymbols::visitFrame_name(), vmSymbols::visitFrame_signature(), &args, CHECK_NULL);
+        call_interface(&result, HotSpotJVMCI::InspectedFrameVisitor::klass(), vmSymbols::visitFrame_name(), vmSymbols::visitFrame_signature(), &args, CHECK_NULL);
         if (result.get_jobject() != NULL) {
           return JNIHandles::make_local(thread, (oop) result.get_jobject());
         }
         assert(initialSkip == 0, "There should be no match before initialSkip == 0");
-        if (HotSpotStackFrameReference::objectsMaterialized(frame_reference) == JNI_TRUE) {
+        if (HotSpotJVMCI::HotSpotStackFrameReference::objectsMaterialized(JVMCIENV, frame_reference()) == JNI_TRUE) {
           // the frame has been deoptimized, we need to re-synchronize the frame and vframe
-          intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(frame_reference);
+          intptr_t* stack_pointer = (intptr_t*) HotSpotJVMCI::HotSpotStackFrameReference::stackPointer(JVMCIENV, frame_reference());
           fst = StackFrameStream(thread);
           while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
             fst.next();
@@ -1172,8 +1237,8 @@
             assert(vf->is_compiled_frame(), "Wrong frame type");
           }
         }
-        frame_reference = HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
-        HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
+        frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
+        HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
       }
 
       if (vf->is_top()) {
@@ -1195,16 +1260,16 @@
   return NULL;
 C2V_END
 
-C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   CallInfo callInfo;
   LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokedynamic, CHECK);
   ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
   cp_cache_entry->set_dynamic_call(cp, callInfo);
 C2V_END
 
-C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* holder = cp->klass_ref_at(index, CHECK);
   Symbol* name = cp->name_ref_at(index);
   if (MethodHandles::is_signature_polymorphic_name(holder, name)) {
@@ -1215,8 +1280,8 @@
   }
 C2V_END
 
-C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
-  constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
+C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+  constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
   if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) {
     // MethodHandle.invoke* --> LambdaForm?
@@ -1256,16 +1321,16 @@
 C2V_END
 
 
-C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv*, jobject))
-  objArrayHandle holders = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), 2, CHECK_NULL);
-  Handle mh = java_lang_String::create_from_str("Ljava/lang/invoke/MethodHandle;", CHECK_NULL);
-  Handle vh = java_lang_String::create_from_str("Ljava/lang/invoke/VarHandle;", CHECK_NULL);
-  holders->obj_at_put(0, mh());
-  holders->obj_at_put(1, vh());
-  return JNIHandles::make_local(THREAD, holders());
+C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject))
+  JVMCIObjectArray holders = JVMCIENV->new_String_array(2, JVMCI_CHECK_NULL);
+  JVMCIObject mh = JVMCIENV->create_string("Ljava/lang/invoke/MethodHandle;", JVMCI_CHECK_NULL);
+  JVMCIObject vh = JVMCIENV->create_string("Ljava/lang/invoke/VarHandle;", JVMCI_CHECK_NULL);
+  JVMCIENV->put_object_at(holders, 0, mh);
+  JVMCIENV->put_object_at(holders, 1, vh);
+  return JVMCIENV->get_jobject(holders);
 C2V_END
 
-C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject))
+C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv* env, jobject))
   //see compute_recording_non_safepoints in debugInfroRec.cpp
   if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
     return true;
@@ -1274,28 +1339,31 @@
 C2V_END
 
 // public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
-C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame, bool invalidate))
-  ResourceMark rm;
-
-  if (hs_frame == NULL) {
-    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
+C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_frame, bool invalidate))
+  JVMCIObject hs_frame = JVMCIENV->wrap(_hs_frame);
+  if (hs_frame.is_null()) {
+    JVMCI_THROW_MSG(NullPointerException, "stack frame is null");
   }
 
-  HotSpotStackFrameReference::klass()->initialize(CHECK);
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG(InternalError, "getNextStackFrame is only supported for HotSpot stack walking");
+  }
+
+  JVMCIENV->HotSpotStackFrameReference_initialize(JVMCI_CHECK);
 
   // look for the given stack frame
   StackFrameStream fst(thread);
-  intptr_t* stack_pointer = (intptr_t*) HotSpotStackFrameReference::stackPointer(hs_frame);
+  intptr_t* stack_pointer = (intptr_t*) JVMCIENV->get_HotSpotStackFrameReference_stackPointer(hs_frame);
   while (fst.current()->sp() != stack_pointer && !fst.is_done()) {
     fst.next();
   }
   if (fst.current()->sp() != stack_pointer) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found")
+    JVMCI_THROW_MSG(IllegalStateException, "stack frame not found");
   }
 
   if (invalidate) {
     if (!fst.current()->is_compiled_frame()) {
-      THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+      JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected");
     }
     assert(fst.current()->cb()->is_nmethod(), "nmethod expected");
     ((nmethod*) fst.current()->cb())->make_not_entrant();
@@ -1307,12 +1375,12 @@
     fstAfterDeopt.next();
   }
   if (fstAfterDeopt.current()->sp() != stack_pointer) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found after deopt")
+    JVMCI_THROW_MSG(IllegalStateException, "stack frame not found after deopt");
   }
 
   vframe* vf = vframe::new_vframe(fstAfterDeopt.current(), fstAfterDeopt.register_map(), thread);
   if (!vf->is_compiled_frame()) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
+    JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected");
   }
 
   GrowableArray<compiledVFrame*>* virtualFrames = new GrowableArray<compiledVFrame*>(10);
@@ -1325,9 +1393,9 @@
     vf = vf->sender();
   }
 
-  int last_frame_number = HotSpotStackFrameReference::frameNumber(hs_frame);
+  int last_frame_number = JVMCIENV->get_HotSpotStackFrameReference_frameNumber(hs_frame);
   if (last_frame_number >= virtualFrames->length()) {
-    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "invalid frame number")
+    JVMCI_THROW_MSG(IllegalStateException, "invalid frame number");
   }
 
   // Reallocate the non-escaping objects and restore their fields.
@@ -1381,49 +1449,50 @@
   }
 
   // all locals are materialized by now
-  HotSpotStackFrameReference::set_localIsVirtual(hs_frame, NULL);
-
+  JVMCIENV->set_HotSpotStackFrameReference_localIsVirtual(hs_frame, NULL);
   // update the locals array
-  objArrayHandle array(THREAD, HotSpotStackFrameReference::locals(hs_frame));
+  JVMCIObjectArray array = JVMCIENV->get_HotSpotStackFrameReference_locals(hs_frame);
   StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals();
   for (int i = 0; i < locals->size(); i++) {
     StackValue* var = locals->at(i);
     if (var->type() == T_OBJECT) {
-      array->obj_at_put(i, locals->at(i)->get_obj()());
+      JVMCIENV->put_object_at(array, i, HotSpotJVMCI::wrap(locals->at(i)->get_obj()()));
     }
   }
-  HotSpotStackFrameReference::set_objectsMaterialized(hs_frame, JNI_TRUE);
+  HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE);
 C2V_END
 
-C2V_VMENTRY(void, writeDebugOutput, (JNIEnv*, jobject, jbyteArray bytes, jint offset, jint length))
+C2V_VMENTRY(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length))
   if (bytes == NULL) {
-    THROW(vmSymbols::java_lang_NullPointerException());
+    JVMCI_THROW(NullPointerException);
   }
-  typeArrayOop array = (typeArrayOop) JNIHandles::resolve(bytes);
+  JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes);
 
   // Check if offset and length are non negative.
   if (offset < 0 || length < 0) {
-    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+    JVMCI_THROW(ArrayIndexOutOfBoundsException);
   }
   // Check if the range is valid.
-  if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array->length())) {
-    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
+  int array_length = JVMCIENV->get_length(array);
+  if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) {
+    JVMCI_THROW(ArrayIndexOutOfBoundsException);
   }
+  jbyte buffer[O_BUFLEN];
   while (length > 0) {
-    jbyte* start = array->byte_at_addr(offset);
-    tty->write((char*) start, MIN2(length, (jint)O_BUFLEN));
+    int copy_len = MIN2(length, (jint)O_BUFLEN);
+    JVMCIENV->copy_bytes_to(array, buffer, offset, copy_len);
+    tty->write((char*) buffer, copy_len);
     length -= O_BUFLEN;
     offset += O_BUFLEN;
   }
 C2V_END
 
-C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject))
+C2V_VMENTRY(void, flushDebugOutput, (JNIEnv* env, jobject))
   tty->flush();
 C2V_END
 
-C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv*, jobject, jlong metaspace_method_data, jint position))
-  ResourceMark rm;
-  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong metaspace_method_data, jint position))
+  MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data);
   ProfileData* profile_data = mdo->data_at(position);
   if (mdo->is_valid(profile_data)) {
     return profile_data->size_in_bytes();
@@ -1437,48 +1506,115 @@
       return profile_data->size_in_bytes();
     }
   }
-  THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position));
+  JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Invalid profile data position %d", position));
 C2V_END
 
-C2V_VMENTRY(jlong, getFingerprint, (JNIEnv*, jobject, jlong metaspace_klass))
+C2V_VMENTRY(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass))
 #if INCLUDE_AOT
-  Klass *k = CompilerToVM::asKlass(metaspace_klass);
+  Klass *k = (Klass*) (address) metaspace_klass;
   if (k->is_instance_klass()) {
     return InstanceKlass::cast(k)->get_stored_fingerprint();
   } else {
     return 0;
   }
 #else
-  THROW_MSG_0(vmSymbols::java_lang_InternalError(), "unimplemented");
+  JVMCI_THROW_MSG_0(InternalError, "unimplemented");
 #endif
 C2V_END
 
-C2V_VMENTRY(jobject, getHostClass, (JNIEnv*, jobject, jobject jvmci_type))
-  InstanceKlass* k = InstanceKlass::cast(CompilerToVM::asKlass(jvmci_type));
+C2V_VMENTRY(jobject, getHostClass, (JNIEnv* env, jobject, jobject jvmci_type))
+  InstanceKlass* k = InstanceKlass::cast(JVMCIENV->asKlass(jvmci_type));
   InstanceKlass* host = k->unsafe_anonymous_host();
   JVMCIKlassHandle handle(THREAD, host);
-  oop result = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
-  return JNIHandles::make_local(THREAD, result);
+  JVMCIObject result = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type))
+  if (jvmci_type == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  if (klass == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  if (!klass->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be instance klass", klass->external_name()));
+  }
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+
+  // Regular instance klass, fill in all local interfaces
+  int size = iklass->local_interfaces()->length();
+  JVMCIObjectArray interfaces = JVMCIENV->new_HotSpotResolvedObjectTypeImpl_array(size, JVMCI_CHECK_NULL);
+  for (int index = 0; index < size; index++) {
+    JVMCIKlassHandle klass(THREAD);
+    Klass* k = iklass->local_interfaces()->at(index);
+    klass = k;
+    JVMCIObject type = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(interfaces, index, type);
+  }
+  return JVMCIENV->get_jobject(interfaces);
 C2V_END
 
-C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame_handle))
-  if (bytecode_frame_handle == NULL) {
-    THROW_0(vmSymbols::java_lang_NullPointerException());
+C2V_VMENTRY(jobject, getComponentType, (JNIEnv* env, jobject, jobject jvmci_type))
+  if (jvmci_type == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  oop mirror = klass->java_mirror();
+  if (java_lang_Class::is_primitive(mirror) ||
+      !java_lang_Class::as_Klass(mirror)->is_array_klass()) {
+    return NULL;
   }
 
-  oop top_bytecode_frame = JNIHandles::resolve_non_null(bytecode_frame_handle);
-  oop bytecode_frame = top_bytecode_frame;
+  oop component_mirror = java_lang_Class::component_mirror(mirror);
+  if (component_mirror == NULL) {
+    return NULL;
+  }
+  Klass* component_klass = java_lang_Class::as_Klass(component_mirror);
+  if (component_klass != NULL) {
+    JVMCIKlassHandle klass_handle(THREAD);
+    klass_handle = component_klass;
+    JVMCIObject result = JVMCIENV->get_jvmci_type(klass_handle, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(result);
+  }
+  BasicType type = java_lang_Class::primitive_type(component_mirror);
+  JVMCIObject result = JVMCIENV->get_jvmci_primitive_type(type);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(void, ensureInitialized, (JNIEnv* env, jobject, jobject jvmci_type))
+  if (jvmci_type == NULL) {
+    JVMCI_THROW(NullPointerException);
+  }
+
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
+  if (klass != NULL && klass->should_be_initialized()) {
+    InstanceKlass* k = InstanceKlass::cast(klass);
+    k->initialize(CHECK);
+  }
+C2V_END
+
+C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle))
+  if (bytecode_frame_handle == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+
+  JVMCIObject top_bytecode_frame = JVMCIENV->wrap(bytecode_frame_handle);
+  JVMCIObject bytecode_frame = top_bytecode_frame;
   int size = 0;
   int callee_parameters = 0;
   int callee_locals = 0;
-  Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
-  int extra_args = method->max_stack() - BytecodeFrame::numStack(bytecode_frame);
+  Method* method = JVMCIENV->asMethod(JVMCIENV->get_BytecodePosition_method(bytecode_frame));
+  int extra_args = method->max_stack() - JVMCIENV->get_BytecodeFrame_numStack(bytecode_frame);
 
-  while (bytecode_frame != NULL) {
-    int locks = BytecodeFrame::numLocks(bytecode_frame);
-    int temps = BytecodeFrame::numStack(bytecode_frame);
-    bool is_top_frame = (bytecode_frame == top_bytecode_frame);
-    Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
+  while (bytecode_frame.is_non_null()) {
+    int locks = JVMCIENV->get_BytecodeFrame_numLocks(bytecode_frame);
+    int temps = JVMCIENV->get_BytecodeFrame_numStack(bytecode_frame);
+    bool is_top_frame = (JVMCIENV->equals(bytecode_frame, top_bytecode_frame));
+    Method* method = JVMCIENV->asMethod(JVMCIENV->get_BytecodePosition_method(bytecode_frame));
 
     int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(),
                                                                  temps + callee_parameters,
@@ -1492,48 +1628,652 @@
     callee_parameters = method->size_of_parameters();
     callee_locals = method->max_locals();
     extra_args = 0;
-    bytecode_frame = BytecodePosition::caller(bytecode_frame);
+    bytecode_frame = JVMCIENV->get_BytecodePosition_caller(bytecode_frame);
   }
   return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord;
 C2V_END
 
-C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_handle))
-  Handle lambda_form(THREAD, JNIHandles::resolve_non_null(lambda_form_handle));
+C2V_VMENTRY(void, compileToBytecode, (JNIEnv* env, jobject, jobject lambda_form_handle))
+  Handle lambda_form = JVMCIENV->asConstant(JVMCIENV->wrap(lambda_form_handle), JVMCI_CHECK);
   if (lambda_form->is_a(SystemDictionary::LambdaForm_klass())) {
     TempNewSymbol compileToBytecode = SymbolTable::new_symbol("compileToBytecode", CHECK);
     JavaValue result(T_VOID);
     JavaCalls::call_special(&result, lambda_form, SystemDictionary::LambdaForm_klass(), compileToBytecode, vmSymbols::void_method_signature(), CHECK);
   } else {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-                err_msg("Unexpected type: %s", lambda_form->klass()->external_name()));
+    JVMCI_THROW_MSG(IllegalArgumentException,
+                    err_msg("Unexpected type: %s", lambda_form->klass()->external_name()))
   }
 C2V_END
 
+C2V_VMENTRY(int, getIdentityHashCode, (JNIEnv* env, jobject, jobject object))
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
+  return obj->identity_hash();
+C2V_END
+
+C2V_VMENTRY(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object))
+  Handle str = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
+  if (!java_lang_String::is_instance(str())) {
+    return false;
+  }
+  int len;
+  jchar* name = java_lang_String::as_unicode_string(str(), len, CHECK_0);
+  return (StringTable::lookup(name, len) != NULL);
+C2V_END
+
+
+C2V_VMENTRY(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle box = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL);
+  BasicType type = java_lang_boxing_object::basic_type(box());
+  jvalue result;
+  if (java_lang_boxing_object::get_value(box(), &result) == T_ILLEGAL) {
+    return NULL;
+  }
+  JVMCIObject boxResult = JVMCIENV->create_box(type, &result, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(boxResult);
+C2V_END
+
+C2V_VMENTRY(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  JVMCIObject box = JVMCIENV->wrap(object);
+  BasicType type = JVMCIENV->get_box_type(box);
+  if (type == T_ILLEGAL) {
+    return NULL;
+  }
+  jvalue value = JVMCIENV->get_boxed_value(type, box);
+  JavaValue box_result(T_OBJECT);
+  JavaCallArguments jargs;
+  Klass* box_klass = NULL;
+  Symbol* box_signature = NULL;
+#define BOX_CASE(bt, v, argtype, name)           \
+  case bt: \
+    jargs.push_##argtype(value.v); \
+    box_klass = SystemDictionary::name##_klass(); \
+    box_signature = vmSymbols::name##_valueOf_signature(); \
+    break
+
+  switch (type) {
+    BOX_CASE(T_BOOLEAN, z, int, Boolean);
+    BOX_CASE(T_BYTE, b, int, Byte);
+    BOX_CASE(T_CHAR, c, int, Character);
+    BOX_CASE(T_SHORT, s, int, Short);
+    BOX_CASE(T_INT, i, int, Integer);
+    BOX_CASE(T_LONG, j, long, Long);
+    BOX_CASE(T_FLOAT, f, float, Float);
+    BOX_CASE(T_DOUBLE, d, double, Double);
+    default:
+      ShouldNotReachHere();
+  }
+#undef BOX_CASE
+
+  JavaCalls::call_static(&box_result,
+                         box_klass,
+                         vmSymbols::valueOf_name(),
+                         box_signature, &jargs, CHECK_NULL);
+  oop hotspot_box = (oop) box_result.get_jobject();
+  JVMCIObject result = JVMCIENV->get_object_constant(hotspot_box, false);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, jobject holder))
+  if (holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = JVMCIENV->asKlass(holder);
+  if (!klass->is_instance_klass()) {
+    JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobjectArray(methods);
+  }
+
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  // Ensure class is linked
+  iklass->link_class(CHECK_NULL);
+
+  GrowableArray<Method*> constructors_array;
+  for (int i = 0; i < iklass->methods()->length(); i++) {
+    Method* m = iklass->methods()->at(i);
+    if (m->is_initializer() && !m->is_static()) {
+      constructors_array.append(m);
+    }
+  }
+  JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(constructors_array.length(), JVMCI_CHECK_NULL);
+  for (int i = 0; i < constructors_array.length(); i++) {
+    JVMCIObject method = JVMCIENV->get_jvmci_method(constructors_array.at(i), JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(methods, i, method);
+  }
+  return JVMCIENV->get_jobjectArray(methods);
+C2V_END
+
+C2V_VMENTRY(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobject holder))
+  if (holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = JVMCIENV->asKlass(holder);
+  if (!klass->is_instance_klass()) {
+    JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobjectArray(methods);
+  }
+
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  // Ensure class is linked
+  iklass->link_class(CHECK_NULL);
+
+  GrowableArray<Method*> methods_array;
+  for (int i = 0; i < iklass->methods()->length(); i++) {
+    Method* m = iklass->methods()->at(i);
+    if (!m->is_initializer() && !m->is_overpass()) {
+      methods_array.append(m);
+    }
+  }
+  JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(methods_array.length(), JVMCI_CHECK_NULL);
+  for (int i = 0; i < methods_array.length(); i++) {
+    JVMCIObject method = JVMCIENV->get_jvmci_method(methods_array.at(i), JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(methods, i, method);
+  }
+  return JVMCIENV->get_jobjectArray(methods);
+C2V_END
+
+C2V_VMENTRY(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile))
+  if (object == NULL || field == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  JVMCIObject field_object = JVMCIENV->wrap(field);
+  JVMCIObject java_type = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_type(field_object);
+  int modifiers = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_modifiers(field_object);
+  Klass* holder = JVMCIENV->asKlass(JVMCIENV->get_HotSpotResolvedJavaFieldImpl_holder(field_object));
+  if (!holder->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Holder %s must be instance klass", holder->external_name()));
+  }
+  InstanceKlass* ik = InstanceKlass::cast(holder);
+  BasicType constant_type;
+  if (JVMCIENV->isa_HotSpotResolvedPrimitiveType(java_type)) {
+    constant_type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(java_type), JVMCI_CHECK_NULL);
+  } else {
+    constant_type = T_OBJECT;
+  }
+  int displacement = JVMCIENV->get_HotSpotResolvedJavaFieldImpl_offset(field_object);
+  fieldDescriptor fd;
+  if (!ik->find_local_field_from_offset(displacement, (modifiers & JVM_ACC_STATIC) != 0, &fd)) {
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Can't find field with displacement %d", displacement));
+  }
+  JVMCIObject base = JVMCIENV->wrap(object);
+  Handle obj;
+  if (JVMCIENV->isa_HotSpotObjectConstantImpl(base)) {
+    obj = JVMCIENV->asConstant(base, JVMCI_CHECK_NULL);
+  } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base)) {
+    Klass* klass = JVMCIENV->asKlass(base);
+    obj = Handle(THREAD, klass->java_mirror());
+  } else {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                         err_msg("Unexpected type: %s", JVMCIENV->klass_name(base)));
+  }
+  jlong value = 0;
+  JVMCIObject kind;
+  switch (constant_type) {
+    case T_OBJECT: {
+      oop object = is_volatile ? obj->obj_field_acquire(displacement) : obj->obj_field(displacement);
+      JVMCIObject result = JVMCIENV->get_object_constant(object);
+      if (result.is_null()) {
+        return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
+      }
+      return JVMCIENV->get_jobject(result);
+    }
+    case T_FLOAT: {
+      float f = is_volatile ? obj->float_field_acquire(displacement) : obj->float_field(displacement);
+      JVMCIObject result = JVMCIENV->call_JavaConstant_forFloat(f, JVMCI_CHECK_NULL);
+      return JVMCIENV->get_jobject(result);
+    }
+    case T_DOUBLE: {
+      double f = is_volatile ? obj->double_field_acquire(displacement) : obj->double_field(displacement);
+      JVMCIObject result = JVMCIENV->call_JavaConstant_forDouble(f, JVMCI_CHECK_NULL);
+      return JVMCIENV->get_jobject(result);
+    }
+    case T_BOOLEAN: value = is_volatile ? obj->bool_field_acquire(displacement) : obj->bool_field(displacement); break;
+    case T_BYTE: value = is_volatile ? obj->byte_field_acquire(displacement) : obj->byte_field(displacement); break;
+    case T_SHORT: value = is_volatile ? obj->short_field_acquire(displacement) : obj->short_field(displacement); break;
+    case T_CHAR: value = is_volatile ? obj->char_field_acquire(displacement) : obj->char_field(displacement); break;
+    case T_INT: value = is_volatile ? obj->int_field_acquire(displacement) : obj->int_field(displacement); break;
+    case T_LONG: value = is_volatile ? obj->long_field_acquire(displacement) : obj->long_field(displacement); break;
+    default:
+      ShouldNotReachHere();
+  }
+  JVMCIObject result = JVMCIENV->call_PrimitiveConstant_forTypeChar(type2char(constant_type), value, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+C2V_VMENTRY(jboolean, isInstance, (JNIEnv* env, jobject, jobject holder, jobject object))
+  if (object == NULL || holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
+  Klass* klass = JVMCIENV->asKlass(JVMCIENV->wrap(holder));
+  return obj->is_a(klass);
+C2V_END
+
+C2V_VMENTRY(jboolean, isAssignableFrom, (JNIEnv* env, jobject, jobject holder, jobject otherHolder))
+  if (holder == NULL || otherHolder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = JVMCIENV->asKlass(JVMCIENV->wrap(holder));
+  Klass* otherKlass = JVMCIENV->asKlass(JVMCIENV->wrap(otherHolder));
+  return otherKlass->is_subtype_of(klass);
+C2V_END
+
+C2V_VMENTRY(jboolean, isTrustedForIntrinsics, (JNIEnv* env, jobject, jobject holder))
+  if (holder == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  InstanceKlass* ik = InstanceKlass::cast(JVMCIENV->asKlass(JVMCIENV->wrap(holder)));
+  if (ik->class_loader_data()->is_builtin_class_loader_data()) {
+    return true;
+  }
+  return false;
+C2V_END
+
+C2V_VMENTRY(jobject, asJavaType, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL);
+  if (java_lang_Class::is_instance(obj())) {
+    if (java_lang_Class::is_primitive(obj())) {
+      JVMCIObject type = JVMCIENV->get_jvmci_primitive_type(java_lang_Class::primitive_type(obj()));
+      return JVMCIENV->get_jobject(type);
+    }
+    Klass* klass = java_lang_Class::as_Klass(obj());
+    JVMCIKlassHandle klass_handle(THREAD);
+    klass_handle = klass;
+    JVMCIObject type = JVMCIENV->get_jvmci_type(klass_handle, JVMCI_CHECK_NULL);
+    return JVMCIENV->get_jobject(type);
+  }
+  return NULL;
+C2V_END
+
+
+C2V_VMENTRY(jobject, asString, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL);
+  const char* str = java_lang_String::as_utf8_string(obj());
+  JVMCIObject result = JVMCIENV->create_string(str, JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+
+C2V_VMENTRY(jboolean, equals, (JNIEnv* env, jobject, jobject x, jlong xHandle, jobject y, jlong yHandle))
+  if (x == NULL || y == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  return JVMCIENV->resolve_handle(xHandle) == JVMCIENV->resolve_handle(yHandle);
+C2V_END
+
+C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv* env, jobject, jobject object))
+  if (object == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  JVMCIObject base_object = JVMCIENV->wrap(object);
+  Handle mirror;
+  if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
+    mirror = Handle(THREAD, JVMCIENV->asKlass(base_object)->java_mirror());
+  } else if (JVMCIENV->isa_HotSpotResolvedPrimitiveType(base_object)) {
+    mirror = JVMCIENV->asConstant(JVMCIENV->get_HotSpotResolvedPrimitiveType_mirror(base_object), JVMCI_CHECK_NULL);
+  } else {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+                         err_msg("Unexpected type: %s", JVMCIENV->klass_name(base_object)));
+ }
+  JVMCIObject result = JVMCIENV->get_object_constant(mirror());
+  return JVMCIENV->get_jobject(result);
+C2V_END
+
+
+C2V_VMENTRY(jint, getArrayLength, (JNIEnv* env, jobject, jobject x))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  if (xobj->klass()->is_array_klass()) {
+    return arrayOop(xobj())->length();
+  }
+  return -1;
+ C2V_END
+
+
+C2V_VMENTRY(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_NULL);
+  if (xobj->klass()->is_array_klass()) {
+    arrayOop array = arrayOop(xobj());
+    BasicType element_type = ArrayKlass::cast(array->klass())->element_type();
+    if (index < 0 || index >= array->length()) {
+      return NULL;
+    }
+    JVMCIObject result;
+
+    if (element_type == T_OBJECT) {
+      result = JVMCIENV->get_object_constant(objArrayOop(xobj())->obj_at(index));
+      if (result.is_null()) {
+        result = JVMCIENV->get_JavaConstant_NULL_POINTER();
+      }
+    } else {
+      jvalue value;
+      switch (element_type) {
+        case T_DOUBLE:        value.d = typeArrayOop(xobj())->double_at(index);        break;
+        case T_FLOAT:         value.f = typeArrayOop(xobj())->float_at(index);         break;
+        case T_LONG:          value.j = typeArrayOop(xobj())->long_at(index);          break;
+        case T_INT:           value.i = typeArrayOop(xobj())->int_at(index);            break;
+        case T_SHORT:         value.s = typeArrayOop(xobj())->short_at(index);          break;
+        case T_CHAR:          value.c = typeArrayOop(xobj())->char_at(index);           break;
+        case T_BYTE:          value.b = typeArrayOop(xobj())->byte_at(index);           break;
+        case T_BOOLEAN:       value.z = typeArrayOop(xobj())->byte_at(index) & 1;       break;
+        default:              ShouldNotReachHere();
+      }
+      result = JVMCIENV->create_box(element_type, &value, JVMCI_CHECK_NULL);
+    }
+    assert(!result.is_null(), "must have a value");
+    return JVMCIENV->get_jobject(result);
+  }
+  return NULL;;
+C2V_END
+
+
+C2V_VMENTRY(jint, arrayBaseOffset, (JNIEnv* env, jobject, jobject kind))
+  if (kind == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->wrap(kind), JVMCI_CHECK_0);
+  return arrayOopDesc::header_size(type) * HeapWordSize;
+C2V_END
+
+C2V_VMENTRY(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind))
+  if (kind == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->wrap(kind), JVMCI_CHECK_0);
+  return type2aelembytes(type);
+C2V_END
+
+C2V_VMENTRY(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->byte_field(displacement);
+}
+
+C2V_VMENTRY(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->short_field(displacement);
+}
+
+C2V_VMENTRY(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->int_field(displacement);
+}
+
+C2V_VMENTRY(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  return xobj->long_field(displacement);
+}
+
+C2V_VMENTRY(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement))
+  if (x == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0);
+  oop res = xobj->obj_field(displacement);
+  JVMCIObject result = JVMCIENV->get_object_constant(res);
+  return JVMCIENV->get_jobject(result);
+}
+
+C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h))
+  jobject handle = (jobject)(address)h;
+  if (handle != NULL) {
+    assert(JVMCI::is_global_handle(handle), "Invalid delete of global JNI handle");
+    *((oop*)handle) = NULL; // Mark the handle as deleted, allocate will reuse it
+  }
+}
+
+C2V_VMENTRY(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror))
+  if (!UseJVMCINativeLibrary) {
+    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)");
+  }
+  if (!JVMCIENV->is_hotspot()) {
+    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "Cannot call registerNativeMethods from JVMCI shared library");
+  }
+  void* shared_library = JVMCIEnv::get_shared_library_handle();
+  if (shared_library == NULL) {
+    // Ensure the JVMCI shared library runtime is initialized.
+    JVMCIEnv __peer_jvmci_env__(false, __FILE__, __LINE__);
+    JVMCIEnv* peerEnv = &__peer_jvmci_env__;
+    HandleMark hm;
+    JVMCIRuntime* runtime = JVMCI::compiler_runtime();
+    JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv);
+    if (peerEnv->has_pending_exception()) {
+      peerEnv->describe_pending_exception(true);
+      JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime");
+    }
+    shared_library = JVMCIEnv::get_shared_library_handle();
+  }
+
+  if (shared_library == NULL) {
+    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is unavailable");
+  }
+
+  if (mirror == NULL) {
+    JVMCI_THROW_0(NullPointerException);
+  }
+  Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
+  if (klass == NULL || !klass->is_instance_klass()) {
+    JVMCI_THROW_MSG_0(IllegalArgumentException, "clazz is for primitive type");
+  }
+
+  InstanceKlass* iklass = InstanceKlass::cast(klass);
+  for (int i = 0; i < iklass->methods()->length(); i++) {
+    Method* method = iklass->methods()->at(i);
+    if (method->is_native()) {
+
+      // Compute argument size
+      int args_size = 1                             // JNIEnv
+                    + (method->is_static() ? 1 : 0) // class for static methods
+                    + method->size_of_parameters(); // actual parameters
+
+      // 1) Try JNI short style
+      stringStream st;
+      char* pure_name = NativeLookup::pure_jni_name(method);
+      os::print_jni_name_prefix_on(&st, args_size);
+      st.print_raw(pure_name);
+      os::print_jni_name_suffix_on(&st, args_size);
+      char* jni_name = st.as_string();
+
+      address entry = (address) os::dll_lookup(shared_library, jni_name);
+      if (entry == NULL) {
+        // 2) Try JNI long style
+        st.reset();
+        char* long_name = NativeLookup::long_jni_name(method);
+        os::print_jni_name_prefix_on(&st, args_size);
+        st.print_raw(pure_name);
+        st.print_raw(long_name);
+        os::print_jni_name_suffix_on(&st, args_size);
+        jni_name = st.as_string();
+        entry = (address) os::dll_lookup(shared_library, jni_name);
+      }
+      if (entry == NULL) {
+        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, method->name_and_sig_as_C_string());
+      }
+      if (method->has_native_function() && entry != method->native_function()) {
+        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("Cannot overwrite existing native implementation for %s",
+            method->name_and_sig_as_C_string()));
+      }
+      method->set_native_function(entry, Method::native_bind_event_is_interesting);
+      if (PrintJNIResolving) {
+        tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]",
+          method->method_holder()->external_name(),
+          method->name()->as_C_string());
+      }
+    }
+  }
+
+  JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm();
+  JVMCIPrimitiveArray result = JVMCIENV->new_longArray(4, JVMCI_CHECK_NULL);
+  JVMCIENV->put_long_at(result, 0, (jlong) (address) javaVM);
+  JVMCIENV->put_long_at(result, 1, (jlong) (address) javaVM->functions->reserved0);
+  JVMCIENV->put_long_at(result, 2, (jlong) (address) javaVM->functions->reserved1);
+  JVMCIENV->put_long_at(result, 3, (jlong) (address) javaVM->functions->reserved2);
+  return (jlongArray) JVMCIENV->get_jobject(result);
+}
+
+C2V_VMENTRY(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle))
+  if (obj_handle == NULL) {
+    return 0L;
+  }
+  JVMCIEnv __peer_jvmci_env__(!JVMCIENV->is_hotspot(), __FILE__, __LINE__);
+  JVMCIEnv* peerEnv = &__peer_jvmci_env__;
+  JVMCIEnv* thisEnv = JVMCIENV;
+
+  JVMCIObject obj = thisEnv->wrap(obj_handle);
+  JVMCIObject result;
+  if (thisEnv->isa_HotSpotResolvedJavaMethodImpl(obj)) {
+    Method* method = thisEnv->asMethod(obj);
+    result = peerEnv->get_jvmci_method(method, JVMCI_CHECK_0);
+  } else if (thisEnv->isa_HotSpotResolvedObjectTypeImpl(obj)) {
+    Klass* klass = thisEnv->asKlass(obj);
+    JVMCIKlassHandle klass_handle(THREAD);
+    klass_handle = klass;
+    result = peerEnv->get_jvmci_type(klass_handle, JVMCI_CHECK_0);
+  } else if (thisEnv->isa_HotSpotResolvedPrimitiveType(obj)) {
+    BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(obj), JVMCI_CHECK_0);
+    result = peerEnv->get_jvmci_primitive_type(type);
+  } else if (thisEnv->isa_IndirectHotSpotObjectConstantImpl(obj) ||
+             thisEnv->isa_DirectHotSpotObjectConstantImpl(obj)) {
+    Handle constant = thisEnv->asConstant(obj, JVMCI_CHECK_0);
+    result = peerEnv->get_object_constant(constant());
+  } else if (thisEnv->isa_HotSpotNmethod(obj)) {
+    nmethod* nm = thisEnv->asNmethod(obj);
+    if (nm != NULL) {
+      JVMCINMethodData* data = nm->jvmci_nmethod_data();
+      if (data != NULL) {
+        if (peerEnv->is_hotspot()) {
+          // Only the mirror in the HotSpot heap is accessible
+          // through JVMCINMethodData
+          oop nmethod_mirror = data->get_nmethod_mirror(nm);
+          if (nmethod_mirror != NULL) {
+            result = HotSpotJVMCI::wrap(nmethod_mirror);
+          }
+        }
+      }
+    }
+    if (result.is_null()) {
+      JVMCIObject methodObject = thisEnv->get_HotSpotNmethod_method(obj);
+      methodHandle mh = thisEnv->asMethod(methodObject);
+      jboolean isDefault = thisEnv->get_HotSpotNmethod_isDefault(obj);
+      jlong compileIdSnapshot = thisEnv->get_HotSpotNmethod_compileIdSnapshot(obj);
+      JVMCIObject name_string = thisEnv->get_InstalledCode_name(obj);
+      const char* cstring = name_string.is_null() ? NULL : thisEnv->as_utf8_string(name_string);
+      // Create a new HotSpotNmethod instance in the peer runtime
+      result = peerEnv->new_HotSpotNmethod(mh(), cstring, isDefault, compileIdSnapshot, JVMCI_CHECK_0);
+      if (nm == NULL) {
+        // nmethod must have been unloaded
+      } else {
+        // Link the new HotSpotNmethod to the nmethod
+        peerEnv->initialize_installed_code(result, nm, JVMCI_CHECK_0);
+        // Only HotSpotNmethod instances in the HotSpot heap are tracked directly by the runtime.
+        if (peerEnv->is_hotspot()) {
+          JVMCINMethodData* data = nm->jvmci_nmethod_data();
+          if (data == NULL) {
+            JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot set HotSpotNmethod mirror for default nmethod");
+          }
+          if (data->get_nmethod_mirror(nm) != NULL) {
+            JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot overwrite existing HotSpotNmethod mirror for nmethod");
+          }
+          oop nmethod_mirror = HotSpotJVMCI::resolve(result);
+          data->set_nmethod_mirror(nm, nmethod_mirror);
+        }
+      }
+    }
+  } else {
+    JVMCI_THROW_MSG_0(IllegalArgumentException,
+                err_msg("Cannot translate object of type: %s", thisEnv->klass_name(obj)));
+  }
+  return (jlong) peerEnv->make_global(result).as_jobject();
+}
+
+C2V_VMENTRY(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle))
+  if (obj_handle == 0L) {
+    return NULL;
+  }
+  jobject global_handle = (jobject) obj_handle;
+  JVMCIObject global_handle_obj = JVMCIENV->wrap((jobject) obj_handle);
+  jobject result = JVMCIENV->make_local(global_handle_obj).as_jobject();
+
+  JVMCIENV->destroy_global(global_handle_obj);
+  return result;
+}
+
+C2V_VMENTRY(void, updateHotSpotNmethod, (JNIEnv* env, jobject, jobject code_handle))
+  JVMCIObject code = JVMCIENV->wrap(code_handle);
+  // Execute this operation for the side effect of updating the InstalledCode state
+  JVMCIENV->asNmethod(code);
+}
+
+C2V_VMENTRY(jbyteArray, getCode, (JNIEnv* env, jobject, jobject code_handle))
+  JVMCIObject code = JVMCIENV->wrap(code_handle);
+  CodeBlob* cb = JVMCIENV->asCodeBlob(code);
+  if (cb == NULL) {
+    return NULL;
+  }
+  int code_size = cb->code_size();
+  JVMCIPrimitiveArray result = JVMCIENV->new_byteArray(code_size, JVMCI_CHECK_NULL);
+  JVMCIENV->copy_bytes_from((jbyte*) cb->code_begin(), result, 0, code_size);
+  return JVMCIENV->get_jbyteArray(result);
+}
+
 C2V_VMENTRY(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method))
-  methodHandle m = CompilerToVM::asMethod(jvmci_method);
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  methodHandle m = JVMCIENV->asMethod(jvmci_method);
   oop executable;
   if (m->is_initializer()) {
     if (m->is_static_initializer()) {
-      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
-        "Cannot create java.lang.reflect.Method for class initializer");
+      JVMCI_THROW_MSG_NULL(IllegalArgumentException,
+          "Cannot create java.lang.reflect.Method for class initializer");
     }
     executable = Reflection::new_constructor(m, CHECK_NULL);
   } else {
     executable = Reflection::new_method(m, false, CHECK_NULL);
   }
-  return JNIHandles::make_local(thread, executable);
+  return JNIHandles::make_local(THREAD, executable);
 }
 
 C2V_VMENTRY(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index))
-  Klass* klass = CompilerToVM::asKlass(jvmci_type);
+  if (env != JavaThread::current()->jni_environment()) {
+    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
+  }
+  Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_instance_klass()) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
         err_msg("Expected non-primitive type, got %s", klass->external_name()));
   }
   InstanceKlass* iklass = InstanceKlass::cast(klass);
   Array<u2>* fields = iklass->fields();
-  if (index < 0 || index > fields->length()) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+  if (index < 0 ||index > fields->length()) {
+    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
         err_msg("Field index %d out of bounds for %s", index, klass->external_name()));
   }
   fieldDescriptor fd(iklass, index);
@@ -1541,27 +2281,90 @@
   return JNIHandles::make_local(env, reflected);
 }
 
+C2V_VMENTRY(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))
+  FailedSpeculation* head = *((FailedSpeculation**)(address) failed_speculations_address);
+  int result_length = 0;
+  for (FailedSpeculation* fs = head; fs != NULL; fs = fs->next()) {
+    result_length++;
+  }
+  int current_length = 0;
+  JVMCIObjectArray current_array = NULL;
+  if (current != NULL) {
+    current_array = JVMCIENV->wrap(current);
+    current_length = JVMCIENV->get_length(current_array);
+    if (current_length == result_length) {
+      // No new failures
+      return current;
+    }
+  }
+  JVMCIObjectArray result = JVMCIENV->new_byte_array_array(result_length, JVMCI_CHECK_NULL);
+  int result_index = 0;
+  for (FailedSpeculation* fs = head; result_index < result_length; fs = fs->next()) {
+    assert(fs != NULL, "npe");
+    JVMCIPrimitiveArray entry;
+    if (result_index < current_length) {
+      entry = (JVMCIPrimitiveArray) JVMCIENV->get_object_at(current_array, result_index);
+    } else {
+      entry = JVMCIENV->new_byteArray(fs->data_len(), JVMCI_CHECK_NULL);
+      JVMCIENV->copy_bytes_from((jbyte*) fs->data(), entry, 0, fs->data_len());
+    }
+    JVMCIENV->put_object_at(result, result_index++, entry);
+  }
+  return JVMCIENV->get_jobjectArray(result);
+}
+
+C2V_VMENTRY(jlong, getFailedSpeculationsAddress, (JNIEnv* env, jobject, jobject jvmci_method))
+  methodHandle method = JVMCIENV->asMethod(jvmci_method);
+  MethodData* method_data = method->method_data();
+  if (method_data == NULL) {
+    ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
+    method_data = MethodData::allocate(loader_data, method, CHECK_0);
+    method->set_method_data(method_data);
+  }
+  return (jlong) method_data->get_failed_speculations_address();
+}
+
+C2V_VMENTRY(void, releaseFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address))
+  FailedSpeculation::free_failed_speculations((FailedSpeculation**)(address) failed_speculations_address);
+}
+
+C2V_VMENTRY(bool, addFailedSpeculation, (JNIEnv* env, jobject, jlong failed_speculations_address, jbyteArray speculation_obj))
+  JVMCIPrimitiveArray speculation_handle = JVMCIENV->wrap(speculation_obj);
+  int speculation_len = JVMCIENV->get_length(speculation_handle);
+  char* speculation = NEW_RESOURCE_ARRAY(char, speculation_len);
+  JVMCIENV->copy_bytes_to(speculation_handle, (jbyte*) speculation, 0, speculation_len);
+  return FailedSpeculation::add_failed_speculation(NULL, (FailedSpeculation**)(address) failed_speculations_address, (address) speculation, speculation_len);
+}
+
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
 
 #define STRING                  "Ljava/lang/String;"
 #define OBJECT                  "Ljava/lang/Object;"
 #define CLASS                   "Ljava/lang/Class;"
+#define OBJECTCONSTANT          "Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;"
+#define HANDLECONSTANT          "Ljdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl;"
 #define EXECUTABLE              "Ljava/lang/reflect/Executable;"
 #define STACK_TRACE_ELEMENT     "Ljava/lang/StackTraceElement;"
 #define INSTALLED_CODE          "Ljdk/vm/ci/code/InstalledCode;"
 #define TARGET_DESCRIPTION      "Ljdk/vm/ci/code/TargetDescription;"
 #define BYTECODE_FRAME          "Ljdk/vm/ci/code/BytecodeFrame;"
+#define JAVACONSTANT            "Ljdk/vm/ci/meta/JavaConstant;"
 #define INSPECTED_FRAME_VISITOR "Ljdk/vm/ci/code/stack/InspectedFrameVisitor;"
 #define RESOLVED_METHOD         "Ljdk/vm/ci/meta/ResolvedJavaMethod;"
 #define HS_RESOLVED_METHOD      "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;"
 #define HS_RESOLVED_KLASS       "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;"
+#define HS_RESOLVED_TYPE        "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaType;"
+#define HS_RESOLVED_FIELD       "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaField;"
+#define HS_INSTALLED_CODE       "Ljdk/vm/ci/hotspot/HotSpotInstalledCode;"
+#define HS_NMETHOD              "Ljdk/vm/ci/hotspot/HotSpotNmethod;"
 #define HS_CONSTANT_POOL        "Ljdk/vm/ci/hotspot/HotSpotConstantPool;"
 #define HS_COMPILED_CODE        "Ljdk/vm/ci/hotspot/HotSpotCompiledCode;"
 #define HS_CONFIG               "Ljdk/vm/ci/hotspot/HotSpotVMConfig;"
 #define HS_METADATA             "Ljdk/vm/ci/hotspot/HotSpotMetaData;"
 #define HS_STACK_FRAME_REF      "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
 #define HS_SPECULATION_LOG      "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;"
+#define METASPACE_OBJECT        "Ljdk/vm/ci/hotspot/MetaspaceObject;"
 #define REFLECTION_EXECUTABLE   "Ljava/lang/reflect/Executable;"
 #define REFLECTION_FIELD        "Ljava/lang/reflect/Field;"
 #define METASPACE_METHOD_DATA   "J"
@@ -1578,17 +2381,18 @@
   {CC "isCompilable",                                 CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(isCompilable)},
   {CC "hasNeverInlineDirective",                      CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(hasNeverInlineDirective)},
   {CC "shouldInlineMethod",                           CC "(" HS_RESOLVED_METHOD ")Z",                                                       FN_PTR(shouldInlineMethod)},
-  {CC "lookupType",                                   CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS,                                           FN_PTR(lookupType)},
+  {CC "lookupType",                                   CC "(" STRING HS_RESOLVED_KLASS "Z)" HS_RESOLVED_TYPE,                                FN_PTR(lookupType)},
+  {CC "lookupClass",                                  CC "(" CLASS ")" HS_RESOLVED_TYPE,                                                    FN_PTR(lookupClass)},
   {CC "lookupNameInPool",                             CC "(" HS_CONSTANT_POOL "I)" STRING,                                                  FN_PTR(lookupNameInPool)},
   {CC "lookupNameAndTypeRefIndexInPool",              CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(lookupNameAndTypeRefIndexInPool)},
   {CC "lookupSignatureInPool",                        CC "(" HS_CONSTANT_POOL "I)" STRING,                                                  FN_PTR(lookupSignatureInPool)},
   {CC "lookupKlassRefIndexInPool",                    CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(lookupKlassRefIndexInPool)},
   {CC "lookupKlassInPool",                            CC "(" HS_CONSTANT_POOL "I)Ljava/lang/Object;",                                       FN_PTR(lookupKlassInPool)},
-  {CC "lookupAppendixInPool",                         CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(lookupAppendixInPool)},
+  {CC "lookupAppendixInPool",                         CC "(" HS_CONSTANT_POOL "I)" OBJECTCONSTANT,                                          FN_PTR(lookupAppendixInPool)},
   {CC "lookupMethodInPool",                           CC "(" HS_CONSTANT_POOL "IB)" HS_RESOLVED_METHOD,                                     FN_PTR(lookupMethodInPool)},
   {CC "constantPoolRemapInstructionOperandFromCache", CC "(" HS_CONSTANT_POOL "I)I",                                                        FN_PTR(constantPoolRemapInstructionOperandFromCache)},
-  {CC "resolveConstantInPool",                        CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(resolveConstantInPool)},
-  {CC "resolvePossiblyCachedConstantInPool",          CC "(" HS_CONSTANT_POOL "I)" OBJECT,                                                  FN_PTR(resolvePossiblyCachedConstantInPool)},
+  {CC "resolveConstantInPool",                        CC "(" HS_CONSTANT_POOL "I)" OBJECTCONSTANT,                                          FN_PTR(resolveConstantInPool)},
+  {CC "resolvePossiblyCachedConstantInPool",          CC "(" HS_CONSTANT_POOL "I)" OBJECTCONSTANT,                                          FN_PTR(resolvePossiblyCachedConstantInPool)},
   {CC "resolveTypeInPool",                            CC "(" HS_CONSTANT_POOL "I)" HS_RESOLVED_KLASS,                                       FN_PTR(resolveTypeInPool)},
   {CC "resolveFieldInPool",                           CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[I)" HS_RESOLVED_KLASS,              FN_PTR(resolveFieldInPool)},
   {CC "resolveInvokeDynamicInPool",                   CC "(" HS_CONSTANT_POOL "I)V",                                                        FN_PTR(resolveInvokeDynamicInPool)},
@@ -1601,20 +2405,21 @@
   {CC "hasFinalizableSubclass",                       CC "(" HS_RESOLVED_KLASS ")Z",                                                        FN_PTR(hasFinalizableSubclass)},
   {CC "getMaxCallTargetOffset",                       CC "(J)J",                                                                            FN_PTR(getMaxCallTargetOffset)},
   {CC "asResolvedJavaMethod",                         CC "(" EXECUTABLE ")" HS_RESOLVED_METHOD,                                             FN_PTR(asResolvedJavaMethod)},
-  {CC "getResolvedJavaMethod",                        CC "(Ljava/lang/Object;J)" HS_RESOLVED_METHOD,                                        FN_PTR(getResolvedJavaMethod)},
-  {CC "getConstantPool",                              CC "(Ljava/lang/Object;)" HS_CONSTANT_POOL,                                           FN_PTR(getConstantPool)},
-  {CC "getResolvedJavaType",                          CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS,                                        FN_PTR(getResolvedJavaType)},
+  {CC "getResolvedJavaMethod",                        CC "(" OBJECTCONSTANT "J)" HS_RESOLVED_METHOD,                                        FN_PTR(getResolvedJavaMethod)},
+  {CC "getConstantPool",                              CC "(" METASPACE_OBJECT ")" HS_CONSTANT_POOL,                                         FN_PTR(getConstantPool)},
+  {CC "getResolvedJavaType0",                         CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS,                                        FN_PTR(getResolvedJavaType0)},
   {CC "readConfiguration",                            CC "()[" OBJECT,                                                                      FN_PTR(readConfiguration)},
-  {CC "installCode",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG ")I",    FN_PTR(installCode)},
+  {CC "installCode",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE "J[B)I",                    FN_PTR(installCode)},
   {CC "getMetadata",                                  CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE HS_METADATA ")I",                          FN_PTR(getMetadata)},
   {CC "resetCompilationStatistics",                   CC "()V",                                                                             FN_PTR(resetCompilationStatistics)},
   {CC "disassembleCodeBlob",                          CC "(" INSTALLED_CODE ")" STRING,                                                     FN_PTR(disassembleCodeBlob)},
-  {CC "executeInstalledCode",                         CC "([" OBJECT INSTALLED_CODE ")" OBJECT,                                             FN_PTR(executeInstalledCode)},
+  {CC "executeHotSpotNmethod",                        CC "([" OBJECT HS_NMETHOD ")" OBJECT,                                                 FN_PTR(executeHotSpotNmethod)},
   {CC "getLineNumberTable",                           CC "(" HS_RESOLVED_METHOD ")[J",                                                      FN_PTR(getLineNumberTable)},
   {CC "getLocalVariableTableStart",                   CC "(" HS_RESOLVED_METHOD ")J",                                                       FN_PTR(getLocalVariableTableStart)},
   {CC "getLocalVariableTableLength",                  CC "(" HS_RESOLVED_METHOD ")I",                                                       FN_PTR(getLocalVariableTableLength)},
   {CC "reprofile",                                    CC "(" HS_RESOLVED_METHOD ")V",                                                       FN_PTR(reprofile)},
-  {CC "invalidateInstalledCode",                      CC "(" INSTALLED_CODE ")V",                                                           FN_PTR(invalidateInstalledCode)},
+  {CC "invalidateHotSpotNmethod",                     CC "(" HS_NMETHOD ")V",                                                               FN_PTR(invalidateHotSpotNmethod)},
+  {CC "readUncompressedOop",                          CC "(J)" OBJECTCONSTANT,                                                              FN_PTR(readUncompressedOop)},
   {CC "collectCounters",                              CC "()[J",                                                                            FN_PTR(collectCounters)},
   {CC "allocateCompileId",                            CC "(" HS_RESOLVED_METHOD "I)I",                                                      FN_PTR(allocateCompileId)},
   {CC "isMature",                                     CC "(" METASPACE_METHOD_DATA ")Z",                                                    FN_PTR(isMature)},
@@ -1629,10 +2434,48 @@
   {CC "getFingerprint",                               CC "(J)J",                                                                            FN_PTR(getFingerprint)},
   {CC "getHostClass",                                 CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_KLASS,                                       FN_PTR(getHostClass)},
   {CC "interpreterFrameSize",                         CC "(" BYTECODE_FRAME ")I",                                                           FN_PTR(interpreterFrameSize)},
-  {CC "compileToBytecode",                            CC "(" OBJECT ")V",                                                                   FN_PTR(compileToBytecode)},
+  {CC "compileToBytecode",                            CC "(" OBJECTCONSTANT ")V",                                                           FN_PTR(compileToBytecode)},
   {CC "getFlagValue",                                 CC "(" STRING ")" OBJECT,                                                             FN_PTR(getFlagValue)},
+  {CC "getObjectAtAddress",                           CC "(J)" OBJECT,                                                                      FN_PTR(getObjectAtAddress)},
+  {CC "getInterfaces",                                CC "(" HS_RESOLVED_KLASS ")[" HS_RESOLVED_KLASS,                                      FN_PTR(getInterfaces)},
+  {CC "getComponentType",                             CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_TYPE,                                        FN_PTR(getComponentType)},
+  {CC "ensureInitialized",                            CC "(" HS_RESOLVED_KLASS ")V",                                                        FN_PTR(ensureInitialized)},
+  {CC "getIdentityHashCode",                          CC "(" OBJECTCONSTANT ")I",                                                           FN_PTR(getIdentityHashCode)},
+  {CC "isInternedString",                             CC "(" OBJECTCONSTANT ")Z",                                                           FN_PTR(isInternedString)},
+  {CC "unboxPrimitive",                               CC "(" OBJECTCONSTANT ")" OBJECT,                                                     FN_PTR(unboxPrimitive)},
+  {CC "boxPrimitive",                                 CC "(" OBJECT ")" OBJECTCONSTANT,                                                     FN_PTR(boxPrimitive)},
+  {CC "getDeclaredConstructors",                      CC "(" HS_RESOLVED_KLASS ")[" RESOLVED_METHOD,                                        FN_PTR(getDeclaredConstructors)},
+  {CC "getDeclaredMethods",                           CC "(" HS_RESOLVED_KLASS ")[" RESOLVED_METHOD,                                        FN_PTR(getDeclaredMethods)},
+  {CC "readFieldValue",                               CC "(" HS_RESOLVED_KLASS HS_RESOLVED_FIELD "Z)" JAVACONSTANT,                         FN_PTR(readFieldValue)},
+  {CC "readFieldValue",                               CC "(" OBJECTCONSTANT HS_RESOLVED_FIELD "Z)" JAVACONSTANT,                            FN_PTR(readFieldValue)},
+  {CC "isInstance",                                   CC "(" HS_RESOLVED_KLASS OBJECTCONSTANT ")Z",                                         FN_PTR(isInstance)},
+  {CC "isAssignableFrom",                             CC "(" HS_RESOLVED_KLASS HS_RESOLVED_KLASS ")Z",                                      FN_PTR(isAssignableFrom)},
+  {CC "isTrustedForIntrinsics",                       CC "(" HS_RESOLVED_KLASS ")Z",                                                        FN_PTR(isTrustedForIntrinsics)},
+  {CC "asJavaType",                                   CC "(" OBJECTCONSTANT ")" HS_RESOLVED_TYPE,                                           FN_PTR(asJavaType)},
+  {CC "asString",                                     CC "(" OBJECTCONSTANT ")" STRING,                                                     FN_PTR(asString)},
+  {CC "equals",                                       CC "(" OBJECTCONSTANT "J" OBJECTCONSTANT "J)Z",                                       FN_PTR(equals)},
+  {CC "getJavaMirror",                                CC "(" HS_RESOLVED_TYPE ")" OBJECTCONSTANT,                                           FN_PTR(getJavaMirror)},
+  {CC "getArrayLength",                               CC "(" OBJECTCONSTANT ")I",                                                           FN_PTR(getArrayLength)},
+  {CC "readArrayElement",                             CC "(" OBJECTCONSTANT "I)Ljava/lang/Object;",                                         FN_PTR(readArrayElement)},
+  {CC "arrayBaseOffset",                              CC "(Ljdk/vm/ci/meta/JavaKind;)I",                                                    FN_PTR(arrayBaseOffset)},
+  {CC "arrayIndexScale",                              CC "(Ljdk/vm/ci/meta/JavaKind;)I",                                                    FN_PTR(arrayIndexScale)},
+  {CC "getByte",                                      CC "(" OBJECTCONSTANT "J)B",                                                          FN_PTR(getByte)},
+  {CC "getShort",                                     CC "(" OBJECTCONSTANT "J)S",                                                          FN_PTR(getShort)},
+  {CC "getInt",                                       CC "(" OBJECTCONSTANT "J)I",                                                          FN_PTR(getInt)},
+  {CC "getLong",                                      CC "(" OBJECTCONSTANT "J)J",                                                          FN_PTR(getLong)},
+  {CC "getObject",                                    CC "(" OBJECTCONSTANT "J)" OBJECTCONSTANT,                                            FN_PTR(getObject)},
+  {CC "deleteGlobalHandle",                           CC "(J)V",                                                                            FN_PTR(deleteGlobalHandle)},
+  {CC "registerNativeMethods",                        CC "(" CLASS ")[J",                                                                   FN_PTR(registerNativeMethods)},
+  {CC "translate",                                    CC "(" OBJECT ")J",                                                                   FN_PTR(translate)},
+  {CC "unhand",                                       CC "(J)" OBJECT,                                                                      FN_PTR(unhand)},
+  {CC "updateHotSpotNmethod",                         CC "(" HS_NMETHOD ")V",                                                               FN_PTR(updateHotSpotNmethod)},
+  {CC "getCode",                                      CC "(" HS_INSTALLED_CODE ")[B",                                                       FN_PTR(getCode)},
   {CC "asReflectionExecutable",                       CC "(" HS_RESOLVED_METHOD ")" REFLECTION_EXECUTABLE,                                  FN_PTR(asReflectionExecutable)},
   {CC "asReflectionField",                            CC "(" HS_RESOLVED_KLASS "I)" REFLECTION_FIELD,                                       FN_PTR(asReflectionField)},
+  {CC "getFailedSpeculations",                        CC "(J[[B)[[B",                                                                       FN_PTR(getFailedSpeculations)},
+  {CC "getFailedSpeculationsAddress",                 CC "(" HS_RESOLVED_METHOD ")J",                                                       FN_PTR(getFailedSpeculationsAddress)},
+  {CC "releaseFailedSpeculations",                    CC "(J)V",                                                                            FN_PTR(releaseFailedSpeculations)},
+  {CC "addFailedSpeculation",                         CC "(J[B)Z",                                                                          FN_PTR(addFailedSpeculation)},
 };
 
 int CompilerToVM::methods_count() {
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Wed May 01 12:31:29 2019 -0700
@@ -24,40 +24,12 @@
 #ifndef SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
 #define SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
 
-#include "jni.h"
+#include "gc/shared/cardTable.hpp"
+#include "jvmci/jvmciExceptions.hpp"
 #include "runtime/javaCalls.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-
-// Helper class to ensure that references to Klass* are kept alive for G1
-class JVMCIKlassHandle : public StackObj {
- private:
-  Klass*     _klass;
-  Handle     _holder;
-  Thread*    _thread;
-
-  Klass*        klass() const                     { return _klass; }
-  Klass*        non_null_klass() const            { assert(_klass != NULL, "resolving NULL _klass"); return _klass; }
+#include "runtime/signature.hpp"
 
- public:
-  /* Constructors */
-  JVMCIKlassHandle (Thread* thread) : _klass(NULL), _thread(thread) {}
-  JVMCIKlassHandle (Thread* thread, Klass* klass);
-
-  JVMCIKlassHandle (const JVMCIKlassHandle &h): _klass(h._klass), _holder(h._holder), _thread(h._thread) {}
-  JVMCIKlassHandle& operator=(const JVMCIKlassHandle &s);
-  JVMCIKlassHandle& operator=(Klass* klass);
-
-  /* Operators for ease of use */
-  Klass*        operator () () const            { return klass(); }
-  Klass*        operator -> () const            { return non_null_klass(); }
-
-  bool    operator == (Klass* o) const          { return klass() == o; }
-  bool    operator == (const JVMCIKlassHandle& h) const  { return klass() == h.klass(); }
-
-  /* Null checks */
-  bool    is_null() const                      { return _klass == NULL; }
-  bool    not_null() const                     { return _klass != NULL; }
-};
+class JVMCIObjectArray;
 
 class CompilerToVM {
  public:
@@ -118,7 +90,7 @@
     static address symbol_clinit;
 
    public:
-    static void initialize(TRAPS);
+     static void initialize(JVMCI_TRAPS);
 
     static int max_oop_map_stack_offset() {
       assert(_max_oop_map_stack_offset > 0, "must be initialized");
@@ -141,59 +113,14 @@
   }
 
   static JNINativeMethod methods[];
+  static JNINativeMethod jni_methods[];
 
-  static objArrayHandle initialize_intrinsics(TRAPS);
+  static JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
  public:
   static int methods_count();
 
-  static inline Method* asMethod(jobject jvmci_method) {
-    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
-  }
-
-  static inline Method* asMethod(Handle jvmci_method) {
-    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
-  }
-
-  static inline Method* asMethod(oop jvmci_method) {
-    return (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(jvmci_method);
-  }
-
-  static inline ConstantPool* asConstantPool(jobject jvmci_constant_pool) {
-    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
-  }
-
-  static inline ConstantPool* asConstantPool(Handle jvmci_constant_pool) {
-    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
-  }
-
-  static inline ConstantPool* asConstantPool(oop jvmci_constant_pool) {
-    return (ConstantPool*) (address) HotSpotConstantPool::metaspaceConstantPool(jvmci_constant_pool);
-  }
+};
 
-  static inline Klass* asKlass(jobject jvmci_type) {
-    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
-  }
-
-  static inline Klass* asKlass(Handle jvmci_type) {
-    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
-  }
-
-  static inline Klass* asKlass(oop jvmci_type) {
-    return java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(jvmci_type));
-  }
-
-  static inline Klass* asKlass(jlong metaspaceKlass) {
-    return (Klass*) (address) metaspaceKlass;
-  }
-
-  static inline MethodData* asMethodData(jlong metaspaceMethodData) {
-    return (MethodData*) (address) metaspaceMethodData;
-  }
-
-  static oop get_jvmci_method(const methodHandle& method, TRAPS);
-
-  static oop get_jvmci_type(JVMCIKlassHandle& klass, TRAPS);
-};
 
 class JavaArgumentUnboxer : public SignatureIterator {
  protected:
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -25,13 +25,10 @@
 #include "ci/ciUtilities.hpp"
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/cardTable.hpp"
-#include "memory/oopFactory.hpp"
-#include "oops/objArrayOop.inline.hpp"
-#include "jvmci/jvmciRuntime.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
 #include "jvmci/vmStructs_jvmci.hpp"
-#include "runtime/flags/jvmFlag.hpp"
-#include "runtime/handles.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/resourceHash.hpp"
 
@@ -88,7 +85,7 @@
 address CompilerToVM::Data::symbol_init;
 address CompilerToVM::Data::symbol_clinit;
 
-void CompilerToVM::Data::initialize(TRAPS) {
+void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
   Klass_vtable_start_offset = in_bytes(Klass::vtable_start_offset());
   Klass_vtable_length_offset = in_bytes(Klass::vtable_length_offset());
 
@@ -157,29 +154,23 @@
 #undef SET_TRIGFUNC
 }
 
-objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) {
-  objArrayHandle vmIntrinsics = oopFactory::new_objArray_handle(VMIntrinsicMethod::klass(), (vmIntrinsics::ID_LIMIT - 1), CHECK_(objArrayHandle()));
+JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
+  JVMCIObjectArray vmIntrinsics = JVMCIENV->new_VMIntrinsicMethod_array(vmIntrinsics::ID_LIMIT - 1, JVMCI_CHECK_NULL);
   int index = 0;
-  // The intrinsics for a class are usually adjacent to each other.
-  // When they are, the string for the class name can be reused.
   vmSymbols::SID kls_sid = vmSymbols::NO_SID;
-  Handle kls_str;
+  JVMCIObject kls_str;
 #define VM_SYMBOL_TO_STRING(s) \
-  java_lang_String::create_from_symbol(vmSymbols::symbol_at(vmSymbols::VM_SYMBOL_ENUM_NAME(s)), CHECK_(objArrayHandle()))
+  JVMCIENV->create_string(vmSymbols::symbol_at(vmSymbols::VM_SYMBOL_ENUM_NAME(s)), JVMCI_CHECK_NULL)
 #define VM_INTRINSIC_INFO(id, kls, name, sig, ignore_fcode) {             \
-    instanceHandle vmIntrinsicMethod = InstanceKlass::cast(VMIntrinsicMethod::klass())->allocate_instance_handle(CHECK_(objArrayHandle())); \
     vmSymbols::SID sid = vmSymbols::VM_SYMBOL_ENUM_NAME(kls);             \
     if (kls_sid != sid) {                                                 \
       kls_str = VM_SYMBOL_TO_STRING(kls);                                 \
       kls_sid = sid;                                                      \
     }                                                                     \
-    Handle name_str = VM_SYMBOL_TO_STRING(name);                          \
-    Handle sig_str = VM_SYMBOL_TO_STRING(sig);                            \
-    VMIntrinsicMethod::set_declaringClass(vmIntrinsicMethod, kls_str());  \
-    VMIntrinsicMethod::set_name(vmIntrinsicMethod, name_str());           \
-    VMIntrinsicMethod::set_descriptor(vmIntrinsicMethod, sig_str());      \
-    VMIntrinsicMethod::set_id(vmIntrinsicMethod, vmIntrinsics::id);       \
-      vmIntrinsics->obj_at_put(index++, vmIntrinsicMethod());             \
+    JVMCIObject name_str = VM_SYMBOL_TO_STRING(name);                    \
+    JVMCIObject sig_str = VM_SYMBOL_TO_STRING(sig);                      \
+    JVMCIObject vmIntrinsicMethod = JVMCIENV->new_VMIntrinsicMethod(kls_str, name_str, sig_str, (jint) vmIntrinsics::id, JVMCI_CHECK_NULL); \
+    JVMCIENV->put_object_at(vmIntrinsics, index++, vmIntrinsicMethod);   \
   }
 
   VM_INTRINSICS_DO(VM_INTRINSIC_INFO, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
@@ -190,9 +181,6 @@
   return vmIntrinsics;
 }
 
-/**
- * The set of VM flags known to be used.
- */
 #define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_intx_flag, do_uintx_flag) \
   do_intx_flag(AllocateInstancePrefetchLines)                              \
   do_intx_flag(AllocatePrefetchDistance)                                   \
@@ -258,30 +246,28 @@
   do_bool_flag(UseTLAB)                                                    \
   do_bool_flag(VerifyOops)                                                 \
 
-#define BOXED_BOOLEAN(name, value) oop name = ((jboolean)(value) ? boxedTrue() : boxedFalse())
-#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
+#define BOXED_BOOLEAN(name, value) name = ((jboolean)(value) ? boxedTrue : boxedFalse)
+#define BOXED_DOUBLE(name, value) do { jvalue p; p.d = (jdouble) (value); name = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL);} while(0)
 #define BOXED_LONG(name, value) \
-  oop name; \
   do { \
     jvalue p; p.j = (jlong) (value); \
-    Handle* e = longs.get(p.j); \
+    JVMCIObject* e = longs.get(p.j); \
     if (e == NULL) { \
-      oop o = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); \
-      Handle h(THREAD, o); \
+      JVMCIObject h = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); \
       longs.put(p.j, h); \
-      name = h(); \
+      name = h; \
     } else { \
-      name = (*e)(); \
+      name = (*e); \
     } \
   } while (0)
 
 #define CSTRING_TO_JSTRING(name, value) \
-  Handle name; \
+  JVMCIObject name; \
   do { \
     if (value != NULL) { \
-      Handle* e = strings.get(value); \
+      JVMCIObject* e = strings.get(value); \
       if (e == NULL) { \
-        Handle h = java_lang_String::create_from_str(value, CHECK_NULL); \
+        JVMCIObject h = JVMCIENV->create_string(value, JVMCI_CHECK_NULL); \
         strings.put(value, h); \
         name = h; \
       } else { \
@@ -290,51 +276,42 @@
     } \
   } while (0)
 
-jobjectArray readConfiguration0(JNIEnv *env, TRAPS) {
-  ResourceMark rm;
-  HandleMark hm;
-
-  // Used to canonicalize Long and String values.
-  ResourceHashtable<jlong, Handle> longs;
-  ResourceHashtable<const char*, Handle, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
+jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) {
+  Thread* THREAD = Thread::current();
+  ResourceHashtable<jlong, JVMCIObject> longs;
+  ResourceHashtable<const char*, JVMCIObject, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
 
   jvalue prim;
-  prim.z = true;  oop boxedTrueOop =  java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
-  Handle boxedTrue(THREAD, boxedTrueOop);
-  prim.z = false; oop boxedFalseOop = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
-  Handle boxedFalse(THREAD, boxedFalseOop);
+  prim.z = true;  JVMCIObject boxedTrue =  JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
+  prim.z = false; JVMCIObject boxedFalse = JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
 
-  CompilerToVM::Data::initialize(CHECK_NULL);
+  CompilerToVM::Data::initialize(JVMCI_CHECK_NULL);
 
-  VMField::klass()->initialize(CHECK_NULL);
-  VMFlag::klass()->initialize(CHECK_NULL);
-  VMIntrinsicMethod::klass()->initialize(CHECK_NULL);
+  JVMCIENV->VMField_initialize(JVMCI_CHECK_NULL);
+  JVMCIENV->VMFlag_initialize(JVMCI_CHECK_NULL);
+  JVMCIENV->VMIntrinsicMethod_initialize(JVMCI_CHECK_NULL);
 
   int len = JVMCIVMStructs::localHotSpotVMStructs_count();
-  objArrayHandle vmFields = oopFactory::new_objArray_handle(VMField::klass(), len, CHECK_NULL);
+  JVMCIObjectArray vmFields = JVMCIENV->new_VMField_array(len, JVMCI_CHECK_NULL);
   for (int i = 0; i < len ; i++) {
     VMStructEntry vmField = JVMCIVMStructs::localHotSpotVMStructs[i];
-    instanceHandle vmFieldObj = InstanceKlass::cast(VMField::klass())->allocate_instance_handle(CHECK_NULL);
     size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
     char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
     sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
     CSTRING_TO_JSTRING(name, name_buf);
     CSTRING_TO_JSTRING(type, vmField.typeString);
-    VMField::set_name(vmFieldObj, name());
-    VMField::set_type(vmFieldObj, type());
-    VMField::set_offset(vmFieldObj, vmField.offset);
-    VMField::set_address(vmFieldObj, (jlong) vmField.address);
+    JVMCIObject box;
     if (vmField.isStatic && vmField.typeString != NULL) {
       if (strcmp(vmField.typeString, "bool") == 0) {
         BOXED_BOOLEAN(box, *(jbyte*) vmField.address);
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else if (strcmp(vmField.typeString, "int") == 0 ||
                  strcmp(vmField.typeString, "jint") == 0) {
         BOXED_LONG(box, *(jint*) vmField.address);
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else if (strcmp(vmField.typeString, "uint64_t") == 0) {
         BOXED_LONG(box, *(uint64_t*) vmField.address);
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else if (strcmp(vmField.typeString, "address") == 0 ||
                  strcmp(vmField.typeString, "intptr_t") == 0 ||
                  strcmp(vmField.typeString, "uintptr_t") == 0 ||
@@ -343,43 +320,47 @@
                  // All foo* types are addresses.
                  vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
         BOXED_LONG(box, *((address*) vmField.address));
-        VMField::set_value(vmFieldObj, box);
+        assert(box.is_non_null(), "must have a box");
       } else {
         JVMCI_ERROR_NULL("VM field %s has unsupported type %s", name_buf, vmField.typeString);
       }
     }
-    vmFields->obj_at_put(i, vmFieldObj());
+    JVMCIObject vmFieldObj = JVMCIENV->new_VMField(name, type, vmField.offset, (jlong) vmField.address, box, JVMCI_CHECK_NULL);
+    JVMCIENV->put_object_at(vmFields, i, vmFieldObj);
   }
 
   int ints_len = JVMCIVMStructs::localHotSpotVMIntConstants_count();
   int longs_len = JVMCIVMStructs::localHotSpotVMLongConstants_count();
   len = ints_len + longs_len;
-  objArrayHandle vmConstants = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
+  JVMCIObjectArray vmConstants = JVMCIENV->new_Object_array(len * 2, JVMCI_CHECK_NULL);
   int insert = 0;
   for (int i = 0; i < ints_len ; i++) {
     VMIntConstantEntry c = JVMCIVMStructs::localHotSpotVMIntConstants[i];
     CSTRING_TO_JSTRING(name, c.name);
+    JVMCIObject value;
     BOXED_LONG(value, c.value);
-    vmConstants->obj_at_put(insert++, name());
-    vmConstants->obj_at_put(insert++, value);
+    JVMCIENV->put_object_at(vmConstants, insert++, name);
+    JVMCIENV->put_object_at(vmConstants, insert++, value);
   }
   for (int i = 0; i < longs_len ; i++) {
     VMLongConstantEntry c = JVMCIVMStructs::localHotSpotVMLongConstants[i];
     CSTRING_TO_JSTRING(name, c.name);
+    JVMCIObject value;
     BOXED_LONG(value, c.value);
-    vmConstants->obj_at_put(insert++, name());
-    vmConstants->obj_at_put(insert++, value);
+    JVMCIENV->put_object_at(vmConstants, insert++, name);
+    JVMCIENV->put_object_at(vmConstants, insert++, value);
   }
   assert(insert == len * 2, "must be");
 
   len = JVMCIVMStructs::localHotSpotVMAddresses_count();
-  objArrayHandle vmAddresses = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
+  JVMCIObjectArray vmAddresses = JVMCIENV->new_Object_array(len * 2, JVMCI_CHECK_NULL);
   for (int i = 0; i < len ; i++) {
     VMAddressEntry a = JVMCIVMStructs::localHotSpotVMAddresses[i];
     CSTRING_TO_JSTRING(name, a.name);
+    JVMCIObject value;
     BOXED_LONG(value, a.value);
-    vmAddresses->obj_at_put(i * 2, name());
-    vmAddresses->obj_at_put(i * 2 + 1, value);
+    JVMCIENV->put_object_at(vmAddresses, i * 2, name);
+    JVMCIENV->put_object_at(vmAddresses, i * 2 + 1, value);
   }
 
 #define COUNT_FLAG(ignore) +1
@@ -393,40 +374,32 @@
 #define CHECK_FLAG(type, name)
 #endif
 
-#define ADD_FLAG(type, name, convert) { \
-  CHECK_FLAG(type, name) \
-  instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
-  CSTRING_TO_JSTRING(fname, #name); \
-  CSTRING_TO_JSTRING(ftype, #type); \
-  VMFlag::set_name(vmFlagObj, fname()); \
-  VMFlag::set_type(vmFlagObj, ftype()); \
-  convert(value, name); \
-  VMFlag::set_value(vmFlagObj, value); \
-  vmFlags->obj_at_put(i++, vmFlagObj()); \
+#define ADD_FLAG(type, name, convert) {                                                \
+  CHECK_FLAG(type, name)                                                               \
+  CSTRING_TO_JSTRING(fname, #name);                                                    \
+  CSTRING_TO_JSTRING(ftype, #type);                                                    \
+  convert(value, name);                                                                \
+  JVMCIObject vmFlagObj = JVMCIENV->new_VMFlag(fname, ftype, value, JVMCI_CHECK_NULL); \
+  JVMCIENV->put_object_at(vmFlags, i++, vmFlagObj);                                    \
 }
 #define ADD_BOOL_FLAG(name)  ADD_FLAG(bool, name, BOXED_BOOLEAN)
 #define ADD_INTX_FLAG(name)  ADD_FLAG(intx, name, BOXED_LONG)
 #define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG)
 
   len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG);
-  objArrayHandle vmFlags = oopFactory::new_objArray_handle(VMFlag::klass(), len, CHECK_NULL);
+  JVMCIObjectArray vmFlags = JVMCIENV->new_VMFlag_array(len, JVMCI_CHECK_NULL);
   int i = 0;
+  JVMCIObject value;
   PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
 
-  objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
-
-  objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 5, CHECK_NULL);
-  data->obj_at_put(0, vmFields());
-  data->obj_at_put(1, vmConstants());
-  data->obj_at_put(2, vmAddresses());
-  data->obj_at_put(3, vmFlags());
-  data->obj_at_put(4, vmIntrinsics());
+  JVMCIObjectArray vmIntrinsics = CompilerToVM::initialize_intrinsics(JVMCI_CHECK_NULL);
 
-  return (jobjectArray) JNIHandles::make_local(THREAD, data);
-#undef COUNT_FLAG
-#undef ADD_FLAG
-#undef ADD_BOOL_FLAG
-#undef ADD_INTX_FLAG
-#undef ADD_UINTX_FLAG
-#undef CHECK_FLAG
+  JVMCIObjectArray data = JVMCIENV->new_Object_array(5, JVMCI_CHECK_NULL);
+  JVMCIENV->put_object_at(data, 0, vmFields);
+  JVMCIENV->put_object_at(data, 1, vmConstants);
+  JVMCIENV->put_object_at(data, 2, vmAddresses);
+  JVMCIENV->put_object_at(data, 3, vmFlags);
+  JVMCIENV->put_object_at(data, 4, vmIntrinsics);
+
+  return JVMCIENV->get_jobjectArray(data);
 }
--- 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
--- a/src/hotspot/share/jvmci/jvmciEnv.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciEnv.hpp	Wed May 01 12:31:29 2019 -0700
@@ -25,14 +25,16 @@
 #ifndef SHARE_JVMCI_JVMCIENV_HPP
 #define SHARE_JVMCI_JVMCIENV_HPP
 
-#include "classfile/systemDictionary.hpp"
-#include "code/debugInfoRec.hpp"
-#include "code/dependencies.hpp"
-#include "code/exceptionHandlerTable.hpp"
-#include "compiler/oopMap.hpp"
+#include "classfile/javaClasses.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
 #include "runtime/thread.hpp"
 
 class CompileTask;
+class JVMCIObject;
+class JVMCIObjectArray;
+class JVMCIPrimitiveArray;
+class JVMCICompiler;
+class JVMCIRuntime;
 
 // Bring the JVMCI compiler thread into the VM state.
 #define JVMCI_VM_ENTRY_MARK                       \
@@ -47,64 +49,58 @@
   JavaThread* thread=JavaThread::current(); \
   Thread* THREAD = thread;
 
-//
-// This class is the top level broker for requests from the compiler
-// to the VM.
-class JVMCIEnv : StackObj {
-  CI_PACKAGE_ACCESS_TO
-
-  friend class JVMCIVMStructs;
-  friend class CompileBroker;
-  friend class Dependencies;  // for get_object, during logging
+// Helper to log more context on a JNI exception
+#define JVMCI_EXCEPTION_CHECK(env, ...) \
+  do { \
+    if (env->ExceptionCheck()) { \
+      if (env != JavaThread::current()->jni_environment() && JVMCIEnv::get_shared_library_path() != NULL) { \
+        tty->print_cr("In JVMCI shared library (%s):", JVMCIEnv::get_shared_library_path()); \
+      } \
+      tty->print_cr(__VA_ARGS__); \
+      return; \
+    } \
+  } while(0)
 
-public:
+// Helper class to ensure that references to Klass* are kept alive for G1
+class JVMCIKlassHandle : public StackObj {
+ private:
+  Klass*     _klass;
+  Handle     _holder;
+  Thread*    _thread;
 
-  enum CodeInstallResult {
-     ok,
-     dependencies_failed,
-     dependencies_invalid,
-     cache_full,
-     code_too_large
-  };
+  Klass*        klass() const                     { return _klass; }
+  Klass*        non_null_klass() const            { assert(_klass != NULL, "resolving NULL _klass"); return _klass; }
 
-  // Look up a klass by name from a particular class loader (the accessor's).
-  // If require_local, result must be defined in that class loader, or NULL.
-  // If !require_local, a result from remote class loader may be reported,
-  // if sufficient class loader constraints exist such that initiating
-  // a class loading request from the given loader is bound to return
-  // the class defined in the remote loader (or throw an error).
-  //
-  // Return an unloaded klass if !require_local and no class at all is found.
-  //
-  // The CI treats a klass as loaded if it is consistently defined in
-  // another loader, even if it hasn't yet been loaded in all loaders
-  // that could potentially see it via delegation.
-  static Klass* get_klass_by_name(Klass* accessing_klass, Symbol* klass_name, bool require_local);
+ public:
+  /* Constructors */
+  JVMCIKlassHandle (Thread* thread) : _klass(NULL), _thread(thread) {}
+  JVMCIKlassHandle (Thread* thread, Klass* klass);
+
+  JVMCIKlassHandle (const JVMCIKlassHandle &h): _klass(h._klass), _holder(h._holder), _thread(h._thread) {}
+  JVMCIKlassHandle& operator=(const JVMCIKlassHandle &s);
+  JVMCIKlassHandle& operator=(Klass* klass);
+
+  /* Operators for ease of use */
+  Klass*        operator () () const            { return klass(); }
+  Klass*        operator -> () const            { return non_null_klass(); }
 
-  // Constant pool access.
-  static Klass* get_klass_by_index(const constantPoolHandle& cpool,
-                                   int klass_index,
-                                   bool& is_accessible,
-                                   Klass* loading_klass);
-  static void   get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd,
-                                   int field_index);
-  static methodHandle  get_method_by_index(const constantPoolHandle& cpool,
-                                    int method_index, Bytecodes::Code bc,
-                                    InstanceKlass* loading_klass);
+  bool    operator == (Klass* o) const          { return klass() == o; }
+  bool    operator == (const JVMCIKlassHandle& h) const  { return klass() == h.klass(); }
 
-  JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter);
+  /* Null checks */
+  bool    is_null() const                      { return _klass == NULL; }
+  bool    not_null() const                     { return _klass != NULL; }
+};
 
-private:
+// A class that maintains the state needed for compilations requested
+// by the CompileBroker.  It is created in the broker and passed through
+// into the code installation step.
+class JVMCICompileState : public ResourceObj {
+  friend class VMStructs;
+ private:
   CompileTask*     _task;
   int              _system_dictionary_modification_counter;
 
-  // Compilation result values
-  bool             _retryable;
-  const char*      _failure_reason;
-
-  // Specifies if _failure_reason is on the C heap.
-  bool             _failure_reason_on_C_heap;
-
   // Cache JVMTI state. Defined as bytes so that reading them from Java
   // via Unsafe is well defined (the C++ type for bool is implementation
   // defined and may not be the same as a Java boolean).
@@ -113,43 +109,20 @@
   jbyte  _jvmti_can_post_on_exceptions;
   jbyte  _jvmti_can_pop_frame;
 
-  // Implementation methods for loading and constant pool access.
-  static Klass* get_klass_by_name_impl(Klass* accessing_klass,
-                                  const constantPoolHandle& cpool,
-                                  Symbol* klass_name,
-                                  bool require_local);
-  static Klass* get_klass_by_index_impl(const constantPoolHandle& cpool,
-                                     int klass_index,
-                                     bool& is_accessible,
-                                     Klass* loading_klass);
-  static void   get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd,
-                                     int field_index);
-  static methodHandle  get_method_by_index_impl(const constantPoolHandle& cpool,
-                                      int method_index, Bytecodes::Code bc,
-                                      InstanceKlass* loading_klass);
+  // Compilation result values.
+  bool             _retryable;
+  const char*      _failure_reason;
 
-  // Helper methods
-  static bool       check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass);
-  static methodHandle  lookup_method(InstanceKlass*  accessor,
-                           Klass*         holder,
-                           Symbol*        name,
-                           Symbol*        sig,
-                           Bytecodes::Code bc,
-                           constantTag     tag);
+  // Specifies if _failure_reason is on the C heap. If so, it is allocated
+  // with the mtJVMCI NMT flag.
+  bool             _failure_reason_on_C_heap;
 
-  private:
-
-  // Is this thread currently in the VM state?
-  static bool is_in_vm();
+ public:
+  JVMCICompileState(CompileTask* task, int system_dictionary_modification_counter);
 
-  // Helper routine for determining the validity of a compilation
-  // with respect to concurrent class loading.
-  static JVMCIEnv::CodeInstallResult validate_compile_task_dependencies(Dependencies* target, Handle compiled_code,
-                                                                        JVMCIEnv* env, char** failure_detail);
-
-public:
   CompileTask* task() { return _task; }
 
+  int system_dictionary_modification_counter() { return _system_dictionary_modification_counter; }
   bool  jvmti_state_changed() const;
   bool  jvmti_can_hotswap_or_post_breakpoint() const { return  _jvmti_can_hotswap_or_post_breakpoint != 0; }
   bool  jvmti_can_access_local_variables() const     { return  _jvmti_can_access_local_variables != 0; }
@@ -165,34 +138,355 @@
     _failure_reason_on_C_heap = reason_on_C_heap;
     _retryable = retryable;
   }
+};
 
-  // Register the result of a compilation.
-  static JVMCIEnv::CodeInstallResult register_method(
-                       const methodHandle&       target,
-                       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);
+
+// This class is a top level wrapper around interactions between HotSpot
+// and the JVMCI Java code.  It supports both a HotSpot heap based
+// runtime with HotSpot oop based accessors as well as a shared library
+// based runtime that is accessed through JNI. It abstracts away all
+// interactions with JVMCI objects so that a single version of the
+// HotSpot C++ code can can work with either runtime.
+class JVMCIEnv : public ResourceObj {
+  friend class JNIAccessMark;
+
+  static char*   _shared_library_path;   // argument to os:dll_load
+  static void*   _shared_library_handle; // result of os::dll_load
+  static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
+
+  // Attaches the current thread to the JavaVM in the shared library,
+  // initializing the shared library VM first if necessary.
+  // Returns the JNI interface pointer of the current thread.
+  // The _shared_library_* fields are initialized by the first
+  // call to this method.
+  static JNIEnv* attach_shared_library();
+
+  // Initializes the _env, _mode and _runtime fields.
+  void init_env_mode_runtime(JNIEnv* parent_env);
+
+  void init(bool is_hotspot, const char* file, int line);
+
+  JNIEnv*                _env;     // JNI env for calling into shared library
+  JVMCIRuntime*          _runtime; // Access to a HotSpotJVMCIRuntime
+  bool             _is_hotspot;    // Which heap is the HotSpotJVMCIRuntime in
+  bool        _throw_to_caller;    // Propagate an exception raised in this env to the caller?
+  const char*            _file;    // The file and ...
+  int                    _line;    // ... line where this JNIEnv was created
+
+  // Translates an exception on the HotSpot heap to an exception on
+  // the shared library heap. The translation includes the stack and
+  // causes of `throwable`. The translated exception is pending in the
+  // shared library thread upon returning.
+  void translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, const Handle& throwable);
+
+public:
+  // Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM).
+  // An exception occurring within the scope is left pending when the
+  // scope closes so that it will be propagated back to Java.
+  // The JVMCIEnv destructor translates the exception object for the
+  // Java runtime if necessary.
+  JVMCIEnv(JNIEnv* env, const char* file, int line);
+
+  // Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
+  // An exception occurring within the scope must not be propagated back to
+  // the CompileBroker.
+  JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line);
+
+  // Opens a JNIEnv scope for a call from within the VM. An exception occurring
+  // within the scope must not be propagated back to the caller.
+  JVMCIEnv(JavaThread* env, const char* file, int line);
+
+  // Opens a JNIEnv scope for accessing `for_object`. An exception occurring
+  // within the scope must not be propagated back to the caller.
+  JVMCIEnv(JVMCIObject for_object, const char* file, int line) {
+    // A JNI call to access an object in the shared library heap
+    // can block or take a long time so do not allow such access
+    // on the VM thread.
+    assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
+        "cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
+    init(for_object.is_hotspot(), file, line);
+  }
+
+  // Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
+  // otherwise for the shared library runtime. An exception occurring
+  // within the scope must not be propagated back to the caller.
+  JVMCIEnv(bool is_hotspot, const char* file, int line) {
+    init(is_hotspot, file, line);
+  }
+
+  ~JVMCIEnv();
+
+  JVMCIRuntime* runtime() {
+    return _runtime;
+  }
+
+  // Initializes Services.savedProperties in the shared library by copying
+  // the values from the same field in the HotSpot heap.
+  void copy_saved_properties();
+
+  jboolean has_pending_exception();
+  void clear_pending_exception();
+
+  // Prints an exception and stack trace of a pending exception.
+  void describe_pending_exception(bool clear);
+
+  int get_length(JVMCIArray array);
+
+  JVMCIObject get_object_at(JVMCIObjectArray array, int index);
+  void put_object_at(JVMCIObjectArray array, int index, JVMCIObject value);
+
+  jboolean get_bool_at(JVMCIPrimitiveArray array, int index);
+  void put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value);
+
+  jbyte get_byte_at(JVMCIPrimitiveArray array, int index);
+  void put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value);
+
+  jint get_int_at(JVMCIPrimitiveArray array, int index);
+  void put_int_at(JVMCIPrimitiveArray array, int index, jint value);
+
+  long get_long_at(JVMCIPrimitiveArray array, int index);
+  void put_long_at(JVMCIPrimitiveArray array, int index, jlong value);
+
+  void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes);
+  void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes);
+
+  JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
+
+  jboolean is_boxing_object(BasicType type, JVMCIObject object);
+
+  // Get the primitive value from a Java boxing object.  It's hard error to
+  // pass a non-primitive BasicType.
+  jvalue get_boxed_value(BasicType type, JVMCIObject object);
+
+  // Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
+  BasicType get_box_type(JVMCIObject object);
+
+  // Create a boxing object of the appropriate primitive type.
+  JVMCIObject create_box(BasicType type, jvalue* value, JVMCI_TRAPS);
+
+  const char* as_utf8_string(JVMCIObject str);
+  char* as_utf8_string(JVMCIObject str, char* buf, int buflen);
+
+  JVMCIObject create_string(Symbol* str, JVMCI_TRAPS) {
+    return create_string(str->as_C_string(), JVMCI_CHECK_(JVMCIObject()));
+  }
+
+  JVMCIObject create_string(const char* str, JVMCI_TRAPS);
+
+  bool equals(JVMCIObject a, JVMCIObject b);
+
+  // Convert into a JNI handle for the appropriate runtime
+  jobject get_jobject(JVMCIObject object)                       { assert(object.as_jobject() == NULL || is_hotspot() == object.is_hotspot(), "mismatch"); return object.as_jobject(); }
+  jarray get_jarray(JVMCIArray array)                           { assert(array.as_jobject() == NULL || is_hotspot() == array.is_hotspot(), "mismatch"); return array.as_jobject(); }
+  jobjectArray get_jobjectArray(JVMCIObjectArray objectArray)   { assert(objectArray.as_jobject() == NULL || is_hotspot() == objectArray.is_hotspot(), "mismatch"); return objectArray.as_jobject(); }
+  jbyteArray get_jbyteArray(JVMCIPrimitiveArray primitiveArray) { assert(primitiveArray.as_jobject() == NULL || is_hotspot() == primitiveArray.is_hotspot(), "mismatch"); return primitiveArray.as_jbyteArray(); }
+
+  JVMCIObject         wrap(jobject obj);
+  JVMCIObjectArray    wrap(jobjectArray obj)  { return (JVMCIObjectArray)    wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jintArray obj)     { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jbooleanArray obj) { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jbyteArray obj)    { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+  JVMCIPrimitiveArray wrap(jlongArray obj)    { return (JVMCIPrimitiveArray) wrap((jobject) obj); }
+
+ private:
+  JVMCIObject wrap(oop obj)                  { assert(is_hotspot(), "must be"); return wrap(JNIHandles::make_local(obj)); }
+  JVMCIObjectArray wrap(objArrayOop obj)     { assert(is_hotspot(), "must be"); return (JVMCIObjectArray) wrap(JNIHandles::make_local(obj)); }
+  JVMCIPrimitiveArray wrap(typeArrayOop obj) { assert(is_hotspot(), "must be"); return (JVMCIPrimitiveArray) wrap(JNIHandles::make_local(obj)); }
+
+ public:
+  // Compiles a method with the JVMIC compiler.
+  // Caller must handle pending exception.
+  JVMCIObject call_HotSpotJVMCIRuntime_compileMethod(JVMCIObject runtime, JVMCIObject method, int entry_bci,
+                                                     jlong compile_state, int id);
+
+  void call_HotSpotJVMCIRuntime_bootstrapFinished(JVMCIObject runtime, JVMCI_TRAPS);
+  void call_HotSpotJVMCIRuntime_shutdown(JVMCIObject runtime);
+  JVMCIObject call_HotSpotJVMCIRuntime_runtime(JVMCI_TRAPS);
+  JVMCIObject call_JVMCI_getRuntime(JVMCI_TRAPS);
+  JVMCIObject call_HotSpotJVMCIRuntime_getCompiler(JVMCIObject runtime, JVMCI_TRAPS);
+
+  JVMCIObject call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCI_TRAPS);
+
+  JVMCIObject call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS);
+  JVMCIObject call_JavaConstant_forFloat(float value, JVMCI_TRAPS);
+  JVMCIObject call_JavaConstant_forDouble(double value, JVMCI_TRAPS);
+
+  BasicType kindToBasicType(JVMCIObject kind, JVMCI_TRAPS);
 
-  // converts the Klass* representing the holder of a method into a
-  // InstanceKlass*.  This is needed since the holder of a method in
-  // the bytecodes could be an array type.  Basically this converts
-  // array types into java/lang/Object and other types stay as they are.
-  static InstanceKlass* get_instance_klass_for_declared_method_holder(Klass* klass);
+#define DO_THROW(name) \
+  void throw_##name(const char* msg = NULL);
+
+  DO_THROW(InternalError)
+  DO_THROW(ArrayIndexOutOfBoundsException)
+  DO_THROW(IllegalStateException)
+  DO_THROW(NullPointerException)
+  DO_THROW(IllegalArgumentException)
+  DO_THROW(InvalidInstalledCodeException)
+  DO_THROW(UnsatisfiedLinkError)
+
+#undef DO_THROW
+
+  void fthrow_error(const char* file, int line, const char* format, ...) ATTRIBUTE_PRINTF(4, 5);
+
+  // Given an instance of HotSpotInstalledCode return the corresponding CodeBlob*
+  CodeBlob* asCodeBlob(JVMCIObject code);
+
+  nmethod* asNmethod(JVMCIObject code) {
+    CodeBlob* cb = asCodeBlob(code);
+    if (cb == NULL) {
+      return NULL;
+    }
+    nmethod* nm = cb->as_nmethod_or_null();
+    guarantee(nm != NULL, "not an nmethod");
+    return nm;
+  }
+
+  MethodData* asMethodData(jlong metaspaceMethodData) {
+    return (MethodData*) (address) metaspaceMethodData;
+  }
+
+  const char* klass_name(JVMCIObject object);
+
+  // Unpack an instance of HotSpotResolvedJavaMethodImpl into the original Method*
+  Method* asMethod(JVMCIObject jvmci_method);
+  Method* asMethod(jobject jvmci_method) { return asMethod(wrap(jvmci_method)); }
+
+  // Unpack an instance of HotSpotResolvedObjectTypeImpl into the original Klass*
+  Klass* asKlass(JVMCIObject jvmci_type);
+  Klass* asKlass(jobject jvmci_type)  { return asKlass(wrap(jvmci_type)); }
+
+  JVMCIObject get_jvmci_method(const methodHandle& method, JVMCI_TRAPS);
+
+  JVMCIObject get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS);
+
+  // Unpack an instance of HotSpotConstantPool into the original ConstantPool*
+  ConstantPool* asConstantPool(JVMCIObject constant_pool);
+  ConstantPool* asConstantPool(jobject constant_pool)  { return asConstantPool(wrap(constant_pool)); }
+
+  JVMCIObject get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS);
+  JVMCIObject get_jvmci_primitive_type(BasicType type);
+
+  Handle asConstant(JVMCIObject object, JVMCI_TRAPS);
+  JVMCIObject get_object_constant(oop objOop, bool compressed = false, bool dont_register = false);
+
+  JVMCIPrimitiveArray new_booleanArray(int length, JVMCI_TRAPS);
+  JVMCIPrimitiveArray new_byteArray(int length, JVMCI_TRAPS);
+  JVMCIPrimitiveArray new_intArray(int length, JVMCI_TRAPS);
+  JVMCIPrimitiveArray new_longArray(int length, JVMCI_TRAPS);
+
+  JVMCIObjectArray new_byte_array_array(int length, JVMCI_TRAPS);
+
+  JVMCIObject new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS);
+  JVMCIObject new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS);
+  JVMCIObject new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS);
+  JVMCIObject new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS);
+  JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS);
+  JVMCIObject new_HotSpotStackFrameReference(JVMCI_TRAPS);
+  JVMCIObject new_JVMCIError(JVMCI_TRAPS);
+
+  jlong make_handle(const Handle& obj);
+  oop resolve_handle(jlong objectHandle);
+
+  // These are analagous to the JNI routines
+  JVMCIObject make_local(JVMCIObject object);
+  JVMCIObject make_global(JVMCIObject object);
+  JVMCIObject make_weak(JVMCIObject object);
+  void destroy_local(JVMCIObject object);
+  void destroy_global(JVMCIObject object);
+  void destroy_weak(JVMCIObject object);
+
+  // Deoptimizes the nmethod (if any) in the HotSpotNmethod.address
+  // field of mirror. The field is subsequently zeroed.
+  void invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS);
+
+  void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS);
+
+ private:
+  JVMCICompileState* _compile_state;
+
+ public:
+  static JavaVM* get_shared_library_javavm() { return _shared_library_javavm; }
+  static void* get_shared_library_handle()   { return _shared_library_handle; }
+  static char* get_shared_library_path()     { return _shared_library_path; }
+
+  // Determines if this is for the JVMCI runtime in the HotSpot
+  // heap (true) or the shared library heap (false).
+  bool is_hotspot() { return _is_hotspot; }
+
+  JVMCICompileState* compile_state() { return _compile_state; }
+  void set_compile_state(JVMCICompileState* compile_state) {
+    assert(_compile_state == NULL, "set only once");
+    _compile_state = compile_state;
+  }
+  // Generate declarations 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 className##_initialize(JVMCI_TRAPS); \
+  JVMCIObjectArray new_##className##_array(int length, JVMCI_TRAPS); \
+  bool isa_##className(JVMCIObject object);
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor)                                                                                                                         \
+  type get_ ## className ## _ ## name(JVMCIObject obj); \
+  void set_ ## className ## _ ## name(JVMCIObject obj, type x);
+
+#define OOPISH_FIELD(className, name, type, hstype, accessor) \
+  FIELD(className, name, type, accessor)
+
+#define STATIC_FIELD(className, name, type) \
+  type get_ ## className ## _ ## name(); \
+  void set_ ## className ## _ ## name(type x);
+
+#define STATIC_OOPISH_FIELD(className, name, type, hstype) \
+  STATIC_FIELD(className, name, type)
+
+#define EMPTY_CAST
+#define CHAR_FIELD(className,  name) FIELD(className, name, jchar, char_field)
+#define INT_FIELD(className,  name) FIELD(className, name, jint, int_field)
+#define BOOLEAN_FIELD(className,  name) FIELD(className, name, jboolean, bool_field)
+#define LONG_FIELD(className,  name) FIELD(className, name, jlong, long_field)
+#define FLOAT_FIELD(className,  name) FIELD(className, name, jfloat, float_field)
+#define OBJECT_FIELD(className,  name, signature) OOPISH_FIELD(className, name, JVMCIObject, oop, obj_field)
+#define OBJECTARRAY_FIELD(className,  name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, objArrayOop, obj_field)
+#define PRIMARRAY_FIELD(className,  name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, typeArrayOop, obj_field)
+
+#define STATIC_INT_FIELD(className, name) STATIC_FIELD(className, name, jint)
+#define STATIC_BOOLEAN_FIELD(className, name) STATIC_FIELD(className, name, jboolean)
+#define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, oop)
+#define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, objArrayOop)
+#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 JNI_START_CLASS
+#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 FIELD
+#undef OOPISH_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OOPISH_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+  // End of JVMCIEnv
 };
 
 #endif // SHARE_JVMCI_JVMCIENV_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmciExceptions.hpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, 2019, 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.
+ *
+ */
+
+#ifndef SHARE_JVMCI_JVMCIEXCEPTIONS_HPP
+#define SHARE_JVMCI_JVMCIEXCEPTIONS_HPP
+
+class JVMCIEnv;
+
+// JVMCIEnv exception utility macros.  Analagous to the regular CHECK, TRAP and THREAD macros.
+
+#define JVMCIENV __jvmci_env__
+#define JVMCI_TRAPS  JVMCIEnv* JVMCIENV
+
+#define JNI_JVMCIENV(env)                                     \
+  JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__);      \
+  JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
+
+#define THREAD_JVMCIENV(thread)                               \
+  JVMCIEnv __stack_jvmci_env__(thread, __FILE__, __LINE__);   \
+  JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
+
+#define JVMCI_PENDING_EXCEPTION                        (JVMCIENV->pending_exception())
+#define JVMCI_HAS_PENDING_EXCEPTION                    (JVMCIENV->has_pending_exception())
+#define JVMCI_CLEAR_PENDING_EXCEPTION                  (JVMCIENV->clear_pending_exception())
+
+#define JVMCI_CHECK                                    JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) return       ; (void)(0
+#define JVMCI_CHECK_(result)                           JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) return result; (void)(0
+#define JVMCI_CHECK_0                                  JVMCI_CHECK_(0)
+#define JVMCI_CHECK_NULL                               JVMCI_CHECK_(NULL)
+#define JVMCI_CHECK_false                              JVMCI_CHECK_(false)
+#define JVMCI_CHECK_OK                                 JVMCI_CHECK_(JVMCI::ok)
+
+#define JVMCI_ERROR(...)       \
+  { JVMCIENV->fthrow_error(__FILE__, __LINE__, __VA_ARGS__); return; }
+
+#define JVMCI_ERROR_(ret, ...) \
+  { JVMCIENV->fthrow_error( __FILE__, __LINE__, __VA_ARGS__); return ret; }
+
+#define JVMCI_ERROR_0(...)    JVMCI_ERROR_(0, __VA_ARGS__)
+#define JVMCI_ERROR_NULL(...) JVMCI_ERROR_(NULL, __VA_ARGS__)
+#define JVMCI_ERROR_OK(...)   JVMCI_ERROR_(JVMCI::ok, __VA_ARGS__)
+
+#define JVMCI_THROW(name) { JVMCIENV->throw_##name(); return; }
+#define JVMCI_THROW_NULL(name) { JVMCIENV->throw_##name(); return NULL; }
+#define JVMCI_THROW_0(name) { JVMCIENV->throw_##name(); return 0; }
+#define JVMCI_THROW_MSG_NULL(name, msg) { JVMCIENV->throw_##name(msg); return NULL; }
+#define JVMCI_THROW_MSG_(name, msg, value) { JVMCIENV->throw_##name(msg); return (value); }
+#define JVMCI_THROW_MSG_0(name, msg) { JVMCIENV->throw_##name(msg); return 0; }
+#define JVMCI_THROW_MSG(name, msg) { JVMCIENV->throw_##name(msg); return; }
+#define JVMCI_THROW_(name, value) { JVMCIENV->throw_##name(); return (value); }
+
+#define JVMCI_CATCH                              \
+  JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) {  \
+    JVMCIENV->describe_pending_exception(true);  \
+    ShouldNotReachHere();                        \
+  } (void)(0
+
+#endif // SHARE_JVMCI_JVMCIEXCEPTIONS_HPP
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -23,95 +23,43 @@
 
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
+#include "interpreter/linkResolver.hpp"
+#include "jvmci/jniAccessMark.inline.hpp"
 #include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciRuntime.hpp"
 #include "memory/resourceArea.hpp"
-#include "oops/oop.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 
+// ------------------------------------------------------------------
 
-// This macro expands for non-inline functions, in class declarations.
+oop HotSpotJVMCI::resolve(JVMCIObject obj) {
+  return JNIHandles::resolve(obj.as_jobject());
+}
 
-#define START_CLASS(name)                                                                                                                                \
-    void name::check(oop obj, const char* field_name, int offset) {                                                                                          \
-      assert(obj != NULL, "NULL field access of %s.%s", #name, field_name);                                                                                  \
-      assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected, found %s", obj->klass()->external_name());                       \
-      assert(offset != 0, "must be valid offset");                                                                                                           \
-    }
+arrayOop HotSpotJVMCI::resolve(JVMCIArray obj) {
+  return (arrayOop) JNIHandles::resolve(obj.as_jobject());
+}
 
-#define END_CLASS
-
-#define FIELD(klass, name, type, accessor, cast)                                                                                                                                \
-    type klass::name(jobject obj)               { check(JNIHandles::resolve(obj), #name, _##name##_offset); return cast JNIHandles::resolve(obj)->accessor(_##name##_offset); }     \
-    void klass::set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj), #name, _##name##_offset); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); }
+objArrayOop HotSpotJVMCI::resolve(JVMCIObjectArray obj) {
+  return (objArrayOop) JNIHandles::resolve(obj.as_jobject());
+}
 
-#define EMPTY_CAST
-#define CHAR_FIELD(klass, name) FIELD(klass, name, jchar, char_field, EMPTY_CAST)
-#define INT_FIELD(klass, name) FIELD(klass, name, jint, int_field, EMPTY_CAST)
-#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, jboolean, bool_field, EMPTY_CAST)
-#define LONG_FIELD(klass, name) FIELD(klass, name, jlong, long_field, EMPTY_CAST)
-#define FLOAT_FIELD(klass, name) FIELD(klass, name, jfloat, float_field, EMPTY_CAST)
-#define OOP_FIELD(klass, name, signature) FIELD(klass, name, oop, obj_field, EMPTY_CAST)
-#define OBJARRAYOOP_FIELD(klass, name, signature) FIELD(klass, name, objArrayOop, obj_field, (objArrayOop))
-#define TYPEARRAYOOP_FIELD(klass, name, signature) FIELD(klass, name, typeArrayOop, obj_field, (typeArrayOop))
-#define STATIC_OOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, oop, signature)
-#define STATIC_OBJARRAYOOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, objArrayOop, signature)
-#define STATIC_OOPISH_FIELD(klassName, name, type, signature)                                                  \
-    type klassName::name() {                                                                                   \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      oop result = HeapAccess<>::oop_load_at(base, _##name##_offset);                                          \
-      return type(result);                                                                                     \
-    }                                                                                                          \
-    void klassName::set_##name(type x) {                                                                       \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName);                                 \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      HeapAccess<>::oop_store_at(base, _##name##_offset, x);                                                   \
-    }
-#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename)                                                     \
-    jtypename klassName::name() {                                                                              \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      return HeapAccess<>::load_at(base, _##name##_offset);                                                    \
-    }                                                                                                          \
-    void klassName::set_##name(jtypename x) {                                                                  \
-      assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
-      InstanceKlass* ik = klassName::klass();                                                                  \
-      oop base = ik->static_field_base_raw();                                                                  \
-      HeapAccess<>::store_at(base, _##name##_offset, x);                                                       \
-    }
+typeArrayOop HotSpotJVMCI::resolve(JVMCIPrimitiveArray obj) {
+  return (typeArrayOop) JNIHandles::resolve(obj.as_jobject());
+}
 
-#define STATIC_INT_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jint)
-#define STATIC_BOOLEAN_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jboolean)
+JVMCIObject HotSpotJVMCI::wrap(oop obj) {
+  assert(Thread::current()->is_Java_thread(), "must be");
+  return JVMCIObject(JNIHandles::make_local(obj), true);
+}
 
-COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, TYPEARRAYOOP_FIELD, OBJARRAYOOP_FIELD, STATIC_OOP_FIELD, STATIC_OBJARRAYOOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
-#undef START_CLASS
-#undef END_CLASS
-#undef FIELD
-#undef CHAR_FIELD
-#undef INT_FIELD
-#undef BOOLEAN_FIELD
-#undef LONG_FIELD
-#undef FLOAT_FIELD
-#undef OOP_FIELD
-#undef TYPEARRAYOOP_FIELD
-#undef OBJARRAYOOP_FIELD
-#undef STATIC_OOPISH_FIELD
-#undef STATIC_OOP_FIELD
-#undef STATIC_OBJARRAYOOP_FIELD
-#undef STATIC_INT_FIELD
-#undef STATIC_BOOLEAN_FIELD
-#undef STATIC_PRIMITIVE_FIELD
-#undef EMPTY_CAST
-
-// This function is similar to javaClasses.cpp, it computes the field offset of a (static or instance) field.
-// It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded.
-
-void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS) {
+/**
+ * Computes the field offset of a static or instance field.
+ * It looks up the name and signature symbols without creating new ones;
+ * all the symbols of these classes need to be already loaded.
+ */
+void HotSpotJVMCI::compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS) {
   InstanceKlass* ik = InstanceKlass::cast(klass);
   Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
   Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
@@ -125,7 +73,7 @@
   fieldDescriptor fd;
   if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
     ResourceMark rm;
-    fatal("Invalid layout of %s %s at %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), ik->external_name());
+    fatal("Could not find field %s.%s with signature %s", ik->external_name(), name, signature);
   }
   guarantee(fd.is_static() == static_field, "static/instance mismatch");
   dest_offset = fd.offset();
@@ -137,33 +85,548 @@
   }
 }
 
-// This piece of macro magic creates the contents of the jvmci_compute_offsets method that initializes the field indices of all the access classes.
+#ifndef PRODUCT
+static void check_resolve_method(const char* call_type, Klass* resolved_klass, Symbol* method_name, Symbol* method_signature, TRAPS) {
+  methodHandle method;
+  LinkInfo link_info(resolved_klass, method_name, method_signature, NULL, LinkInfo::skip_access_check);
+  if (strcmp(call_type, "call_static") == 0) {
+    method = LinkResolver::resolve_static_call_or_null(link_info);
+  } else if (strcmp(call_type, "call_virtual") == 0) {
+    method = LinkResolver::resolve_virtual_call_or_null(resolved_klass, link_info);
+  } else if (strcmp(call_type, "call_special") == 0) {
+    method = LinkResolver::resolve_special_call_or_null(link_info);
+  } else {
+    fatal("Unknown or unsupported call type: %s", call_type);
+  }
+  if (method.is_null()) {
+    fatal("Could not resolve %s.%s%s", resolved_klass->external_name(), method_name->as_C_string(), method_signature->as_C_string());
+  }
+}
+#endif
 
-#define START_CLASS(name) { Klass* k = SystemDictionary::name##_klass(); assert(k != NULL, "Could not find class " #name "");
+jclass JNIJVMCI::_box_classes[T_CONFLICT+1];
+jclass JNIJVMCI::_byte_array;
+jfieldID JNIJVMCI::_box_fields[T_CONFLICT+1];
+jmethodID JNIJVMCI::_box_constructors[T_CONFLICT+1];
+jmethodID JNIJVMCI::_Class_getName_method;
+
+jmethodID JNIJVMCI::_HotSpotResolvedJavaMethodImpl_fromMetaspace_method;
+jmethodID JNIJVMCI::_HotSpotConstantPool_fromMetaspace_method;
+jmethodID JNIJVMCI::_HotSpotResolvedObjectTypeImpl_fromMetaspace_method;
+jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method;
+
+#define START_CLASS(className, fullClassName)                          { \
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::fullClassName(), true, CHECK); \
+  className::_klass = InstanceKlass::cast(k); \
+  className::_klass->initialize(CHECK);
 
 #define END_CLASS }
 
-#define FIELD(klass, name, signature, static_field) compute_offset(klass::_##name##_offset, k, #name, signature, static_field, CHECK);
-#define CHAR_FIELD(klass, name) FIELD(klass, name, "C", false)
-#define INT_FIELD(klass, name) FIELD(klass, name, "I", false)
-#define BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", false)
-#define LONG_FIELD(klass, name) FIELD(klass, name, "J", false)
-#define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false)
-#define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false)
-#define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true)
-#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true)
-#define STATIC_BOOLEAN_FIELD(klass, name) FIELD(klass, name, "Z", true)
+#define FIELD(className, name, signature, static_field) compute_offset(className::_##name##_offset, className::_klass, #name, signature, static_field, CHECK);
+#define CHAR_FIELD(className, name) FIELD(className, name, "C", false)
+#define INT_FIELD(className, name) FIELD(className, name, "I", false)
+#define BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", false)
+#define LONG_FIELD(className, name) FIELD(className, name, "J", false)
+#define FLOAT_FIELD(className, name) FIELD(className, name, "F", false)
+#define OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, false)
+#define STATIC_OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, true)
+#define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true)
+#define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true)
+#ifdef PRODUCT
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+#else
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+  check_resolve_method(#hsCallType, k, vmSymbols::methodName##_name(), vmSymbols::signatureSymbolName(), CHECK);
+#define CONSTRUCTOR(className, signature) { \
+  TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK); \
+  check_resolve_method("call_special", k, vmSymbols::object_initializer_name(), sig, CHECK); \
+  }
+#endif
+/**
+ * Computes and initializes the offsets used by HotSpotJVMCI.
+ */
+void HotSpotJVMCI::compute_offsets(TRAPS) {
+  JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, OBJECT_FIELD, OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECT_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_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+// ------------------------------------------------------------------
+
+#define START_CLASS(className, fullClassName)                                           \
+  void HotSpotJVMCI::className::initialize(JVMCI_TRAPS) {                               \
+    Thread* THREAD = Thread::current();                                                 \
+    className::klass()->initialize(CHECK);                                              \
+  }                                                                                     \
+  bool HotSpotJVMCI::className::is_instance(JVMCIEnv* env, JVMCIObject object) {        \
+    return resolve(object)->is_a(className::klass());                                   \
+  }                                                                                     \
+  void HotSpotJVMCI::className::check(oop obj, const char* field_name, int offset) {    \
+    assert(obj != NULL, "NULL field access of %s.%s", #className, field_name); \
+    assert(obj->is_a(className::klass()), "wrong class, " #className " expected, found %s", obj->klass()->external_name()); \
+    assert(offset != 0, "must be valid offset");                                        \
+  }                                                                                     \
+  InstanceKlass* HotSpotJVMCI::className::_klass = NULL;
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor, cast)                     \
+  type HotSpotJVMCI::className::name(JVMCIEnv* env, oop obj)               { className::check(obj, #name, className::_##name##_offset); return cast obj->accessor(className::_##name##_offset); } \
+  void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, oop obj, type x) { className::check(obj, #name, className::_##name##_offset); obj->accessor##_put(className::_##name##_offset, x); }
+
+#define EMPTY_CAST
+#define CHAR_FIELD(className, name) FIELD(className, name, jchar, char_field, EMPTY_CAST)
+#define INT_FIELD(className, name) FIELD(className, name, jint, int_field, EMPTY_CAST)
+#define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, bool_field, EMPTY_CAST)
+#define LONG_FIELD(className, name) FIELD(className, name, jlong, long_field, EMPTY_CAST)
+#define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, float_field, EMPTY_CAST)
+
+#define OBJECT_FIELD(className, name, signature) FIELD(className, name, oop, obj_field, EMPTY_CAST)
+#define OBJECTARRAY_FIELD(className, name, signature) FIELD(className, name, objArrayOop, obj_field, (objArrayOop))
+#define PRIMARRAY_FIELD(className, name, signature) FIELD(className, name, typeArrayOop, obj_field, (typeArrayOop))
+#define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, oop)
+#define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, objArrayOop)
+#define STATIC_OOPISH_FIELD(className, name, type)                                                                        \
+    type HotSpotJVMCI::className::name(JVMCIEnv* env) {                                                                   \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      oop result = HeapAccess<>::oop_load_at(base, className::_##name##_offset);                                          \
+      return type(result);                                                                                                \
+    }                                                                                                                     \
+    void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, type x) {                                                     \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      assert(className::klass() != NULL, "Class not yet loaded: " #className);                                            \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      HeapAccess<>::oop_store_at(base, className::_##name##_offset, x);                                                   \
+    }
+#define STATIC_PRIMITIVE_FIELD(className, name, jtypename)                                                                \
+    jtypename HotSpotJVMCI::className::get_##name(JVMCIEnv* env) {                                                        \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      return HeapAccess<>::load_at(base, className::_##name##_offset);                                                    \
+    }                                                                                                                     \
+    void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, jtypename x) {                                                \
+      assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className);         \
+      InstanceKlass* ik = className::klass();                                                                             \
+      oop base = ik->static_field_base_raw();                                                                             \
+      HeapAccess<>::store_at(base, _##name##_offset, x);                                                                  \
+    }
+
+#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint)
+#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean)
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+/**
+ * Generates the method and field definitions for the classes in HotSpotJVMCI. For example:
+ *
+ * void HotSpotJVMCI::Architecture::initialize(JVMCIEnv* env) { ... }
+ * bool HotSpotJVMCI::Architecture::is_instance(JVMCIEnv* env, JVMCIObject object) { ... }
+ * void HotSpotJVMCI::Architecture::check(oop obj, const char* field_name, int offset) { ... }
+ *  oop HotSpotJVMCI::Architecture::wordKind(JVMCIEnv* env, oop obj) { ... }
+ * void HotSpotJVMCI::Architecture::set_wordKind(JVMCIEnv* env, oop obj, oop x) { ... }
+ *
+ * InstanceKlass *HotSpotJVMCI::Architecture::_klass = NULL;
+ */
+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 STATIC_PRIMITIVE_FIELD
+#undef EMPTY_CAST
+
+/**
+ * Initializes the JNI id of a field. As per the JNI specification,
+ * this ensures the declaring class is initialized.
+ */
+void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, const char* class_name, const char* name, const char* signature, bool static_field) {
+  if (JVMCILibDumpJNIConfig != NULL) {
+    fileStream* st = JVMCIGlobals::get_jni_config_file();
+    st->print_cr("field %s %s %s", class_name, name, signature);
+    return;
+  }
+  if (env->ExceptionCheck()) {
+    return;
+  }
+  if (static_field) {
+    // Class initialization barrier
+    fieldid = env->GetStaticFieldID(clazz, name, signature);
+  } else {
+    // Class initialization barrier
+    fieldid = env->GetFieldID(clazz, name, signature);
+  }
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionDescribe();
+    env->ExceptionClear();
+    ResourceMark rm;
+    Thread* THREAD = Thread::current();
+    fatal("Could not find field %s.%s with signature %s", class_name, name, signature);
+  }
+}
 
+#define START_CLASS(className, fullClassName) {                                             \
+  current_class_name = vmSymbols::fullClassName()->as_C_string();                           \
+  if (JVMCILibDumpJNIConfig != NULL) {                                                      \
+    fileStream* st = JVMCIGlobals::get_jni_config_file();                                   \
+    st->print_cr("class %s", current_class_name);                                           \
+  } else {                                                                                  \
+    jclass k = env->FindClass(current_class_name);                                          \
+    JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", current_class_name);                        \
+    assert(k != NULL, #fullClassName " not initialized");                                   \
+    className::_class = (jclass) env->NewGlobalRef(k);                                      \
+  }
 
-void JVMCIJavaClasses::compute_offsets(TRAPS) {
-  COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+#define END_CLASS current_class_name = NULL; }
+
+#define FIELD(className, name, signature, static_field) initialize_field_id(env, className::_##name##_field_id, className::_class, current_class_name, #name, signature, static_field);
+#define CHAR_FIELD(className, name) FIELD(className, name, "C", false)
+#define INT_FIELD(className, name) FIELD(className, name, "I", false)
+#define BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", false)
+#define LONG_FIELD(className, name) FIELD(className, name, "J", false)
+#define FLOAT_FIELD(className, name) FIELD(className, name, "F", false)
+#define OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, false)
+#define STATIC_OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, true)
+#define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true)
+#define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true)
+
+#define GET_JNI_METHOD(jniGetMethod, dst, clazz, methodName, signature)                        \
+          if (JVMCILibDumpJNIConfig != NULL) {                                                       \
+            fileStream* st = JVMCIGlobals::get_jni_config_file();                                    \
+            st->print_cr("method %s %s %s", current_class_name, methodName, signature);              \
+          } else {                                                                                   \
+                  dst = env->jniGetMethod(clazz, methodName, signature);                                   \
+                  JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", current_class_name, methodName, signature); \
+                assert(dst != NULL, "uninitialized");                                          \
+          }
+
+#define GET_JNI_CONSTRUCTOR(clazz, signature) \
+  GET_JNI_METHOD(GetMethodID, JNIJVMCI::clazz::_constructor, clazz::_class, "<init>", signature) \
+
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+     GET_JNI_METHOD(jniGetMethod,                                        \
+                    className::_##methodName##_method,                   \
+                    className::clazz(),                                  \
+                    vmSymbols::methodName##_name()->as_C_string(),       \
+                    vmSymbols::signatureSymbolName()->as_C_string())
+
+#define CONSTRUCTOR(className, signature) \
+  GET_JNI_CONSTRUCTOR(className, signature)
+
+extern "C" {
+  void     JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
+  jobject  JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
 }
 
+#define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string()
+/**
+ * Initializes the JNI method and field ids used in JNIJVMCI.
+ */
+void JNIJVMCI::initialize_ids(JNIEnv* env) {
+  ResourceMark rm;
+  const char* current_class_name = NULL;
+  JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, OBJECT_FIELD, OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECT_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
+
+  IN_CLASS(java_lang_Class);
+  GET_JNI_METHOD(GetMethodID, _Class_getName_method, Class::_class, "getName", "()Ljava/lang/String;");
+
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedPrimitiveType_fromMetaspace_method, HotSpotResolvedPrimitiveType::_class,
+                                                                                          vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                          vmSymbols::primitive_fromMetaspace_signature()->as_C_string());
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedObjectTypeImpl_fromMetaspace_method, HotSpotResolvedObjectTypeImpl::_class,
+                                                                                           vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                           vmSymbols::klass_fromMetaspace_signature()->as_C_string());
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotConstantPool);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotConstantPool_fromMetaspace_method, HotSpotConstantPool::_class,
+                                                                                  vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                  vmSymbols::constantPool_fromMetaspace_signature()->as_C_string());
+  IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl);
+  GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedJavaMethodImpl_fromMetaspace_method, HotSpotResolvedJavaMethodImpl::_class,
+                                                                                           vmSymbols::fromMetaspace_name()->as_C_string(),
+                                                                                           vmSymbols::method_fromMetaspace_signature()->as_C_string());
+
+#define BOX_CLASSES(generate)     \
+  generate(Boolean, T_BOOLEAN, Z) \
+  generate(Byte, T_BYTE, B)       \
+  generate(Character, T_CHAR, C)  \
+  generate(Short, T_SHORT, S)     \
+  generate(Integer, T_INT, I)     \
+  generate(Long, T_LONG, J)       \
+  generate(Float, T_FLOAT, F)     \
+  generate(Double, T_DOUBLE, D)   \
+
+#define DO_BOX_CLASS(klass, basicType, type) \
+  current_class_name = "java/lang/" #klass;                                                                       \
+  if (JVMCILibDumpJNIConfig == NULL) {                                                                            \
+    _box_classes[basicType] = env->FindClass("java/lang/" #klass);                                                \
+    JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", #klass);                                                          \
+    _box_classes[basicType] = (jclass) env->NewGlobalRef(_box_classes[basicType]);                                \
+    assert(_box_classes[basicType] != NULL, "uninitialized");                                                     \
+    _box_fields[basicType] = env->GetFieldID(_box_classes[basicType], "value", #type);                            \
+    JVMCI_EXCEPTION_CHECK(env, "GetFieldID(%s, value, %s)", #klass, #type);                                       \
+    GET_JNI_METHOD(GetMethodID, _box_constructors[basicType], _box_classes[basicType], "<init>", "(" #type ")V"); \
+  } else {                                                                                                        \
+    fileStream* st = JVMCIGlobals::get_jni_config_file();                                                         \
+    st->print_cr("field %s value %s", current_class_name, #type);                                                 \
+    st->print_cr("method %s <init> (%s)V", current_class_name, #type);                                            \
+  }
+
+  BOX_CLASSES(DO_BOX_CLASS);
+
+  if (JVMCILibDumpJNIConfig == NULL) {
+    _byte_array = env->FindClass("[B");
+    JVMCI_EXCEPTION_CHECK(env, "FindClass([B)");
+    _byte_array = (jclass) env->NewGlobalRef(_byte_array);
+    assert(_byte_array != NULL, "uninitialized");
+  } else {
+    fileStream* st = JVMCIGlobals::get_jni_config_file();
+    st->print_cr("class [B");
+  }
+
+#define DUMP_ALL_NATIVE_METHODS(class_symbol) do {                                                                  \
+  current_class_name = class_symbol->as_C_string();                                                                 \
+  Klass* k = SystemDictionary::resolve_or_fail(class_symbol, true, CHECK_EXIT);                                     \
+  InstanceKlass* iklass = InstanceKlass::cast(k);                                                                   \
+  Array<Method*>* methods = iklass->methods();                                                                      \
+  for (int i = 0; i < methods->length(); i++) {                                                                     \
+    Method* m = methods->at(i);                                                                                     \
+    if (m->is_native()) {                                                                                           \
+      st->print_cr("method %s %s %s", current_class_name, m->name()->as_C_string(), m->signature()->as_C_string()); \
+    }                                                                                                               \
+  }                                                                                                                 \
+} while(0)
+
+  if (JVMCILibDumpJNIConfig != NULL) {
+    Thread* THREAD = Thread::current();
+    fileStream* st = JVMCIGlobals::get_jni_config_file();
+
+    DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
+
+    st->flush();
+    tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);
+    vm_exit(0);
+  }
+
+#undef DUMP_ALL_NATIVE_METHODS
+#undef DO_BOX_CLASS
+#undef BOX_CLASSES
+#undef IN_CLASS
+
+#define CC (char*)  /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f))
+
+  if (env != JavaThread::current()->jni_environment()) {
+    jclass clazz = env->FindClass("jdk/vm/ci/hotspot/CompilerToVM");
+    if (env->ExceptionCheck()) {
+      env->ExceptionDescribe();
+      guarantee(false, "Could not find class jdk/vm/ci/hotspot/CompilerToVM");
+    }
+    JNINativeMethod CompilerToVM_native_methods[] = {
+      { CC"registerNatives",     CC"()V", FN_PTR(JVM_RegisterJVMCINatives)     },
+    };
+    env->RegisterNatives(clazz, CompilerToVM_native_methods, 1);
+    if (env->ExceptionCheck()) {
+      env->ExceptionDescribe();
+      guarantee(false, "");
+    }
+
+    JNINativeMethod JVMCI_native_methods[] = {
+      { CC"initializeRuntime",   CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) },
+    };
+    env->RegisterNatives(JVMCI::clazz(), JVMCI_native_methods, 1);
+    if (env->ExceptionCheck()) {
+      env->ExceptionDescribe();
+      guarantee(false, "");
+    }
+  }
+}
+
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD2
+
 #define EMPTY0
 #define EMPTY1(x)
 #define EMPTY2(x,y)
-#define FIELD2(klass, name) int klass::_##name##_offset = 0;
-#define FIELD3(klass, name, sig) FIELD2(klass, name)
+#define FIELD3(className, name, sig) FIELD2(className, name)
+#define FIELD2(className, name) \
+  jfieldID JNIJVMCI::className::_##name##_field_id = 0; \
+  int HotSpotJVMCI::className::_##name##_offset = 0;
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+// Generates the definitions of static fields used by the accessors. For example:
+//  jfieldID JNIJVMCI::Architecture::_wordKind_field_id = 0;
+//  jfieldID HotSpotJVMCI::Architecture::_wordKind_offset = 0;
+JVMCI_CLASSES_DO(EMPTY2, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2, 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_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
+#undef STATIC_INT_FIELD
+#undef STATIC_BOOLEAN_FIELD
+#undef EMPTY_CAST
+
+
+#define START_CLASS(className, fullClassName)                                                                                     \
+  void JNIJVMCI::className::initialize(JVMCI_TRAPS) {                                                                             \
+    /* should already be initialized */                                                                                           \
+  }                                                                                                                               \
+  bool JNIJVMCI::className::is_instance(JVMCIEnv* jvmciEnv, JVMCIObject object) {                                                 \
+    JNIAccessMark jni(jvmciEnv);                                                                                                  \
+    return jni()->IsInstanceOf(object.as_jobject(), className::clazz()) != 0;                                                     \
+  }                                                                                                                               \
+  void JNIJVMCI::className::check(JVMCIEnv* jvmciEnv, JVMCIObject obj, const char* field_name, jfieldID offset) {                 \
+    assert(obj.is_non_null(), "NULL field access of %s.%s", #className, field_name);                                     \
+    assert(jvmciEnv->isa_##className(obj), "wrong class, " #className " expected, found %s", jvmciEnv->klass_name(obj)); \
+    assert(offset != 0, "must be valid offset");                                                                                  \
+  }                                                                                                                               \
+  jclass JNIJVMCI::className::_class = NULL;
+
+#define END_CLASS
+
+#define FIELD(className, name, type, accessor, cast)                                                                \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj) {                                       \
+   className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                                           \
+   JNIAccessMark jni(jvmciEnv);                               \
+   return cast jni()->Get##accessor##Field(resolve_handle(obj), className::_##name##_field_id); \
+  }                                                                                                                 \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x) {                               \
+    className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                                          \
+    JNIAccessMark jni(jvmciEnv); \
+    jni()->Set##accessor##Field(resolve_handle(obj), className::_##name##_field_id, 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)
 
-COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2)
+#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 JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj) {                           \
+    className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                              \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    return cast wrap(jni()->Get##accessor##Field(resolve_handle(obj), className::_##name##_field_id));  \
+  }                                                                                                     \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x) {                   \
+    className::check(jvmciEnv, obj, #name, className::_##name##_field_id);                              \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    jni()->Set##accessor##Field(resolve_handle(obj), className::_##name##_field_id, resolve_handle(x)); \
+  }
+
+#define STATIC_OOPISH_FIELD(className, name, type, accessor, cast)                                      \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv) {                                            \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    return cast wrap(jni()->GetStatic##accessor##Field(className::clazz(), className::_##name##_field_id));  \
+  }                                                                                                     \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, type x) {                                    \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    jni()->SetStatic##accessor##Field(className::clazz(), className::_##name##_field_id, resolve_handle(x)); \
+  }
 
+#define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast)                                   \
+  type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv) {                                            \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    return cast jni()->GetStatic##accessor##Field(className::clazz(), className::_##name##_field_id);   \
+  }                                                                                                     \
+  void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, type x) {                                    \
+    JNIAccessMark jni(jvmciEnv);                                                                        \
+    jni()->SetStatic##accessor##Field(className::clazz(), className::_##name##_field_id, 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) \
+  jmethodID JNIJVMCI::className::_##methodName##_method;
+
+#define CONSTRUCTOR(className, signature) \
+  jmethodID JNIJVMCI::className::_constructor;
+
+/**
+ * Generates the method definitions for the classes in HotSpotJVMCI.
+ */
+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 METHOD
+#undef CONSTRUCTOR
+#undef START_CLASS
+#undef END_CLASS
+#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 STATIC_PRIMITIVE_FIELD
+#undef OOPISH_FIELD
+#undef EMPTY_CAST
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Wed May 01 12:31:29 2019 -0700
@@ -24,361 +24,644 @@
 #ifndef SHARE_JVMCI_JVMCIJAVACLASSES_HPP
 #define SHARE_JVMCI_JVMCIJAVACLASSES_HPP
 
-#include "classfile/systemDictionary.hpp"
-#include "oops/access.hpp"
-#include "oops/instanceMirrorKlass.hpp"
-#include "oops/oop.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "jvmci/jvmciExceptions.hpp"
+#include "jvmci/jvmciObject.hpp"
+#include "runtime/jniHandles.hpp"
 
-class JVMCIJavaClasses : AllStatic {
- public:
-  static void compute_offsets(TRAPS);
-};
-
-/* This macro defines the structure of the JVMCI classes accessed from VM code.
- * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles.
+/*
+ * This macro defines the structure of the JVMCI classes accessed from VM code.  It is used to
+ * generate accessors similar to javaClasses.hpp, but with specializations for HotSpot and JNI based
+ * access.
  *
- * The public interface of these classes will look like this:
-
- * class StackSlot : AllStatic {
- * public:
- *   static Klass* klass();
- *   static jint  index(oop obj);
- *   static jint  index(Handle obj);
- *   static jint  index(jobject obj);
- *   static void set_index(oop obj, jint x);
- *   static void set_index(Handle obj, jint x);
- *   static void set_index(jobject obj, jint x);
- * };
+ * HotSpotJVMCI: This class contains accessors based on the VM internal
+ * interface to Java. It is used for JVMCI Java code executing on the HotSpot heap.
  *
+ * JNIJVMCI: This class contains JNI based accessors and is used for JVMCI
+ * Java code executing in the JVMCI shared library.
  */
 
-#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, typeArrayOop_field, objArrayOop_field, static_oop_field, static_objArrayOop_field, static_int_field, static_boolean_field) \
-  start_class(Architecture)                                                                                                                                    \
-    oop_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;")                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(TargetDescription)                                                                                                                               \
-    oop_field(TargetDescription, arch, "Ljdk/vm/ci/code/Architecture;")                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotResolvedObjectTypeImpl)                                                                                                                   \
-    oop_field(HotSpotResolvedObjectTypeImpl, javaClass, "Ljava/lang/Class;")                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotResolvedJavaMethodImpl)                                                                                                                   \
-    long_field(HotSpotResolvedJavaMethodImpl, metaspaceMethod)                                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(InstalledCode)                                                                                                                                   \
-    long_field(InstalledCode, address)                                                                                                                         \
-    long_field(InstalledCode, entryPoint)                                                                                                                      \
-    long_field(InstalledCode, version)                                                                                                                         \
-    oop_field(InstalledCode, name, "Ljava/lang/String;")                                                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotInstalledCode)                                                                                                                            \
-    int_field(HotSpotInstalledCode, size)                                                                                                                      \
-    long_field(HotSpotInstalledCode, codeStart)                                                                                                                \
-    int_field(HotSpotInstalledCode, codeSize)                                                                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotNmethod)                                                                                                                                  \
-    boolean_field(HotSpotNmethod, isDefault)                                                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledCode)                                                                                                                             \
-    oop_field(HotSpotCompiledCode, name, "Ljava/lang/String;")                                                                                                 \
-    typeArrayOop_field(HotSpotCompiledCode, targetCode, "[B")                                                                                                  \
-    int_field(HotSpotCompiledCode, targetCodeSize)                                                                                                             \
-    objArrayOop_field(HotSpotCompiledCode, sites, "[Ljdk/vm/ci/code/site/Site;")                                                                               \
-    objArrayOop_field(HotSpotCompiledCode, assumptions, "[Ljdk/vm/ci/meta/Assumptions$Assumption;")                                                            \
-    objArrayOop_field(HotSpotCompiledCode, methods, "[Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                    \
-    objArrayOop_field(HotSpotCompiledCode, comments, "[Ljdk/vm/ci/hotspot/HotSpotCompiledCode$Comment;")                                                       \
-    typeArrayOop_field(HotSpotCompiledCode, dataSection, "[B")                                                                                                 \
-    int_field(HotSpotCompiledCode, dataSectionAlignment)                                                                                                       \
-    objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/site/DataPatch;")                                                             \
-    boolean_field(HotSpotCompiledCode, isImmutablePIC)                                                                                                         \
-    int_field(HotSpotCompiledCode, totalFrameSize)                                                                                                             \
-    oop_field(HotSpotCompiledCode, deoptRescueSlot, "Ljdk/vm/ci/code/StackSlot;")                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledCode_Comment)                                                                                                                     \
-    oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                                                                         \
-    int_field(HotSpotCompiledCode_Comment, pcOffset)                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompiledNmethod)                                                                                                                          \
-    oop_field(HotSpotCompiledNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                                                                 \
-    oop_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;")                                                                        \
-    int_field(HotSpotCompiledNmethod, entryBCI)                                                                                                                \
-    int_field(HotSpotCompiledNmethod, id)                                                                                                                      \
-    long_field(HotSpotCompiledNmethod, jvmciEnv)                                                                                                               \
-    boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess)                                                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotJVMCIMetaAccessContext)                                                                                                                   \
-    static_objArrayOop_field(HotSpotJVMCIMetaAccessContext, allContexts, "[Ljava/lang/ref/WeakReference;")                                                     \
-    objArrayOop_field(HotSpotJVMCIMetaAccessContext, metadataRoots, "[Ljava/lang/Object;")                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotForeignCallTarget)                                                                                                                        \
-    long_field(HotSpotForeignCallTarget, address)                                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(VMField)                                                                                                                                         \
-    oop_field(VMField, name, "Ljava/lang/String;")                                                                                                             \
-    oop_field(VMField, type, "Ljava/lang/String;")                                                                                                             \
-    long_field(VMField, offset)                                                                                                                                \
-    long_field(VMField, address)                                                                                                                               \
-    oop_field(VMField, value, "Ljava/lang/Object;")                                                                                                            \
-  end_class                                                                                                                                                    \
-  start_class(VMFlag)                                                                                                                                          \
-    oop_field(VMFlag, name, "Ljava/lang/String;")                                                                                                              \
-    oop_field(VMFlag, type, "Ljava/lang/String;")                                                                                                              \
-    oop_field(VMFlag, value, "Ljava/lang/Object;")                                                                                                             \
-  end_class                                                                                                                                                    \
-  start_class(VMIntrinsicMethod)                                                                                                                               \
-    oop_field(VMIntrinsicMethod, declaringClass, "Ljava/lang/String;")                                                                                         \
-    oop_field(VMIntrinsicMethod, name, "Ljava/lang/String;")                                                                                                   \
-    oop_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;")                                                                                             \
-    int_field(VMIntrinsicMethod, id)                                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_NoFinalizableSubclass)                                                                                                               \
-    oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                            \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_ConcreteSubtype)                                                                                                                     \
-    oop_field(Assumptions_ConcreteSubtype, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                       \
-    oop_field(Assumptions_ConcreteSubtype, subtype, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_LeafType)                                                                                                                            \
-    oop_field(Assumptions_LeafType, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_ConcreteMethod)                                                                                                                      \
-    oop_field(Assumptions_ConcreteMethod, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                       \
-    oop_field(Assumptions_ConcreteMethod, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                        \
-    oop_field(Assumptions_ConcreteMethod, impl, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(Assumptions_CallSiteTargetValue)                                                                                                                 \
-    oop_field(Assumptions_CallSiteTargetValue, callSite, "Ljdk/vm/ci/meta/JavaConstant;")                                                                      \
-    oop_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljdk/vm/ci/meta/JavaConstant;")                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(site_Site)                                                                                                                                       \
-    int_field(site_Site, pcOffset)                                                                                                                             \
-  end_class                                                                                                                                                    \
-  start_class(site_Call)                                                                                                                                       \
-    oop_field(site_Call, target, "Ljdk/vm/ci/meta/InvokeTarget;")                                                                                              \
-    oop_field(site_Call, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(site_DataPatch)                                                                                                                                  \
-    oop_field(site_DataPatch, reference, "Ljdk/vm/ci/code/site/Reference;")                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(site_ConstantReference)                                                                                                                          \
-    oop_field(site_ConstantReference, constant, "Ljdk/vm/ci/meta/VMConstant;")                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(site_DataSectionReference)                                                                                                                       \
-    int_field(site_DataSectionReference, offset)                                                                                                               \
-  end_class                                                                                                                                                    \
-  start_class(site_InfopointReason)                                                                                                                            \
-    static_oop_field(site_InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                 \
-    static_oop_field(site_InfopointReason, CALL, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                      \
-    static_oop_field(site_InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/site/InfopointReason;")                                                        \
-  end_class                                                                                                                                                    \
-  start_class(site_Infopoint)                                                                                                                                  \
-    oop_field(site_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                                                                         \
-    oop_field(site_Infopoint, reason, "Ljdk/vm/ci/code/site/InfopointReason;")                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(site_ExceptionHandler)                                                                                                                           \
-    int_field(site_ExceptionHandler, handlerPos)                                                                                                               \
-  end_class                                                                                                                                                    \
-  start_class(site_Mark)                                                                                                                                       \
-    oop_field(site_Mark, id, "Ljava/lang/Object;")                                                                                                             \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompilationRequestResult)                                                                                                                 \
-    oop_field(HotSpotCompilationRequestResult, failureMessage, "Ljava/lang/String;")                                                                           \
-    boolean_field(HotSpotCompilationRequestResult, retry)                                                                                                      \
-    int_field(HotSpotCompilationRequestResult, inlinedBytecodes)                                                                                               \
-  end_class                                                                                                                                                    \
-  start_class(DebugInfo)                                                                                                                                       \
-    oop_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;")                                                                                \
-    oop_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;")                                                                                        \
-    oop_field(DebugInfo, calleeSaveInfo, "Ljdk/vm/ci/code/RegisterSaveLayout;")                                                                                \
-    objArrayOop_field(DebugInfo, virtualObjectMapping, "[Ljdk/vm/ci/code/VirtualObject;")                                                                      \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotReferenceMap)                                                                                                                             \
-    objArrayOop_field(HotSpotReferenceMap, objects, "[Ljdk/vm/ci/code/Location;")                                                                              \
-    objArrayOop_field(HotSpotReferenceMap, derivedBase, "[Ljdk/vm/ci/code/Location;")                                                                          \
-    typeArrayOop_field(HotSpotReferenceMap, sizeInBytes, "[I")                                                                                                 \
-    int_field(HotSpotReferenceMap, maxRegisterSize)                                                                                                            \
-  end_class                                                                                                                                                    \
-  start_class(RegisterSaveLayout)                                                                                                                              \
-    objArrayOop_field(RegisterSaveLayout, registers, "[Ljdk/vm/ci/code/Register;")                                                                             \
-    typeArrayOop_field(RegisterSaveLayout, slots, "[I")                                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(BytecodeFrame)                                                                                                                                   \
-    objArrayOop_field(BytecodeFrame, values, "[Ljdk/vm/ci/meta/JavaValue;")                                                                                    \
-    objArrayOop_field(BytecodeFrame, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                                                                  \
-    int_field(BytecodeFrame, numLocals)                                                                                                                        \
-    int_field(BytecodeFrame, numStack)                                                                                                                         \
-    int_field(BytecodeFrame, numLocks)                                                                                                                         \
-    boolean_field(BytecodeFrame, rethrowException)                                                                                                             \
-    boolean_field(BytecodeFrame, duringCall)                                                                                                                   \
-    static_int_field(BytecodeFrame, UNKNOWN_BCI)                                                                                                               \
-    static_int_field(BytecodeFrame, UNWIND_BCI)                                                                                                                \
-    static_int_field(BytecodeFrame, BEFORE_BCI)                                                                                                                \
-    static_int_field(BytecodeFrame, AFTER_BCI)                                                                                                                 \
-    static_int_field(BytecodeFrame, AFTER_EXCEPTION_BCI)                                                                                                       \
-    static_int_field(BytecodeFrame, INVALID_FRAMESTATE_BCI)                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(BytecodePosition)                                                                                                                                \
-    oop_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;")                                                                                   \
-    oop_field(BytecodePosition, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                                                                                 \
-    int_field(BytecodePosition, bci)                                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(JavaConstant)                                                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(PrimitiveConstant)                                                                                                                               \
-    oop_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;")                                                                                            \
-    long_field(PrimitiveConstant, primitive)                                                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(RawConstant)                                                                                                                                     \
-    long_field(RawConstant, primitive)                                                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(NullConstant)                                                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotCompressedNullConstant)                                                                                                                   \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotObjectConstantImpl)                                                                                                                       \
-    oop_field(HotSpotObjectConstantImpl, object, "Ljava/lang/Object;")                                                                                         \
-    boolean_field(HotSpotObjectConstantImpl, compressed)                                                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotMetaspaceConstantImpl)                                                                                                                    \
-    oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceWrapperObject;")                                                     \
-    boolean_field(HotSpotMetaspaceConstantImpl, compressed)                                                                                                    \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotSentinelConstant)                                                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(JavaKind)                                                                                                                                        \
-    char_field(JavaKind, typeChar)                                                                                                                             \
-    static_oop_field(JavaKind, Boolean, "Ljdk/vm/ci/meta/JavaKind;")                                                                                           \
-    static_oop_field(JavaKind, Byte, "Ljdk/vm/ci/meta/JavaKind;")                                                                                              \
-    static_oop_field(JavaKind, Char, "Ljdk/vm/ci/meta/JavaKind;")                                                                                              \
-    static_oop_field(JavaKind, Short, "Ljdk/vm/ci/meta/JavaKind;")                                                                                             \
-    static_oop_field(JavaKind, Int, "Ljdk/vm/ci/meta/JavaKind;")                                                                                               \
-    static_oop_field(JavaKind, Long, "Ljdk/vm/ci/meta/JavaKind;")                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(ValueKind)                                                                                                                                       \
-    oop_field(ValueKind, platformKind, "Ljdk/vm/ci/meta/PlatformKind;")                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(Value)                                                                                                                                           \
-    oop_field(Value, valueKind, "Ljdk/vm/ci/meta/ValueKind;")                                                                                                  \
-    static_oop_field(Value, ILLEGAL, "Ljdk/vm/ci/meta/AllocatableValue;")                                                                                      \
-  end_class                                                                                                                                                    \
-  start_class(RegisterValue)                                                                                                                                   \
-    oop_field(RegisterValue, reg, "Ljdk/vm/ci/code/Register;")                                                                                                 \
-  end_class                                                                                                                                                    \
-  start_class(code_Location)                                                                                                                                   \
-    oop_field(code_Location, reg, "Ljdk/vm/ci/code/Register;")                                                                                                 \
-    int_field(code_Location, offset)                                                                                                                           \
-  end_class                                                                                                                                                    \
-  start_class(code_Register)                                                                                                                                   \
-    int_field(code_Register, number)                                                                                                                           \
-    int_field(code_Register, encoding)                                                                                                                         \
-  end_class                                                                                                                                                    \
-  start_class(StackSlot)                                                                                                                                       \
-    int_field(StackSlot, offset)                                                                                                                               \
-    boolean_field(StackSlot, addFrameSize)                                                                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(VirtualObject)                                                                                                                                   \
-    int_field(VirtualObject, id)                                                                                                                               \
-    oop_field(VirtualObject, type, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                                                                        \
-    objArrayOop_field(VirtualObject, values, "[Ljdk/vm/ci/meta/JavaValue;")                                                                                    \
-    objArrayOop_field(VirtualObject, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(StackLockValue)                                                                                                                                  \
-    oop_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;")                                                                                             \
-    oop_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;")                                                                                       \
-    boolean_field(StackLockValue, eliminated)                                                                                                                  \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotSpeculationLog)                                                                                                                           \
-    long_field(HotSpotSpeculationLog, lastFailed)                                                                                                              \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotStackFrameReference)                                                                                                                      \
-    oop_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;")                                                                    \
-    boolean_field(HotSpotStackFrameReference, objectsMaterialized)                                                                                             \
-    long_field(HotSpotStackFrameReference, stackPointer)                                                                                                       \
-    int_field(HotSpotStackFrameReference, frameNumber)                                                                                                         \
-    int_field(HotSpotStackFrameReference, bci)                                                                                                                 \
-    oop_field(HotSpotStackFrameReference, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                                                             \
-    objArrayOop_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;")                                                                               \
-    typeArrayOop_field(HotSpotStackFrameReference, localIsVirtual, "[Z")                                                                                       \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotMetaData)                                                                                                                                 \
-    typeArrayOop_field(HotSpotMetaData, pcDescBytes, "[B")                                                                                                     \
-    typeArrayOop_field(HotSpotMetaData, scopesDescBytes, "[B")                                                                                                 \
-    typeArrayOop_field(HotSpotMetaData, relocBytes, "[B")                                                                                                      \
-    typeArrayOop_field(HotSpotMetaData, exceptionBytes, "[B")                                                                                                  \
-    typeArrayOop_field(HotSpotMetaData, oopMaps, "[B")                                                                                                         \
-    objArrayOop_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;")                                                                                        \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotConstantPool)                                                                                                                             \
-    long_field(HotSpotConstantPool, metaspaceConstantPool)                                                                                                     \
-  end_class                                                                                                                                                    \
-  start_class(HotSpotJVMCIRuntime)                                                                                                                             \
-    objArrayOop_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;")                                                                 \
-  end_class                                                                                                                                                    \
+#define 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, \
+                         jvmci_method, \
+                         jvmci_constructor) \
+  start_class(Services, jdk_vm_ci_services_Services)                                                          \
+    jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, Services, initializeSavedProperties, byte_array_void_signature, (JVMCIObject serializedProperties)) \
+  end_class                                                                                                   \
+  start_class(Architecture, jdk_vm_ci_code_Architecture)                                                      \
+    object_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;")                                     \
+  end_class                                                                                                   \
+  start_class(TargetDescription, jdk_vm_ci_code_TargetDescription)                                            \
+    object_field(TargetDescription, arch, "Ljdk/vm/ci/code/Architecture;")                                    \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedObjectTypeImpl, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl)                 \
+    long_field(HotSpotResolvedObjectTypeImpl, metadataPointer)                                                \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedPrimitiveType, jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType)                   \
+    object_field(HotSpotResolvedPrimitiveType, mirror, "Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;")       \
+  object_field(HotSpotResolvedPrimitiveType, kind, "Ljdk/vm/ci/meta/JavaKind;")                               \
+    static_objectarray_field(HotSpotResolvedPrimitiveType, primitives, "[Ljdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType;") \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedJavaFieldImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl)                   \
+    object_field(HotSpotResolvedJavaFieldImpl, type, "Ljdk/vm/ci/meta/JavaType;")                             \
+    object_field(HotSpotResolvedJavaFieldImpl, holder, "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;")   \
+    int_field(HotSpotResolvedJavaFieldImpl, offset)                                                           \
+    int_field(HotSpotResolvedJavaFieldImpl, modifiers)                                                        \
+  end_class                                                                                                   \
+  start_class(HotSpotResolvedJavaMethodImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl)                 \
+    long_field(HotSpotResolvedJavaMethodImpl, metadataHandle)                                                 \
+  end_class                                                                                                   \
+  start_class(InstalledCode, jdk_vm_ci_code_InstalledCode)                                                    \
+    long_field(InstalledCode, address)                                                                        \
+    long_field(InstalledCode, entryPoint)                                                                     \
+    long_field(InstalledCode, version)                                                                        \
+    object_field(InstalledCode, name, "Ljava/lang/String;")                                                   \
+  end_class                                                                                                   \
+  start_class(HotSpotInstalledCode, jdk_vm_ci_hotspot_HotSpotInstalledCode)                                   \
+    int_field(HotSpotInstalledCode, size)                                                                     \
+    long_field(HotSpotInstalledCode, codeStart)                                                               \
+    int_field(HotSpotInstalledCode, codeSize)                                                                 \
+  end_class                                                                                                   \
+  start_class(HotSpotNmethod, jdk_vm_ci_hotspot_HotSpotNmethod)                                               \
+    boolean_field(HotSpotNmethod, isDefault)                                                                  \
+    long_field(HotSpotNmethod, compileIdSnapshot)                                                             \
+    object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;")                 \
+    jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
+  end_class                                                                                                   \
+  start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode)                                     \
+    object_field(HotSpotCompiledCode, name, "Ljava/lang/String;")                                             \
+    primarray_field(HotSpotCompiledCode, targetCode, "[B")                                                    \
+    int_field(HotSpotCompiledCode, targetCodeSize)                                                            \
+    objectarray_field(HotSpotCompiledCode, sites, "[Ljdk/vm/ci/code/site/Site;")                              \
+    objectarray_field(HotSpotCompiledCode, assumptions, "[Ljdk/vm/ci/meta/Assumptions$Assumption;")           \
+    objectarray_field(HotSpotCompiledCode, methods, "[Ljdk/vm/ci/meta/ResolvedJavaMethod;")                   \
+    objectarray_field(HotSpotCompiledCode, comments, "[Ljdk/vm/ci/hotspot/HotSpotCompiledCode$Comment;")      \
+    primarray_field(HotSpotCompiledCode, dataSection, "[B")                                                   \
+    int_field(HotSpotCompiledCode, dataSectionAlignment)                                                      \
+    objectarray_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/site/DataPatch;")            \
+    boolean_field(HotSpotCompiledCode, isImmutablePIC)                                                        \
+    int_field(HotSpotCompiledCode, totalFrameSize)                                                            \
+    object_field(HotSpotCompiledCode, deoptRescueSlot, "Ljdk/vm/ci/code/StackSlot;")                          \
+  end_class                                                                                                   \
+  start_class(HotSpotCompiledCode_Comment, jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment)                     \
+    object_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;")                                     \
+    int_field(HotSpotCompiledCode_Comment, pcOffset)                                                          \
+  end_class                                                                                                   \
+  start_class(HotSpotCompiledNmethod, jdk_vm_ci_hotspot_HotSpotCompiledNmethod)                               \
+    object_field(HotSpotCompiledNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")             \
+    object_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;")                    \
+    int_field(HotSpotCompiledNmethod, entryBCI)                                                               \
+    int_field(HotSpotCompiledNmethod, id)                                                                     \
+    long_field(HotSpotCompiledNmethod, compileState)                                                           \
+    boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess)                                                    \
+  end_class                                                                                                   \
+  start_class(HotSpotForeignCallTarget, jdk_vm_ci_hotspot_HotSpotForeignCallTarget)                           \
+    long_field(HotSpotForeignCallTarget, address)                                                             \
+  end_class                                                                                                   \
+  start_class(VMField, jdk_vm_ci_hotspot_VMField)                                                             \
+    object_field(VMField, name, "Ljava/lang/String;")                                                         \
+    object_field(VMField, type, "Ljava/lang/String;")                                                         \
+    long_field(VMField, offset)                                                                               \
+    long_field(VMField, address)                                                                              \
+    object_field(VMField, value, "Ljava/lang/Object;")                                                        \
+    jvmci_constructor(VMField, "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/Object;)V")                 \
+  end_class                                                                                                   \
+  start_class(VMFlag, jdk_vm_ci_hotspot_VMFlag)                                                               \
+    object_field(VMFlag, name, "Ljava/lang/String;")                                                          \
+    object_field(VMFlag, type, "Ljava/lang/String;")                                                          \
+    object_field(VMFlag, value, "Ljava/lang/Object;")                                                         \
+    jvmci_constructor(VMFlag, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V")                    \
+  end_class                                                                                                   \
+  start_class(VMIntrinsicMethod, jdk_vm_ci_hotspot_VMIntrinsicMethod)                                         \
+    object_field(VMIntrinsicMethod, declaringClass, "Ljava/lang/String;")                                     \
+    object_field(VMIntrinsicMethod, name, "Ljava/lang/String;")                                               \
+    object_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;")                                         \
+    int_field(VMIntrinsicMethod, id)                                                                          \
+    jvmci_constructor(VMIntrinsicMethod, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")        \
+  end_class                                                                                                   \
+  start_class(Assumptions_NoFinalizableSubclass, jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass)            \
+    object_field(Assumptions_NoFinalizableSubclass, receiverType, "Ljdk/vm/ci/meta/ResolvedJavaType;")        \
+  end_class                                                                                                   \
+  start_class(Assumptions_ConcreteSubtype, jdk_vm_ci_meta_Assumptions_ConcreteSubtype)                        \
+    object_field(Assumptions_ConcreteSubtype, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                   \
+    object_field(Assumptions_ConcreteSubtype, subtype, "Ljdk/vm/ci/meta/ResolvedJavaType;")                   \
+  end_class                                                                                                   \
+  start_class(Assumptions_LeafType, jdk_vm_ci_meta_Assumptions_LeafType)                                      \
+    object_field(Assumptions_LeafType, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                          \
+  end_class                                                                                                   \
+  start_class(Assumptions_ConcreteMethod, jdk_vm_ci_meta_Assumptions_ConcreteMethod)                          \
+    object_field(Assumptions_ConcreteMethod, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                   \
+    object_field(Assumptions_ConcreteMethod, context, "Ljdk/vm/ci/meta/ResolvedJavaType;")                    \
+    object_field(Assumptions_ConcreteMethod, impl, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                     \
+  end_class                                                                                                   \
+  start_class(Assumptions_CallSiteTargetValue, jdk_vm_ci_meta_Assumptions_CallSiteTargetValue)                \
+    object_field(Assumptions_CallSiteTargetValue, callSite, "Ljdk/vm/ci/meta/JavaConstant;")                  \
+    object_field(Assumptions_CallSiteTargetValue, methodHandle, "Ljdk/vm/ci/meta/JavaConstant;")              \
+  end_class                                                                                                   \
+  start_class(site_Site, jdk_vm_ci_code_site_Site)                                                            \
+    int_field(site_Site, pcOffset)                                                                            \
+  end_class                                                                                                   \
+  start_class(site_Call, jdk_vm_ci_code_site_Call)                                                            \
+    object_field(site_Call, target, "Ljdk/vm/ci/meta/InvokeTarget;")                                          \
+  end_class                                                                                                   \
+  start_class(site_DataPatch, jdk_vm_ci_code_site_DataPatch)                                                  \
+    object_field(site_DataPatch, reference, "Ljdk/vm/ci/code/site/Reference;")                                \
+  end_class                                                                                                   \
+  start_class(site_ConstantReference, jdk_vm_ci_code_site_ConstantReference)                                  \
+    object_field(site_ConstantReference, constant, "Ljdk/vm/ci/meta/VMConstant;")                             \
+  end_class                                                                                                   \
+  start_class(site_DataSectionReference, jdk_vm_ci_code_site_DataSectionReference)                            \
+    int_field(site_DataSectionReference, offset)                                                              \
+  end_class                                                                                                   \
+  start_class(site_InfopointReason, jdk_vm_ci_code_site_InfopointReason)                                      \
+    static_object_field(site_InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/site/InfopointReason;")             \
+    static_object_field(site_InfopointReason, CALL, "Ljdk/vm/ci/code/site/InfopointReason;")                  \
+    static_object_field(site_InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/site/InfopointReason;")    \
+  end_class                                                                                                   \
+  start_class(site_Infopoint, jdk_vm_ci_code_site_Infopoint)                                                  \
+    object_field(site_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;")                                     \
+    object_field(site_Infopoint, reason, "Ljdk/vm/ci/code/site/InfopointReason;")                             \
+  end_class                                                                                                   \
+  start_class(site_ExceptionHandler, jdk_vm_ci_code_site_ExceptionHandler)                                    \
+    int_field(site_ExceptionHandler, handlerPos)                                                              \
+  end_class                                                                                                   \
+  start_class(site_Mark, jdk_vm_ci_code_site_Mark)                                                            \
+    object_field(site_Mark, id, "Ljava/lang/Object;")                                                         \
+  end_class                                                                                                   \
+  start_class(HotSpotCompilationRequestResult, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult)             \
+    object_field(HotSpotCompilationRequestResult, failureMessage, "Ljava/lang/String;")                       \
+    boolean_field(HotSpotCompilationRequestResult, retry)                                                     \
+    int_field(HotSpotCompilationRequestResult, inlinedBytecodes)                                              \
+  end_class                                                                                                   \
+  start_class(DebugInfo, jdk_vm_ci_code_DebugInfo)                                                            \
+    object_field(DebugInfo, bytecodePosition, "Ljdk/vm/ci/code/BytecodePosition;")                            \
+    object_field(DebugInfo, referenceMap, "Ljdk/vm/ci/code/ReferenceMap;")                                    \
+    object_field(DebugInfo, calleeSaveInfo, "Ljdk/vm/ci/code/RegisterSaveLayout;")                            \
+    objectarray_field(DebugInfo, virtualObjectMapping, "[Ljdk/vm/ci/code/VirtualObject;")                     \
+  end_class                                                                                                   \
+  start_class(HotSpotReferenceMap, jdk_vm_ci_hotspot_HotSpotReferenceMap)                                     \
+    objectarray_field(HotSpotReferenceMap, objects, "[Ljdk/vm/ci/code/Location;")                             \
+    objectarray_field(HotSpotReferenceMap, derivedBase, "[Ljdk/vm/ci/code/Location;")                         \
+    primarray_field(HotSpotReferenceMap, sizeInBytes, "[I")                                                   \
+    int_field(HotSpotReferenceMap, maxRegisterSize)                                                           \
+  end_class                                                                                                   \
+  start_class(RegisterSaveLayout, jdk_vm_ci_code_RegisterSaveLayout)                                          \
+    objectarray_field(RegisterSaveLayout, registers, "[Ljdk/vm/ci/code/Register;")                            \
+    primarray_field(RegisterSaveLayout, slots, "[I")                                                          \
+  end_class                                                                                                   \
+  start_class(BytecodeFrame, jdk_vm_ci_code_BytecodeFrame)                                                    \
+    objectarray_field(BytecodeFrame, values, "[Ljdk/vm/ci/meta/JavaValue;")                                   \
+    objectarray_field(BytecodeFrame, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                 \
+    int_field(BytecodeFrame, numLocals)                                                                       \
+    int_field(BytecodeFrame, numStack)                                                                        \
+    int_field(BytecodeFrame, numLocks)                                                                        \
+    boolean_field(BytecodeFrame, rethrowException)                                                            \
+    boolean_field(BytecodeFrame, duringCall)                                                                  \
+    static_int_field(BytecodeFrame, UNKNOWN_BCI)                                                              \
+    static_int_field(BytecodeFrame, UNWIND_BCI)                                                               \
+    static_int_field(BytecodeFrame, BEFORE_BCI)                                                               \
+    static_int_field(BytecodeFrame, AFTER_BCI)                                                                \
+    static_int_field(BytecodeFrame, AFTER_EXCEPTION_BCI)                                                      \
+    static_int_field(BytecodeFrame, INVALID_FRAMESTATE_BCI)                                                   \
+  end_class                                                                                                   \
+  start_class(BytecodePosition, jdk_vm_ci_code_BytecodePosition)                                              \
+    object_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;")                               \
+    object_field(BytecodePosition, method, "Ljdk/vm/ci/meta/ResolvedJavaMethod;")                             \
+    int_field(BytecodePosition, bci)                                                                          \
+  end_class                                                                                                   \
+  start_class(JavaConstant, jdk_vm_ci_meta_JavaConstant)                                                      \
+    static_object_field(JavaConstant, NULL_POINTER, "Ljdk/vm/ci/meta/JavaConstant;")                          \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forFloat, forFloat_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forDouble, forDouble_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(ResolvedJavaMethod, jdk_vm_ci_meta_ResolvedJavaMethod)                                          \
+  end_class                                                                                                   \
+  start_class(PrimitiveConstant, jdk_vm_ci_meta_PrimitiveConstant)                                            \
+    object_field(PrimitiveConstant, kind, "Ljdk/vm/ci/meta/JavaKind;")                                        \
+    long_field(PrimitiveConstant, primitive)                                                                  \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, PrimitiveConstant, forTypeChar, forTypeChar_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(RawConstant, jdk_vm_ci_meta_RawConstant)                                                        \
+  end_class                                                                                                   \
+  start_class(NullConstant, jdk_vm_ci_meta_NullConstant)                                                      \
+  end_class                                                                                                   \
+  start_class(HotSpotCompressedNullConstant, jdk_vm_ci_hotspot_HotSpotCompressedNullConstant)                 \
+  end_class                                                                                                   \
+  start_class(HotSpotObjectConstantImpl, jdk_vm_ci_hotspot_HotSpotObjectConstantImpl)                         \
+    boolean_field(HotSpotObjectConstantImpl, compressed)                                                      \
+  end_class                                                                                                   \
+  start_class(DirectHotSpotObjectConstantImpl, jdk_vm_ci_hotspot_DirectHotSpotObjectConstantImpl)             \
+    object_field(DirectHotSpotObjectConstantImpl, object, "Ljava/lang/Object;")                               \
+    jvmci_constructor(DirectHotSpotObjectConstantImpl, "(Ljava/lang/Object;Z)V")                              \
+  end_class                                                                                                   \
+  start_class(IndirectHotSpotObjectConstantImpl, jdk_vm_ci_hotspot_IndirectHotSpotObjectConstantImpl)         \
+    long_field(IndirectHotSpotObjectConstantImpl, objectHandle)                                               \
+    jvmci_constructor(IndirectHotSpotObjectConstantImpl, "(JZZ)V")                                            \
+  end_class                                                                                                   \
+  start_class(HotSpotMetaspaceConstantImpl, jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl)                   \
+    object_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceObject;")        \
+    boolean_field(HotSpotMetaspaceConstantImpl, compressed)                                                   \
+  end_class                                                                                                   \
+  start_class(HotSpotSentinelConstant, jdk_vm_ci_hotspot_HotSpotSentinelConstant)                             \
+  end_class                                                                                                   \
+  start_class(JavaKind, jdk_vm_ci_meta_JavaKind)                                                              \
+    char_field(JavaKind, typeChar)                                                                            \
+    static_object_field(JavaKind, Boolean, "Ljdk/vm/ci/meta/JavaKind;")                                       \
+    static_object_field(JavaKind, Byte, "Ljdk/vm/ci/meta/JavaKind;")                                          \
+    static_object_field(JavaKind, Char, "Ljdk/vm/ci/meta/JavaKind;")                                          \
+    static_object_field(JavaKind, Short, "Ljdk/vm/ci/meta/JavaKind;")                                         \
+    static_object_field(JavaKind, Int, "Ljdk/vm/ci/meta/JavaKind;")                                           \
+    static_object_field(JavaKind, Long, "Ljdk/vm/ci/meta/JavaKind;")                                          \
+  end_class                                                                                                   \
+  start_class(ValueKind, jdk_vm_ci_meta_ValueKind)                                                            \
+    object_field(ValueKind, platformKind, "Ljdk/vm/ci/meta/PlatformKind;")                                    \
+  end_class                                                                                                   \
+  start_class(Value, jdk_vm_ci_meta_Value)                                                                    \
+    object_field(Value, valueKind, "Ljdk/vm/ci/meta/ValueKind;")                                              \
+    static_object_field(Value, ILLEGAL, "Ljdk/vm/ci/meta/AllocatableValue;")                                  \
+  end_class                                                                                                   \
+  start_class(RegisterValue, jdk_vm_ci_code_RegisterValue)                                                    \
+    object_field(RegisterValue, reg, "Ljdk/vm/ci/code/Register;")                                             \
+  end_class                                                                                                   \
+  start_class(code_Location, jdk_vm_ci_code_Location)                                                         \
+    object_field(code_Location, reg, "Ljdk/vm/ci/code/Register;")                                             \
+    int_field(code_Location, offset)                                                                          \
+  end_class                                                                                                   \
+  start_class(code_Register, jdk_vm_ci_code_Register)                                                         \
+    int_field(code_Register, number)                                                                          \
+    int_field(code_Register, encoding)                                                                        \
+  end_class                                                                                                   \
+  start_class(StackSlot, jdk_vm_ci_code_StackSlot)                                                            \
+    int_field(StackSlot, offset)                                                                              \
+    boolean_field(StackSlot, addFrameSize)                                                                    \
+  end_class                                                                                                   \
+  start_class(VirtualObject, jdk_vm_ci_code_VirtualObject)                                                    \
+    int_field(VirtualObject, id)                                                                              \
+    object_field(VirtualObject, type, "Ljdk/vm/ci/meta/ResolvedJavaType;")                                    \
+    objectarray_field(VirtualObject, values, "[Ljdk/vm/ci/meta/JavaValue;")                                   \
+    objectarray_field(VirtualObject, slotKinds, "[Ljdk/vm/ci/meta/JavaKind;")                                 \
+  end_class                                                                                                   \
+  start_class(StackLockValue, jdk_vm_ci_code_StackLockValue)                                                  \
+    object_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;")                                         \
+    object_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;")                                   \
+    boolean_field(StackLockValue, eliminated)                                                                 \
+  end_class                                                                                                   \
+  start_class(HotSpotStackFrameReference, jdk_vm_ci_hotspot_HotSpotStackFrameReference)                       \
+    object_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;")                \
+    boolean_field(HotSpotStackFrameReference, objectsMaterialized)                                            \
+    long_field(HotSpotStackFrameReference, stackPointer)                                                      \
+    int_field(HotSpotStackFrameReference, frameNumber)                                                        \
+    int_field(HotSpotStackFrameReference, bci)                                                                \
+    object_field(HotSpotStackFrameReference, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")         \
+    objectarray_field(HotSpotStackFrameReference, locals, "[Ljava/lang/Object;")                              \
+    primarray_field(HotSpotStackFrameReference, localIsVirtual, "[Z")                                         \
+  end_class                                                                                                   \
+  start_class(HotSpotMetaData, jdk_vm_ci_hotspot_HotSpotMetaData)                                             \
+    primarray_field(HotSpotMetaData, pcDescBytes, "[B")                                                       \
+    primarray_field(HotSpotMetaData, scopesDescBytes, "[B")                                                   \
+    primarray_field(HotSpotMetaData, relocBytes, "[B")                                                        \
+    primarray_field(HotSpotMetaData, exceptionBytes, "[B")                                                    \
+    primarray_field(HotSpotMetaData, oopMaps, "[B")                                                           \
+    object_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;")                                            \
+  end_class                                                                                                   \
+  start_class(HotSpotConstantPool, jdk_vm_ci_hotspot_HotSpotConstantPool)                                     \
+    long_field(HotSpotConstantPool, metadataHandle)                                                           \
+  end_class                                                                                                   \
+  start_class(HotSpotJVMCIRuntime, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime)                                     \
+    objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;")                \
+    jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature, (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong env, int id)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, decodeThrowable, decodeThrowable_signature, (JVMCIObject encodedThrowable)) \
+    jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
+    jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \
+    jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, callToString, callToString_signature, (JVMCIObject object, JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(JVMCIError, jdk_vm_ci_common_JVMCIError)                                                        \
+    jvmci_constructor(JVMCIError, "(Ljava/lang/String;)V")                                                    \
+  end_class                                                                                                   \
+  start_class(InspectedFrameVisitor, jdk_vm_ci_code_stack_InspectedFrameVisitor)                              \
+  end_class                                                                                                   \
+  start_class(JVMCI, jdk_vm_ci_runtime_JVMCI)                                                                 \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, getRuntime, getRuntime_signature, (JVMCI_TRAPS)) \
+    jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, initializeRuntime, initializeRuntime_signature, (JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(Object, java_lang_Object)                                                                       \
+  end_class                                                                                                   \
+  start_class(String, java_lang_String)                                                                       \
+  end_class                                                                                                   \
+  start_class(Class, java_lang_Class)                                                                         \
+    jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, Class, getName, void_string_signature, (JVMCI_TRAPS)) \
+  end_class                                                                                                   \
+  start_class(ArrayIndexOutOfBoundsException, java_lang_ArrayIndexOutOfBoundsException)                       \
+    jvmci_constructor(ArrayIndexOutOfBoundsException, "(Ljava/lang/String;)V")                                \
+  end_class                                                                                                   \
+  start_class(IllegalStateException, java_lang_IllegalStateException)                                         \
+    jvmci_constructor(IllegalStateException, "(Ljava/lang/String;)V")                                         \
+  end_class                                                                                                   \
+  start_class(NullPointerException, java_lang_NullPointerException)                                           \
+    jvmci_constructor(NullPointerException, "(Ljava/lang/String;)V")                                          \
+  end_class                                                                                                   \
+  start_class(IllegalArgumentException, java_lang_IllegalArgumentException)                                   \
+    jvmci_constructor(IllegalArgumentException, "(Ljava/lang/String;)V")                                      \
+  end_class                                                                                                   \
+  start_class(InternalError, java_lang_InternalError)                                                         \
+    jvmci_constructor(InternalError, "(Ljava/lang/String;)V")                                                 \
+  end_class                                                                                                   \
+  start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException)                    \
+    jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V")                                 \
+  end_class                                                                                                   \
+  start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError)                                           \
+    jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V")                                          \
+  end_class                                                                                                   \
+  start_class(StackTraceElement, java_lang_StackTraceElement)                                                 \
+    object_field(StackTraceElement, declaringClass, "Ljava/lang/String;")                                     \
+    object_field(StackTraceElement, methodName, "Ljava/lang/String;")                                         \
+    object_field(StackTraceElement, fileName, "Ljava/lang/String;")                                           \
+    int_field(StackTraceElement, lineNumber)                                                                  \
+    jvmci_constructor(StackTraceElement, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")        \
+  end_class                                                                                                   \
+  start_class(Throwable, java_lang_Throwable)                                                                 \
+    object_field(Throwable, detailMessage, "Ljava/lang/String;")                                              \
+  end_class                                                                                                   \
   /* end*/
 
-#define START_CLASS(name)                                                                                                                                      \
-class name : AllStatic {                                                                                                                                       \
-  private:                                                                                                                                                     \
-    friend class JVMCICompiler;                                                                                                                                \
-    static void check(oop obj, const char* field_name, int offset);                                                                                            \
-    static void compute_offsets(TRAPS);                                                                                                                        \
-  public:                                                                                                                                                      \
-  static InstanceKlass* klass() { return SystemDictionary::name##_klass_is_loaded() ? SystemDictionary::name##_klass() : NULL; }
+class JVMCICompiler;
+class JVMCIEnv;
+
+#define START_CLASS(simpleClassName, fullClassName)      \
+  class simpleClassName { \
+    friend class JVMCIEnv; \
+    static void initialize(JVMCI_TRAPS); \
+    static bool is_instance(JVMCIEnv* jvmciEnv, JVMCIObject object); \
 
 #define END_CLASS };
 
-#define FIELD(name, type, accessor, cast)                                                                                                                         \
-    static int _##name##_offset;                                                                                                                                  \
-    static type name(oop obj)                   { check(obj, #name, _##name##_offset); return cast obj->accessor(_##name##_offset); }                             \
-    static type name(Handle obj)                { check(obj(), #name, _##name##_offset); return cast obj->accessor(_##name##_offset); }                           \
-    static type name(jobject obj);                                                                                                                                \
-    static void set_##name(oop obj, type x)     { check(obj, #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); }                                \
-    static void set_##name(Handle obj, type x)  { check(obj(), #name, _##name##_offset); obj->accessor##_put(_##name##_offset, x); }                              \
-    static void set_##name(jobject obj, type x);                                                                                                                  \
+#define EMPTY_CAST
+#define CHAR_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jchar)
+#define INT_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jint)
+#define BOOLEAN_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jboolean)
+#define LONG_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jlong)
+#define FLOAT_FIELD(simpleClassName,  name) FIELD(simpleClassName, name, jfloat)
+
+#define OBJECT_FIELD(simpleClassName,  name, signature) OOPISH_FIELD(simpleClassName, name, JVMCIObject, oop)
+#define OBJECTARRAY_FIELD(simpleClassName,  name, signature) OOPISH_FIELD(simpleClassName, name, JVMCIObjectArray, objArrayOop)
+#define PRIMARRAY_FIELD(simpleClassName,  name, signature) OOPISH_FIELD(simpleClassName, name, JVMCIPrimitiveArray, typeArrayOop)
+
+#define STATIC_INT_FIELD(simpleClassName, name) STATIC_FIELD(simpleClassName, name, jint)
+#define STATIC_BOOLEAN_FIELD(simpleClassName, name) STATIC_FIELD(simpleClassName, name, jboolean)
+#define STATIC_OBJECT_FIELD(simpleClassName, name, signature) STATIC_OOPISH_FIELD(simpleClassName, name, JVMCIObject, oop)
+#define STATIC_OBJECTARRAY_FIELD(simpleClassName, name, signature) STATIC_OOPISH_FIELD(simpleClassName, name, JVMCIObjectArray, objArrayOop)
+
+#define HS_START_CLASS(simpleClassName, fullClassName)                               \
+  START_CLASS(simpleClassName, fullClassName)                                        \
+  friend class HotSpotJVMCI;                                                         \
+ private:                                                                            \
+  static void check(oop obj, const char* field_name, int offset);                    \
+  static InstanceKlass* _klass;                                                      \
+ public:                                                                             \
+  static InstanceKlass* klass() { assert(_klass != NULL, "uninit"); return _klass; } \
+  static Symbol* symbol() { return vmSymbols::fullClassName(); }
+
+#define FIELD(simpleClassName, name, type)                                                                   \
+  private:                                                                                                   \
+    static int _##name##_offset;                                                                             \
+  public:                                                                                                    \
+    static type get_ ## name(JVMCIEnv* env, JVMCIObject obj) { return name(env, resolve(obj)); }             \
+    static void set_ ## name(JVMCIEnv* env, JVMCIObject obj, type x) { set_ ## name(env, resolve(obj), x); } \
+    static type name(JVMCIEnv* env, oop obj);                                                                \
+    static void set_ ## name(JVMCIEnv* env, oop obj, type x);
+
+#define OOPISH_FIELD(simpleClassName, name, type, hstype)                                                                \
+  private:                                                                                                                       \
+    static int _##name##_offset;                                                                                                 \
+  public:                                                                                                                        \
+    static type get_  ## name(JVMCIEnv* env, JVMCIObject obj) { return (type) wrap(name(env, resolve(obj))); }                   \
+    static void set_  ## name(JVMCIEnv* env, JVMCIObject obj, type x) { set_  ## name(env, resolve(obj), (hstype) resolve(x)); } \
+    static hstype name(JVMCIEnv* env, oop obj);                                                                                  \
+    static void set_  ## name(JVMCIEnv* env, oop obj, hstype x);
+
+#define STATIC_FIELD(simpleClassName, name, type)     \
+  private:                                            \
+    static int _##name##_offset;                      \
+  public:                                             \
+    static type get_  ## name(JVMCIEnv* env);         \
+    static void set_  ## name(JVMCIEnv* env, type x);
+
+#define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype)                                  \
+  private:                                                                                        \
+    static int _##name##_offset;                                                                  \
+  public:                                                                                         \
+    static type get_  ## name(JVMCIEnv* env) { return (type) wrap(name(env)); }                   \
+    static void set_  ## name(JVMCIEnv* env, type x) { set_  ## name(env, (hstype) resolve(x)); } \
+    static hstype name(JVMCIEnv* env);                                                            \
+    static void set_  ## name(JVMCIEnv* env, hstype hstype);
+
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, simpleClassName, methodName, signatureSymbolName, args)
+#define CONSTRUCTOR(className, signature)
+
+/**
+ * VM internal interface to Java classes, methods and objects. For example:
+ *
+ * class HotSpotJVMCI {
+ *   ...
+ *   class Architecture {
+ *     static void initialize(JVMCIEnv* env);
+ *     static bool is_instance(JVMCIEnv* env, JVMCIObject object);
+ *    private:
+ *     static void check(oop obj, const char *field_name, int offset);
+ *    public:
+ *     static InstanceKlass *klass() { ... }
+ *     static Symbol *symbol() { return vmSymbols::jdk_vm_ci_code_Architecture(); }
+ *    private:
+ *     static int _wordKind_offset;
+ *    public:
+ *     static JVMCIObject get_wordKind(JVMCIEnv *env, JVMCIObject obj) { ... }
+ *     static void set_wordKind(JVMCIEnv *env, JVMCIObject obj, JVMCIObject x) { ... }
+ *     static oop wordKind(JVMCIEnv *env, oop obj);
+ *     static void set_wordKind(JVMCIEnv *env, oop obj, oop x);
+ *   }
+ *   ...
+ * };
+ */
+class HotSpotJVMCI {
+  friend class JVMCIEnv;
+
+ public:
+
+  static oop resolve(JVMCIObject obj);
+
+  static arrayOop resolve(JVMCIArray obj);
+  static objArrayOop resolve(JVMCIObjectArray obj);
+  static typeArrayOop resolve(JVMCIPrimitiveArray obj);
+
+  static JVMCIObject wrap(jobject obj) { return JVMCIObject(obj, true); }
+  static JVMCIObject wrap(oop obj);
+
+  static inline Method* asMethod(JVMCIEnv* env, oop jvmci_method) {
+    return *(Method**) HotSpotResolvedJavaMethodImpl::metadataHandle(env, jvmci_method);
+  }
+  static inline ConstantPool* asConstantPool(JVMCIEnv* env, oop jvmci_constant_pool) {
+    return *(ConstantPool**) HotSpotConstantPool::metadataHandle(env, jvmci_constant_pool);
+  }
+  static inline Klass* asKlass(JVMCIEnv* env, oop jvmci_type) {
+    return (Klass*) HotSpotResolvedObjectTypeImpl::metadataPointer(env, jvmci_type);
+  }
+
+  static void compute_offsets(TRAPS);
+  static void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS);
 
-#define EMPTY_CAST
-#define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field, EMPTY_CAST)
-#define INT_FIELD(klass, name) FIELD(name, jint, int_field, EMPTY_CAST)
-#define BOOLEAN_FIELD(klass, name) FIELD(name, jboolean, bool_field, EMPTY_CAST)
-#define LONG_FIELD(klass, name) FIELD(name, jlong, long_field, EMPTY_CAST)
-#define FLOAT_FIELD(klass, name) FIELD(name, jfloat, float_field, EMPTY_CAST)
-#define OOP_FIELD(klass, name, signature) FIELD(name, oop, obj_field, EMPTY_CAST)
-#define OBJARRAYOOP_FIELD(klass, name, signature) FIELD(name, objArrayOop, obj_field, (objArrayOop))
-#define TYPEARRAYOOP_FIELD(klass, name, signature) FIELD(name, typeArrayOop, obj_field, (typeArrayOop))
-#define STATIC_OOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, oop, signature)
-#define STATIC_OBJARRAYOOP_FIELD(klassName, name, signature) STATIC_OOPISH_FIELD(klassName, name, objArrayOop, signature)
-#define STATIC_OOPISH_FIELD(klassName, name, type, signature)                                                  \
-    static int _##name##_offset;                                                                               \
-    static type name();                                                                                        \
-    static void set_##name(type x);
-#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename)                                                     \
-    static int _##name##_offset;                                                                               \
-    static jtypename name();                                                                                   \
-    static void set_##name(jtypename x);
+  JVMCI_CLASSES_DO(HS_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 HS_START_CLASS
+
+#define JNI_START_CLASS(simpleClassName, fullClassName)                                             \
+  START_CLASS(simpleClassName, fullClassName)                                                       \
+  friend class JNIJVMCI;                                                                            \
+  private:                                                                                          \
+  static void check(JVMCIEnv* jvmciEnv, JVMCIObject obj, const char* field_name, jfieldID offset);  \
+  static jclass _class;                                                                             \
+public:                                                                                             \
+ static jclass clazz() { assert(_class != NULL, #fullClassName " uninitialized"); return _class; }                         \
+ static jclass fullClassName ##_class()  { assert(_class != NULL, "uninit"); return _class; }
+
+#undef METHOD
+#undef CONSTRUCTOR
+#undef FIELD
+#undef OOPISH_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OOPISH_FIELD
+
+#define FIELD(simpleClassName, name, type)                                \
+  private:                                                                \
+    static jfieldID _##name##_field_id;                                   \
+  public:                                                                 \
+    static type get_  ## name(JVMCIEnv* jvmciEnv, JVMCIObject obj);       \
+    static void set_  ## name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x);
+
+#define OOPISH_FIELD(simpleClassName, name, type, hstype) \
+  FIELD(simpleClassName, name, type)
+
+#define STATIC_FIELD(simpleClassName, name, type)   \
+  private:                                          \
+    static jfieldID _##name##_field_id;             \
+  public:                                           \
+    static type get_  ## name(JVMCIEnv* jvmciEnv);  \
+    static void set_  ## name(JVMCIEnv* jvmciEnv, type x);
+
+#define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype) \
+  STATIC_FIELD(simpleClassName, name, type)
+
+#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
+  public:                                                                                                           \
+    static jmethodID methodName##_method() { return _##methodName##_method; }                                       \
+  private:                                                                                                          \
+    static jmethodID _##methodName##_method;
+
+#define CONSTRUCTOR(className, signature)                                                                           \
+  public:                                                                                                           \
+    static jmethodID constructor() { return _constructor; }                                                         \
+  private:                                                                                                          \
+    static jmethodID _constructor;
 
-#define STATIC_INT_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jint)
-#define STATIC_BOOLEAN_FIELD(klassName, name) STATIC_PRIMITIVE_FIELD(klassName, name, jboolean)
+/**
+ * JNI based interface to Java classes, methods and objects. For example:
+ *
+ * class JNIJVMCI {
+ *   ...
+ *   class Architecture {
+ *     static void initialize(JVMCIEnv* env);
+ *     static bool is_instance(JVMCIEnv* env, JVMCIObject object);
+ *    private:
+ *     static void check(oop obj, const char *field_name, int offset);
+ *     static jclass _class;
+ *    public:
+ *     static jclass clazz() { return _class; }
+ *     static jclass jdk_vm_ci_code_Architecture_class() { return _class; }
+ *    private:
+ *     static jfieldID _wordKind_field_id;
+ *    public:
+ *     static JVMCIObject get_wordKind(JVMCIEnv *env, JVMCIObject obj) { ... }
+ *     static void set_wordKind(JVMCIEnv *env, JVMCIObject obj, JVMCIObject x) { ... }
+ *   }
+ *   ...
+ * };
+ */
+class JNIJVMCI {
+  friend class JVMCIEnv;
 
-COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, TYPEARRAYOOP_FIELD, OBJARRAYOOP_FIELD, STATIC_OOP_FIELD, STATIC_OBJARRAYOOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
+  static jclass _byte_array;
+  static jclass _box_classes[T_CONFLICT+1];
+  static jfieldID _box_fields[T_CONFLICT+1];
+  static jmethodID _box_constructors[T_CONFLICT+1];
+  static jmethodID _Class_getName_method;
+
+  static jmethodID _HotSpotResolvedJavaMethodImpl_fromMetaspace_method;
+  static jmethodID _HotSpotConstantPool_fromMetaspace_method;
+  static jmethodID _HotSpotResolvedObjectTypeImpl_fromMetaspace_method;
+  static jmethodID _HotSpotResolvedPrimitiveType_fromMetaspace_method;
+
+ public:
+  static jmethodID Class_getName_method() { return _Class_getName_method; }
+
+  static jclass    byte_array()           { assert(_byte_array != NULL, "uninit");      return _byte_array; }
+
+  static jclass    box_class(BasicType type)       { assert(_box_classes[type]!= NULL, "uninit");      return _box_classes[type]; }
+  static jfieldID  box_field(BasicType type)       { assert(_box_fields[type]!= NULL, "uninit");       return _box_fields[type]; }
+  static jmethodID box_constructor(BasicType type) { assert(_box_constructors[type]!= NULL, "uninit"); return _box_constructors[type]; }
+
+  static jmethodID HotSpotResolvedJavaMethodImpl_fromMetaspace_method()     { assert(_HotSpotResolvedJavaMethodImpl_fromMetaspace_method     != NULL, "uninit"); return _HotSpotResolvedJavaMethodImpl_fromMetaspace_method; }
+  static jmethodID HotSpotConstantPool_fromMetaspace_method()           { assert(_HotSpotConstantPool_fromMetaspace_method           != NULL, "uninit"); return _HotSpotConstantPool_fromMetaspace_method; }
+  static jmethodID HotSpotResolvedObjectTypeImpl_fromMetaspace_method() { assert(_HotSpotResolvedObjectTypeImpl_fromMetaspace_method != NULL, "uninit"); return _HotSpotResolvedObjectTypeImpl_fromMetaspace_method; }
+  static jmethodID HotSpotResolvedPrimitiveType_fromMetaspace_method()  { assert(_HotSpotResolvedPrimitiveType_fromMetaspace_method  != NULL, "uninit"); return _HotSpotResolvedPrimitiveType_fromMetaspace_method; }
+
+  static void initialize_ids(JNIEnv* env);
+  static void initialize_field_id(JNIEnv* env, jfieldID &dest_offset, jclass klass, const char* klass_name, const char* name, const char* signature, bool static_field);
+
+  static jobject resolve_handle(JVMCIObject obj) { return obj.as_jobject(); }
+  static JVMCIObject wrap(jobject obj) { return JVMCIObject(obj, false); }
+
+  JVMCI_CLASSES_DO(JNI_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 JNI_START_CLASS
 #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 OOP_FIELD
-#undef TYPEARRAYOOP_FIELD
-#undef OBJARRAYOOP_FIELD
+#undef OBJECT_FIELD
+#undef PRIMARRAY_FIELD
+#undef OBJECTARRAY_FIELD
+#undef FIELD
+#undef OOPISH_FIELD
+#undef STATIC_FIELD
 #undef STATIC_OOPISH_FIELD
-#undef STATIC_OOP_FIELD
-#undef STATIC_OBJARRAYOOP_FIELD
+#undef STATIC_FIELD
+#undef STATIC_OBJECT_FIELD
+#undef STATIC_OBJECTARRAY_FIELD
 #undef STATIC_INT_FIELD
 #undef STATIC_BOOLEAN_FIELD
 #undef STATIC_PRIMITIVE_FIELD
 #undef EMPTY_CAST
 
-void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS);
-
 #endif // SHARE_JVMCI_JVMCIJAVACLASSES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/jvmciObject.hpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef SHARE_JVMCI_JVMCIOBJECT_HPP
+#define SHARE_JVMCI_JVMCIOBJECT_HPP
+
+#include "jni.h"
+#include "utilities/debug.hpp"
+
+class JVMCIArray;
+class JVMCIPrimitiveArray;
+class JVMCIObjectArray;
+
+class JVMCIObject {
+
+ private:
+  jobject _object;
+  bool _is_hotspot;
+
+ public:
+  JVMCIObject(): _object(NULL), _is_hotspot(false) {}
+  JVMCIObject(jobject o, bool is_hotspot): _object(o), _is_hotspot(is_hotspot) { }
+
+  static JVMCIObject create(jobject o, bool is_hotspot) { JVMCIObject r(o, is_hotspot); return r; }
+  jobject as_jobject() { return _object; }
+  jobject as_jweak()   { return (jweak) _object; }
+  jstring as_jstring() { return (jstring) _object; }
+  bool is_hotspot() { return _is_hotspot; }
+
+  bool is_null() const { return _object == NULL; }
+  bool is_non_null() const { return _object != NULL; }
+
+  operator JVMCIArray();
+  operator JVMCIPrimitiveArray();
+  operator JVMCIObjectArray();
+};
+
+class JVMCIArray : public JVMCIObject {
+ public:
+  JVMCIArray() {}
+  JVMCIArray(jobject o, bool is_hotspot): JVMCIObject(o, is_hotspot) {}
+  jarray as_jobject() { return (jarray) JVMCIObject::as_jobject(); }
+};
+
+class JVMCIObjectArray : public JVMCIArray {
+ public:
+  JVMCIObjectArray() {}
+  JVMCIObjectArray(void* v): JVMCIArray() { assert(v == NULL, "must be NULL"); }
+  JVMCIObjectArray(jobject o, bool is_hotspot): JVMCIArray(o, is_hotspot) {}
+
+  jobjectArray as_jobject() { return (jobjectArray) JVMCIArray::as_jobject(); }
+};
+
+class JVMCIPrimitiveArray : public JVMCIArray {
+ public:
+  JVMCIPrimitiveArray() {}
+  JVMCIPrimitiveArray(void* v): JVMCIArray() { assert(v == NULL, "must be NULL"); }
+  JVMCIPrimitiveArray(jobject o, bool is_hotspot): JVMCIArray(o, is_hotspot) {}
+
+  jbooleanArray as_jbooleanArray() { return (jbooleanArray) as_jobject(); }
+  jbyteArray    as_jbyteArray()    { return (jbyteArray) as_jobject();    }
+  jcharArray    as_jcharArray()    { return (jcharArray) as_jobject();    }
+  jshortArray   as_jshortArray()   { return (jshortArray) as_jobject();   }
+  jintArray     as_jintArray()     { return (jintArray) as_jobject();     }
+  jfloatArray   as_jfloatArray()   { return (jfloatArray) as_jobject();   }
+  jlongArray    as_jlongArray()    { return (jlongArray) as_jobject();    }
+  jdoubleArray  as_jdoubleArray()  { return (jdoubleArray) as_jobject();  }
+};
+
+inline JVMCIObject::operator JVMCIArray() { return JVMCIArray(_object, _is_hotspot); }
+inline JVMCIObject::operator JVMCIPrimitiveArray() { return JVMCIPrimitiveArray(_object, _is_hotspot); }
+inline JVMCIObject::operator JVMCIObjectArray() { return JVMCIObjectArray(_object, _is_hotspot); }
+
+#endif // SHARE_JVMCI_JVMCIOBJECT_HPP
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Wed May 01 12:31:29 2019 -0700
@@ -22,69 +22,24 @@
  */
 
 #include "precompiled.hpp"
-#include "jvm.h"
-#include "asm/codeBuffer.hpp"
-#include "classfile/javaClasses.inline.hpp"
-#include "classfile/moduleEntry.hpp"
-#include "code/codeCache.hpp"
-#include "code/compiledMethod.inline.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/disassembler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jniAccessMark.inline.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciRuntime.hpp"
 #include "logging/log.hpp"
-#include "memory/allocation.inline.hpp"
 #include "memory/oopFactory.hpp"
-#include "memory/resourceArea.hpp"
+#include "oops/constantPool.inline.hpp"
+#include "oops/method.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
 #include "runtime/biasedLocking.hpp"
+#include "runtime/deoptimization.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/frame.inline.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/interfaceSupport.inline.hpp"
-#include "runtime/jniHandles.inline.hpp"
-#include "runtime/reflection.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "runtime/threadSMR.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/defaultStream.hpp"
-#include "utilities/macros.hpp"
 #if INCLUDE_G1GC
 #include "gc/g1/g1ThreadLocalData.hpp"
 #endif // INCLUDE_G1GC
 
-#if defined(_MSC_VER)
-#define strtoll _strtoi64
-#endif
-
-jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
-bool JVMCIRuntime::_well_known_classes_initialized = false;
-bool JVMCIRuntime::_shutdown_called = false;
-
-BasicType JVMCIRuntime::kindToBasicType(Handle kind, TRAPS) {
-  if (kind.is_null()) {
-    THROW_(vmSymbols::java_lang_NullPointerException(), T_ILLEGAL);
-  }
-  jchar ch = 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);
-  }
-}
-
 // Simple helper to see if the caller of a runtime stub which
 // entered the VM has been deoptimized
 
@@ -151,23 +106,23 @@
   JRT_BLOCK;
   assert(klass->is_klass(), "not a class");
   Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
-  InstanceKlass* ik = InstanceKlass::cast(klass);
+  InstanceKlass* h = InstanceKlass::cast(klass);
   {
     RetryableAllocationMark ram(thread, null_on_fail);
-    ik->check_valid_for_instantiation(true, CHECK);
+    h->check_valid_for_instantiation(true, CHECK);
     oop obj;
     if (null_on_fail) {
-      if (!ik->is_initialized()) {
+      if (!h->is_initialized()) {
         // Cannot re-execute class initialization without side effects
         // so return without attempting the initialization
         return;
       }
     } else {
       // make sure klass is initialized
-      ik->initialize(CHECK);
+      h->initialize(CHECK);
     }
     // allocate instance and return via TLS
-    obj = ik->allocate_instance(CHECK);
+    obj = h->allocate_instance(CHECK);
     thread->set_vm_result(obj);
   }
   JRT_BLOCK_END;
@@ -289,6 +244,7 @@
   }
 #ifdef ASSERT
   assert(exception.not_null(), "NULL exceptions should be handled by throw_exception");
+  assert(oopDesc::is_oop(exception()), "just checking");
   // Check that exception is a subclass of Throwable, otherwise we have a VerifyError
   if (!(exception->is_a(SystemDictionary::Throwable_klass()))) {
     if (ExitVMOnVerifyError) vm_exit(-1);
@@ -369,10 +325,11 @@
     thread->set_exception_oop(exception());
     thread->set_exception_pc(pc);
 
-    // the exception cache is used only by non-implicit exceptions
-    // Update the exception cache only when there didn't happen
-    // another exception during the computation of the compiled
-    // exception handler. Checking for exception oop equality is not
+    // The exception cache is used only for non-implicit exceptions
+    // Update the exception cache only when another exception did
+    // occur during the computation of the compiled exception handler
+    // (e.g., when loading the class of the catch type).
+    // Checking for exception oop equality is not
     // sufficient because some exceptions are pre-allocated and reused.
     if (continuation != NULL && !recursive_exception && !SharedRuntime::deopt_blob()->contains(continuation)) {
       cm->add_handler_for_exception_and_pc(exception, pc, continuation);
@@ -429,12 +386,11 @@
     TRACE_jvmci_3("%s: entered locking slow case with obj=" INTPTR_FORMAT ", type=%s, mark=" INTPTR_FORMAT ", lock=" INTPTR_FORMAT, thread->name(), p2i(obj), type, p2i(mark), p2i(lock));
     tty->flush();
   }
-#ifdef ASSERT
   if (PrintBiasedLockingStatistics) {
     Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
   }
-#endif
   Handle h_obj(thread, obj);
+  assert(oopDesc::is_oop(h_obj()), "must be NULL or an object");
   if (UseBiasedLocking) {
     // Retry fast entry if bias is revoked to avoid unnecessary inflation
     ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
@@ -455,7 +411,7 @@
   // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown
   EXCEPTION_MARK;
 
-#ifdef DEBUG
+#ifdef ASSERT
   if (!oopDesc::is_oop(obj)) {
     ResetNoHandleMark rhm;
     nmethod* method = thread->last_frame().cb()->as_nmethod_or_null();
@@ -586,10 +542,8 @@
     size_t detail_msg_length = strlen(buf) * 2;
     detail_msg = (char *) NEW_RESOURCE_ARRAY(u_char, detail_msg_length);
     jio_snprintf(detail_msg, detail_msg_length, buf, value);
-    report_vm_error(__FILE__, __LINE__, error_msg, "%s", detail_msg);
-  } else {
-    report_vm_error(__FILE__, __LINE__, error_msg);
   }
+  report_vm_error(__FILE__, __LINE__, error_msg, "%s", detail_msg);
 JRT_END
 
 JRT_LEAF(oopDesc*, JVMCIRuntime::load_and_clear_exception(JavaThread* thread))
@@ -693,205 +647,934 @@
   }
 JRT_END
 
-JRT_ENTRY(int, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
+JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
   deopt_caller();
-  return value;
+  return (jint) value;
 JRT_END
 
-void JVMCIRuntime::force_initialization(TRAPS) {
-  JVMCIRuntime::initialize_well_known_classes(CHECK);
-
-  ResourceMark rm;
-  TempNewSymbol getCompiler = SymbolTable::new_symbol("getCompiler", CHECK);
-  TempNewSymbol sig = SymbolTable::new_symbol("()Ljdk/vm/ci/runtime/JVMCICompiler;", CHECK);
-  Handle jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK);
-  JavaValue result(T_OBJECT);
-  JavaCalls::call_virtual(&result, jvmciRuntime, HotSpotJVMCIRuntime::klass(), getCompiler, sig, CHECK);
-}
 
 // private static JVMCIRuntime JVMCI.initializeRuntime()
-JVM_ENTRY(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
+JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
+  JNI_JVMCIENV(env);
   if (!EnableJVMCI) {
-    THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
+    JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
   }
-  JVMCIRuntime::initialize_HotSpotJVMCIRuntime(CHECK_NULL);
-  jobject ret = JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject(CHECK_NULL);
-  return ret;
+  JVMCIENV->runtime()->initialize_HotSpotJVMCIRuntime(JVMCI_CHECK_NULL);
+  JVMCIObject runtime = JVMCIENV->runtime()->get_HotSpotJVMCIRuntime(JVMCI_CHECK_NULL);
+  return JVMCIENV->get_jobject(runtime);
 JVM_END
 
-Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, const char* signature, JavaCallArguments* args, TRAPS) {
-  TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_(Handle()));
-  Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_(Handle()));
-  TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_(Handle()));
-  TempNewSymbol sig = SymbolTable::new_symbol(signature, CHECK_(Handle()));
-  JavaValue result(T_OBJECT);
-  if (args == NULL) {
-    JavaCalls::call_static(&result, klass, runtime, sig, CHECK_(Handle()));
+void JVMCIRuntime::call_getCompiler(TRAPS) {
+  THREAD_JVMCIENV(JavaThread::current());
+  JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK);
+  initialize(JVMCIENV);
+  JVMCIENV->call_HotSpotJVMCIRuntime_getCompiler(jvmciRuntime, JVMCI_CHECK);
+}
+
+void JVMCINMethodData::initialize(
+  int nmethod_mirror_index,
+  const char* name,
+  FailedSpeculation** failed_speculations)
+{
+  _failed_speculations = failed_speculations;
+  _nmethod_mirror_index = nmethod_mirror_index;
+  if (name != NULL) {
+    _has_name = true;
+    char* dest = (char*) this->name();
+    strcpy(dest, name);
   } else {
-    JavaCalls::call_static(&result, klass, runtime, sig, args, CHECK_(Handle()));
+    _has_name = false;
+  }
+}
+
+void JVMCINMethodData::add_failed_speculation(nmethod* nm, jlong speculation) {
+  uint index = (speculation >> 32) & 0xFFFFFFFF;
+  int length = (int) speculation;
+  if (index + length > (uint) nm->speculations_size()) {
+    fatal(INTPTR_FORMAT "[index: %d, length: %d] out of bounds wrt encoded speculations of length %u", speculation, index, length, nm->speculations_size());
+  }
+  address data = nm->speculations_begin() + index;
+  FailedSpeculation::add_failed_speculation(nm, _failed_speculations, data, length);
+}
+
+oop JVMCINMethodData::get_nmethod_mirror(nmethod* nm) {
+  if (_nmethod_mirror_index == -1) {
+    return NULL;
   }
-  return Handle(THREAD, (oop)result.get_jobject());
+  return nm->oop_at(_nmethod_mirror_index);
+}
+
+void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {
+  assert(_nmethod_mirror_index != -1, "cannot set JVMCI mirror for nmethod");
+  oop* addr = nm->oop_addr_at(_nmethod_mirror_index);
+  assert(new_mirror != NULL, "use clear_nmethod_mirror to clear the mirror");
+  assert(*addr == NULL, "cannot overwrite non-null mirror");
+
+  *addr = new_mirror;
+
+  // Since we've patched some oops in the nmethod,
+  // (re)register it with the heap.
+  Universe::heap()->register_nmethod(nm);
+}
+
+void JVMCINMethodData::clear_nmethod_mirror(nmethod* nm) {
+  if (_nmethod_mirror_index != -1) {
+    oop* addr = nm->oop_addr_at(_nmethod_mirror_index);
+    *addr = NULL;
+  }
 }
 
-Handle JVMCIRuntime::get_HotSpotJVMCIRuntime(TRAPS) {
-  initialize_JVMCI(CHECK_(Handle()));
-  return Handle(THREAD, JNIHandles::resolve_non_null(_HotSpotJVMCIRuntime_instance));
+void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
+  oop nmethod_mirror = get_nmethod_mirror(nm);
+  if (nmethod_mirror == NULL) {
+    return;
+  }
+
+  // Update the values in the mirror if it still refers to nm.
+  // We cannot use JVMCIObject to wrap the mirror as this is called
+  // during GC, forbidding the creation of JNIHandles.
+  JVMCIEnv* jvmciEnv = NULL;
+  nmethod* current = (nmethod*) HotSpotJVMCI::InstalledCode::address(jvmciEnv, nmethod_mirror);
+  if (nm == current) {
+    if (!nm->is_alive()) {
+      // Break the link from the mirror to nm such that
+      // future invocations via the mirror will result in
+      // an InvalidInstalledCodeException.
+      HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);
+      HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
+    } else if (nm->is_not_entrant()) {
+      // Zero the entry point so any new invocation will fail but keep
+      // the address link around that so that existing activations can
+      // be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code).
+      HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
+    }
+  }
+}
+
+void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
+  if (is_HotSpotJVMCIRuntime_initialized()) {
+    if (JVMCIENV->is_hotspot() && UseJVMCINativeLibrary) {
+      JVMCI_THROW_MSG(InternalError, "JVMCI has already been enabled in the JVMCI shared library");
+    }
+  }
+
+  initialize(JVMCIENV);
+
+  // This should only be called in the context of the JVMCI class being initialized
+  JVMCIObject result = JVMCIENV->call_HotSpotJVMCIRuntime_runtime(JVMCI_CHECK);
+
+  _HotSpotJVMCIRuntime_instance = JVMCIENV->make_global(result);
+}
+
+void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) {
+  assert(this != NULL, "sanity");
+  // Check first without JVMCI_lock
+  if (_initialized) {
+    return;
+  }
+
+  MutexLocker locker(JVMCI_lock);
+  // Check again under JVMCI_lock
+  if (_initialized) {
+    return;
+  }
+
+  while (_being_initialized) {
+    JVMCI_lock->wait();
+    if (_initialized) {
+      return;
+    }
+  }
+
+  _being_initialized = true;
+
+  {
+    MutexUnlocker unlock(JVMCI_lock);
+
+    HandleMark hm;
+    ResourceMark rm;
+    JavaThread* THREAD = JavaThread::current();
+    if (JVMCIENV->is_hotspot()) {
+      HotSpotJVMCI::compute_offsets(CHECK_EXIT);
+    } else {
+      JNIAccessMark jni(JVMCIENV);
+
+      JNIJVMCI::initialize_ids(jni.env());
+      if (jni()->ExceptionCheck()) {
+        jni()->ExceptionDescribe();
+        fatal("JNI exception during init");
+      }
+    }
+    create_jvmci_primitive_type(T_BOOLEAN, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_BYTE, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_CHAR, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_SHORT, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_INT, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_LONG, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_FLOAT, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_DOUBLE, JVMCI_CHECK_EXIT_((void)0));
+    create_jvmci_primitive_type(T_VOID, JVMCI_CHECK_EXIT_((void)0));
+
+    if (!JVMCIENV->is_hotspot()) {
+      JVMCIENV->copy_saved_properties();
+    }
+  }
+
+  _initialized = true;
+  _being_initialized = false;
+  JVMCI_lock->notify_all();
 }
 
-void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
-  guarantee(!is_HotSpotJVMCIRuntime_initialized(), "cannot reinitialize HotSpotJVMCIRuntime");
-  JVMCIRuntime::initialize_well_known_classes(CHECK);
-  // This should only be called in the context of the JVMCI class being initialized
-  InstanceKlass* klass = SystemDictionary::JVMCI_klass();
-  guarantee(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD),
-         "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
+JVMCIObject JVMCIRuntime::create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS) {
+  Thread* THREAD = Thread::current();
+  // These primitive types are long lived and are created before the runtime is fully set up
+  // so skip registering them for scanning.
+  JVMCIObject mirror = JVMCIENV->get_object_constant(java_lang_Class::primitive_mirror(type), false, true);
+  if (JVMCIENV->is_hotspot()) {
+    JavaValue result(T_OBJECT);
+    JavaCallArguments args;
+    args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(mirror)));
+    args.push_int(type2char(type));
+    JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedPrimitiveType::klass(), vmSymbols::fromMetaspace_name(), vmSymbols::primitive_fromMetaspace_signature(), &args, CHECK_(JVMCIObject()));
 
-  Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
-                             "runtime",
-                             "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
-  _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result);
+    return JVMCIENV->wrap(JNIHandles::make_local((oop)result.get_jobject()));
+  } else {
+    JNIAccessMark jni(JVMCIENV);
+    jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedPrimitiveType::clazz(),
+                                           JNIJVMCI::HotSpotResolvedPrimitiveType_fromMetaspace_method(),
+                                           mirror.as_jobject(), type2char(type));
+    if (jni()->ExceptionCheck()) {
+      return JVMCIObject();
+    }
+    return JVMCIENV->wrap(result);
+  }
+}
+
+void JVMCIRuntime::initialize_JVMCI(JVMCI_TRAPS) {
+  if (!is_HotSpotJVMCIRuntime_initialized()) {
+    initialize(JVMCI_CHECK);
+    JVMCIENV->call_JVMCI_getRuntime(JVMCI_CHECK);
+  }
+}
+
+JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
+  initialize(JVMCIENV);
+  initialize_JVMCI(JVMCI_CHECK_(JVMCIObject()));
+  return _HotSpotJVMCIRuntime_instance;
 }
 
-void JVMCIRuntime::initialize_JVMCI(TRAPS) {
-  if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) {
-    callStatic("jdk/vm/ci/runtime/JVMCI",
-               "getRuntime",
-               "()Ljdk/vm/ci/runtime/JVMCIRuntime;", NULL, CHECK);
+
+// private void CompilerToVM.registerNatives()
+JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
+
+#ifdef _LP64
+#ifndef TARGET_ARCH_sparc
+  uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
+  uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
+  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
+#endif // TARGET_ARCH_sparc
+#else
+  fatal("check TLAB allocation code for address space conflicts");
+#endif
+
+  JNI_JVMCIENV(env);
+
+  if (!EnableJVMCI) {
+    JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
   }
-  assert(is_HotSpotJVMCIRuntime_initialized(), "what?");
+
+  JVMCIENV->runtime()->initialize(JVMCIENV);
+
+  {
+    ResourceMark rm;
+    HandleMark hm(thread);
+    ThreadToNativeFromVM trans(thread);
+
+    // Ensure _non_oop_bits is initialized
+    Universe::non_oop_word();
+
+    if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count())) {
+      if (!env->ExceptionCheck()) {
+        for (int i = 0; i < CompilerToVM::methods_count(); i++) {
+          if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods + i, 1)) {
+            guarantee(false, "Error registering JNI method %s%s", CompilerToVM::methods[i].name, CompilerToVM::methods[i].signature);
+            break;
+          }
+        }
+      } else {
+        env->ExceptionDescribe();
+      }
+      guarantee(false, "Failed registering CompilerToVM native methods");
+    }
+  }
+JVM_END
+
+
+void JVMCIRuntime::shutdown() {
+  if (is_HotSpotJVMCIRuntime_initialized()) {
+    _shutdown_called = true;
+
+    THREAD_JVMCIENV(JavaThread::current());
+    JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance);
+  }
+}
+
+void JVMCIRuntime::bootstrap_finished(TRAPS) {
+  if (is_HotSpotJVMCIRuntime_initialized()) {
+    THREAD_JVMCIENV(JavaThread::current());
+    JVMCIENV->call_HotSpotJVMCIRuntime_bootstrapFinished(_HotSpotJVMCIRuntime_instance, JVMCIENV);
+  }
 }
 
-bool JVMCIRuntime::can_initialize_JVMCI() {
-  // Initializing JVMCI requires the module system to be initialized past phase 3.
-  // The JVMCI API itself isn't available until phase 2 and ServiceLoader (which
-  // JVMCI initialization requires) isn't usable until after phase 3. Testing
-  // whether the system loader is initialized satisfies all these invariants.
-  if (SystemDictionary::java_system_loader() == NULL) {
-    return false;
+void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool clear) {
+  if (HAS_PENDING_EXCEPTION) {
+    Handle exception(THREAD, PENDING_EXCEPTION);
+    const char* exception_file = THREAD->exception_file();
+    int exception_line = THREAD->exception_line();
+    CLEAR_PENDING_EXCEPTION;
+    if (exception->is_a(SystemDictionary::ThreadDeath_klass())) {
+      // Don't print anything if we are being killed.
+    } else {
+      java_lang_Throwable::print(exception(), tty);
+      tty->cr();
+      java_lang_Throwable::print_stack_trace(exception, tty);
+
+      // Clear and ignore any exceptions raised during printing
+      CLEAR_PENDING_EXCEPTION;
+    }
+    if (!clear) {
+      THREAD->set_pending_exception(exception(), exception_file, exception_line);
+    }
   }
-  assert(Universe::is_module_initialized(), "must be");
+}
+
+
+void JVMCIRuntime::exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* message) {
+  JavaThread* THREAD = JavaThread::current();
+
+  static volatile int report_error = 0;
+  if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) {
+    // Only report an error once
+    tty->print_raw_cr(message);
+    if (JVMCIENV != NULL) {
+      JVMCIENV->describe_pending_exception(true);
+    } else {
+      describe_pending_hotspot_exception(THREAD, true);
+    }
+  } else {
+    // Allow error reporting thread to print the stack trace.  Windows
+    // doesn't allow uninterruptible wait for JavaThreads
+    const bool interruptible = true;
+    os::sleep(THREAD, 200, interruptible);
+  }
+
+  before_exit(THREAD);
+  vm_exit(-1);
+}
+
+// ------------------------------------------------------------------
+// Note: the logic of this method should mirror the logic of
+// constantPoolOopDesc::verify_constant_pool_resolve.
+bool JVMCIRuntime::check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass) {
+  if (accessing_klass->is_objArray_klass()) {
+    accessing_klass = ObjArrayKlass::cast(accessing_klass)->bottom_klass();
+  }
+  if (!accessing_klass->is_instance_klass()) {
+    return true;
+  }
+
+  if (resolved_klass->is_objArray_klass()) {
+    // Find the element klass, if this is an array.
+    resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
+  }
+  if (resolved_klass->is_instance_klass()) {
+    Reflection::VerifyClassAccessResults result =
+      Reflection::verify_class_access(accessing_klass, InstanceKlass::cast(resolved_klass), true);
+    return result == Reflection::ACCESS_OK;
+  }
   return true;
 }
 
-void JVMCIRuntime::initialize_well_known_classes(TRAPS) {
-  if (JVMCIRuntime::_well_known_classes_initialized == false) {
-    guarantee(can_initialize_JVMCI(), "VM is not yet sufficiently booted to initialize JVMCI");
-    SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID;
-    SystemDictionary::resolve_wk_klasses_through(SystemDictionary::LAST_JVMCI_WKID, scan, CHECK);
-    JVMCIJavaClasses::compute_offsets(CHECK);
-    JVMCIRuntime::_well_known_classes_initialized = true;
-  }
-}
+// ------------------------------------------------------------------
+Klass* JVMCIRuntime::get_klass_by_name_impl(Klass*& accessing_klass,
+                                          const constantPoolHandle& cpool,
+                                          Symbol* sym,
+                                          bool require_local) {
+  JVMCI_EXCEPTION_CONTEXT;
 
-void JVMCIRuntime::metadata_do(void f(Metadata*)) {
-  // For simplicity, the existence of HotSpotJVMCIMetaAccessContext in
-  // the SystemDictionary well known classes should ensure the other
-  // classes have already been loaded, so make sure their order in the
-  // table enforces that.
-  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) <
-         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
-  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotConstantPool) <
-         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
-  assert(SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl) <
-         SystemDictionary::WK_KLASS_ENUM_NAME(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext), "must be loaded earlier");
-
-  if (HotSpotJVMCIMetaAccessContext::klass() == NULL ||
-      !HotSpotJVMCIMetaAccessContext::klass()->is_linked()) {
-    // Nothing could be registered yet
-    return;
+  // 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);
   }
 
-  // WeakReference<HotSpotJVMCIMetaAccessContext>[]
-  objArrayOop allContexts = HotSpotJVMCIMetaAccessContext::allContexts();
-  if (allContexts == NULL) {
-    return;
+  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());
   }
 
-  // These must be loaded at this point but the linking state doesn't matter.
-  assert(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass() != NULL, "must be loaded");
-  assert(SystemDictionary::HotSpotConstantPool_klass() != NULL, "must be loaded");
-  assert(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass() != NULL, "must be loaded");
+  Klass* found_klass;
+  {
+    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);
+    }
+  }
 
-  for (int i = 0; i < allContexts->length(); i++) {
-    oop ref = allContexts->obj_at(i);
-    if (ref != NULL) {
-      oop referent = java_lang_ref_Reference::referent(ref);
-      if (referent != NULL) {
-        // Chunked Object[] with last element pointing to next chunk
-        objArrayOop metadataRoots = HotSpotJVMCIMetaAccessContext::metadataRoots(referent);
-        while (metadataRoots != NULL) {
-          for (int typeIndex = 0; typeIndex < metadataRoots->length() - 1; typeIndex++) {
-            oop reference = metadataRoots->obj_at(typeIndex);
-            if (reference == NULL) {
-              continue;
-            }
-            oop metadataRoot = java_lang_ref_Reference::referent(reference);
-            if (metadataRoot == NULL) {
-              continue;
-            }
-            if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
-              Method* method = CompilerToVM::asMethod(metadataRoot);
-              f(method);
-            } else if (metadataRoot->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
-              ConstantPool* constantPool = CompilerToVM::asConstantPool(metadataRoot);
-              f(constantPool);
-            } else if (metadataRoot->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
-              Klass* klass = CompilerToVM::asKlass(metadataRoot);
-              f(klass);
-            } else {
-              metadataRoot->print();
-              ShouldNotReachHere();
-            }
-          }
-          metadataRoots = (objArrayOop)metadataRoots->obj_at(metadataRoots->length() - 1);
-          assert(metadataRoots == NULL || metadataRoots->is_objArray(), "wrong type");
+  // If we fail to find an array klass, look again for its element type.
+  // The element type may be available either locally or via constraints.
+  // In either case, if we can find the element type in the system dictionary,
+  // we must build an array type around it.  The CI requires array klasses
+  // to be loaded if their element klasses are loaded, except when memory
+  // is exhausted.
+  if (sym->char_at(0) == '[' &&
+      (sym->char_at(1) == '[' || sym->char_at(1) == 'L')) {
+    // We have an unloaded array.
+    // Build it on the fly if the element class exists.
+    TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                                                 sym->utf8_length()-1,
+                                                 CHECK_NULL);
+
+    // Get element Klass recursively.
+    Klass* elem_klass =
+      get_klass_by_name_impl(accessing_klass,
+                             cpool,
+                             elem_sym,
+                             require_local);
+    if (elem_klass != NULL) {
+      // Now make an array for it
+      return elem_klass->array_klass(THREAD);
+    }
+  }
+
+  if (found_klass == NULL && !cpool.is_null() && cpool->has_preresolution()) {
+    // Look inside the constant pool for pre-resolved class entries.
+    for (int i = cpool->length() - 1; i >= 1; i--) {
+      if (cpool->tag_at(i).is_klass()) {
+        Klass*  kls = cpool->resolved_klass_at(i);
+        if (kls->name() == sym) {
+          return kls;
         }
       }
     }
   }
+
+  return found_klass;
+}
+
+// ------------------------------------------------------------------
+Klass* JVMCIRuntime::get_klass_by_name(Klass* accessing_klass,
+                                  Symbol* klass_name,
+                                  bool require_local) {
+  ResourceMark rm;
+  constantPoolHandle cpool;
+  return get_klass_by_name_impl(accessing_klass,
+                                                 cpool,
+                                                 klass_name,
+                                                 require_local);
+}
+
+// ------------------------------------------------------------------
+// Implementation of get_klass_by_index.
+Klass* JVMCIRuntime::get_klass_by_index_impl(const constantPoolHandle& cpool,
+                                        int index,
+                                        bool& is_accessible,
+                                        Klass* accessor) {
+  JVMCI_EXCEPTION_CONTEXT;
+  Klass* klass = ConstantPool::klass_at_if_loaded(cpool, index);
+  Symbol* klass_name = NULL;
+  if (klass == NULL) {
+    klass_name = cpool->klass_name_at(index);
+  }
+
+  if (klass == NULL) {
+    // Not found in constant pool.  Use the name to do the lookup.
+    Klass* k = get_klass_by_name_impl(accessor,
+                                        cpool,
+                                        klass_name,
+                                        false);
+    // Calculate accessibility the hard way.
+    if (k == NULL) {
+      is_accessible = false;
+    } else if (k->class_loader() != accessor->class_loader() &&
+               get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) {
+      // Loaded only remotely.  Not linked yet.
+      is_accessible = false;
+    } else {
+      // Linked locally, and we must also check public/private, etc.
+      is_accessible = check_klass_accessibility(accessor, k);
+    }
+    if (!is_accessible) {
+      return NULL;
+    }
+    return k;
+  }
+
+  // It is known to be accessible, since it was found in the constant pool.
+  is_accessible = true;
+  return klass;
+}
+
+// ------------------------------------------------------------------
+// Get a klass from the constant pool.
+Klass* JVMCIRuntime::get_klass_by_index(const constantPoolHandle& cpool,
+                                   int index,
+                                   bool& is_accessible,
+                                   Klass* accessor) {
+  ResourceMark rm;
+  Klass* result = get_klass_by_index_impl(cpool, index, is_accessible, accessor);
+  return result;
 }
 
-// private static void CompilerToVM.registerNatives()
-JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
-  if (!EnableJVMCI) {
-    THROW_MSG(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled");
+// ------------------------------------------------------------------
+// Implementation of get_field_by_index.
+//
+// Implementation note: the results of field lookups are cached
+// in the accessor klass.
+void JVMCIRuntime::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc,
+                                        int index) {
+  JVMCI_EXCEPTION_CONTEXT;
+
+  assert(klass->is_linked(), "must be linked before using its constant-pool");
+
+  constantPoolHandle cpool(thread, klass->constants());
+
+  // Get the field's name, signature, and type.
+  Symbol* name  = cpool->name_ref_at(index);
+
+  int nt_index = cpool->name_and_type_ref_index_at(index);
+  int sig_index = cpool->signature_ref_index_at(nt_index);
+  Symbol* signature = cpool->symbol_at(sig_index);
+
+  // Get the field's declared holder.
+  int holder_index = cpool->klass_ref_index_at(index);
+  bool holder_is_accessible;
+  Klass* declared_holder = get_klass_by_index(cpool, holder_index,
+                                               holder_is_accessible,
+                                               klass);
+
+  // The declared holder of this field may not have been loaded.
+  // Bail out with partial field information.
+  if (!holder_is_accessible) {
+    return;
+  }
+
+
+  // Perform the field lookup.
+  Klass*  canonical_holder =
+    InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc);
+  if (canonical_holder == NULL) {
+    return;
+  }
+
+  assert(canonical_holder == field_desc.field_holder(), "just checking");
+}
+
+// ------------------------------------------------------------------
+// Get a field by index from a klass's constant pool.
+void JVMCIRuntime::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 JVMCIRuntime::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();
   }
 
-#ifdef _LP64
-#ifndef SPARC
-  uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
-  uintptr_t allocation_end = heap_end + ((uintptr_t)16) * 1024 * 1024 * 1024;
-  guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)");
-#endif // !SPARC
-#else
-  fatal("check TLAB allocation code for address space conflicts");
-#endif // _LP64
+  return dest_method;
+}
+
+
+// ------------------------------------------------------------------
+methodHandle JVMCIRuntime::get_method_by_index_impl(const constantPoolHandle& cpool,
+                                          int index, Bytecodes::Code bc,
+                                          InstanceKlass* accessor) {
+  if (bc == Bytecodes::_invokedynamic) {
+    ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
+    bool is_resolved = !cpce->is_f1_null();
+    if (is_resolved) {
+      // Get the invoker Method* from the constant pool.
+      // (The appendix argument, if any, will be noted in the method's signature.)
+      Method* adapter = cpce->f1_as_method();
+      return methodHandle(adapter);
+    }
+
+    return NULL;
+  }
+
+  int holder_index = cpool->klass_ref_index_at(index);
+  bool holder_is_accessible;
+  Klass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+
+  // Get the method's name and signature.
+  Symbol* name_sym = cpool->name_ref_at(index);
+  Symbol* sig_sym  = cpool->signature_ref_at(index);
 
-  JVMCIRuntime::initialize_well_known_classes(CHECK);
+  if (cpool->has_preresolution()
+      || ((holder == SystemDictionary::MethodHandle_klass() || holder == SystemDictionary::VarHandle_klass()) &&
+          MethodHandles::is_signature_polymorphic_name(holder, name_sym))) {
+    // Short-circuit lookups for JSR 292-related call sites.
+    // That is, do not rely only on name-based lookups, because they may fail
+    // if the names are not resolvable in the boot class loader (7056328).
+    switch (bc) {
+    case Bytecodes::_invokevirtual:
+    case Bytecodes::_invokeinterface:
+    case Bytecodes::_invokespecial:
+    case Bytecodes::_invokestatic:
+      {
+        Method* m = ConstantPool::method_at_if_loaded(cpool, index);
+        if (m != NULL) {
+          return m;
+        }
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  if (holder_is_accessible) { // Our declared holder is loaded.
+    constantTag tag = cpool->tag_ref_at(index);
+    methodHandle m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag);
+    if (!m.is_null()) {
+      // We found the method.
+      return m;
+    }
+  }
+
+  // Either the declared holder was not loaded, or the method could
+  // not be found.
+
+  return NULL;
+}
+
+// ------------------------------------------------------------------
+InstanceKlass* JVMCIRuntime::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 InstanceKlass::cast(SystemDictionary::Object_klass());
+  } else {
+    ShouldNotReachHere();
+  }
+  return NULL;
+}
+
 
-  {
-    ThreadToNativeFromVM trans(thread);
-    env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count());
+// ------------------------------------------------------------------
+methodHandle JVMCIRuntime::get_method_by_index(const constantPoolHandle& cpool,
+                                     int index, Bytecodes::Code bc,
+                                     InstanceKlass* accessor) {
+  ResourceMark rm;
+  return get_method_by_index_impl(cpool, index, bc, accessor);
+}
+
+// ------------------------------------------------------------------
+// Check for changes to the system dictionary during compilation
+// class loads, evolution, breakpoints
+JVMCI::CodeInstallResult JVMCIRuntime::validate_compile_task_dependencies(Dependencies* dependencies, JVMCICompileState* compile_state, char** failure_detail) {
+  // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
+  if (compile_state != NULL && compile_state->jvmti_state_changed()) {
+    *failure_detail = (char*) "Jvmti state change during compilation invalidated dependencies";
+    return JVMCI::dependencies_failed;
   }
-JVM_END
+
+  // Dependencies must be checked when the system dictionary changes
+  // or if we don't know whether it has changed (i.e., compile_state == NULL).
+  bool counter_changed = compile_state == NULL || compile_state->system_dictionary_modification_counter() != SystemDictionary::number_of_modifications();
+  CompileTask* task = compile_state == NULL ? NULL : compile_state->task();
+  Dependencies::DepType result = dependencies->validate_dependencies(task, counter_changed, failure_detail);
+  if (result == Dependencies::end_marker) {
+    return JVMCI::ok;
+  }
+
+  if (!Dependencies::is_klass_type(result) || counter_changed) {
+    return JVMCI::dependencies_failed;
+  }
+  // The dependencies were invalid at the time of installation
+  // without any intervening modification of the system
+  // dictionary.  That means they were invalidly constructed.
+  return JVMCI::dependencies_invalid;
+}
+
+
+void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& method, int entry_bci) {
+  JVMCI_EXCEPTION_CONTEXT
+
+  JVMCICompileState* compile_state = JVMCIENV->compile_state();
 
-void JVMCIRuntime::shutdown(TRAPS) {
-  if (_HotSpotJVMCIRuntime_instance != NULL) {
-    _shutdown_called = true;
-    HandleMark hm(THREAD);
-    Handle receiver = get_HotSpotJVMCIRuntime(CHECK);
-    JavaValue result(T_VOID);
-    JavaCallArguments args;
-    args.push_oop(receiver);
-    JavaCalls::call_special(&result, receiver->klass(), vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, CHECK);
+  bool is_osr = entry_bci != InvocationEntryBci;
+  if (compiler->is_bootstrapping() && is_osr) {
+    // no OSR compilations during bootstrap - the compiler is just too slow at this point,
+    // and we know that there are no endless loops
+    compile_state->set_failure(true, "No OSR during boostrap");
+    return;
+  }
+
+  HandleMark hm;
+  JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
+  if (JVMCIENV->has_pending_exception()) {
+    JVMCIENV->describe_pending_exception(true);
+    compile_state->set_failure(false, "exception getting HotSpotJVMCIRuntime object");
+    return;
+  }
+  JVMCIObject jvmci_method = JVMCIENV->get_jvmci_method(method, JVMCIENV);
+  if (JVMCIENV->has_pending_exception()) {
+    JVMCIENV->describe_pending_exception(true);
+    compile_state->set_failure(false, "exception getting JVMCI wrapper method");
+    return;
+  }
+
+  JVMCIObject result_object = JVMCIENV->call_HotSpotJVMCIRuntime_compileMethod(receiver, jvmci_method, entry_bci,
+                                                                     (jlong) compile_state, compile_state->task()->compile_id());
+  if (!JVMCIENV->has_pending_exception()) {
+    if (result_object.is_non_null()) {
+      JVMCIObject failure_message = JVMCIENV->get_HotSpotCompilationRequestResult_failureMessage(result_object);
+      if (failure_message.is_non_null()) {
+        // Copy failure reason into resource memory first ...
+        const char* failure_reason = JVMCIENV->as_utf8_string(failure_message);
+        // ... and then into the C heap.
+        failure_reason = os::strdup(failure_reason, mtJVMCI);
+        bool retryable = JVMCIENV->get_HotSpotCompilationRequestResult_retry(result_object) != 0;
+        compile_state->set_failure(retryable, failure_reason, true);
+      } else {
+        if (compile_state->task()->code() == NULL) {
+          compile_state->set_failure(true, "no nmethod produced");
+        } else {
+          compile_state->task()->set_num_inlined_bytecodes(JVMCIENV->get_HotSpotCompilationRequestResult_inlinedBytecodes(result_object));
+          compiler->inc_methods_compiled();
+        }
+      }
+    } else {
+      assert(false, "JVMCICompiler.compileMethod should always return non-null");
+    }
+  } else {
+    // An uncaught exception was thrown during compilation. Generally these
+    // should be handled by the Java code in some useful way but if they leak
+    // through to here report them instead of dying or silently ignoring them.
+    JVMCIENV->describe_pending_exception(true);
+    compile_state->set_failure(false, "unexpected exception thrown");
+  }
+  if (compiler->is_bootstrapping()) {
+    compiler->set_bootstrap_compilation_request_handled();
   }
 }
 
-void JVMCIRuntime::bootstrap_finished(TRAPS) {
-  HandleMark hm(THREAD);
-  Handle receiver = get_HotSpotJVMCIRuntime(CHECK);
-  JavaValue result(T_VOID);
-  JavaCallArguments args;
-  args.push_oop(receiver);
-  JavaCalls::call_special(&result, receiver->klass(), vmSymbols::bootstrapFinished_method_name(), vmSymbols::void_method_signature(), &args, CHECK);
+
+// ------------------------------------------------------------------
+JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
+                                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,
+                                int compile_id,
+                                bool has_unsafe_access,
+                                bool has_wide_vector,
+                                JVMCIObject compiled_code,
+                                JVMCIObject nmethod_mirror,
+                                FailedSpeculation** failed_speculations,
+                                char* speculations,
+                                int speculations_len) {
+  JVMCI_EXCEPTION_CONTEXT;
+  nm = NULL;
+  int comp_level = CompLevel_full_optimization;
+  char* failure_detail = NULL;
+
+  bool install_default = JVMCIENV->get_HotSpotNmethod_isDefault(nmethod_mirror) != 0;
+  assert(JVMCIENV->isa_HotSpotNmethod(nmethod_mirror), "must be");
+  JVMCIObject name = JVMCIENV->get_InstalledCode_name(nmethod_mirror);
+  const char* nmethod_mirror_name = name.is_null() ? NULL : JVMCIENV->as_utf8_string(name);
+  int nmethod_mirror_index;
+  if (!install_default) {
+    // Reserve or initialize mirror slot in the oops table.
+    OopRecorder* oop_recorder = debug_info->oop_recorder();
+    nmethod_mirror_index = oop_recorder->allocate_oop_index(nmethod_mirror.is_hotspot() ? nmethod_mirror.as_jobject() : NULL);
+  } else {
+    // A default HotSpotNmethod mirror is never tracked by the nmethod
+    nmethod_mirror_index = -1;
+  }
+
+  JVMCI::CodeInstallResult result;
+  {
+    // To prevent compile queue updates.
+    MutexLocker locker(MethodCompileQueue_lock, THREAD);
+
+    // Prevent SystemDictionary::add_to_hierarchy from running
+    // and invalidating our dependencies until we install this method.
+    MutexLocker ml(Compile_lock);
+
+    // Encode the dependencies now, so we can check them right away.
+    dependencies->encode_content_bytes();
+
+    // Record the dependencies for the current compile in the log
+    if (LogCompilation) {
+      for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
+        deps.log_dependency();
+      }
+    }
+
+    // Check for {class loads, evolution, breakpoints} during compilation
+    result = validate_compile_task_dependencies(dependencies, JVMCIENV->compile_state(), &failure_detail);
+    if (result != JVMCI::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,
+                                 speculations, speculations_len,
+                                 nmethod_mirror_index, nmethod_mirror_name, failed_speculations);
+
+
+      // Free codeBlobs
+      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.)
+        if (JVMCIENV->compile_state() != NULL) {
+          JVMCIENV->compile_state()->task()->set_code(nm);
+        }
+
+        JVMCINMethodData* data = nm->jvmci_nmethod_data();
+        assert(data != NULL, "must be");
+        if (install_default) {
+          assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm) == NULL, "must be");
+          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);
+          }
+        } else {
+          assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm) == HotSpotJVMCI::resolve(nmethod_mirror), "must be");
+        }
+        nm->make_in_use();
+      }
+      result = nm != NULL ? JVMCI::ok :JVMCI::cache_full;
+    }
+  }
+
+  // String creation must be done outside lock
+  if (failure_detail != NULL) {
+    // A failure to allocate the string is silently ignored.
+    JVMCIObject message = JVMCIENV->create_string(failure_detail, JVMCIENV);
+    JVMCIENV->set_HotSpotCompiledNmethod_installationFailureMessage(compiled_code, message);
+  }
+
+  // JVMTI -- compiled method notification (must be done outside lock)
+  if (nm != NULL) {
+    nm->post_compiled_method_load_event();
+  }
+
+  return result;
 }
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp	Wed May 01 12:31:29 2019 -0700
@@ -24,23 +24,68 @@
 #ifndef SHARE_JVMCI_JVMCIRUNTIME_HPP
 #define SHARE_JVMCI_JVMCIRUNTIME_HPP
 
-#include "interpreter/interpreter.hpp"
-#include "memory/allocation.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/deoptimization.hpp"
+#include "code/nmethod.hpp"
+#include "jvmci/jvmci.hpp"
+#include "jvmci/jvmciExceptions.hpp"
+#include "jvmci/jvmciObject.hpp"
+
+class JVMCIEnv;
+class JVMCICompiler;
+class JVMCICompileState;
 
-#define JVMCI_ERROR(...)       \
-  { Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::jdk_vm_ci_common_JVMCIError(), __VA_ARGS__); return; }
+// Encapsulates the JVMCI metadata for an nmethod.
+// JVMCINMethodData objects are inlined into nmethods
+// at nmethod::_jvmci_data_offset.
+class JVMCINMethodData {
+  // Index for the HotSpotNmethod mirror in the nmethod's oops table.
+  // This is -1 if there is no mirror in the oops table.
+  int _nmethod_mirror_index;
+
+  // Is HotSpotNmethod.name non-null? If so, the value is
+  // embedded in the end of this object.
+  bool _has_name;
+
+  // Address of the failed speculations list to which a speculation
+  // is appended when it causes a deoptimization.
+  FailedSpeculation** _failed_speculations;
 
-#define JVMCI_ERROR_(ret, ...) \
-  { Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::jdk_vm_ci_common_JVMCIError(), __VA_ARGS__); return ret; }
+public:
+  // Computes the size of a JVMCINMethodData object
+  static int compute_size(const char* nmethod_mirror_name) {
+    int size = sizeof(JVMCINMethodData);
+    if (nmethod_mirror_name != NULL) {
+      size += (int) strlen(nmethod_mirror_name) + 1;
+    }
+    return size;
+  }
+
+  void initialize(int nmethod_mirror_index,
+             const char* name,
+             FailedSpeculation** failed_speculations);
+
+  // Adds `speculation` to the failed speculations list.
+  void add_failed_speculation(nmethod* nm, jlong speculation);
 
-#define JVMCI_ERROR_0(...)    JVMCI_ERROR_(0, __VA_ARGS__)
-#define JVMCI_ERROR_NULL(...) JVMCI_ERROR_(NULL, __VA_ARGS__)
-#define JVMCI_ERROR_OK(...)   JVMCI_ERROR_(JVMCIEnv::ok, __VA_ARGS__)
-#define CHECK_OK              CHECK_(JVMCIEnv::ok)
+  // Gets the JVMCI name of the nmethod (which may be NULL).
+  const char* name() { return _has_name ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : NULL; }
+
+  // Clears the HotSpotNmethod.address field in the  mirror. If nm
+  // is dead, the HotSpotNmethod.entryPoint field is also cleared.
+  void invalidate_nmethod_mirror(nmethod* nm);
+
+  // Gets the mirror from nm's oops table.
+  oop get_nmethod_mirror(nmethod* nm);
 
-class JVMCIRuntime: public AllStatic {
+  // Sets the mirror in nm's oops table.
+  void set_nmethod_mirror(nmethod* nm, oop mirror);
+
+  // Clears the mirror in nm's oops table.
+  void clear_nmethod_mirror(nmethod* nm);
+};
+
+// A top level class that represents an initialized JVMCI runtime.
+// There is one instance of this class per HotSpotJVMCIRuntime object.
+class JVMCIRuntime: public CHeapObj<mtJVMCI> {
  public:
   // Constants describing whether JVMCI wants to be able to adjust the compilation
   // level selected for a method by the VM compilation policy and if so, based on
@@ -52,57 +97,187 @@
   };
 
  private:
-  static jobject _HotSpotJVMCIRuntime_instance;
-  static bool _well_known_classes_initialized;
+  volatile bool _being_initialized;
+  volatile bool _initialized;
+
+  JVMCIObject _HotSpotJVMCIRuntime_instance;
+
+  bool _shutdown_called;
+
+  JVMCIObject create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS);
 
-  static bool _shutdown_called;
+  // Implementation methods for loading and constant pool access.
+  static Klass* get_klass_by_name_impl(Klass*& accessing_klass,
+                                       const constantPoolHandle& cpool,
+                                       Symbol* klass_name,
+                                       bool require_local);
+  static Klass*   get_klass_by_index_impl(const constantPoolHandle& cpool,
+                                          int klass_index,
+                                          bool& is_accessible,
+                                          Klass* loading_klass);
+  static void   get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd,
+                                        int field_index);
+  static methodHandle  get_method_by_index_impl(const constantPoolHandle& cpool,
+                                                int method_index, Bytecodes::Code bc,
+                                                InstanceKlass* loading_klass);
+
+  // Helper methods
+  static bool       check_klass_accessibility(Klass* accessing_klass, Klass* resolved_klass);
+  static methodHandle  lookup_method(InstanceKlass*  accessor,
+                                     Klass*  holder,
+                                     Symbol*         name,
+                                     Symbol*         sig,
+                                     Bytecodes::Code bc,
+                                     constantTag     tag);
 
  public:
-  static bool is_HotSpotJVMCIRuntime_initialized() {
-    return _HotSpotJVMCIRuntime_instance != NULL;
+  JVMCIRuntime() {
+    _initialized = false;
+    _being_initialized = false;
+    _shutdown_called = false;
   }
 
   /**
+   * Compute offsets and construct any state required before executing JVMCI code.
+   */
+  void initialize(JVMCIEnv* jvmciEnv);
+
+  /**
    * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary
    */
-  static Handle get_HotSpotJVMCIRuntime(TRAPS);
+  JVMCIObject get_HotSpotJVMCIRuntime(JVMCI_TRAPS);
 
-  static jobject get_HotSpotJVMCIRuntime_jobject(TRAPS) {
-    initialize_JVMCI(CHECK_NULL);
-    assert(_HotSpotJVMCIRuntime_instance != NULL, "must be");
-    return _HotSpotJVMCIRuntime_instance;
+  bool is_HotSpotJVMCIRuntime_initialized() {
+    return _HotSpotJVMCIRuntime_instance.is_non_null();
   }
 
-  static Handle callStatic(const char* className, const char* methodName, const char* returnType, JavaCallArguments* args, TRAPS);
-
-  /**
-   * Determines if the VM is sufficiently booted to initialize JVMCI.
-   */
-  static bool can_initialize_JVMCI();
-
   /**
    * Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
    */
-  static void initialize_JVMCI(TRAPS);
+  void initialize_JVMCI(JVMCI_TRAPS);
 
   /**
    * Explicitly initialize HotSpotJVMCIRuntime itself
    */
-  static void initialize_HotSpotJVMCIRuntime(TRAPS);
+  void initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS);
 
-  static void initialize_well_known_classes(TRAPS);
-
-  static void metadata_do(void f(Metadata*));
+  void call_getCompiler(TRAPS);
 
-  static void shutdown(TRAPS);
+  void shutdown();
 
-  static void bootstrap_finished(TRAPS);
-
-  static bool shutdown_called() {
+  bool shutdown_called() {
     return _shutdown_called;
   }
 
-  static BasicType kindToBasicType(Handle kind, TRAPS);
+  void bootstrap_finished(TRAPS);
+
+  // Look up a klass by name from a particular class loader (the accessor's).
+  // If require_local, result must be defined in that class loader, or NULL.
+  // If !require_local, a result from remote class loader may be reported,
+  // if sufficient class loader constraints exist such that initiating
+  // a class loading request from the given loader is bound to return
+  // the class defined in the remote loader (or throw an error).
+  //
+  // Return an unloaded klass if !require_local and no class at all is found.
+  //
+  // The CI treats a klass as loaded if it is consistently defined in
+  // another loader, even if it hasn't yet been loaded in all loaders
+  // that could potentially see it via delegation.
+  static Klass* get_klass_by_name(Klass* accessing_klass,
+                                  Symbol* klass_name,
+                                  bool require_local);
+
+  // Constant pool access.
+  static Klass*   get_klass_by_index(const constantPoolHandle& cpool,
+                                     int klass_index,
+                                     bool& is_accessible,
+                                     Klass* loading_klass);
+  static void   get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd,
+                                   int field_index);
+  static methodHandle  get_method_by_index(const constantPoolHandle& cpool,
+                                           int method_index, Bytecodes::Code bc,
+                                           InstanceKlass* loading_klass);
+
+  // converts the Klass* representing the holder of a method into a
+  // InstanceKlass*.  This is needed since the holder of a method in
+  // the bytecodes could be an array type.  Basically this converts
+  // array types into java/lang/Object and other types stay as they are.
+  static InstanceKlass* get_instance_klass_for_declared_method_holder(Klass* klass);
+
+  // Helper routine for determining the validity of a compilation
+  // with respect to concurrent class loading.
+  static JVMCI::CodeInstallResult validate_compile_task_dependencies(Dependencies* target, JVMCICompileState* task, char** failure_detail);
+
+  // Compiles `target` with the JVMCI compiler.
+  void compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& target, int entry_bci);
+
+  // Register the result of a compilation.
+  JVMCI::CodeInstallResult register_method(JVMCIEnv* JVMCIENV,
+                       const methodHandle&       target,
+                       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,
+                       int                       compile_id,
+                       bool                      has_unsafe_access,
+                       bool                      has_wide_vector,
+                       JVMCIObject               compiled_code,
+                       JVMCIObject               nmethod_mirror,
+                       FailedSpeculation**       failed_speculations,
+                       char*                     speculations,
+                       int                       speculations_len);
+
+  /**
+   * Exits the VM due to an unexpected exception.
+   */
+  static void exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* message);
+
+  static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear);
+
+#define CHECK_EXIT THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(NULL, buf); \
+    return; \
+  } \
+  (void)(0
+
+#define CHECK_EXIT_(v) THREAD);                 \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(NULL, buf); \
+    return v; \
+  } \
+  (void)(0
+
+#define JVMCI_CHECK_EXIT JVMCIENV); \
+  if (JVMCIENV->has_pending_exception()) {      \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(JVMCIENV, buf); \
+    return; \
+  } \
+  (void)(0
+
+#define JVMCI_CHECK_EXIT_(result) JVMCIENV); \
+  if (JVMCIENV->has_pending_exception()) {      \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::exit_on_pending_exception(JVMCIENV, buf); \
+    return result; \
+  } \
+  (void)(0
+
+  static BasicType kindToBasicType(const Handle& kind, TRAPS);
 
   static void new_instance_common(JavaThread* thread, Klass* klass, bool null_on_fail);
   static void new_array_common(JavaThread* thread, Klass* klass, jint length, bool null_on_fail);
@@ -162,11 +337,8 @@
   static void throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
   static void throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);
 
-  // Forces initialization of the JVMCI runtime.
-  static void force_initialization(TRAPS);
-
   // Test only function
-  static int test_deoptimize_call_int(JavaThread* thread, int value);
+  static jint test_deoptimize_call_int(JavaThread* thread, int value);
 };
 
 // Tracing macros.
@@ -177,10 +349,10 @@
 #define IF_TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4)) ; else
 #define IF_TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5)) ; else
 
-#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print("JVMCITrace-1: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print("   JVMCITrace-2: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print("      JVMCITrace-3: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print("         JVMCITrace-4: "), true))) ; else tty->print_cr
-#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print("            JVMCITrace-5: "), true))) ; else tty->print_cr
+#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print(PTR_FORMAT " JVMCITrace-1: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print(PTR_FORMAT "    JVMCITrace-2: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print(PTR_FORMAT "       JVMCITrace-3: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print(PTR_FORMAT "          JVMCITrace-4: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
+#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print(PTR_FORMAT "             JVMCITrace-5: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
 
 #endif // SHARE_JVMCI_JVMCIRUNTIME_HPP
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -27,8 +27,11 @@
 #include "jvmci/jvmci_globals.hpp"
 #include "gc/shared/gcConfig.hpp"
 #include "utilities/defaultStream.hpp"
+#include "utilities/ostream.hpp"
 #include "runtime/globals_extension.hpp"
 
+fileStream* JVMCIGlobals::_jni_config_file = NULL;
+
 JVMCI_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
             MATERIALIZE_PD_DEVELOPER_FLAG, \
             MATERIALIZE_PRODUCT_FLAG, \
@@ -79,6 +82,10 @@
       return false;
     }
     FLAG_SET_DEFAULT(EnableJVMCI, true);
+    if (BootstrapJVMCI && UseJVMCINativeLibrary) {
+      jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary");
+      return false;
+    }
   }
 
   if (!EnableJVMCI) {
@@ -97,7 +104,9 @@
   CHECK_NOT_SET(JVMCINMethodSizeLimit,        EnableJVMCI)
   CHECK_NOT_SET(MethodProfileWidth,           EnableJVMCI)
   CHECK_NOT_SET(JVMCIPrintProperties,         EnableJVMCI)
-  CHECK_NOT_SET(TraceUncollectedSpeculations, EnableJVMCI)
+  CHECK_NOT_SET(UseJVMCINativeLibrary,        EnableJVMCI)
+  CHECK_NOT_SET(JVMCILibPath,                 EnableJVMCI)
+  CHECK_NOT_SET(JVMCILibDumpJNIConfig,        EnableJVMCI)
 
 #ifndef PRODUCT
 #define JVMCI_CHECK4(type, name, value, doc) assert(name##checked, #name " flag not checked");
@@ -110,10 +119,21 @@
 #undef JVMCI_CHECK3
 #undef JVMCI_CHECK4
 #undef JVMCI_FLAG_CHECKED
-#endif
+#endif // PRODUCT
 #undef CHECK_NOT_SET
+
+  if (JVMCILibDumpJNIConfig != NULL) {
+    _jni_config_file = new(ResourceObj::C_HEAP, mtJVMCI) fileStream(JVMCILibDumpJNIConfig);
+    if (_jni_config_file == NULL || !_jni_config_file->is_open()) {
+      jio_fprintf(defaultStream::error_stream(),
+          "Could not open file for dumping JVMCI shared library JNI config: %s\n", JVMCILibDumpJNIConfig);
+      return false;
+    }
+  }
+
   return true;
 }
+
 void JVMCIGlobals::check_jvmci_supported_gc() {
   if (EnableJVMCI) {
     // Check if selected GC is supported by JVMCI and Java compiler
--- a/src/hotspot/share/jvmci/jvmci_globals.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp	Wed May 01 12:31:29 2019 -0700
@@ -25,7 +25,7 @@
 #ifndef SHARE_JVMCI_JVMCI_GLOBALS_HPP
 #define SHARE_JVMCI_JVMCI_GLOBALS_HPP
 
-#include "runtime/globals.hpp"
+#include "utilities/ostream.hpp"
 
 //
 // Defines all global flags used by the JVMCI compiler. Only flags that need
@@ -62,11 +62,13 @@
           "Print JVMCI bootstrap progress and summary")                     \
                                                                             \
   experimental(intx, JVMCIThreads, 1,                                       \
-          "Force number of JVMCI compiler threads to use")                  \
+          "Force number of JVMCI compiler threads to use. Ignored if "      \
+          "UseJVMCICompiler is false.")                                     \
           range(1, max_jint)                                                \
                                                                             \
   experimental(intx, JVMCIHostThreads, 1,                                   \
-          "Force number of compiler threads for JVMCI host compiler")       \
+          "Force number of C1 compiler threads. Ignored if "                \
+          "UseJVMCICompiler is false.")                                     \
           range(1, max_jint)                                                \
                                                                             \
   NOT_COMPILER2(product(intx, MaxVectorSize, 64,                            \
@@ -97,8 +99,17 @@
   experimental(intx, MethodProfileWidth, 0,                                 \
           "Number of methods to record in call profile")                    \
                                                                             \
-  develop(bool, TraceUncollectedSpeculations, false,                        \
-          "Print message when a failed speculation was not collected")      \
+  experimental(ccstr, JVMCILibPath, NULL,                                   \
+          "LD path for loading the JVMCI shared library")                   \
+                                                                            \
+  experimental(ccstr, JVMCILibDumpJNIConfig, NULL,                          \
+          "Dumps to the given file a description of the classes, fields "   \
+          "and methods the JVMCI shared library must provide")              \
+                                                                            \
+  experimental(bool, UseJVMCINativeLibrary, false,                          \
+          "Execute JVMCI Java code from a shared library "                  \
+          "instead of loading it from class files and executing it "        \
+          "on the HotSpot heap")                                            \
                                                                             \
   NOT_COMPILER2(diagnostic(bool, UseMultiplyToLenIntrinsic, false,          \
           "Enables intrinsification of BigInteger.multiplyToLen()"))        \
@@ -130,14 +141,22 @@
             IGNORE_CONSTRAINT, \
             IGNORE_WRITEABLE)
 
+// The base name for the shared library containing the JVMCI based compiler
+#define JVMCI_SHARED_LIBRARY_NAME "jvmcicompiler"
+
 class JVMCIGlobals {
+ private:
+  static fileStream* _jni_config_file;
  public:
-  // Return true if jvmci flags are consistent. If not consistent,
+
+  // Returns true if jvmci flags are consistent. If not consistent,
   // an error message describing the inconsistency is printed before
   // returning false.
   static bool check_jvmci_flags_are_consistent();
 
   // Check and exit VM with error if selected GC is not supported by JVMCI.
   static void check_jvmci_supported_gc();
+
+  static fileStream* get_jni_config_file() { return _jni_config_file; }
 };
 #endif // SHARE_JVMCI_JVMCI_GLOBALS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/metadataHandleBlock.cpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019, 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 "jvmci/metadataHandleBlock.hpp"
+
+MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
+intptr_t             MetadataHandleBlock::_free_list = 0;
+int                  MetadataHandleBlock::_allocate_before_rebuild = 0;
+
+jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
+  assert(obj->is_valid() && obj->is_metadata(), "must be");
+
+  if (_last == NULL) {
+    // This is the first allocation.
+    _last = this;
+  }
+
+  HandleRecord* handle = get_handle();
+
+  if (handle != NULL) {
+    handle->set_value(obj);
+#ifdef METADATA_TRACK_NAMES
+    handle->set_name(obj->print_value_string());
+#endif
+    return (jmetadata) handle;
+  }
+
+  // Check if unused block follow last
+  if (_last->_next != NULL) {
+    // update last and retry
+    _last = _last->_next;
+    return allocate_metadata_handle(obj);
+  }
+
+  // No space available, we have to rebuild free list or expand
+  if (_allocate_before_rebuild == 0) {
+    rebuild_free_list();        // updates _allocate_before_rebuild counter
+  } else {
+    // Append new block
+    // This can block, but the caller has a metadata handle around this object.
+    _last->_next = allocate_block();
+    _last = _last->_next;
+    _allocate_before_rebuild--;
+  }
+  return allocate_metadata_handle(obj);  // retry
+}
+
+
+void MetadataHandleBlock::rebuild_free_list() {
+  assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
+  int free = 0;
+  int blocks = 0;
+  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+    for (int index = 0; index < current->_top; index++) {
+      HandleRecord* handle = &(current->_handles)[index];
+      if (handle->value() == NULL) {
+        // this handle was cleared out by a delete call, reuse it
+        chain_free_list(handle);
+        free++;
+      }
+    }
+    // we should not rebuild free list if there are unused handles at the end
+    assert(current->_top == block_size_in_handles, "just checking");
+    blocks++;
+  }
+  // Heuristic: if more than half of the handles are NOT free we rebuild next time
+  // as well, otherwise we append a corresponding number of new blocks before
+  // attempting a free list rebuild again.
+  int total = blocks * block_size_in_handles;
+  int extra = total - 2*free;
+  if (extra > 0) {
+    // Not as many free handles as we would like - compute number of new blocks to append
+    _allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles;
+  }
+}
+
+void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
+  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+    for (int index = 0; index < current->_top; index++) {
+      HandleRecord* root = &(current->_handles)[index];
+      Metadata* value = root->value();
+      // traverse heap pointers only, not deleted handles or free list
+      // pointers
+      if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
+        assert(value->is_valid(), "invalid metadata %s", get_name(index));
+        f(value);
+      }
+    }
+    // the next handle block is valid only if current block is full
+    if (current->_top < block_size_in_handles) {
+      break;
+    }
+  }
+}
+
+// Visit any live metadata handles and clean them up.  Since clearing of these handles is driven by
+// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
+void MetadataHandleBlock::do_unloading() {
+  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+    for (int index = 0; index < current->_top; index++) {
+      HandleRecord* handle = &(current->_handles)[index];
+      Metadata* value = handle->value();
+      // traverse heap pointers only, not deleted handles or free list
+      // pointers
+      if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
+        Klass* klass = NULL;
+        if (value->is_klass()) {
+          klass = (Klass*)value;
+        } else if (value->is_method()) {
+          Method* m = (Method*)value;
+          klass = m->method_holder();
+        } else if (value->is_constantPool()) {
+          ConstantPool* cp = (ConstantPool*)value;
+          klass = cp->pool_holder();
+        } else {
+          ShouldNotReachHere();
+        }
+        if (klass->class_loader_data()->is_unloading()) {
+          // This needs to be marked so that it's no longer scanned
+          // but can't be put on the free list yet. The
+          // HandleCleaner will set this to NULL and
+          // put it on the free list.
+          jlong old_value = Atomic::cmpxchg((jlong) (ptr_tag), (jlong*)handle, (jlong) value);
+          if (old_value == (jlong) value) {
+            // Success
+          } else {
+            guarantee(old_value == 0, "only other possible value");
+          }
+        }
+      }
+    }
+    // the next handle block is valid only if current block is full
+    if (current->_top < block_size_in_handles) {
+      break;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jvmci/metadataHandleBlock.hpp	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
+#define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
+
+#include "oops/constantPool.hpp"
+#include "oops/metadata.hpp"
+#include "oops/method.hpp"
+#include "runtime/handles.hpp"
+#include "runtime/os.hpp"
+
+#ifdef ASSERT
+#define METADATA_TRACK_NAMES
+#endif
+
+struct _jmetadata {
+ private:
+  Metadata* _value;
+#ifdef METADATA_TRACK_NAMES
+  // Debug data for tracking stale metadata
+  const char* _name;
+#endif
+
+ public:
+  Metadata* value() { return _value; }
+
+#ifdef METADATA_TRACK_NAMES
+  void initialize() {
+    _value = NULL;
+    _name = NULL;
+  }
+#endif
+
+  void set_value(Metadata* value) {
+    _value = value;
+  }
+
+#ifdef METADATA_TRACK_NAMES
+  const char* name() { return _name; }
+  void set_name(const char* name) {
+    if (_name != NULL) {
+      os::free((void*) _name);
+      _name = NULL;
+    }
+    if (name != NULL) {
+      _name = os::strdup(name);
+    }
+  }
+#endif
+};
+
+typedef struct _jmetadata HandleRecord;
+typedef struct _jmetadata *jmetadata;
+
+// JVMCI maintains direct references to metadata. To make these references safe in the face of
+// class redefinition, they are held in handles so they can be scanned during GC. They are
+// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
+// passed back to the Java code which is responsible for setting the handle to NULL when it
+// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
+// rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
+class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
+ private:
+  enum SomeConstants {
+    block_size_in_handles  = 32,      // Number of handles per handle block
+    ptr_tag = 1,
+    ptr_mask = ~((intptr_t)ptr_tag)
+  };
+
+
+  // Free handles always have their low bit set so those pointers can
+  // be distinguished from handles which are in use.  The last handle
+  // on the free list has a NULL pointer with the tag bit set, so it's
+  // clear that the handle has been reclaimed.  The _free_list is
+  // always a real pointer to a handle.
+
+  HandleRecord    _handles[block_size_in_handles]; // The handles
+  int             _top;                         // Index of next unused handle
+  MetadataHandleBlock* _next;                   // Link to next block
+
+  // The following instance variables are only used by the first block in a chain.
+  // Having two types of blocks complicates the code and the space overhead is negligible.
+  static MetadataHandleBlock* _last;                   // Last block in use
+  static intptr_t        _free_list;                   // Handle free list
+  static int             _allocate_before_rebuild;     // Number of blocks to allocate before rebuilding free list
+
+  MetadataHandleBlock() {
+    _top = 0;
+    _next = NULL;
+#ifdef METADATA_TRACK_NAMES
+    for (int i = 0; i < block_size_in_handles; i++) {
+      _handles[i].initialize();
+    }
+#endif
+  }
+
+  const char* get_name(int index) {
+#ifdef METADATA_TRACK_NAMES
+    return _handles[index].name();
+#else
+    return "<missing>";
+#endif
+  }
+
+  static HandleRecord* get_free_handle() {
+    assert(_free_list != 0, "should check before calling");
+    HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
+    _free_list = (ptr_mask & (intptr_t) (handle->value()));
+    assert(_free_list != ptr_tag, "should be null");
+    handle->set_value(NULL);
+    return handle;
+  }
+
+  static HandleRecord* get_handle() {
+    assert(_last != NULL, "sanity");
+    // Try last block
+    if (_last->_top < block_size_in_handles) {
+      return &(_last->_handles)[_last->_top++];
+    } else if (_free_list != 0) {
+      // Try free list
+      return get_free_handle();
+    }
+    return NULL;
+  }
+
+  void rebuild_free_list();
+
+  jmetadata allocate_metadata_handle(Metadata* metadata);
+
+ public:
+  jmetadata allocate_handle(const methodHandle& handle)       { return allocate_metadata_handle(handle()); }
+  jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
+
+  static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); }
+
+  // Adds `handle` to the free list in this block
+  static void chain_free_list(HandleRecord* handle) {
+    handle->set_value((Metadata*) (ptr_tag | _free_list));
+#ifdef METADATA_TRACK_NAMES
+    handle->set_name(NULL);
+#endif
+    _free_list = (intptr_t) handle;
+  }
+
+  void metadata_do(void f(Metadata*));
+
+  void do_unloading();
+};
+
+#endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
--- a/src/hotspot/share/jvmci/systemDictionary_jvmci.hpp	Wed May 01 12:41:26 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.
- */
-
-#ifndef SHARE_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
-#define SHARE_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
-
-#if !INCLUDE_JVMCI
-#define JVMCI_WK_KLASSES_DO(do_klass)
-#else
-#define JVMCI_WK_KLASSES_DO(do_klass)                                                                      \
-  /* JVMCI classes. These are loaded on-demand. */                                                         \
-  do_klass(JVMCI_klass,                                  jdk_vm_ci_runtime_JVMCI                          ) \
-  do_klass(HotSpotCompiledCode_klass,                    jdk_vm_ci_hotspot_HotSpotCompiledCode            ) \
-  do_klass(HotSpotCompiledCode_Comment_klass,            jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment    ) \
-  do_klass(HotSpotCompiledNmethod_klass,                 jdk_vm_ci_hotspot_HotSpotCompiledNmethod         ) \
-  do_klass(HotSpotForeignCallTarget_klass,               jdk_vm_ci_hotspot_HotSpotForeignCallTarget       ) \
-  do_klass(HotSpotReferenceMap_klass,                    jdk_vm_ci_hotspot_HotSpotReferenceMap            ) \
-  do_klass(HotSpotInstalledCode_klass,                   jdk_vm_ci_hotspot_HotSpotInstalledCode           ) \
-  do_klass(HotSpotNmethod_klass,                         jdk_vm_ci_hotspot_HotSpotNmethod                 ) \
-  do_klass(HotSpotResolvedJavaMethodImpl_klass,          jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl  ) \
-  do_klass(HotSpotResolvedObjectTypeImpl_klass,          jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl  ) \
-  do_klass(HotSpotCompressedNullConstant_klass,          jdk_vm_ci_hotspot_HotSpotCompressedNullConstant  ) \
-  do_klass(HotSpotObjectConstantImpl_klass,              jdk_vm_ci_hotspot_HotSpotObjectConstantImpl      ) \
-  do_klass(HotSpotMetaspaceConstantImpl_klass,           jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl   ) \
-  do_klass(HotSpotSentinelConstant_klass,                jdk_vm_ci_hotspot_HotSpotSentinelConstant        ) \
-  do_klass(HotSpotStackFrameReference_klass,             jdk_vm_ci_hotspot_HotSpotStackFrameReference     ) \
-  do_klass(HotSpotMetaData_klass,                        jdk_vm_ci_hotspot_HotSpotMetaData                ) \
-  do_klass(HotSpotConstantPool_klass,                    jdk_vm_ci_hotspot_HotSpotConstantPool            ) \
-  do_klass(HotSpotJVMCIMetaAccessContext_klass,          jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext  ) \
-  do_klass(HotSpotJVMCIRuntime_klass,                    jdk_vm_ci_hotspot_HotSpotJVMCIRuntime            ) \
-  do_klass(HotSpotSpeculationLog_klass,                  jdk_vm_ci_hotspot_HotSpotSpeculationLog          ) \
-  do_klass(HotSpotCompilationRequestResult_klass,        jdk_vm_ci_hotspot_HotSpotCompilationRequestResult) \
-  do_klass(VMField_klass,                                jdk_vm_ci_hotspot_VMField                        ) \
-  do_klass(VMFlag_klass,                                 jdk_vm_ci_hotspot_VMFlag                         ) \
-  do_klass(VMIntrinsicMethod_klass,                      jdk_vm_ci_hotspot_VMIntrinsicMethod              ) \
-  do_klass(Assumptions_ConcreteMethod_klass,             jdk_vm_ci_meta_Assumptions_ConcreteMethod        ) \
-  do_klass(Assumptions_NoFinalizableSubclass_klass,      jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass ) \
-  do_klass(Assumptions_ConcreteSubtype_klass,            jdk_vm_ci_meta_Assumptions_ConcreteSubtype       ) \
-  do_klass(Assumptions_LeafType_klass,                   jdk_vm_ci_meta_Assumptions_LeafType              ) \
-  do_klass(Assumptions_CallSiteTargetValue_klass,        jdk_vm_ci_meta_Assumptions_CallSiteTargetValue   ) \
-  do_klass(Architecture_klass,                           jdk_vm_ci_code_Architecture                      ) \
-  do_klass(TargetDescription_klass,                      jdk_vm_ci_code_TargetDescription                 ) \
-  do_klass(BytecodePosition_klass,                       jdk_vm_ci_code_BytecodePosition                  ) \
-  do_klass(DebugInfo_klass,                              jdk_vm_ci_code_DebugInfo                         ) \
-  do_klass(RegisterSaveLayout_klass,                     jdk_vm_ci_code_RegisterSaveLayout                ) \
-  do_klass(BytecodeFrame_klass,                          jdk_vm_ci_code_BytecodeFrame                     ) \
-  do_klass(InstalledCode_klass,                          jdk_vm_ci_code_InstalledCode                     ) \
-  do_klass(code_Location_klass,                          jdk_vm_ci_code_Location                          ) \
-  do_klass(code_Register_klass,                          jdk_vm_ci_code_Register                          ) \
-  do_klass(RegisterValue_klass,                          jdk_vm_ci_code_RegisterValue                     ) \
-  do_klass(StackSlot_klass,                              jdk_vm_ci_code_StackSlot                         ) \
-  do_klass(StackLockValue_klass,                         jdk_vm_ci_code_StackLockValue                    ) \
-  do_klass(VirtualObject_klass,                          jdk_vm_ci_code_VirtualObject                     ) \
-  do_klass(site_Call_klass,                              jdk_vm_ci_code_site_Call                         ) \
-  do_klass(site_ConstantReference_klass,                 jdk_vm_ci_code_site_ConstantReference            ) \
-  do_klass(site_DataPatch_klass,                         jdk_vm_ci_code_site_DataPatch                    ) \
-  do_klass(site_DataSectionReference_klass,              jdk_vm_ci_code_site_DataSectionReference         ) \
-  do_klass(site_ExceptionHandler_klass,                  jdk_vm_ci_code_site_ExceptionHandler             ) \
-  do_klass(site_Mark_klass,                              jdk_vm_ci_code_site_Mark                         ) \
-  do_klass(site_Infopoint_klass,                         jdk_vm_ci_code_site_Infopoint                    ) \
-  do_klass(site_Site_klass,                              jdk_vm_ci_code_site_Site                         ) \
-  do_klass(site_InfopointReason_klass,                   jdk_vm_ci_code_site_InfopointReason              ) \
-  do_klass(InspectedFrameVisitor_klass,                  jdk_vm_ci_code_stack_InspectedFrameVisitor       ) \
-  do_klass(JavaConstant_klass,                           jdk_vm_ci_meta_JavaConstant                      ) \
-  do_klass(PrimitiveConstant_klass,                      jdk_vm_ci_meta_PrimitiveConstant                 ) \
-  do_klass(RawConstant_klass,                            jdk_vm_ci_meta_RawConstant                       ) \
-  do_klass(NullConstant_klass,                           jdk_vm_ci_meta_NullConstant                      ) \
-  do_klass(ExceptionHandler_klass,                       jdk_vm_ci_meta_ExceptionHandler                  ) \
-  do_klass(JavaKind_klass,                               jdk_vm_ci_meta_JavaKind                          ) \
-  do_klass(ValueKind_klass,                              jdk_vm_ci_meta_ValueKind                         ) \
-  do_klass(Value_klass,                                  jdk_vm_ci_meta_Value                             )
-#endif
-
-#endif // SHARE_JVMCI_SYSTEMDICTIONARY_JVMCI_HPP
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Wed May 01 12:31:29 2019 -0700
@@ -23,27 +23,16 @@
  */
 
 #include "precompiled.hpp"
-#include "code/codeBlob.hpp"
-#include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
-#include "gc/shared/cardTable.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "jvmci/jvmciCodeInstaller.hpp"
 #include "jvmci/jvmciCompilerToVM.hpp"
-#include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
 #include "jvmci/vmStructs_compiler_runtime.hpp"
 #include "jvmci/vmStructs_jvmci.hpp"
-#include "oops/oop.hpp"
-#include "oops/oopHandle.hpp"
 #include "oops/objArrayKlass.hpp"
-#include "runtime/flags/jvmFlag.hpp"
-#include "runtime/globals.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "runtime/thread.hpp"
-#include "runtime/vm_version.hpp"
 #if INCLUDE_G1GC
-#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/g1/g1ThreadLocalData.hpp"
@@ -180,7 +169,7 @@
   volatile_nonstatic_field(JavaThread,         _is_method_handle_return,                      int)                                   \
   nonstatic_field(JavaThread,                  _osthread,                                     OSThread*)                             \
   nonstatic_field(JavaThread,                  _pending_deoptimization,                       int)                                   \
-  nonstatic_field(JavaThread,                  _pending_failed_speculation,                   long)                                  \
+  nonstatic_field(JavaThread,                  _pending_failed_speculation,                   jlong)                                 \
   nonstatic_field(JavaThread,                  _pending_transfer_to_interpreter,              bool)                                  \
   nonstatic_field(JavaThread,                  _jvmci_counters,                               jlong*)                                \
   nonstatic_field(JavaThread,                  _should_post_on_exceptions_flag,               int)                                   \
@@ -189,12 +178,6 @@
   static_field(java_lang_Class,                _klass_offset,                                 int)                                   \
   static_field(java_lang_Class,                _array_klass_offset,                           int)                                   \
                                                                                                                                      \
-  nonstatic_field(JVMCIEnv,                    _task,                                         CompileTask*)                          \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_hotswap_or_post_breakpoint,         jbyte)                                 \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_access_local_variables,             jbyte)                                 \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_post_on_exceptions,                 jbyte)                                 \
-  nonstatic_field(JVMCIEnv,                    _jvmti_can_pop_frame,                          jbyte)                                 \
-                                                                                                                                     \
   nonstatic_field(InvocationCounter,           _counter,                                      unsigned int)                          \
                                                                                                                                      \
   nonstatic_field(Klass,                       _secondary_super_cache,                        Klass*)                                \
@@ -209,6 +192,7 @@
   nonstatic_field(Klass,                       _java_mirror,                                  OopHandle)                             \
   nonstatic_field(Klass,                       _modifier_flags,                               jint)                                  \
   nonstatic_field(Klass,                       _access_flags,                                 AccessFlags)                           \
+  nonstatic_field(Klass,                       _class_loader_data,                            ClassLoaderData*)                      \
                                                                                                                                      \
   nonstatic_field(LocalVariableTableElement,   start_bci,                                     u2)                                    \
   nonstatic_field(LocalVariableTableElement,   length,                                        u2)                                    \
@@ -359,6 +343,7 @@
   declare_toplevel_type(JVMFlag)                                          \
   declare_toplevel_type(JVMFlag*)                                         \
   declare_toplevel_type(InvocationCounter)                                \
+  declare_toplevel_type(JVMCICompileState)                                \
   declare_toplevel_type(JVMCIEnv)                                         \
   declare_toplevel_type(LocalVariableTableElement)                        \
   declare_toplevel_type(narrowKlass)                                      \
@@ -401,6 +386,7 @@
   declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \
   declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM)             \
   declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC)   \
+  declare_preprocessor_constant("JVM_ACC_INTERFACE", JVM_ACC_INTERFACE)   \
                                                                           \
   declare_constant(JVM_CONSTANT_Utf8)                                     \
   declare_constant(JVM_CONSTANT_Unicode)                                  \
@@ -544,11 +530,11 @@
   declare_constant(JumpData::taken_off_set)                               \
   declare_constant(JumpData::displacement_off_set)                        \
                                                                           \
-  declare_constant(JVMCIEnv::ok)                                          \
-  declare_constant(JVMCIEnv::dependencies_failed)                         \
-  declare_constant(JVMCIEnv::dependencies_invalid)                        \
-  declare_constant(JVMCIEnv::cache_full)                                  \
-  declare_constant(JVMCIEnv::code_too_large)                              \
+  declare_preprocessor_constant("JVMCIEnv::ok",                   JVMCI::ok)                      \
+  declare_preprocessor_constant("JVMCIEnv::dependencies_failed",  JVMCI::dependencies_failed)     \
+  declare_preprocessor_constant("JVMCIEnv::dependencies_invalid", JVMCI::dependencies_invalid)    \
+  declare_preprocessor_constant("JVMCIEnv::cache_full",           JVMCI::cache_full)              \
+  declare_preprocessor_constant("JVMCIEnv::code_too_large",       JVMCI::code_too_large)          \
   declare_constant(JVMCIRuntime::none)                                    \
   declare_constant(JVMCIRuntime::by_holder)                               \
   declare_constant(JVMCIRuntime::by_full_signature)                       \
--- a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp	Wed May 01 12:31:29 2019 -0700
@@ -28,78 +28,110 @@
 #if !INCLUDE_JVMCI
 #define JVMCI_VM_SYMBOLS_DO(template, do_alias)
 #else
-#define JVMCI_VM_SYMBOLS_DO(template, do_alias)                                                                            \
-  template(jdk_vm_ci_runtime_JVMCI,                               "jdk/vm/ci/runtime/JVMCI")                               \
-  template(jdk_vm_ci_hotspot_HotSpotCompiledCode,                 "jdk/vm/ci/hotspot/HotSpotCompiledCode")                 \
-  template(jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment,         "jdk/vm/ci/hotspot/HotSpotCompiledCode$Comment")         \
-  template(jdk_vm_ci_hotspot_HotSpotCompiledNmethod,              "jdk/vm/ci/hotspot/HotSpotCompiledNmethod")              \
-  template(jdk_vm_ci_hotspot_HotSpotForeignCallTarget,            "jdk/vm/ci/hotspot/HotSpotForeignCallTarget")            \
-  template(jdk_vm_ci_hotspot_HotSpotReferenceMap,                 "jdk/vm/ci/hotspot/HotSpotReferenceMap")                 \
-  template(jdk_vm_ci_hotspot_CompilerToVM,                        "jdk/vm/ci/hotspot/CompilerToVM")                        \
-  template(jdk_vm_ci_hotspot_HotSpotInstalledCode,                "jdk/vm/ci/hotspot/HotSpotInstalledCode")                \
-  template(jdk_vm_ci_hotspot_HotSpotNmethod,                      "jdk/vm/ci/hotspot/HotSpotNmethod")                      \
-  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl")       \
-  template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl")       \
-  template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant,       "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant")       \
-  template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl,           "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl")           \
-  template(jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl,        "jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl")        \
-  template(jdk_vm_ci_hotspot_HotSpotSentinelConstant,             "jdk/vm/ci/hotspot/HotSpotSentinelConstant")             \
-  template(jdk_vm_ci_hotspot_HotSpotStackFrameReference,          "jdk/vm/ci/hotspot/HotSpotStackFrameReference")          \
-  template(jdk_vm_ci_hotspot_HotSpotMetaData,                     "jdk/vm/ci/hotspot/HotSpotMetaData")                     \
-  template(jdk_vm_ci_hotspot_HotSpotConstantPool,                 "jdk/vm/ci/hotspot/HotSpotConstantPool")                 \
-  template(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext,       "jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext")       \
-  template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime")                 \
-  template(jdk_vm_ci_hotspot_HotSpotSpeculationLog,               "jdk/vm/ci/hotspot/HotSpotSpeculationLog")               \
-  template(jdk_vm_ci_hotspot_HotSpotCompilationRequestResult,     "jdk/vm/ci/hotspot/HotSpotCompilationRequestResult")     \
-  template(jdk_vm_ci_hotspot_VMField,                             "jdk/vm/ci/hotspot/VMField")                             \
-  template(jdk_vm_ci_hotspot_VMFlag,                              "jdk/vm/ci/hotspot/VMFlag")                              \
-  template(jdk_vm_ci_hotspot_VMIntrinsicMethod,                   "jdk/vm/ci/hotspot/VMIntrinsicMethod")                   \
-  template(jdk_vm_ci_meta_JavaConstant,                           "jdk/vm/ci/meta/JavaConstant")                           \
-  template(jdk_vm_ci_meta_PrimitiveConstant,                      "jdk/vm/ci/meta/PrimitiveConstant")                      \
-  template(jdk_vm_ci_meta_RawConstant,                            "jdk/vm/ci/meta/RawConstant")                            \
-  template(jdk_vm_ci_meta_NullConstant,                           "jdk/vm/ci/meta/NullConstant")                           \
-  template(jdk_vm_ci_meta_ExceptionHandler,                       "jdk/vm/ci/meta/ExceptionHandler")                       \
-  template(jdk_vm_ci_meta_JavaKind,                               "jdk/vm/ci/meta/JavaKind")                               \
-  template(jdk_vm_ci_meta_ValueKind,                              "jdk/vm/ci/meta/ValueKind")                              \
-  template(jdk_vm_ci_meta_Value,                                  "jdk/vm/ci/meta/Value")                                  \
-  template(jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            "jdk/vm/ci/meta/Assumptions$ConcreteSubtype")            \
-  template(jdk_vm_ci_meta_Assumptions_LeafType,                   "jdk/vm/ci/meta/Assumptions$LeafType")                   \
-  template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass")      \
-  template(jdk_vm_ci_meta_Assumptions_ConcreteMethod,             "jdk/vm/ci/meta/Assumptions$ConcreteMethod")             \
-  template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue")        \
-  template(jdk_vm_ci_code_Architecture,                           "jdk/vm/ci/code/Architecture")                           \
-  template(jdk_vm_ci_code_BytecodeFrame,                          "jdk/vm/ci/code/BytecodeFrame")                          \
-  template(jdk_vm_ci_code_BytecodePosition,                       "jdk/vm/ci/code/BytecodePosition")                       \
-  template(jdk_vm_ci_code_DebugInfo,                              "jdk/vm/ci/code/DebugInfo")                              \
-  template(jdk_vm_ci_code_InstalledCode,                          "jdk/vm/ci/code/InstalledCode")                          \
-  template(jdk_vm_ci_code_Location,                               "jdk/vm/ci/code/Location")                               \
-  template(jdk_vm_ci_code_Register,                               "jdk/vm/ci/code/Register")                               \
-  template(jdk_vm_ci_code_RegisterValue,                          "jdk/vm/ci/code/RegisterValue")                          \
-  template(jdk_vm_ci_code_StackSlot,                              "jdk/vm/ci/code/StackSlot")                              \
-  template(jdk_vm_ci_code_StackLockValue,                         "jdk/vm/ci/code/StackLockValue")                         \
-  template(jdk_vm_ci_code_TargetDescription,                      "jdk/vm/ci/code/TargetDescription")                      \
-  template(jdk_vm_ci_code_VirtualObject,                          "jdk/vm/ci/code/VirtualObject")                          \
-  template(jdk_vm_ci_code_RegisterSaveLayout,                     "jdk/vm/ci/code/RegisterSaveLayout")                     \
-  template(jdk_vm_ci_code_InvalidInstalledCodeException,          "jdk/vm/ci/code/InvalidInstalledCodeException")          \
-  template(jdk_vm_ci_code_site_Call,                              "jdk/vm/ci/code/site/Call")                              \
-  template(jdk_vm_ci_code_site_ConstantReference,                 "jdk/vm/ci/code/site/ConstantReference")                 \
-  template(jdk_vm_ci_code_site_DataPatch,                         "jdk/vm/ci/code/site/DataPatch")                         \
-  template(jdk_vm_ci_code_site_DataSectionReference,              "jdk/vm/ci/code/site/DataSectionReference")              \
-  template(jdk_vm_ci_code_site_ExceptionHandler,                  "jdk/vm/ci/code/site/ExceptionHandler")                  \
-  template(jdk_vm_ci_code_site_Mark,                              "jdk/vm/ci/code/site/Mark")                              \
-  template(jdk_vm_ci_code_site_Infopoint,                         "jdk/vm/ci/code/site/Infopoint")                         \
-  template(jdk_vm_ci_code_stack_InspectedFrameVisitor,            "jdk/vm/ci/code/stack/InspectedFrameVisitor")            \
-  template(jdk_vm_ci_code_site_Site,                              "jdk/vm/ci/code/site/Site")                              \
-  template(jdk_vm_ci_code_site_InfopointReason,                   "jdk/vm/ci/code/site/InfopointReason")                   \
-  template(jdk_vm_ci_common_JVMCIError,                           "jdk/vm/ci/common/JVMCIError")                           \
-  template(visitFrame_name,                                       "visitFrame")                                            \
-  template(visitFrame_signature,                                  "(Ljdk/vm/ci/code/stack/InspectedFrame;)Ljava/lang/Object;") \
-  template(compileMethod_name,                                    "compileMethod")                                         \
+#define JVMCI_VM_SYMBOLS_DO(template, do_alias)                                                                                           \
+  template(jdk_vm_ci_services_Services,                           "jdk/vm/ci/services/Services")                                          \
+  template(jdk_vm_ci_runtime_JVMCI,                               "jdk/vm/ci/runtime/JVMCI")                                              \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledCode,                 "jdk/vm/ci/hotspot/HotSpotCompiledCode")                                \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledCode_Comment,         "jdk/vm/ci/hotspot/HotSpotCompiledCode$Comment")                        \
+  template(jdk_vm_ci_hotspot_HotSpotCompiledNmethod,              "jdk/vm/ci/hotspot/HotSpotCompiledNmethod")                             \
+  template(jdk_vm_ci_hotspot_HotSpotForeignCallTarget,            "jdk/vm/ci/hotspot/HotSpotForeignCallTarget")                           \
+  template(jdk_vm_ci_hotspot_HotSpotReferenceMap,                 "jdk/vm/ci/hotspot/HotSpotReferenceMap")                                \
+  template(jdk_vm_ci_hotspot_CompilerToVM,                        "jdk/vm/ci/hotspot/CompilerToVM")                                       \
+  template(jdk_vm_ci_hotspot_HotSpotInstalledCode,                "jdk/vm/ci/hotspot/HotSpotInstalledCode")                               \
+  template(jdk_vm_ci_hotspot_HotSpotNmethod,                      "jdk/vm/ci/hotspot/HotSpotNmethod")                                     \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl")                      \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl,       "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl")                      \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType,        "jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType")                       \
+  template(jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl,        "jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl")                       \
+  template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant,       "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant")                      \
+  template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl,           "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl")                          \
+  template(jdk_vm_ci_hotspot_DirectHotSpotObjectConstantImpl,     "jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl")                    \
+  template(jdk_vm_ci_hotspot_IndirectHotSpotObjectConstantImpl,   "jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl")                  \
+  template(jdk_vm_ci_hotspot_HotSpotMetaspaceConstantImpl,        "jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl")                       \
+  template(jdk_vm_ci_hotspot_HotSpotSentinelConstant,             "jdk/vm/ci/hotspot/HotSpotSentinelConstant")                            \
+  template(jdk_vm_ci_hotspot_HotSpotStackFrameReference,          "jdk/vm/ci/hotspot/HotSpotStackFrameReference")                         \
+  template(jdk_vm_ci_hotspot_HotSpotMetaData,                     "jdk/vm/ci/hotspot/HotSpotMetaData")                                    \
+  template(jdk_vm_ci_hotspot_HotSpotConstantPool,                 "jdk/vm/ci/hotspot/HotSpotConstantPool")                                \
+  template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime")                                \
+  template(jdk_vm_ci_hotspot_HotSpotSpeculationLog,               "jdk/vm/ci/hotspot/HotSpotSpeculationLog")                              \
+  template(jdk_vm_ci_hotspot_HotSpotCompilationRequestResult,     "jdk/vm/ci/hotspot/HotSpotCompilationRequestResult")                    \
+  template(jdk_vm_ci_hotspot_VMField,                             "jdk/vm/ci/hotspot/VMField")                                            \
+  template(jdk_vm_ci_hotspot_VMFlag,                              "jdk/vm/ci/hotspot/VMFlag")                                             \
+  template(jdk_vm_ci_hotspot_VMIntrinsicMethod,                   "jdk/vm/ci/hotspot/VMIntrinsicMethod")                                  \
+  template(jdk_vm_ci_meta_ResolvedJavaMethod,                     "jdk/vm/ci/meta/ResolvedJavaMethod")                                    \
+  template(jdk_vm_ci_meta_JavaConstant,                           "jdk/vm/ci/meta/JavaConstant")                                          \
+  template(jdk_vm_ci_meta_PrimitiveConstant,                      "jdk/vm/ci/meta/PrimitiveConstant")                                     \
+  template(jdk_vm_ci_meta_RawConstant,                            "jdk/vm/ci/meta/RawConstant")                                           \
+  template(jdk_vm_ci_meta_NullConstant,                           "jdk/vm/ci/meta/NullConstant")                                          \
+  template(jdk_vm_ci_meta_ExceptionHandler,                       "jdk/vm/ci/meta/ExceptionHandler")                                      \
+  template(jdk_vm_ci_meta_JavaKind,                               "jdk/vm/ci/meta/JavaKind")                                              \
+  template(jdk_vm_ci_meta_ValueKind,                              "jdk/vm/ci/meta/ValueKind")                                             \
+  template(jdk_vm_ci_meta_Value,                                  "jdk/vm/ci/meta/Value")                                                 \
+  template(jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            "jdk/vm/ci/meta/Assumptions$ConcreteSubtype")                           \
+  template(jdk_vm_ci_meta_Assumptions_LeafType,                   "jdk/vm/ci/meta/Assumptions$LeafType")                                  \
+  template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass")                     \
+  template(jdk_vm_ci_meta_Assumptions_ConcreteMethod,             "jdk/vm/ci/meta/Assumptions$ConcreteMethod")                            \
+  template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue")                       \
+  template(jdk_vm_ci_code_Architecture,                           "jdk/vm/ci/code/Architecture")                                          \
+  template(jdk_vm_ci_code_BytecodeFrame,                          "jdk/vm/ci/code/BytecodeFrame")                                         \
+  template(jdk_vm_ci_code_BytecodePosition,                       "jdk/vm/ci/code/BytecodePosition")                                      \
+  template(jdk_vm_ci_code_DebugInfo,                              "jdk/vm/ci/code/DebugInfo")                                             \
+  template(jdk_vm_ci_code_InstalledCode,                          "jdk/vm/ci/code/InstalledCode")                                         \
+  template(jdk_vm_ci_code_Location,                               "jdk/vm/ci/code/Location")                                              \
+  template(jdk_vm_ci_code_Register,                               "jdk/vm/ci/code/Register")                                              \
+  template(jdk_vm_ci_code_RegisterValue,                          "jdk/vm/ci/code/RegisterValue")                                         \
+  template(jdk_vm_ci_code_StackSlot,                              "jdk/vm/ci/code/StackSlot")                                             \
+  template(jdk_vm_ci_code_StackLockValue,                         "jdk/vm/ci/code/StackLockValue")                                        \
+  template(jdk_vm_ci_code_TargetDescription,                      "jdk/vm/ci/code/TargetDescription")                                     \
+  template(jdk_vm_ci_code_VirtualObject,                          "jdk/vm/ci/code/VirtualObject")                                         \
+  template(jdk_vm_ci_code_RegisterSaveLayout,                     "jdk/vm/ci/code/RegisterSaveLayout")                                    \
+  template(jdk_vm_ci_code_InvalidInstalledCodeException,          "jdk/vm/ci/code/InvalidInstalledCodeException")                         \
+  template(jdk_vm_ci_code_site_Call,                              "jdk/vm/ci/code/site/Call")                                             \
+  template(jdk_vm_ci_code_site_ConstantReference,                 "jdk/vm/ci/code/site/ConstantReference")                                \
+  template(jdk_vm_ci_code_site_DataPatch,                         "jdk/vm/ci/code/site/DataPatch")                                        \
+  template(jdk_vm_ci_code_site_DataSectionReference,              "jdk/vm/ci/code/site/DataSectionReference")                             \
+  template(jdk_vm_ci_code_site_ExceptionHandler,                  "jdk/vm/ci/code/site/ExceptionHandler")                                 \
+  template(jdk_vm_ci_code_site_Mark,                              "jdk/vm/ci/code/site/Mark")                                             \
+  template(jdk_vm_ci_code_site_Infopoint,                         "jdk/vm/ci/code/site/Infopoint")                                        \
+  template(jdk_vm_ci_code_stack_InspectedFrameVisitor,            "jdk/vm/ci/code/stack/InspectedFrameVisitor")                           \
+  template(jdk_vm_ci_code_site_Site,                              "jdk/vm/ci/code/site/Site")                                             \
+  template(jdk_vm_ci_code_site_InfopointReason,                   "jdk/vm/ci/code/site/InfopointReason")                                  \
+  template(jdk_vm_ci_common_JVMCIError,                           "jdk/vm/ci/common/JVMCIError")                                          \
+                                                                                                                                          \
+  template(visitFrame_name,                                       "visitFrame")                                                           \
+  template(visitFrame_signature,                                  "(Ljdk/vm/ci/code/stack/InspectedFrame;)Ljava/lang/Object;")            \
+  template(compileMethod_name,                                    "compileMethod")                                                        \
   template(compileMethod_signature,                               "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \
-  template(fromMetaspace_name,                                    "fromMetaspace")                                         \
-  template(method_fromMetaspace_signature,                        "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")      \
-  template(constantPool_fromMetaspace_signature,                  "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;")            \
-  template(klass_fromMetaspace_signature,                         "(Ljava/lang/Class;)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;")
+  template(encodeThrowable_name,                                  "encodeThrowable")                                                      \
+  template(encodeThrowable_signature,                             "(Ljava/lang/Throwable;)Ljava/lang/String;")                            \
+  template(decodeThrowable_name,                                  "decodeThrowable")                                                      \
+  template(decodeThrowable_signature,                             "(Ljava/lang/String;)Ljava/lang/Throwable;")                            \
+  template(fromMetaspace_name,                                    "fromMetaspace")                                                        \
+  template(method_fromMetaspace_signature,                        "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;")                     \
+  template(constantPool_fromMetaspace_signature,                  "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;")                           \
+  template(klass_fromMetaspace_signature,                         "(JLjava/lang/String;)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
+  template(primitive_fromMetaspace_signature,                     "(Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;C)Ljdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType;") \
+  template(getRuntime_name,                                       "getRuntime")                                                           \
+  template(getRuntime_signature,                                  "()Ljdk/vm/ci/runtime/JVMCIRuntime;")                                   \
+  template(initializeRuntime_name,                                "initializeRuntime")                                                    \
+  do_alias(initializeRuntime_signature, getRuntime_signature)                                                                             \
+  template(runtime_name,                                          "runtime")                                                              \
+  template(runtime_signature,                                     "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;")                            \
+  template(getCompiler_name,                                      "getCompiler")                                                          \
+  template(getCompiler_signature,                                 "()Ljdk/vm/ci/runtime/JVMCICompiler;")                                  \
+  template(callToString_name,                                     "callToString")                                                         \
+  template(callToString_signature,                                "(Ljava/lang/Object;)Ljava/lang/String;")                               \
+  template(getName_name,                                          "getName")                                                              \
+  template(bootstrapFinished_name,                                "bootstrapFinished")                                                    \
+  template(forTypeChar_name,                                      "forTypeChar")                                                          \
+  template(forTypeChar_signature,                                 "(CJ)Ljdk/vm/ci/meta/PrimitiveConstant;")                               \
+  template(forFloat_name,                                         "forFloat")                                                             \
+  template(forFloat_signature,                                    "(F)Ljdk/vm/ci/meta/PrimitiveConstant;")                                \
+  template(forDouble_name,                                        "forDouble")                                                            \
+  template(forDouble_signature,                                   "(D)Ljdk/vm/ci/meta/PrimitiveConstant;")                                \
+  template(method_string_bool_long_signature,                     "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
+  template(initializeSavedProperties_name,                        "initializeSavedProperties")                                            \
+
 #endif
 
 #endif // SHARE_JVMCI_VMSYMBOLS_JVMCI_HPP
--- a/src/hotspot/share/memory/allocation.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/memory/allocation.hpp	Wed May 01 12:31:29 2019 -0700
@@ -118,6 +118,7 @@
   f(mtCode,          "Code")        /* generated code                            */ \
   f(mtGC,            "GC")                                                          \
   f(mtCompiler,      "Compiler")                                                    \
+  f(mtJVMCI,         "JVMCI")                                                       \
   f(mtInternal,      "Internal")    /* memory used by VM, but does not belong to */ \
                                     /* any of above categories, and not used by  */ \
                                     /* NMT                                       */ \
--- a/src/hotspot/share/oops/method.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/oops/method.cpp	Wed May 01 12:31:29 2019 -0700
@@ -116,6 +116,11 @@
 void Method::deallocate_contents(ClassLoaderData* loader_data) {
   MetadataFactory::free_metadata(loader_data, constMethod());
   set_constMethod(NULL);
+#if INCLUDE_JVMCI
+  if (method_data()) {
+    FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address());
+  }
+#endif
   MetadataFactory::free_metadata(loader_data, method_data());
   set_method_data(NULL);
   MetadataFactory::free_metadata(loader_data, method_counters());
--- a/src/hotspot/share/oops/methodData.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/oops/methodData.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -846,6 +846,86 @@
   return false;
 }
 
+#if INCLUDE_JVMCI
+
+void* FailedSpeculation::operator new(size_t size, size_t fs_size) throw() {
+  return CHeapObj<mtCompiler>::operator new(fs_size, std::nothrow);
+}
+
+FailedSpeculation::FailedSpeculation(address speculation, int speculation_len) : _data_len(speculation_len), _next(NULL) {
+  memcpy(data(), speculation, speculation_len);
+}
+
+// A heuristic check to detect nmethods that outlive a failed speculations list.
+static void guarantee_failed_speculations_alive(nmethod* nm, FailedSpeculation** failed_speculations_address) {
+  jlong head = (jlong)(address) *failed_speculations_address;
+  if ((head & 0x1) == 0x1) {
+    stringStream st;
+    if (nm != NULL) {
+      st.print("%d", nm->compile_id());
+      Method* method = nm->method();
+      st.print_raw("{");
+      if (method != NULL) {
+        method->print_name(&st);
+      } else {
+        const char* jvmci_name = nm->jvmci_name();
+        if (jvmci_name != NULL) {
+          st.print_raw(jvmci_name);
+        }
+      }
+      st.print_raw("}");
+    } else {
+      st.print("<unknown>");
+    }
+    fatal("Adding to failed speculations list that appears to have been freed. Source: %s", st.as_string());
+  }
+}
+
+bool FailedSpeculation::add_failed_speculation(nmethod* nm, FailedSpeculation** failed_speculations_address, address speculation, int speculation_len) {
+  assert(failed_speculations_address != NULL, "must be");
+  size_t fs_size = sizeof(FailedSpeculation) + speculation_len;
+  FailedSpeculation* fs = new (fs_size) FailedSpeculation(speculation, speculation_len);
+  if (fs == NULL) {
+    // no memory -> ignore failed speculation
+    return false;
+  }
+
+  guarantee(is_aligned(fs, sizeof(FailedSpeculation*)), "FailedSpeculation objects must be pointer aligned");
+  guarantee_failed_speculations_alive(nm, failed_speculations_address);
+
+  FailedSpeculation** cursor = failed_speculations_address;
+  do {
+    if (*cursor == NULL) {
+      FailedSpeculation* old_fs = Atomic::cmpxchg(fs, cursor, (FailedSpeculation*) NULL);
+      if (old_fs == NULL) {
+        // Successfully appended fs to end of the list
+        return true;
+      }
+      cursor = old_fs->next_adr();
+    } else {
+      cursor = (*cursor)->next_adr();
+    }
+  } while (true);
+}
+
+void FailedSpeculation::free_failed_speculations(FailedSpeculation** failed_speculations_address) {
+  assert(failed_speculations_address != NULL, "must be");
+  FailedSpeculation* fs = *failed_speculations_address;
+  while (fs != NULL) {
+    FailedSpeculation* next = fs->next();
+    delete fs;
+    fs = next;
+  }
+
+  // Write an unaligned value to failed_speculations_address to denote
+  // that it is no longer a valid pointer. This is allows for the check
+  // in add_failed_speculation against adding to a freed failed
+  // speculations list.
+  long* head = (long*) failed_speculations_address;
+  (*head) = (*head) | 0x1;
+}
+#endif // INCLUDE_JVMCI
+
 int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) {
 #if INCLUDE_JVMCI
   if (ProfileTraps) {
@@ -1227,6 +1307,7 @@
 
 #if INCLUDE_JVMCI
   _jvmci_ir_size = 0;
+  _failed_speculations = NULL;
 #endif
 
 #if INCLUDE_RTM_OPT
--- a/src/hotspot/share/oops/methodData.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/oops/methodData.hpp	Wed May 01 12:31:29 2019 -0700
@@ -1949,6 +1949,42 @@
 };
 
 
+#if INCLUDE_JVMCI
+// Encapsulates an encoded speculation reason. These are linked together in
+// a list that is atomically appended to during deoptimization. Entries are
+// never removed from the list.
+// @see jdk.vm.ci.hotspot.HotSpotSpeculationLog.HotSpotSpeculationEncoding
+class FailedSpeculation: public CHeapObj<mtCompiler> {
+ private:
+  // The length of HotSpotSpeculationEncoding.toByteArray(). The data itself
+  // is an array embedded at the end of this object.
+  int   _data_len;
+
+  // Next entry in a linked list.
+  FailedSpeculation* _next;
+
+  FailedSpeculation(address data, int data_len);
+
+  FailedSpeculation** next_adr() { return &_next; }
+
+  // Placement new operator for inlining the speculation data into
+  // the FailedSpeculation object.
+  void* operator new(size_t size, size_t fs_size) throw();
+
+ public:
+  char* data()         { return (char*)(((address) this) + sizeof(FailedSpeculation)); }
+  int data_len() const { return _data_len; }
+  FailedSpeculation* next() const { return _next; }
+
+  // Atomically appends a speculation from nm to the list whose head is at (*failed_speculations_address).
+  // Returns false if the FailedSpeculation object could not be allocated.
+  static bool add_failed_speculation(nmethod* nm, FailedSpeculation** failed_speculations_address, address speculation, int speculation_len);
+
+  // Frees all entries in the linked list whose head is at (*failed_speculations_address).
+  static void free_failed_speculations(FailedSpeculation** failed_speculations_address);
+};
+#endif
+
 class MethodData : public Metadata {
   friend class VMStructs;
   friend class JVMCIVMStructs;
@@ -2030,7 +2066,8 @@
 
 #if INCLUDE_JVMCI
   // Support for HotSpotMethodData.setCompiledIRSize(int)
-  int               _jvmci_ir_size;
+  int                _jvmci_ir_size;
+  FailedSpeculation* _failed_speculations;
 #endif
 
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
@@ -2191,6 +2228,12 @@
   InvocationCounter* invocation_counter()     { return &_invocation_counter; }
   InvocationCounter* backedge_counter()       { return &_backedge_counter;   }
 
+#if INCLUDE_JVMCI
+  FailedSpeculation** get_failed_speculations_address() {
+    return &_failed_speculations;
+  }
+#endif
+
 #if INCLUDE_RTM_OPT
   int rtm_state() const {
     return _rtm_state;
--- a/src/hotspot/share/opto/chaitin.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/opto/chaitin.cpp	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -2084,9 +2084,7 @@
 // Dump a register name into a buffer.  Be intelligent if we get called
 // before allocation is complete.
 char *PhaseChaitin::dump_register( const Node *n, char *buf  ) const {
-  if( this == NULL ) {          // Not got anything?
-    sprintf(buf,"N%d",n->_idx); // Then use Node index
-  } else if( _node_regs ) {
+  if( _node_regs ) {
     // Post allocation, use direct mappings, no LRG info available
     print_reg( get_reg_first(n), this, buf );
   } else {
--- a/src/hotspot/share/prims/jni.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/prims/jni.cpp	Wed May 01 12:31:29 2019 -0700
@@ -88,10 +88,6 @@
 #include "utilities/histogram.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/vmError.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 
 static jint CurrentVersion = JNI_VERSION_10;
 
@@ -1318,14 +1314,15 @@
     THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
   }
 
+  Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
+
   // Throw a NoSuchMethodError exception if we have an instance of a
   // primitive java.lang.Class
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig));
   }
 
-  Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
-
   // Make sure class is linked and initialized before handing id's out to
   // Method*s.
   klass->initialize(CHECK_NULL);
@@ -1346,7 +1343,8 @@
     }
   }
   if (m == NULL || (m->is_static() != is_static)) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig));
   }
   return m->jmethod_id();
 }
@@ -2014,22 +2012,26 @@
   jfieldID ret = 0;
   DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret);
 
+  Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
+
   // The class should have been loaded (we have an instance of the class
   // passed in) so the field and signature should already be in the symbol
   // table.  If they're not there, the field doesn't exist.
   TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
   TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
   if (fieldname == NULL || signame == NULL) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
   }
-  Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
+
   // Make sure class is initialized before handing id's out to fields
   k->initialize(CHECK_NULL);
 
   fieldDescriptor fd;
   if (!k->is_instance_klass() ||
       !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
-    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
+    ResourceMark rm;
+    THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
   }
 
   // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Wed May 01 12:31:29 2019 -0700
@@ -62,6 +62,9 @@
 #if INCLUDE_ZGC
 #include "gc/z/zGlobals.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 
 // JvmtiTagHashmapEntry
 //
@@ -3034,6 +3037,17 @@
   // exceptions) will be visible.
   blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
   Universe::oops_do(&blk);
+  if (blk.stopped()) {
+    return false;
+  }
+
+#if INCLUDE_JVMCI
+  blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
+  JVMCI::oops_do(&blk);
+  if (blk.stopped()) {
+    return false;
+  }
+#endif
 
   return true;
 }
--- a/src/hotspot/share/prims/nativeLookup.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/prims/nativeLookup.hpp	Wed May 01 12:31:29 2019 -0700
@@ -33,11 +33,6 @@
 
 class NativeLookup : AllStatic {
  private:
-  // JNI name computation
-  static char* pure_jni_name(const methodHandle& method);
-  static char* long_jni_name(const methodHandle& method);
-  static char* critical_jni_name(const methodHandle& method);
-
   // Style specific lookup
   static address lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS);
   static address lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style);
@@ -45,6 +40,11 @@
   static address lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS);
   static address lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS);
  public:
+  // JNI name computation
+  static char* pure_jni_name(const methodHandle& method);
+  static char* long_jni_name(const methodHandle& method);
+  static char* critical_jni_name(const methodHandle& method);
+
   // Lookup native function. May throw UnsatisfiedLinkError.
   static address lookup(const methodHandle& method, bool& in_base_library, TRAPS);
   static address lookup_critical_entry(const methodHandle& method);
--- a/src/hotspot/share/runtime/arguments.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.cpp	Wed May 01 12:31:29 2019 -0700
@@ -57,9 +57,6 @@
 #include "utilities/defaultStream.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/stringUtils.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 #if INCLUDE_JFR
 #include "jfr/jfr.hpp"
 #endif
--- a/src/hotspot/share/runtime/deoptimization.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Wed May 01 12:31:29 2019 -0700
@@ -63,11 +63,6 @@
 #include "utilities/preserveException.hpp"
 #include "utilities/xmlstream.hpp"
 
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
-#include "jvmci/jvmciJavaClasses.hpp"
-#endif
-
 
 bool DeoptimizationMarker::_is_active = false;
 
@@ -1520,33 +1515,11 @@
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
 #if INCLUDE_JVMCI
-    long speculation = thread->pending_failed_speculation();
-    if (nm->is_compiled_by_jvmci()) {
-      if (speculation != 0) {
-        oop speculation_log = nm->as_nmethod()->speculation_log();
-        if (speculation_log != NULL) {
-          if (TraceDeoptimization || TraceUncollectedSpeculations) {
-            if (HotSpotSpeculationLog::lastFailed(speculation_log) != 0) {
-              tty->print_cr("A speculation that was not collected by the compiler is being overwritten");
-            }
-          }
-          if (TraceDeoptimization) {
-            tty->print_cr("Saving speculation to speculation log");
-          }
-          HotSpotSpeculationLog::set_lastFailed(speculation_log, speculation);
-        } else {
-          if (TraceDeoptimization) {
-            tty->print_cr("Speculation present but no speculation log");
-          }
-        }
-        thread->set_pending_failed_speculation(0);
-      } else {
-        if (TraceDeoptimization) {
-          tty->print_cr("No speculation");
-        }
-      }
+    jlong           speculation = thread->pending_failed_speculation();
+    if (nm->is_compiled_by_jvmci() && nm->is_nmethod()) { // Exclude AOTed methods
+      nm->as_nmethod()->update_speculation(thread);
     } else {
-      assert(speculation == 0, "There should not be a speculation for method compiled by non-JVMCI compilers");
+      assert(speculation == 0, "There should not be a speculation for methods compiled by non-JVMCI compilers");
     }
 
     if (trap_bci == SynchronizationEntryBCI) {
@@ -1595,6 +1568,11 @@
         xtty->begin_head("uncommon_trap thread='" UINTX_FORMAT "' %s",
                          os::current_thread_id(),
                          format_trap_request(buf, sizeof(buf), trap_request));
+#if INCLUDE_JVMCI
+        if (speculation != 0) {
+          xtty->print(" speculation='" JLONG_FORMAT "'", speculation);
+        }
+#endif
         nm->log_identity(xtty);
       }
       Symbol* class_name = NULL;
@@ -1640,7 +1618,7 @@
         tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id());
 #if INCLUDE_JVMCI
         if (nm->is_nmethod()) {
-          char* installed_code_name = nm->as_nmethod()->jvmci_installed_code_name(buf, sizeof(buf));
+          const char* installed_code_name = nm->as_nmethod()->jvmci_name();
           if (installed_code_name != NULL) {
             tty->print(" (JVMCI: installed code name=%s) ", installed_code_name);
           }
--- a/src/hotspot/share/runtime/frame.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/frame.cpp	Wed May 01 12:31:29 2019 -0700
@@ -629,7 +629,7 @@
 #if INCLUDE_JVMCI
         if (cm->is_nmethod()) {
           nmethod* nm = cm->as_nmethod();
-          char* jvmciName = nm->jvmci_installed_code_name(buf, buflen);
+          const char* jvmciName = nm->jvmci_name();
           if (jvmciName != NULL) {
             st->print(" (%s)", jvmciName);
           }
--- a/src/hotspot/share/runtime/init.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/init.cpp	Wed May 01 12:31:29 2019 -0700
@@ -27,6 +27,9 @@
 #include "classfile/symbolTable.hpp"
 #include "code/icBuffer.hpp"
 #include "gc/shared/collectedHeap.hpp"
+#if INCLUDE_JVMCI
+#include "jvmci/jvmci.hpp"
+#endif
 #include "interpreter/bytecodes.hpp"
 #include "logging/log.hpp"
 #include "logging/logTag.hpp"
@@ -140,6 +143,11 @@
   if (!compileBroker_init()) {
     return JNI_EINVAL;
   }
+#if INCLUDE_JVMCI
+  if (EnableJVMCI) {
+    JVMCI::initialize_globals();
+  }
+#endif
 
   if (!universe_post_init()) {
     return JNI_ERR;
--- a/src/hotspot/share/runtime/java.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/java.cpp	Wed May 01 12:31:29 2019 -0700
@@ -36,8 +36,7 @@
 #include "jfr/jfrEvents.hpp"
 #include "jfr/support/jfrThreadId.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmci.hpp"
 #endif
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
@@ -439,15 +438,7 @@
   }
 
 #if INCLUDE_JVMCI
-  // We are not using CATCH here because we want the exit to continue normally.
-  Thread* THREAD = thread;
-  JVMCIRuntime::shutdown(THREAD);
-  if (HAS_PENDING_EXCEPTION) {
-    HandleMark hm(THREAD);
-    Handle exception(THREAD, PENDING_EXCEPTION);
-    CLEAR_PENDING_EXCEPTION;
-    java_lang_Throwable::java_printStackTrace(exception, THREAD);
-  }
+  JVMCI::shutdown();
 #endif
 
   // Hang forever on exit if we're reporting an error.
--- a/src/hotspot/share/runtime/javaCalls.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/javaCalls.cpp	Wed May 01 12:31:29 2019 -0700
@@ -44,10 +44,6 @@
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
-#if INCLUDE_JVMCI
-#include "jvmci/jvmciJavaClasses.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#endif
 
 // -----------------------------------------------------
 // Implementation of JavaCallWrapper
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Wed May 01 12:31:29 2019 -0700
@@ -157,6 +157,13 @@
 Mutex*   CDSClassFileStream_lock      = NULL;
 #endif
 
+#if INCLUDE_JVMCI
+Monitor* JVMCI_lock                   = NULL;
+Mutex*   JVMCIGlobalAlloc_lock        = NULL;
+Mutex*   JVMCIGlobalActive_lock       = NULL;
+#endif
+
+
 #define MAX_NUM_MUTEX 128
 static Monitor * _mutex_array[MAX_NUM_MUTEX];
 static int _num_mutex;
@@ -348,6 +355,12 @@
 #if INCLUDE_CDS && INCLUDE_JVMTI
   def(CDSClassFileStream_lock      , PaddedMutex  , max_nonleaf, false, Monitor::_safepoint_check_always);
 #endif
+
+#if INCLUDE_JVMCI
+  def(JVMCI_lock                   , PaddedMonitor, nonleaf+2,   true,  Monitor::_safepoint_check_always);
+  def(JVMCIGlobalAlloc_lock        , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
+  def(JVMCIGlobalActive_lock       , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
+#endif
 }
 
 GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/src/hotspot/share/runtime/mutexLocker.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Wed May 01 12:31:29 2019 -0700
@@ -155,6 +155,12 @@
 extern Monitor* CodeHeapStateAnalytics_lock;     // lock print functions against concurrent analyze functions.
                                                  // Only used locally in PrintCodeCacheLayout processing.
 
+#if INCLUDE_JVMCI
+extern Monitor* JVMCI_lock;                      // Monitor to control initialization of JVMCI
+extern Mutex*   JVMCIGlobalAlloc_lock;           // JVMCI global storage allocate list lock
+extern Mutex*   JVMCIGlobalActive_lock;          // JVMCI global storage active list lock
+#endif
+
 // A MutexLocker provides mutual exclusion with respect to a given mutex
 // for the scope which contains the locker.  The lock is an OS lock, not
 // an object lock, and the two do not interoperate.  Do not use Mutex-based
--- a/src/hotspot/share/runtime/thread.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/thread.cpp	Wed May 01 12:31:29 2019 -0700
@@ -117,9 +117,8 @@
 #include "utilities/singleWriterSynchronizer.hpp"
 #include "utilities/vmError.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciCompiler.hpp"
-#include "jvmci/jvmciRuntime.hpp"
-#include "logging/logHandle.hpp"
+#include "jvmci/jvmci.hpp"
+#include "jvmci/jvmciEnv.hpp"
 #endif
 #ifdef COMPILER1
 #include "c1/c1_Compiler.hpp"
@@ -1576,16 +1575,17 @@
   return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
 }
 
-void JavaThread::collect_counters(typeArrayOop array) {
+void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) {
   if (JVMCICounterSize > 0) {
     JavaThreadIteratorWithHandle jtiwh;
-    for (int i = 0; i < array->length(); i++) {
-      array->long_at_put(i, _jvmci_old_thread_counters[i]);
+    int len = jvmci_env->get_length(array);
+    for (int i = 0; i < len; i++) {
+      jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]);
     }
     for (; JavaThread *tp = jtiwh.next(); ) {
       if (jvmci_counters_include(tp)) {
-        for (int i = 0; i < array->length(); i++) {
-          array->long_at_put(i, array->long_at(i) + tp->_jvmci_counters[i]);
+        for (int i = 0; i < len; i++) {
+          jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]);
         }
       }
     }
@@ -3922,10 +3922,8 @@
   bool force_JVMCI_intialization = false;
   if (EnableJVMCI) {
     // Initialize JVMCI eagerly when it is explicitly requested.
-    // Or when JVMCIPrintProperties is enabled.
-    // The JVMCI Java initialization code will read this flag and
-    // do the printing if it's set.
-    force_JVMCI_intialization = EagerJVMCI || JVMCIPrintProperties;
+    // Or when JVMCILibDumpJNIConfig or JVMCIPrintProperties is enabled.
+    force_JVMCI_intialization = EagerJVMCI || JVMCIPrintProperties || JVMCILibDumpJNIConfig;
 
     if (!force_JVMCI_intialization) {
       // 8145270: Force initialization of JVMCI runtime otherwise requests for blocking
@@ -3974,7 +3972,7 @@
 
 #if INCLUDE_JVMCI
   if (force_JVMCI_intialization) {
-    JVMCIRuntime::force_initialization(CHECK_JNI_ERR);
+    JVMCI::initialize_compiler(CHECK_JNI_ERR);
     CompileBroker::compilation_init_phase2();
   }
 #endif
@@ -4274,7 +4272,7 @@
     JavaValue result(T_VOID);
     JavaCalls::call_static(&result,
                            shutdown_klass,
-                           vmSymbols::shutdown_method_name(),
+                           vmSymbols::shutdown_name(),
                            vmSymbols::void_method_signature(),
                            THREAD);
   }
--- a/src/hotspot/share/runtime/thread.hpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/thread.hpp	Wed May 01 12:31:29 2019 -0700
@@ -88,6 +88,9 @@
 class ICRefillVerifier;
 class IdealGraphPrinter;
 
+class JVMCIEnv;
+class JVMCIPrimitiveArray;
+
 class Metadata;
 class ResourceArea;
 
@@ -1132,7 +1135,7 @@
 
   // An id of a speculation that JVMCI compiled code can use to further describe and
   // uniquely identify the  speculative optimization guarded by the uncommon trap
-  long       _pending_failed_speculation;
+  jlong     _pending_failed_speculation;
 
   // These fields are mutually exclusive in terms of live ranges.
   union {
@@ -1149,7 +1152,7 @@
 
  public:
   static jlong* _jvmci_old_thread_counters;
-  static void collect_counters(typeArrayOop array);
+  static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array);
  private:
 #endif // INCLUDE_JVMCI
 
@@ -1532,11 +1535,11 @@
 
 #if INCLUDE_JVMCI
   int  pending_deoptimization() const             { return _pending_deoptimization; }
-  long pending_failed_speculation() const         { return _pending_failed_speculation; }
+  jlong pending_failed_speculation() const        { return _pending_failed_speculation; }
   bool has_pending_monitorenter() const           { return _pending_monitorenter; }
   void set_pending_monitorenter(bool b)           { _pending_monitorenter = b; }
   void set_pending_deoptimization(int reason)     { _pending_deoptimization = reason; }
-  void set_pending_failed_speculation(long failed_speculation) { _pending_failed_speculation = failed_speculation; }
+  void set_pending_failed_speculation(jlong failed_speculation) { _pending_failed_speculation = failed_speculation; }
   void set_pending_transfer_to_interpreter(bool b) { _pending_transfer_to_interpreter = b; }
   void set_jvmci_alternate_call_target(address a) { assert(_jvmci._alternate_call_target == NULL, "must be"); _jvmci._alternate_call_target = a; }
   void set_jvmci_implicit_exception_pc(address a) { assert(_jvmci._implicit_exception_pc == NULL, "must be"); _jvmci._implicit_exception_pc = a; }
--- a/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Wed May 01 12:31:29 2019 -0700
@@ -34,7 +34,7 @@
 #include "code/scopeDesc.hpp"
 #include "oops/method.inline.hpp"
 #if INCLUDE_JVMCI
-#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmci.hpp"
 #endif
 
 #ifdef TIERED
--- a/src/hotspot/share/runtime/vmOperations.cpp	Wed May 01 12:41:26 2019 -0400
+++ b/src/hotspot/share/runtime/vmOperations.cpp	Wed May 01 12:31:29 2019 -0700
@@ -435,7 +435,20 @@
       if (thr!=thr_cur && thr->thread_state() == _thread_in_native) {
         num_active++;
         if (thr->is_Compiler_thread()) {
+#if INCLUDE_JVMCI
+          CompilerThread* ct = (CompilerThread*) thr;
+          if (ct->compiler() == NULL || !ct->compiler()->is_jvmci() || !UseJVMCINativeLibrary) {
+            num_active_compiler_thread++;
+          } else {
+            // When using a compiler in a JVMCI shared library, it's possible
+            // for one compiler thread to grab a lock in the shared library,
+            // enter HotSpot and go to sleep on the shutdown safepoint. Another
+            // JVMCI shared library compiler thread can then attempt to grab the
+            // lock and thus never make progress.
+          }
+#else
           num_active_compiler_thread++;
+#endif
         }
       }
     }
--- a/src/java.base/share/classes/module-info.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/java.base/share/classes/module-info.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -214,6 +214,7 @@
         java.sql,
         java.sql.rowset,
         jdk.dynalink,
+        jdk.internal.vm.ci,
         jdk.scripting.nashorn,
         jdk.unsupported;
     exports jdk.internal.vm to
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -191,7 +191,9 @@
     public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
 
     /**
-     * Return the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+     * Gets the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+     *
+     * @return {@code null} if there no deterministic {@link PlatformKind} for {@code javaKind}
      */
     public abstract PlatformKind getPlatformKind(JavaKind javaKind);
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -87,7 +87,11 @@
 
     @Override
     public int hashCode() {
-        return getBCI();
+        int hc = method.hashCode() * 31 + bci;
+        if (caller != null) {
+            hc = (hc * 31) + caller.hashCode();
+        }
+        return hc;
     }
 
     /**
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -44,6 +44,8 @@
      *            created.
      * @return a reference to the ready-to-run code
      * @throws BailoutException if the code installation failed
+     * @throws IllegalArgumentException if {@code installedCode != null} and this object does not
+     *             support a predefined {@link InstalledCode} object
      */
     default InstalledCode addCode(ResolvedJavaMethod method, CompiledCode compiledCode, SpeculationLog log, InstalledCode installedCode) {
         return installCode(method, compiledCode, installedCode, log, false);
@@ -58,6 +60,8 @@
      * @param compiledCode the compiled code to be added
      * @return a reference to the ready-to-run code
      * @throws BailoutException if the code installation failed
+     * @throws IllegalArgumentException if {@code installedCode != null} and this object does not
+     *             support a predefined {@link InstalledCode} object
      */
     default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompiledCode compiledCode) {
         return installCode(method, compiledCode, null, null, true);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -52,14 +52,14 @@
     /**
      * @return the address of entity representing this installed code.
      */
-    public final long getAddress() {
+    public long getAddress() {
         return address;
     }
 
     /**
      * @return the address of the normal entry point of the installed code.
      */
-    public final long getEntryPoint() {
+    public long getEntryPoint() {
         return entryPoint;
     }
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InvalidInstalledCodeException.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -27,5 +27,12 @@
  */
 public final class InvalidInstalledCodeException extends Exception {
 
+    public InvalidInstalledCodeException() {
+    }
+
+    public InvalidInstalledCodeException(String message) {
+        super(message);
+    }
+
     private static final long serialVersionUID = -3540232440794244844L;
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -24,6 +24,8 @@
 
 import java.util.concurrent.atomic.AtomicInteger;
 
+import jdk.vm.ci.services.Services;
+
 /**
  * A facility for timing a step in the runtime initialization sequence. This is independent from all
  * other JVMCI code so as to not perturb the initialization sequence. It is enabled by setting the
@@ -58,21 +60,32 @@
     }
 
     public static InitTimer timer(String name) {
-        return ENABLED ? new InitTimer(name) : null;
+        return isEnabled() ? new InitTimer(name) : null;
     }
 
     public static InitTimer timer(String name, Object suffix) {
-        return ENABLED ? new InitTimer(name + suffix) : null;
+        return isEnabled() ? new InitTimer(name + suffix) : null;
     }
 
     /**
-     * Specifies if initialization timing is enabled. Note: This property cannot use
+     * Determines if initialization timing is enabled. Note: This property cannot use
      * {@code HotSpotJVMCIRuntime.Option} since that class is not visible from this package.
      */
-    private static final boolean ENABLED = Boolean.getBoolean("jvmci.InitTimer");
+    private static boolean isEnabled() {
+        if (enabledPropertyValue == null) {
+            enabledPropertyValue = Boolean.parseBoolean(Services.getSavedProperty("jvmci.InitTimer"));
+            nesting = new AtomicInteger();
+        }
+        return enabledPropertyValue;
+    }
 
-    public static final AtomicInteger nesting = ENABLED ? new AtomicInteger() : null;
-    public static final String SPACES = "                                            ";
+    /**
+     * Cache for value of {@code jvmci.InitTimer} system property.
+     */
+    @NativeImageReinitialize private static Boolean enabledPropertyValue;
+
+    private static AtomicInteger nesting;
+    private static final String SPACES = "                                            ";
 
     /**
      * Used to assert the invariant that all related initialization happens on the same thread.
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/NativeImageReinitialize.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/NativeImageReinitialize.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -28,7 +28,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Denotes a field that should have the default value for its type when building a native image.
+ * Denotes a field that should have the default value for its type in an ahead of time image.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.FIELD})
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -24,6 +24,7 @@
 
 import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+import jdk.vm.ci.services.Services;
 
 /**
  * Used to access native configuration details.
@@ -36,7 +37,7 @@
         super(config);
     }
 
-    final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+    final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux");
 
     final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -24,6 +24,7 @@
 
 import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+import jdk.vm.ci.services.Services;
 
 /**
  * Used to access AMD64 specific native configuration details.
@@ -34,7 +35,7 @@
         super(config);
     }
 
-    final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+    final boolean windowsOs = Services.getSavedProperty("os.name", "").startsWith("Windows");
 
     final boolean useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
     final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Cleaner.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * A cleaner tracks a referent object and includes some {@linkplain #doCleanup() cleanup code} that
+ * is run some time after the referent object has become weakly-reachable.
+ *
+ * This is like {@link sun.misc.Cleaner} but with weak semantics instead of phantom. Objects
+ * referenced by this might be referenced by {@link ResolvedJavaType} which is kept alive by a
+ * {@link WeakReference} so we need equivalent reference strength.
+ */
+abstract class Cleaner extends WeakReference<Object> {
+
+    /**
+     * Head of linked list of cleaners.
+     */
+    @NativeImageReinitialize private static Cleaner first;
+
+    /**
+     * Linked list pointers.
+     */
+    private Cleaner next = null;
+    private Cleaner prev = null;
+
+    Cleaner(Object referent) {
+        super(referent, queue);
+        add(this);
+    }
+
+    private static synchronized Cleaner add(Cleaner cl) {
+        if (first != null) {
+            clean();
+        }
+        if (first != null) {
+            cl.next = first;
+            first.prev = cl;
+        }
+        first = cl;
+        return cl;
+    }
+
+    /**
+     * Removes {@code cl} from the linked list of cleaners.
+     */
+    private static synchronized void remove(Cleaner cl) {
+        // If already removed, do nothing
+        if (cl.next == cl) {
+            return;
+        }
+
+        // Update list
+        if (first == cl) {
+            if (cl.next != null) {
+                first = cl.next;
+            } else {
+                first = cl.prev;
+            }
+        }
+        if (cl.next != null) {
+            cl.next.prev = cl.prev;
+        }
+        if (cl.prev != null) {
+            cl.prev.next = cl.next;
+        }
+
+        // Indicate removal by pointing the cleaner to itself
+        cl.next = cl;
+        cl.prev = cl;
+    }
+
+    /**
+     * Performs the cleanup action now that this object's referent has become weakly reachable.
+     */
+    abstract void doCleanup();
+
+    /**
+     * Remove the cleaners whose referents have become weakly reachable.
+     */
+    static void clean() {
+        Cleaner c = (Cleaner) queue.poll();
+        while (c != null) {
+            remove(c);
+            c.doCleanup();
+            c = (Cleaner) queue.poll();
+        }
+    }
+
+    /**
+     * The {@link ReferenceQueue} to which {@link Cleaner}s are enqueued once their referents'
+     * become unreachable.
+     */
+    private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -36,6 +36,10 @@
 import jdk.vm.ci.code.stack.InspectedFrameVisitor;
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
@@ -51,17 +55,60 @@
      */
     private static native void registerNatives();
 
-    static {
-        initialize();
-    }
+    /**
+     * These values mirror the equivalent values from {@link Unsafe} but are approriate for the JVM
+     * being compiled against.
+     */
+    // Checkstyle: stop
+    final int ARRAY_BOOLEAN_BASE_OFFSET;
+    final int ARRAY_BYTE_BASE_OFFSET;
+    final int ARRAY_SHORT_BASE_OFFSET;
+    final int ARRAY_CHAR_BASE_OFFSET;
+    final int ARRAY_INT_BASE_OFFSET;
+    final int ARRAY_LONG_BASE_OFFSET;
+    final int ARRAY_FLOAT_BASE_OFFSET;
+    final int ARRAY_DOUBLE_BASE_OFFSET;
+    final int ARRAY_OBJECT_BASE_OFFSET;
+    final int ARRAY_BOOLEAN_INDEX_SCALE;
+    final int ARRAY_BYTE_INDEX_SCALE;
+    final int ARRAY_SHORT_INDEX_SCALE;
+    final int ARRAY_CHAR_INDEX_SCALE;
+    final int ARRAY_INT_INDEX_SCALE;
+    final int ARRAY_LONG_INDEX_SCALE;
+    final int ARRAY_FLOAT_INDEX_SCALE;
+    final int ARRAY_DOUBLE_INDEX_SCALE;
+    final int ARRAY_OBJECT_INDEX_SCALE;
+    // Checkstyle: resume
 
     @SuppressWarnings("try")
-    private static void initialize() {
+    CompilerToVM() {
         try (InitTimer t = timer("CompilerToVM.registerNatives")) {
             registerNatives();
+            ARRAY_BOOLEAN_BASE_OFFSET = arrayBaseOffset(JavaKind.Boolean);
+            ARRAY_BYTE_BASE_OFFSET = arrayBaseOffset(JavaKind.Byte);
+            ARRAY_SHORT_BASE_OFFSET = arrayBaseOffset(JavaKind.Short);
+            ARRAY_CHAR_BASE_OFFSET = arrayBaseOffset(JavaKind.Char);
+            ARRAY_INT_BASE_OFFSET = arrayBaseOffset(JavaKind.Int);
+            ARRAY_LONG_BASE_OFFSET = arrayBaseOffset(JavaKind.Long);
+            ARRAY_FLOAT_BASE_OFFSET = arrayBaseOffset(JavaKind.Float);
+            ARRAY_DOUBLE_BASE_OFFSET = arrayBaseOffset(JavaKind.Double);
+            ARRAY_OBJECT_BASE_OFFSET = arrayBaseOffset(JavaKind.Object);
+            ARRAY_BOOLEAN_INDEX_SCALE = arrayIndexScale(JavaKind.Boolean);
+            ARRAY_BYTE_INDEX_SCALE = arrayIndexScale(JavaKind.Byte);
+            ARRAY_SHORT_INDEX_SCALE = arrayIndexScale(JavaKind.Short);
+            ARRAY_CHAR_INDEX_SCALE = arrayIndexScale(JavaKind.Char);
+            ARRAY_INT_INDEX_SCALE = arrayIndexScale(JavaKind.Int);
+            ARRAY_LONG_INDEX_SCALE = arrayIndexScale(JavaKind.Long);
+            ARRAY_FLOAT_INDEX_SCALE = arrayIndexScale(JavaKind.Float);
+            ARRAY_DOUBLE_INDEX_SCALE = arrayIndexScale(JavaKind.Double);
+            ARRAY_OBJECT_INDEX_SCALE = arrayIndexScale(JavaKind.Object);
         }
     }
 
+    native int arrayBaseOffset(JavaKind kind);
+
+    native int arrayIndexScale(JavaKind kind);
+
     /**
      * Gets the {@link CompilerToVM} instance associated with the singleton
      * {@link HotSpotJVMCIRuntime} instance.
@@ -152,13 +199,16 @@
      * Converts a name to a type.
      *
      * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format
-     * @param accessingClass the context of resolution (must not be null)
+     * @param accessingClass the context of resolution. A value of {@code null} implies that the
+     *            class should be resolved with the class loader.
      * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
      *            either return a {@link ResolvedJavaType} or throw an exception
      * @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
      * @throws ClassNotFoundException if {@code resolve == true} and the resolution failed
      */
-    native HotSpotResolvedObjectTypeImpl lookupType(String name, Class<?> accessingClass, boolean resolve) throws ClassNotFoundException;
+    native HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, boolean resolve) throws ClassNotFoundException;
+
+    native HotSpotResolvedJavaType lookupClass(Class<?> javaClass);
 
     /**
      * Resolves the entry at index {@code cpi} in {@code constantPool} to an object.
@@ -167,7 +217,7 @@
      * entry types: {@code JVM_CONSTANT_MethodHandle}, {@code JVM_CONSTANT_MethodHandleInError},
      * {@code JVM_CONSTANT_MethodType} and {@code JVM_CONSTANT_MethodTypeInError}.
      */
-    native Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi);
+    native HotSpotObjectConstantImpl resolveConstantInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
      * Resolves the entry at index {@code cpi} in {@code constantPool} to an object, looking in the
@@ -176,7 +226,7 @@
      * The behavior of this method is undefined if {@code cpi} does not denote a
      * {@code JVM_CONSTANT_String} entry.
      */
-    native Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi);
+    native HotSpotObjectConstantImpl resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
      * Gets the {@code JVM_CONSTANT_NameAndType} index from the entry at index {@code cpi} in
@@ -318,7 +368,7 @@
      * Gets the appendix object (if any) associated with the entry at index {@code cpi} in
      * {@code constantPool}.
      */
-    native Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi);
+    native HotSpotObjectConstantImpl lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi);
 
     /**
      * Installs the result of a compilation into the code cache.
@@ -335,7 +385,7 @@
      * @throws JVMCIError if there is something wrong with the compiled code or the associated
      *             metadata.
      */
-    native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog);
+    native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, long failedSpeculationsAddress, byte[] speculations);
 
     /**
      * Generates the VM metadata for some compiled code and copies them into {@code metaData}. This
@@ -433,10 +483,10 @@
     /**
      * Executes some {@code installedCode} with arguments {@code args}.
      *
-     * @return the result of executing {@code installedCode}
-     * @throws InvalidInstalledCodeException if {@code installedCode} has been invalidated
+     * @return the result of executing {@code nmethodMirror}
+     * @throws InvalidInstalledCodeException if {@code nmethodMirror} has been invalidated
      */
-    native Object executeInstalledCode(Object[] args, InstalledCode installedCode) throws InvalidInstalledCodeException;
+    native Object executeHotSpotNmethod(Object[] args, HotSpotNmethod nmethodMirror) throws InvalidInstalledCodeException;
 
     /**
      * Gets the line number table for {@code method}. The line number table is encoded as (bci,
@@ -472,6 +522,19 @@
     native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method);
 
     /**
+     * Reads an object pointer within a VM data structure. That is, any {@link VMField} whose
+     * {@link VMField#type type} is {@code "oop"} (e.g.,
+     * {@code Klass::_java_mirror}, {@code JavaThread::_threadObj}).
+     *
+     * Note that {@link Unsafe#getObject(Object, long)} cannot be used for this since it does a
+     * {@code narrowOop} read if the VM is using compressed oops whereas oops within VM data
+     * structures are (currently) always uncompressed.
+     *
+     * @param address address of an oop field within a VM data structure
+     */
+    native HotSpotObjectConstantImpl readUncompressedOop(long address);
+
+    /**
      * Sets flags on {@code method} indicating that it should never be inlined or compiled by the
      * VM.
      */
@@ -484,10 +547,12 @@
     native void reprofile(HotSpotResolvedJavaMethodImpl method);
 
     /**
-     * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
-     * raised the next time {@code installedCode} is executed.
+     * Invalidates {@code nmethodMirror} such that {@link InvalidInstalledCodeException} will be
+     * raised the next time {@code nmethodMirror} is {@linkplain #executeHotSpotNmethod executed}.
+     * The {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and any
+     * current activations of the {@code nmethod} are deoptimized.
      */
-    native void invalidateInstalledCode(InstalledCode installedCode);
+    native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror);
 
     /**
      * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
@@ -572,7 +637,7 @@
      * @param displacement
      * @return null or the resolved method for this location
      */
-    native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
+    native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(HotSpotObjectConstantImpl base, long displacement);
 
     /**
      * Gets the {@code ConstantPool*} associated with {@code object} and returns a
@@ -586,7 +651,7 @@
      * @throws IllegalArgumentException if {@code object} is neither a
      *             {@link HotSpotResolvedJavaMethodImpl} nor a {@link HotSpotResolvedObjectTypeImpl}
      */
-    native HotSpotConstantPool getConstantPool(Object object);
+    native HotSpotConstantPool getConstantPool(MetaspaceObject object);
 
     /**
      * Read a HotSpot Klass* value from the memory location described by {@code base} plus
@@ -604,7 +669,19 @@
      * @param compressed true if the location contains a compressed Klass*
      * @return null or the resolved method for this location
      */
-    native HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, boolean compressed);
+    private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed);
+
+    HotSpotResolvedObjectTypeImpl getResolvedJavaType(MetaspaceObject base, long displacement, boolean compressed) {
+        return getResolvedJavaType0(base, displacement, compressed);
+    }
+
+    HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotObjectConstantImpl base, long displacement, boolean compressed) {
+        return getResolvedJavaType0(base, displacement, compressed);
+    }
+
+    HotSpotResolvedObjectTypeImpl getResolvedJavaType(long displacement, boolean compressed) {
+        return getResolvedJavaType0(null, displacement, compressed);
+    }
 
     /**
      * Return the size of the HotSpot ProfileData* pointed at by {@code position}. If
@@ -641,7 +718,7 @@
      * Invokes non-public method {@code java.lang.invoke.LambdaForm.compileToBytecode()} on
      * {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
      */
-    native void compileToBytecode(Object lambdaForm);
+    native void compileToBytecode(HotSpotObjectConstantImpl lambdaForm);
 
     /**
      * Gets the value of the VM flag named {@code name}.
@@ -660,6 +737,164 @@
     native HotSpotResolvedObjectTypeImpl getHostClass(HotSpotResolvedObjectTypeImpl type);
 
     /**
+     * Gets the object at the address {@code oopAddress}.
+     *
+     * @param oopAddress a valid {@code oopDesc**} value
+     */
+    native Object getObjectAtAddress(long oopAddress);
+
+    /**
+     * @see ResolvedJavaType#getInterfaces()
+     */
+    native HotSpotResolvedObjectTypeImpl[] getInterfaces(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * @see ResolvedJavaType#getComponentType()
+     */
+    native HotSpotResolvedJavaType getComponentType(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Forces initialization of {@code type}.
+     */
+    native void ensureInitialized(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Checks if {@code object} is a String and is an interned string value.
+     */
+    native boolean isInternedString(HotSpotObjectConstantImpl object);
+
+    /**
+     * Gets the {@linkplain System#identityHashCode(Object) identity} has code for the object
+     * represented by this constant.
+     */
+    native int getIdentityHashCode(HotSpotObjectConstantImpl object);
+
+    /**
+     * Converts a constant object representing a boxed primitive into a boxed primitive.
+     */
+    native Object unboxPrimitive(HotSpotObjectConstantImpl object);
+
+    /**
+     * Converts a boxed primitive into a JavaConstant representing the same value.
+     */
+    native HotSpotObjectConstantImpl boxPrimitive(Object source);
+
+    /**
+     * Gets the {@link ResolvedJavaMethod}s for all the constructors of the type {@code holder}.
+     */
+    native ResolvedJavaMethod[] getDeclaredConstructors(HotSpotResolvedObjectTypeImpl holder);
+
+    /**
+     * Gets the {@link ResolvedJavaMethod}s for all the non-constructor methods of the type
+     * {@code holder}.
+     */
+    native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl holder);
+
+    /**
+     * Reads the current value of a static field.
+     */
+    native JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl resolvedObjectType, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    /**
+     * Reads the current value of an instance field.
+     */
+    native JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    /**
+     * @see ResolvedJavaType#isInstance(JavaConstant)
+     */
+    native boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl object);
+
+    /**
+     * @see ResolvedJavaType#isAssignableFrom(ResolvedJavaType)
+     */
+    native boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType);
+
+    /**
+     * @see ConstantReflectionProvider#asJavaType(Constant)
+     */
+    native HotSpotResolvedJavaType asJavaType(HotSpotObjectConstantImpl object);
+
+    /**
+     * Converts a String constant into a String.
+     */
+    native String asString(HotSpotObjectConstantImpl object);
+
+    /**
+     * Compares the contents of {@code xHandle} and {@code yHandle} for pointer equality.
+     */
+    native boolean equals(HotSpotObjectConstantImpl x, long xHandle, HotSpotObjectConstantImpl y, long yHandle);
+
+    /**
+     * Gets a {@link JavaConstant} wrapping the {@link java.lang.Class} mirror for {@code type}.
+     */
+    native HotSpotObjectConstantImpl getJavaMirror(HotSpotResolvedJavaType type);
+
+    /**
+     * Returns the length of the array if {@code object} represents an array or -1 otherwise.
+     */
+    native int getArrayLength(HotSpotObjectConstantImpl object);
+
+    /**
+     * Reads the element at {@code index} if {@code object} is an array. Elements of an object array
+     * are returned as {@link JavaConstant}s and primitives are returned as boxed values. The value
+     * {@code null} is returned if the {@code index} is out of range or object is not an array.
+     */
+    native Object readArrayElement(HotSpotObjectConstantImpl object, int index);
+
+    /**
+     * Reads a byte sized value from {@code displacement} in {@code object}.
+     */
+    native byte getByte(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads a short sized value from {@code displacement} in {@code object}.
+     */
+    native short getShort(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads an int sized value from {@code displacement} in {@code object}.
+     */
+    native int getInt(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads a long sized value from {@code displacement} in {@code object}.
+     */
+    native long getLong(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * Reads a Java object from {@code displacement} in {@code object}.
+     */
+    native HotSpotObjectConstantImpl getObject(HotSpotObjectConstantImpl object, long displacement);
+
+    /**
+     * @see HotSpotJVMCIRuntime#registerNativeMethods
+     */
+    native long[] registerNativeMethods(Class<?> clazz);
+
+    /**
+     * @see HotSpotJVMCIRuntime#translate(Object)
+     */
+    native long translate(Object obj);
+
+    /**
+     * @see HotSpotJVMCIRuntime#unhand(Class, long)
+     */
+    native Object unhand(long handle);
+
+    /**
+     * Updates {@code address} and {@code entryPoint} fields of {@code nmethodMirror} based on the
+     * current state of the {@code nmethod} identified by {@code address} and
+     * {@code nmethodMirror.compileId} in the code cache.
+     */
+    native void updateHotSpotNmethod(HotSpotNmethod nmethodMirror);
+
+    /**
+     * @see InstalledCode#getCode()
+     */
+    native byte[] getCode(HotSpotInstalledCode code);
+
+    /**
      * Gets a {@link Executable} corresponding to {@code method}.
      */
     native Executable asReflectionExecutable(HotSpotResolvedJavaMethodImpl method);
@@ -671,4 +906,45 @@
      * @param fieldIndex the {@code fieldDescriptor::index()} denoting the field
      */
     native Field asReflectionField(HotSpotResolvedObjectTypeImpl holder, int fieldIndex);
+
+    /**
+     * @see HotSpotJVMCIRuntime#getIntrinsificationTrustPredicate(Class...)
+     */
+    native boolean isTrustedForIntrinsics(HotSpotResolvedObjectTypeImpl type);
+
+    /**
+     * Releases the resources backing the global JNI {@code handle}. This is equivalent to the
+     * {@code DeleteGlobalRef} JNI function.
+     */
+    native void deleteGlobalHandle(long handle);
+
+    /**
+     * Gets the failed speculations pointed to by {@code *failedSpeculationsAddress}.
+     *
+     * @param currentFailures the known failures at {@code failedSpeculationsAddress}
+     * @return the list of failed speculations with each entry being a single speculation in the
+     *         format emitted by {@link HotSpotSpeculationEncoding#toByteArray()}
+     */
+    native byte[][] getFailedSpeculations(long failedSpeculationsAddress, byte[][] currentFailures);
+
+    /**
+     * Gets the address of the {@code MethodData::_failed_speculations} field in the
+     * {@code MethodData} associated with {@code method}. This will create and install the
+     * {@code MethodData} if it didn't already exist.
+     */
+    native long getFailedSpeculationsAddress(HotSpotResolvedJavaMethodImpl method);
+
+    /**
+     * Frees the failed speculations pointed to by {@code *failedSpeculationsAddress}.
+     */
+    native void releaseFailedSpeculations(long failedSpeculationsAddress);
+
+    /**
+     * Adds a speculation to the failed speculations pointed to by
+     * {@code *failedSpeculationsAddress}.
+     *
+     * @return {@code false} if the speculation could not be appended to the list
+     */
+    native boolean addFailedSpeculation(long failedSpeculationsAddress, byte[] speculation);
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+final class DirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl {
+
+    static JavaConstant forObject(Object object, boolean compressed) {
+        if (object == null) {
+            return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
+        } else {
+            return new DirectHotSpotObjectConstantImpl(object, compressed);
+        }
+    }
+
+    static HotSpotObjectConstantImpl forNonNullObject(Object object, boolean compressed) {
+        if (object == null) {
+            throw new NullPointerException();
+        }
+        return new DirectHotSpotObjectConstantImpl(object, compressed);
+    }
+
+    private DirectHotSpotObjectConstantImpl(Object object, boolean compressed) {
+        super(compressed);
+        assert object != null;
+        this.object = object;
+    }
+
+    final Object object;
+
+    @Override
+    public JavaConstant compress() {
+        assert !compressed;
+        return new DirectHotSpotObjectConstantImpl(object, true);
+    }
+
+    @Override
+    public JavaConstant uncompress() {
+        assert compressed;
+        return new DirectHotSpotObjectConstantImpl(object, false);
+    }
+
+    @Override
+    public int getIdentityHashCode() {
+        return System.identityHashCode(object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+/**
+ * This class manages a set of {@code jobject} and {@code jmetadata} handles whose lifetimes are
+ * dependent on associated {@link IndirectHotSpotObjectConstantImpl} and
+ * {@link MetaspaceHandleObject} wrapper objects respectively.
+ *
+ * The general theory of operation is that all wrappers are created by calling into the VM which
+ * calls back out to actually create the wrapper instance. During the call the VM keeps the object
+ * or metadata reference alive through the use of handles. Once the call completes the wrapper
+ * object is registered here and will be scanned during metadata scanning. The weakness of the
+ * reference to the wrapper object allows the handles to be reclaimed when they are no longer used.
+ */
+final class HandleCleaner extends Cleaner {
+
+    /**
+     * A {@code jmetadata} or {@code jobject} handle.
+     */
+    private final long handle;
+
+    /**
+     * Specifies if {@link #handle} is a {@code jobject} or {@code jmetadata}.
+     */
+    private final boolean isJObject;
+
+    private HandleCleaner(Object wrapper, long handle, boolean isJObject) {
+        super(wrapper);
+        this.handle = handle;
+        this.isJObject = isJObject;
+    }
+
+    /**
+     * Releases the resource associated with {@code this.handle}.
+     */
+    @Override
+    void doCleanup() {
+        if (isJObject) {
+            // The sentinel value used to denote a free handle is
+            // an object on the HotSpot heap so we call into the
+            // VM to set the target of an object handle to this value.
+            CompilerToVM.compilerToVM().deleteGlobalHandle(handle);
+        } else {
+            // Setting the target of a jmetadata handle to 0 enables
+            // the handle to be reused. See MetadataHandleBlock in
+            // jvmciRuntime.cpp for more info.
+            long value = UNSAFE.getLong(null, handle);
+            UNSAFE.compareAndSetLong(null, handle, value, 0);
+        }
+    }
+
+    /**
+     * Registers a cleaner for {@code handle}. The cleaner will release the handle some time after
+     * {@code wrapper} is detected as unreachable by the garbage collector.
+     */
+    @SuppressWarnings("unused")
+    static void create(Object wrapper, long handle) {
+        assert wrapper instanceof IndirectHotSpotObjectConstantImpl || wrapper instanceof MetaspaceHandleObject;
+        new HandleCleaner(wrapper, handle, wrapper instanceof IndirectHotSpotObjectConstantImpl);
+    }
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -23,6 +23,7 @@
 package jdk.vm.ci.hotspot;
 
 import java.util.Map;
+import java.util.Objects;
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.code.BytecodeFrame;
@@ -102,25 +103,42 @@
     @Override
     public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) {
         InstalledCode resultInstalledCode;
-        if (installedCode == null) {
-            if (method == null) {
-                // Must be a stub
-                resultInstalledCode = new HotSpotRuntimeStub(((HotSpotCompiledCode) compiledCode).getName());
-            } else {
-                resultInstalledCode = new HotSpotNmethod((HotSpotResolvedJavaMethod) method, ((HotSpotCompiledCode) compiledCode).getName(), isDefault);
-            }
+        if (installedCode != null) {
+            throw new IllegalArgumentException("InstalledCode argument must be null");
+        }
+        HotSpotCompiledCode hsCompiledCode = (HotSpotCompiledCode) compiledCode;
+        String name = hsCompiledCode.getName();
+        HotSpotCompiledNmethod hsCompiledNmethod = null;
+        if (method == null) {
+            // Must be a stub
+            resultInstalledCode = new HotSpotRuntimeStub(name);
         } else {
-            resultInstalledCode = installedCode;
+            hsCompiledNmethod = (HotSpotCompiledNmethod) hsCompiledCode;
+            HotSpotResolvedJavaMethodImpl hsMethod = (HotSpotResolvedJavaMethodImpl) method;
+            resultInstalledCode = new HotSpotNmethod(hsMethod, name, isDefault, hsCompiledNmethod.id);
         }
 
-        HotSpotSpeculationLog speculationLog = (log != null && log.hasSpeculations()) ? (HotSpotSpeculationLog) log : null;
+        HotSpotSpeculationLog speculationLog = null;
+        if (log != null) {
+            if (log.hasSpeculations()) {
+                speculationLog = (HotSpotSpeculationLog) log;
+            }
+        }
 
-        int result = runtime.getCompilerToVM().installCode(target, (HotSpotCompiledCode) compiledCode, resultInstalledCode, speculationLog);
+        byte[] speculations;
+        long failedSpeculationsAddress;
+        if (speculationLog != null) {
+            speculations = speculationLog.getFlattenedSpeculations(true);
+            failedSpeculationsAddress = speculationLog.getFailedSpeculationsAddress();
+        } else {
+            speculations = new byte[0];
+            failedSpeculationsAddress = 0L;
+        }
+        int result = runtime.getCompilerToVM().installCode(target, (HotSpotCompiledCode) compiledCode, resultInstalledCode, failedSpeculationsAddress, speculations);
         if (result != config.codeInstallResultOk) {
             String resultDesc = config.getCodeInstallResultDescription(result);
-            if (compiledCode instanceof HotSpotCompiledNmethod) {
-                HotSpotCompiledNmethod compiledNmethod = (HotSpotCompiledNmethod) compiledCode;
-                String msg = compiledNmethod.getInstallationFailureMessage();
+            if (hsCompiledNmethod != null) {
+                String msg = hsCompiledNmethod.getInstallationFailureMessage();
                 if (msg != null) {
                     msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
                 } else {
@@ -139,7 +157,11 @@
 
     @Override
     public void invalidateInstalledCode(InstalledCode installedCode) {
-        runtime.getCompilerToVM().invalidateInstalledCode(installedCode);
+        if (installedCode instanceof HotSpotNmethod) {
+            runtime.getCompilerToVM().invalidateHotSpotNmethod((HotSpotNmethod) installedCode);
+        } else {
+            throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName());
+        }
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -29,7 +29,14 @@
  * the address of a {@code JVMCIEnv} object that provides native context for a compilation.
  */
 public class HotSpotCompilationRequest extends CompilationRequest {
-    private final long jvmciEnv;
+    /**
+     * Address of the native {@code JVMCICompileState} associated with the request.
+     */
+    private final long compileState;
+
+    /**
+     * An identifier for the request.
+     */
     private final int id;
 
     /**
@@ -39,10 +46,10 @@
      * @param method the method to be compiled
      * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
      *            method's entry point
-     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     * @param compileState address of a native {@code JVMCICompileState} object or 0L
      */
-    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv) {
-        this(method, entryBCI, jvmciEnv, method.allocateCompileId(entryBCI));
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long compileState) {
+        this(method, entryBCI, compileState, method.allocateCompileId(entryBCI));
     }
 
     /**
@@ -51,12 +58,12 @@
      * @param method the method to be compiled
      * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
      *            method's entry point
-     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     * @param compileState address of a native {@code JVMCICompileState} object or 0L
      * @param id an identifier for the request
      */
-    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
         super(method, entryBCI);
-        this.jvmciEnv = jvmciEnv;
+        this.compileState = compileState;
         this.id = id;
     }
 
@@ -66,10 +73,12 @@
     }
 
     /**
-     * Gets the address of the native {@code JVMCIEnv} object or 0L if no such object exists.
+     * Gets the address of the native {@code JVMCICompileState} or 0L if no such object exists. This
+     * method should really be named {@code getCompileState} but must remain as is for API
+     * stability.
      */
     public long getJvmciEnv() {
-        return jvmciEnv;
+        return compileState;
     }
 
     /**
@@ -78,5 +87,4 @@
     public int getId() {
         return id;
     }
-
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -42,9 +42,9 @@
     protected final int id;
 
     /**
-     * Address of a native {@code JVMCIEnv} object or 0L if no such object exists.
+     * Address of a native {@code JVMCICompileState} object or 0L if no such object exists.
      */
-    protected final long jvmciEnv;
+    protected final long compileState;
 
     protected final boolean hasUnsafeAccess;
 
@@ -56,12 +56,12 @@
 
     public HotSpotCompiledNmethod(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection,
                     int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot, HotSpotResolvedJavaMethod method, int entryBCI,
-                    int id, long jvmciEnv, boolean hasUnsafeAccess) {
+                    int id, long compileState, boolean hasUnsafeAccess) {
         super(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, totalFrameSize, deoptRescueSlot);
         this.method = method;
         this.entryBCI = entryBCI;
         this.id = id;
-        this.jvmciEnv = jvmciEnv;
+        this.compileState = compileState;
         this.hasUnsafeAccess = hasUnsafeAccess;
     }
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -27,9 +27,8 @@
 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.invoke.MethodHandle;
-
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.meta.ConstantPool;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaField;
@@ -45,7 +44,7 @@
 /**
  * Implementation of {@link ConstantPool} for HotSpot.
  */
-public final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject {
+public final class HotSpotConstantPool implements ConstantPool, MetaspaceHandleObject {
 
     /**
      * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
@@ -97,76 +96,86 @@
         }
     }
 
-    /**
-     * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and
-     * internal ones.
-     */
-    private enum JVM_CONSTANT {
-        // @formatter:off
-        Utf8(config().jvmConstantUtf8),
-        Integer(config().jvmConstantInteger),
-        Long(config().jvmConstantLong),
-        Float(config().jvmConstantFloat),
-        Double(config().jvmConstantDouble),
-        Class(config().jvmConstantClass),
-        UnresolvedClass(config().jvmConstantUnresolvedClass),
-        UnresolvedClassInError(config().jvmConstantUnresolvedClassInError),
-        String(config().jvmConstantString),
-        Fieldref(config().jvmConstantFieldref),
-        MethodRef(config().jvmConstantMethodref),
-        InterfaceMethodref(config().jvmConstantInterfaceMethodref),
-        NameAndType(config().jvmConstantNameAndType),
-        MethodHandle(config().jvmConstantMethodHandle),
-        MethodHandleInError(config().jvmConstantMethodHandleInError),
-        MethodType(config().jvmConstantMethodType),
-        MethodTypeInError(config().jvmConstantMethodTypeInError),
-        InvokeDynamic(config().jvmConstantInvokeDynamic);
-        // @formatter:on
+    static final class JvmConstant {
+        private final int tag;
+        private final String name;
 
-        private final int tag;
-
-        private static final int ExternalMax = config().jvmConstantExternalMax;
-        private static final int InternalMin = config().jvmConstantInternalMin;
-        private static final int InternalMax = config().jvmConstantInternalMax;
-
-        JVM_CONSTANT(int tag) {
+        JvmConstant(int tag, String name) {
             this.tag = tag;
+            this.name = name;
         }
 
-        /**
-         * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy
-         * initialization.
-         */
-        static class TagValueMap {
-            private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1];
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    /**
+     * {@code JVM_CONSTANT} constants used in the VM including both public and internal ones.
+     */
+    static final class JvmConstants {
+
+        private final HotSpotVMConfig c = config();
+        private final int externalMax = c.jvmConstantExternalMax;
+        private final int internalMax = c.jvmConstantInternalMax;
+        private final int internalMin = c.jvmConstantInternalMin;
+        private final JvmConstant[] table = new JvmConstant[externalMax + 1 + (internalMax - internalMin) + 1];
 
-            static {
-                assert InternalMin > ExternalMax;
-                for (JVM_CONSTANT e : values()) {
-                    table[indexOf(e.tag)] = e;
+        final JvmConstant jvmUtf8 = add(new JvmConstant(c.jvmConstantUtf8, "Utf8"));
+        final JvmConstant jvmInteger = add(new JvmConstant(c.jvmConstantInteger, "Integer"));
+        final JvmConstant jvmLong = add(new JvmConstant(c.jvmConstantLong, "Long"));
+        final JvmConstant jvmFloat = add(new JvmConstant(c.jvmConstantFloat, "Float"));
+        final JvmConstant jvmDouble = add(new JvmConstant(c.jvmConstantDouble, "Double"));
+        final JvmConstant jvmClass = add(new JvmConstant(c.jvmConstantClass, "Class"));
+        final JvmConstant jvmUnresolvedClass = add(new JvmConstant(c.jvmConstantUnresolvedClass, "UnresolvedClass"));
+        final JvmConstant jvmUnresolvedClassInError = add(new JvmConstant(c.jvmConstantUnresolvedClassInError, "UnresolvedClassInError"));
+        final JvmConstant jvmString = add(new JvmConstant(c.jvmConstantString, "String"));
+        final JvmConstant jvmFieldref = add(new JvmConstant(c.jvmConstantFieldref, "Fieldref"));
+        final JvmConstant jvmMethodref = add(new JvmConstant(c.jvmConstantMethodref, "Methodref"));
+        final JvmConstant jvmInterfaceMethodref = add(new JvmConstant(c.jvmConstantInterfaceMethodref, "InterfaceMethodref"));
+        final JvmConstant jvmNameAndType = add(new JvmConstant(c.jvmConstantNameAndType, "NameAndType"));
+        final JvmConstant jvmMethodHandle = add(new JvmConstant(c.jvmConstantMethodHandle, "MethodHandle"));
+        final JvmConstant jvmMethodHandleInError = add(new JvmConstant(c.jvmConstantMethodHandleInError, "MethodHandleInError"));
+        final JvmConstant jvmMethodType = add(new JvmConstant(c.jvmConstantMethodType, "MethodType"));
+        final JvmConstant jvmMethodTypeInError = add(new JvmConstant(c.jvmConstantMethodTypeInError, "MethodTypeInError"));
+        final JvmConstant jvmInvokeDynamic = add(new JvmConstant(c.jvmConstantInvokeDynamic, "InvokeDynamic"));
+
+        private JvmConstant add(JvmConstant constant) {
+            table[indexOf(constant.tag)] = constant;
+            return constant;
+        }
+
+        private int indexOf(int tag) {
+            if (tag >= internalMin) {
+                return tag - internalMin + externalMax + 1;
+            } else {
+                assert tag <= externalMax;
+            }
+            return tag;
+        }
+
+        JvmConstant get(int tag) {
+            JvmConstant res = table[indexOf(tag)];
+            if (res != null) {
+                return res;
+            }
+            throw new JVMCIError("Unknown JvmConstant tag %s", tag);
+        }
+
+        @NativeImageReinitialize private static volatile JvmConstants instance;
+
+        static JvmConstants instance() {
+            JvmConstants result = instance;
+            if (result == null) {
+                synchronized (JvmConstants.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new JvmConstants();
+                    }
                 }
             }
-
-            private static int indexOf(int tag) {
-                if (tag >= InternalMin) {
-                    return tag - InternalMin + ExternalMax + 1;
-                } else {
-                    assert tag <= ExternalMax;
-                }
-                return tag;
-            }
-
-            static JVM_CONSTANT get(int tag) {
-                JVM_CONSTANT res = table[indexOf(tag)];
-                if (res != null) {
-                    return res;
-                }
-                throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag);
-            }
-        }
-
-        public static JVM_CONSTANT getEnum(int tag) {
-            return TagValueMap.get(tag);
+            return result;
         }
     }
 
@@ -182,15 +191,18 @@
     }
 
     /**
-     * Reference to the C++ ConstantPool object.
+     * Handle to the {@code ConstantPool} VM object. The handle is in
+     * {@code JVMCI::_metadata_handles}.
      */
-    private final long metaspaceConstantPool;
+    private final long metadataHandle;
+
     private volatile LookupTypeCacheElement lastLookupType;
+    private final JvmConstants constants;
 
     /**
      * Gets the JVMCI mirror from a HotSpot constant pool.The VM is responsible for ensuring that
      * the ConstantPool is kept alive for the duration of this call and the
-     * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
+     * {@link HotSpotJVMCIRuntime} keeps it alive after that.
      *
      * Called from the VM.
      *
@@ -198,14 +210,15 @@
      * @return the {@link HotSpotConstantPool} corresponding to {@code metaspaceConstantPool}
      */
     @SuppressWarnings("unused")
+    @VMEntryPoint
     private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) {
-        HotSpotConstantPool cp = new HotSpotConstantPool(metaspaceConstantPool);
-        runtime().metaAccessContext.add(cp);
-        return cp;
+        return new HotSpotConstantPool(metaspaceConstantPool);
     }
 
-    private HotSpotConstantPool(long metaspaceConstantPool) {
-        this.metaspaceConstantPool = metaspaceConstantPool;
+    private HotSpotConstantPool(long metadataHandle) {
+        this.metadataHandle = metadataHandle;
+        this.constants = JvmConstants.instance();
+        HandleCleaner.create(this, metadataHandle);
     }
 
     /**
@@ -271,12 +284,12 @@
     }
 
     long getMetaspaceConstantPool() {
-        return metaspaceConstantPool;
+        return getMetaspacePointer();
     }
 
     @Override
-    public long getMetaspacePointer() {
-        return getMetaspaceConstantPool();
+    public long getMetadataHandle() {
+        return metadataHandle;
     }
 
     /**
@@ -285,7 +298,7 @@
      * @param index constant pool index
      * @return constant pool tag
      */
-    private JVM_CONSTANT getTagAt(int index) {
+    private JvmConstant getTagAt(int index) {
         assert checkBounds(index);
         HotSpotVMConfig config = config();
         final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset);
@@ -293,7 +306,7 @@
         if (tag == 0) {
             return null;
         }
-        return JVM_CONSTANT.getEnum(tag);
+        return constants.get(tag);
     }
 
     /**
@@ -315,7 +328,7 @@
      * @return integer constant pool entry at index
      */
     private int getIntAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Integer);
+        assert checkTag(index, constants.jvmInteger);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -327,7 +340,7 @@
      * @return long constant pool entry
      */
     private long getLongAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Long);
+        assert checkTag(index, constants.jvmLong);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -339,7 +352,7 @@
      * @return float constant pool entry
      */
     private float getFloatAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Float);
+        assert checkTag(index, constants.jvmFloat);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -351,7 +364,7 @@
      * @return float constant pool entry
      */
     private double getDoubleAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.Double);
+        assert checkTag(index, constants.jvmDouble);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -363,7 +376,7 @@
      * @return {@code JVM_CONSTANT_NameAndType} constant pool entry
      */
     private int getNameAndTypeAt(int index) {
-        assert checkTag(index, JVM_CONSTANT.NameAndType);
+        assert checkTag(index, constants.jvmNameAndType);
         int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
@@ -470,22 +483,23 @@
      * @param tag expected tag
      * @throws AssertionError if the check fails
      */
-    private boolean checkTag(int index, JVM_CONSTANT tag) {
-        final JVM_CONSTANT tagAt = getTagAt(index);
+    private boolean checkTag(int index, JvmConstant tag) {
+        final JvmConstant tagAt = getTagAt(index);
         assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag;
         return true;
     }
 
     /**
-     * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref},
-     * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}.
+     * Asserts that the constant pool tag at index {@code index} is a
+     * {@link JvmConstants#jvmFieldref}, or a {@link JvmConstants#jvmMethodref}, or a
+     * {@link JvmConstants#jvmInterfaceMethodref}.
      *
      * @param index constant pool index
      * @throws AssertionError if the check fails
      */
     private boolean checkTagIsFieldOrMethod(int index) {
-        final JVM_CONSTANT tagAt = getTagAt(index);
-        assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt;
+        final JvmConstant tagAt = getTagAt(index);
+        assert tagAt == constants.jvmFieldref || tagAt == constants.jvmMethodref || tagAt == constants.jvmInterfaceMethodref : tagAt;
         return true;
     }
 
@@ -505,35 +519,33 @@
     @Override
     public Object lookupConstant(int cpi) {
         assert cpi != 0;
-        final JVM_CONSTANT tag = getTagAt(cpi);
-        switch (tag) {
-            case Integer:
+        final JvmConstant tag = getTagAt(cpi);
+        switch (tag.name) {
+            case "Integer":
                 return JavaConstant.forInt(getIntAt(cpi));
-            case Long:
+            case "Long":
                 return JavaConstant.forLong(getLongAt(cpi));
-            case Float:
+            case "Float":
                 return JavaConstant.forFloat(getFloatAt(cpi));
-            case Double:
+            case "Double":
                 return JavaConstant.forDouble(getDoubleAt(cpi));
-            case Class:
-            case UnresolvedClass:
-            case UnresolvedClassInError:
+            case "Class":
+            case "UnresolvedClass":
+            case "UnresolvedClassInError":
                 final int opcode = -1;  // opcode is not used
                 return lookupType(cpi, opcode);
-            case String:
+            case "String":
                 /*
                  * Normally, we would expect a String here, but unsafe anonymous classes can have
                  * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
                  * entries do not have a symbol in the constant pool slot.
                  */
-                Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
-                return HotSpotObjectConstantImpl.forObject(string);
-            case MethodHandle:
-            case MethodHandleInError:
-            case MethodType:
-            case MethodTypeInError:
-                Object obj = compilerToVM().resolveConstantInPool(this, cpi);
-                return HotSpotObjectConstantImpl.forObject(obj);
+                return compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
+            case "MethodHandle":
+            case "MethodHandleInError":
+            case "MethodType":
+            case "MethodTypeInError":
+                return compilerToVM().resolveConstantInPool(this, cpi);
             default:
                 throw new JVMCIError("Unknown constant pool tag %s", tag);
         }
@@ -541,7 +553,7 @@
 
     @Override
     public String lookupUtf8(int cpi) {
-        assert checkTag(cpi, JVM_CONSTANT.Utf8);
+        assert checkTag(cpi, constants.jvmUtf8);
         return compilerToVM().getSymbol(getEntryAt(cpi));
     }
 
@@ -554,12 +566,7 @@
     public JavaConstant lookupAppendix(int cpi, int opcode) {
         assert Bytecodes.isInvoke(opcode);
         final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
-        Object appendix = compilerToVM().lookupAppendixInPool(this, index);
-        if (appendix == null) {
-            return null;
-        } else {
-            return HotSpotObjectConstantImpl.forObject(appendix);
-        }
+        return compilerToVM().lookupAppendixInPool(this, index);
     }
 
     /**
@@ -587,7 +594,7 @@
             String name = getNameOf(index);
             HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index));
             if (opcode == Bytecodes.INVOKEDYNAMIC) {
-                HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class);
+                HotSpotResolvedObjectType holder = runtime().getMethodHandleClass();
                 return new UnresolvedJavaMethod(name, signature, holder);
             } else {
                 final int klassIndex = getKlassRefIndexAt(index);
@@ -709,40 +716,37 @@
                 throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
         }
 
-        final JVM_CONSTANT tag = getTagAt(index);
+        final JvmConstant tag = getTagAt(index);
         if (tag == null) {
-            assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long;
+            assert getTagAt(index - 1) == constants.jvmDouble || getTagAt(index - 1) == constants.jvmLong;
             return;
         }
-        switch (tag) {
-            case MethodRef:
-            case Fieldref:
-            case InterfaceMethodref:
+        switch (tag.name) {
+            case "Methodref":
+            case "Fieldref":
+            case "InterfaceMethodref":
                 index = getUncachedKlassRefIndexAt(index);
                 // Read the tag only once because it could change between multiple reads.
-                final JVM_CONSTANT klassTag = getTagAt(index);
-                assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
+                final JvmConstant klassTag = getTagAt(index);
+                assert klassTag == constants.jvmClass || klassTag == constants.jvmUnresolvedClass || klassTag == constants.jvmUnresolvedClassInError : klassTag;
                 // fall through
-            case Class:
-            case UnresolvedClass:
-            case UnresolvedClassInError:
+            case "Class":
+            case "UnresolvedClass":
+            case "UnresolvedClassInError":
                 final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index);
-                if (initialize) {
-                    Class<?> klass = type.mirror();
-                    if (!klass.isPrimitive() && !klass.isArray()) {
-                        UNSAFE.ensureClassInitialized(klass);
-                    }
+                if (initialize && !type.isPrimitive() && !type.isArray()) {
+                    type.ensureInitialized();
                 }
-                if (tag == JVM_CONSTANT.MethodRef) {
+                if (tag == constants.jvmMethodref) {
                     if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
                         final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
-                        assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+                        assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
                         compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
                     }
                 }
 
                 break;
-            case InvokeDynamic:
+            case "InvokeDynamic":
                 if (isInvokedynamicIndex(cpi)) {
                     compilerToVM().resolveInvokeDynamicInPool(this, cpi);
                 }
@@ -788,7 +792,7 @@
     public boolean isResolvedDynamicInvoke(int cpi, int opcode) {
         if (Bytecodes.isInvokeHandleAlias(opcode)) {
             final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
-            assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+            assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
             int op = compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
             return op == opcode;
         }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPoolObject.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -23,21 +23,19 @@
 package jdk.vm.ci.hotspot;
 
 import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 
 /**
  * Represents a constant that was retrieved from a constant pool. Used to keep track of the constant
  * pool slot for the constant.
  */
-public final class HotSpotConstantPoolObject extends HotSpotObjectConstantImpl {
+public final class HotSpotConstantPoolObject implements JavaConstant {
 
-    static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, Object object) {
+    public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
         return new HotSpotConstantPoolObject(type, cpi, object);
     }
 
-    public static JavaConstant forObject(HotSpotResolvedObjectType type, int cpi, JavaConstant object) {
-        return forObject(type, cpi, ((HotSpotObjectConstantImpl) object).object());
-    }
-
+    private final JavaConstant constant;
     private final HotSpotResolvedObjectType type;
     private final int cpi;
 
@@ -49,24 +47,72 @@
         return cpi;
     }
 
-    HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, Object object) {
-        super(object, false);
+    HotSpotConstantPoolObject(HotSpotResolvedObjectType type, int cpi, JavaConstant constant) {
         this.type = type;
         this.cpi = cpi;
+        this.constant = constant;
     }
 
     @Override
     public boolean equals(Object o) {
         if (o instanceof HotSpotConstantPoolObject) {
-            if (super.equals(o)) {
-                HotSpotConstantPoolObject other = (HotSpotConstantPoolObject) o;
-                return type.equals(other.type) && cpi == other.cpi;
-            }
+            HotSpotConstantPoolObject other = (HotSpotConstantPoolObject) o;
+            return type.equals(other.type) && cpi == other.cpi && constant.equals(other.constant);
         }
         return false;
     }
 
     @Override
+    public int hashCode() {
+        return constant.hashCode() + cpi + type.hashCode();
+    }
+
+    @Override
+    public JavaKind getJavaKind() {
+        return constant.getJavaKind();
+    }
+
+    @Override
+    public boolean isNull() {
+        return constant.isNull();
+    }
+
+    @Override
+    public boolean isDefaultForKind() {
+        return constant.isDefaultForKind();
+    }
+
+    @Override
+    public Object asBoxedPrimitive() {
+        return constant.asBoxedPrimitive();
+    }
+
+    @Override
+    public int asInt() {
+        return constant.asInt();
+    }
+
+    @Override
+    public boolean asBoolean() {
+        return constant.asBoolean();
+    }
+
+    @Override
+    public long asLong() {
+        return constant.asLong();
+    }
+
+    @Override
+    public float asFloat() {
+        return constant.asFloat();
+    }
+
+    @Override
+    public double asDouble() {
+        return 0;
+    }
+
+    @Override
     public String toValueString() {
         return getCpType().getName() + getCpi();
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -22,7 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.reflect.Array;
 import java.util.Objects;
 
 import jdk.vm.ci.common.JVMCIError;
@@ -65,7 +64,7 @@
         if (x == y) {
             return true;
         } else if (x instanceof HotSpotObjectConstantImpl) {
-            return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).object() == ((HotSpotObjectConstantImpl) y).object();
+            return y instanceof HotSpotObjectConstantImpl && x.equals(y);
         } else {
             return Objects.equals(x, y);
         }
@@ -77,11 +76,8 @@
             return null;
         }
 
-        Object arrayObject = ((HotSpotObjectConstantImpl) array).object();
-        if (!arrayObject.getClass().isArray()) {
-            return null;
-        }
-        return Array.getLength(arrayObject);
+        HotSpotObjectConstantImpl arrayObject = ((HotSpotObjectConstantImpl) array);
+        return runtime.getReflection().getLength(arrayObject);
     }
 
     @Override
@@ -89,18 +85,8 @@
         if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
             return null;
         }
-        Object a = ((HotSpotObjectConstantImpl) array).object();
-
-        if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) {
-            return null;
-        }
-
-        if (a instanceof Object[]) {
-            Object element = ((Object[]) a)[index];
-            return HotSpotObjectConstantImpl.forObject(element);
-        } else {
-            return JavaConstant.forBoxedPrimitive(Array.get(a, index));
-        }
+        HotSpotObjectConstantImpl arrayObject = ((HotSpotObjectConstantImpl) array);
+        return runtime.getReflection().readArrayElement(arrayObject, index);
     }
 
     /**
@@ -135,7 +121,7 @@
         if (source == null || !source.getJavaKind().isPrimitive() || !isBoxCached(source)) {
             return null;
         }
-        return HotSpotObjectConstantImpl.forObject(source.asBoxedPrimitive());
+        return runtime.getReflection().boxPrimitive(source);
     }
 
     @Override
@@ -146,28 +132,25 @@
         if (source.isNull()) {
             return null;
         }
-        return JavaConstant.forBoxedPrimitive(((HotSpotObjectConstantImpl) source).object());
+        return runtime.getReflection().unboxPrimitive((HotSpotObjectConstantImpl) source);
     }
 
     @Override
     public JavaConstant forString(String value) {
-        return HotSpotObjectConstantImpl.forObject(value);
+        return runtime.getReflection().forObject(value);
     }
 
     public JavaConstant forObject(Object value) {
-        return HotSpotObjectConstantImpl.forObject(value);
+        return runtime.getReflection().forObject(value);
     }
 
     @Override
     public ResolvedJavaType asJavaType(Constant constant) {
-        if (constant instanceof HotSpotObjectConstant) {
-            Object obj = ((HotSpotObjectConstantImpl) constant).object();
-            if (obj instanceof Class) {
-                return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType((Class<?>) obj);
-            }
+        if (constant instanceof HotSpotObjectConstantImpl) {
+            return ((HotSpotObjectConstantImpl) constant).asJavaType();
         }
         if (constant instanceof HotSpotMetaspaceConstant) {
-            MetaspaceWrapperObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
+            MetaspaceObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
             if (obj instanceof HotSpotResolvedObjectTypeImpl) {
                 return (ResolvedJavaType) obj;
             }
@@ -179,15 +162,15 @@
     public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) {
         HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
         if (hotspotField.isStatic()) {
-            HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
+            HotSpotResolvedObjectTypeImpl holder = (HotSpotResolvedObjectTypeImpl) hotspotField.getDeclaringClass();
             if (holder.isInitialized()) {
-                return memoryAccess.readFieldValue(hotspotField, holder.mirror(), field.isVolatile());
+                return holder.readFieldValue(hotspotField, field.isVolatile());
             }
         } else {
-            if (receiver.isNonNull()) {
-                Object object = ((HotSpotObjectConstantImpl) receiver).object();
+            if (receiver.isNonNull() && receiver instanceof HotSpotObjectConstantImpl) {
+                HotSpotObjectConstantImpl object = ((HotSpotObjectConstantImpl) receiver);
                 if (hotspotField.isInObject(receiver)) {
-                    return memoryAccess.readFieldValue(hotspotField, object, field.isVolatile());
+                    return object.readFieldValue(hotspotField, field.isVolatile());
                 }
             }
         }
@@ -196,7 +179,7 @@
 
     @Override
     public JavaConstant asJavaClass(ResolvedJavaType type) {
-        return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedJavaType) type).mirror());
+        return ((HotSpotResolvedJavaType) type).getJavaMirror();
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -22,28 +22,28 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
 
-import jdk.internal.misc.Unsafe;
 import jdk.vm.ci.code.InstalledCode;
 
 /**
- * Implementation of {@link InstalledCode} for HotSpot.
+ * Implementation of {@link InstalledCode} for HotSpot representing a {@code CodeBlob}. The address
+ * of the {@code CodeBlob} is stored in {@link InstalledCode#address}.
  */
 public abstract class HotSpotInstalledCode extends InstalledCode {
 
     /**
-     * Total size of the code blob.
+     * Total size of the code blob (i.e. {@code CodeBlob::size()}).
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
 
     /**
-     * Start address of the code.
+     * Start address of the code (i.e. {@code CodeBlob::code_begin()}).
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
 
     /**
-     * Size of the code.
+     * Size of the code (i.e. {@code CodeBlob::code_size()}).
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
 
@@ -52,7 +52,7 @@
     }
 
     /**
-     * @return the total size of this code blob
+     * Gets the value of {@code CodeBlob::size()}.
      */
     public int getSize() {
         return size;
@@ -61,22 +61,25 @@
     @Override
     public abstract String toString();
 
+    /**
+     * Gets the value of {@code CodeBlob::code_begin()} if {@linkplain #isValid() valid}, 0
+     * otherwise.
+     */
     @Override
     public long getStart() {
         return codeStart;
     }
 
+    /**
+     * Gets the value of {@code CodeBlob::code_size()} if {@linkplain #isValid() valid}, 0
+     * otherwise.
+     */
     public long getCodeSize() {
         return codeSize;
     }
 
     @Override
     public byte[] getCode() {
-        if (!isValid()) {
-            return null;
-        }
-        byte[] code = new byte[codeSize];
-        UNSAFE.copyMemory(null, codeStart, code, Unsafe.ARRAY_BYTE_BASE_OFFSET, codeSize);
-        return code;
+        return compilerToVM().getCode(this);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJDKReflection.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link HotSpotJVMCIReflection} in terms of standard JDK reflection API. This is
+ * only available when running in the HotSpot heap.
+ */
+final class HotSpotJDKReflection extends HotSpotJVMCIReflection {
+
+    @Override
+    Object resolveObject(HotSpotObjectConstantImpl object) {
+        if (object == null) {
+            return null;
+        }
+        return ((DirectHotSpotObjectConstantImpl) object).object;
+    }
+
+    @Override
+    boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj) {
+        Class<?> javaMirror = getMirror(holder);
+        Object value = resolveObject(obj);
+        return javaMirror.isInstance(value);
+    }
+
+    @Override
+    boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.isAssignableFrom(getMirror(otherType));
+
+    }
+
+    @Override
+    Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.getAnnotations();
+    }
+
+    @Override
+    Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.getDeclaredAnnotations();
+    }
+
+    @Override
+    <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.getAnnotation(annotationClass);
+    }
+
+    @Override
+    boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.isLocalClass();
+    }
+
+    @Override
+    boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return javaMirror.isMemberClass();
+    }
+
+    @Override
+    HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder) {
+        Class<?> javaMirror = getMirror(holder);
+        return (HotSpotResolvedObjectType) runtime().fromClass(javaMirror.getEnclosingClass());
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
+        Class<?> javaMirror = getMirror(holder);
+        return readFieldValue(field, javaMirror, isVolatile);
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
+        Object value = resolveObject(object);
+        return readFieldValue(field, value, isVolatile);
+    }
+
+    @Override
+    boolean equals(HotSpotObjectConstantImpl a, HotSpotObjectConstantImpl b) {
+        return resolveObject(a) == resolveObject(b) && a.isCompressed() == b.isCompressed();
+    }
+
+    @Override
+    JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType holder) {
+        return holder.mirror;
+    }
+
+    @Override
+    ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
+        java.lang.reflect.Parameter[] javaParameters = getMethod(javaMethod).getParameters();
+        ResolvedJavaMethod.Parameter[] res = new ResolvedJavaMethod.Parameter[javaParameters.length];
+        for (int i = 0; i < res.length; i++) {
+            java.lang.reflect.Parameter src = javaParameters[i];
+            String paramName = src.isNamePresent() ? src.getName() : null;
+            res[i] = new ResolvedJavaMethod.Parameter(paramName, src.getModifiers(), javaMethod, i);
+        }
+        return res;
+    }
+
+    @Override
+    Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getParameterAnnotations();
+    }
+
+    @Override
+    Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getGenericParameterTypes();
+    }
+
+    @Override
+    Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
+        return getField(javaField).getAnnotations();
+    }
+
+    @Override
+    Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getAnnotations();
+    }
+
+    @Override
+    Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethod(javaMethod).getDeclaredAnnotations();
+    }
+
+    @Override
+    Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
+        return getField(javaField).getDeclaredAnnotations();
+    }
+
+    @Override
+    <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass) {
+        return getMethod(javaMethod).getAnnotation(annotationClass);
+    }
+
+    @Override
+    <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass) {
+        return getField(javaField).getAnnotation(annotationClass);
+    }
+
+    @Override
+    HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
+        Object value = resolveObject(object);
+        Class<?> theClass = value.getClass();
+        return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(theClass);
+    }
+
+    @Override
+    String asString(HotSpotObjectConstantImpl object) {
+        Object value = resolveObject(object);
+        if (value instanceof String) {
+            return (String) value;
+        }
+        return null;
+    }
+
+    @Override
+    ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object) {
+        Object value = resolveObject(object);
+        if (value instanceof Class) {
+            Class<?> javaClass = (Class<?>) value;
+            return runtime().fromClass(javaClass);
+        }
+        if (value instanceof ResolvedJavaType) {
+            return (ResolvedJavaType) value;
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type) {
+        Object value = resolveObject(object);
+        if (type.isInstance(value)) {
+            return (T) value;
+        }
+        return null;
+    }
+
+    @Override
+    Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type) {
+        Object value = resolveObject(object);
+        if (getMirror(type).isInstance(value)) {
+            return value;
+        }
+        return null;
+    }
+
+    @Override
+    String formatString(HotSpotObjectConstantImpl object) {
+        return JavaKind.Object.format(resolveObject(object));
+    }
+
+    @Override
+    Integer getLength(HotSpotObjectConstantImpl arrayObject) {
+        Object object = resolveObject(arrayObject);
+        if (object.getClass().isArray()) {
+            return Array.getLength(object);
+        }
+        return null;
+    }
+
+    @Override
+    JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index) {
+        Object a = resolveObject(arrayObject);
+        if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) {
+            return null;
+        }
+        if (a instanceof Object[]) {
+            Object element = ((Object[]) a)[index];
+            return forObject(element);
+        } else {
+            if (a instanceof int[]) {
+                return JavaConstant.forInt(((int[]) a)[index]);
+            } else if (a instanceof char[]) {
+                return JavaConstant.forChar(((char[]) a)[index]);
+            } else if (a instanceof byte[]) {
+                return JavaConstant.forByte(((byte[]) a)[index]);
+            } else if (a instanceof long[]) {
+                return JavaConstant.forLong(((long[]) a)[index]);
+            } else if (a instanceof short[]) {
+                return JavaConstant.forShort(((short[]) a)[index]);
+            } else if (a instanceof float[]) {
+                return JavaConstant.forFloat(((float[]) a)[index]);
+            } else if (a instanceof double[]) {
+                return JavaConstant.forDouble(((double[]) a)[index]);
+            } else if (a instanceof boolean[]) {
+                return JavaConstant.forBoolean(((boolean[]) a)[index]);
+            } else {
+                throw new JVMCIError("Should not reach here");
+            }
+        }
+    }
+
+    @Override
+    JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source) {
+        return JavaConstant.forBoxedPrimitive(resolveObject(source));
+    }
+
+    @Override
+    JavaConstant forObject(Object value) {
+        if (value == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return forNonNullObject(value);
+    }
+
+    private static HotSpotObjectConstantImpl forNonNullObject(Object value) {
+        return DirectHotSpotObjectConstantImpl.forNonNullObject(value, false);
+    }
+
+    @Override
+    JavaConstant boxPrimitive(JavaConstant source) {
+        return forNonNullObject(source.asBoxedPrimitive());
+    }
+
+    @Override
+    int getInt(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getInt((resolveObject(object)), displacement);
+    }
+
+    @Override
+    byte getByte(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getByte(resolveObject(object), displacement);
+    }
+
+    @Override
+    short getShort(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getShort(resolveObject(object), displacement);
+    }
+
+    @Override
+    long getLong(HotSpotObjectConstantImpl object, long displacement) {
+        return UNSAFE.getLong(resolveObject(object), displacement);
+    }
+
+    @Override
+    void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
+        checkRead(kind, displacement, type, resolveObject(constant));
+    }
+
+    /**
+     * Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
+     * as initialization is idempotent.
+     */
+    private long oopSizeOffset;
+
+    private static int computeOopSizeOffset(HotSpotJVMCIRuntime runtime) {
+        MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
+        ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
+        for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
+            if (f.getName().equals("oop_size")) {
+                int offset = f.getOffset();
+                assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
+                return offset;
+            }
+        }
+        throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
+    }
+
+    long oopSizeOffset() {
+        if (oopSizeOffset == 0) {
+            oopSizeOffset = computeOopSizeOffset(runtime());
+        }
+        return oopSizeOffset;
+    }
+
+    private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object) {
+        if (type.isArray()) {
+            ResolvedJavaType componentType = type.getComponentType();
+            JavaKind componentKind = componentType.getJavaKind();
+            final int headerSize = runtime().getArrayBaseOffset(componentKind);
+            int sizeOfElement = runtime().getArrayIndexScale(componentKind);
+            int length = Array.getLength(object);
+            long arrayEnd = headerSize + (sizeOfElement * length);
+            boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
+            if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
+                int index = (int) ((displacement - headerSize) / sizeOfElement);
+                throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
+                                " at offset " + displacement + " (index ~ " + index + ") in " +
+                                type.toJavaName() + " object of length " + length);
+            }
+        } else if (kind != JavaKind.Object) {
+            long size;
+            if (object instanceof Class) {
+                int wordSize = runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
+                size = UNSAFE.getInt(object, oopSizeOffset()) * wordSize;
+            } else {
+                size = Math.abs(type.instanceSize());
+            }
+            int bytesToRead = kind.getByteCount();
+            if (displacement + bytesToRead > size || displacement < 0) {
+                throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
+                                type.toJavaName() + " object of size " + size);
+            }
+        } else {
+            ResolvedJavaField field = null;
+            if (object instanceof Class) {
+                // Read of a static field
+                HotSpotResolvedJavaType hotSpotResolvedJavaType = runtime().fromClass((Class<?>) object);
+                if (hotSpotResolvedJavaType instanceof HotSpotResolvedObjectTypeImpl) {
+                    HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) hotSpotResolvedJavaType;
+                    field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
+                }
+            }
+            if (field == null) {
+                field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
+            }
+            if (field == null) {
+                throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
+                                " at offset " + displacement + " in " + type.toJavaName() + " object");
+            }
+            if (field.getJavaKind() != JavaKind.Object) {
+                throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
+                                " at offset " + displacement + " in " + type.toJavaName() + " object");
+            }
+        }
+        return true;
+    }
+
+    JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj, boolean isVolatile) {
+        assert obj != null;
+        assert !field.isStatic() || obj instanceof Class;
+        long displacement = field.getOffset();
+
+        assert checkRead(field.getJavaKind(), displacement,
+                        (HotSpotResolvedObjectType) runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(field.isStatic() ? (Class<?>) obj : obj.getClass()),
+                        obj);
+        JavaKind kind = field.getJavaKind();
+        switch (kind) {
+            case Boolean:
+                return JavaConstant.forBoolean(isVolatile ? UNSAFE.getBooleanVolatile(obj, displacement) : UNSAFE.getBoolean(obj, displacement));
+            case Byte:
+                return JavaConstant.forByte(isVolatile ? UNSAFE.getByteVolatile(obj, displacement) : UNSAFE.getByte(obj, displacement));
+            case Char:
+                return JavaConstant.forChar(isVolatile ? UNSAFE.getCharVolatile(obj, displacement) : UNSAFE.getChar(obj, displacement));
+            case Short:
+                return JavaConstant.forShort(isVolatile ? UNSAFE.getShortVolatile(obj, displacement) : UNSAFE.getShort(obj, displacement));
+            case Int:
+                return JavaConstant.forInt(isVolatile ? UNSAFE.getIntVolatile(obj, displacement) : UNSAFE.getInt(obj, displacement));
+            case Long:
+                return JavaConstant.forLong(isVolatile ? UNSAFE.getLongVolatile(obj, displacement) : UNSAFE.getLong(obj, displacement));
+            case Float:
+                return JavaConstant.forFloat(isVolatile ? UNSAFE.getFloatVolatile(obj, displacement) : UNSAFE.getFloat(obj, displacement));
+            case Double:
+                return JavaConstant.forDouble(isVolatile ? UNSAFE.getDoubleVolatile(obj, displacement) : UNSAFE.getDouble(obj, displacement));
+            case Object:
+                return forObject(isVolatile ? UNSAFE.getReferenceVolatile(obj, displacement) : UNSAFE.getReference(obj, displacement));
+            default:
+                throw new IllegalArgumentException("Unsupported kind: " + kind);
+
+        }
+    }
+
+    /**
+     * Gets a {@link Method} object corresponding to {@code method}. This method guarantees the same
+     * {@link Method} object is returned if called twice on the same {@code method} value.
+     */
+    private static Executable getMethod(HotSpotResolvedJavaMethodImpl method) {
+        assert !method.isClassInitializer() : method;
+        if (method.toJavaCache == null) {
+            synchronized (method) {
+                if (method.toJavaCache == null) {
+                    method.toJavaCache = compilerToVM().asReflectionExecutable(method);
+                }
+            }
+        }
+        return method.toJavaCache;
+    }
+
+    /**
+     * Gets a {@link Field} object corresponding to {@code field}. This method guarantees the same
+     * {@link Field} object is returned if called twice on the same {@code field} value. This is
+     * required to ensure the results of {@link HotSpotResolvedJavaFieldImpl#getAnnotations()} and
+     * {@link HotSpotResolvedJavaFieldImpl#getAnnotation(Class)} are stable (i.e., for a given field
+     * {@code f} and annotation class {@code a}, the same object is returned for each call to
+     * {@code f.getAnnotation(a)}).
+     */
+    private static Field getField(HotSpotResolvedJavaFieldImpl field) {
+        HotSpotResolvedObjectTypeImpl declaringClass = field.getDeclaringClass();
+        synchronized (declaringClass) {
+            HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = declaringClass.reflectionFieldCache;
+            if (cache == null) {
+                cache = new HashMap<>();
+                declaringClass.reflectionFieldCache = cache;
+            }
+            Field reflect = cache.get(field);
+            if (reflect == null) {
+                reflect = compilerToVM().asReflectionField(field.getDeclaringClass(), field.getIndex());
+                cache.put(field, reflect);
+            }
+            return reflect;
+        }
+    }
+
+    Class<?> getMirror(HotSpotResolvedObjectTypeImpl holder) {
+        return (Class<?>) resolveObject((HotSpotObjectConstantImpl) holder.getJavaMirror());
+    }
+
+    Class<?> getMirror(HotSpotResolvedJavaType type) {
+        assert type != null;
+        if (type instanceof HotSpotResolvedPrimitiveType) {
+            return (Class<?>) resolveObject(((HotSpotResolvedPrimitiveType) type).mirror);
+        } else {
+            return getMirror((HotSpotResolvedObjectTypeImpl) type);
+        }
+    }
+}
+
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -22,10 +22,12 @@
  */
 package jdk.vm.ci.hotspot;
 
+import java.util.List;
 import java.util.Set;
 
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
 import jdk.vm.ci.runtime.JVMCICompiler;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
@@ -33,6 +35,8 @@
 import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.JVMCIServiceLocator;
 
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+
 final class HotSpotJVMCICompilerConfig {
 
     /**
@@ -61,7 +65,7 @@
     /**
      * Factory of the selected system compiler.
      */
-    private static JVMCICompilerFactory compilerFactory;
+    @NativeImageReinitialize private static JVMCICompilerFactory compilerFactory;
 
     /**
      * Gets the selected system compiler factory.
@@ -78,7 +82,7 @@
                 if (compilerName.isEmpty() || compilerName.equals("null")) {
                     factory = new DummyCompilerFactory();
                 } else {
-                    for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                    for (JVMCICompilerFactory f : getJVMCICompilerFactories()) {
                         if (f.getCompilerName().equals(compilerName)) {
                             factory = f;
                         }
@@ -89,7 +93,7 @@
                 }
             } else {
                 // Auto select a single available compiler
-                for (JVMCICompilerFactory f : JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class)) {
+                for (JVMCICompilerFactory f : getJVMCICompilerFactories()) {
                     if (factory == null) {
                         openJVMCITo(f.getClass().getModule());
                         factory = f;
@@ -113,15 +117,21 @@
      * Opens all JVMCI packages to {@code otherModule}.
      */
     private static void openJVMCITo(Module otherModule) {
-        Module jvmci = HotSpotJVMCICompilerConfig.class.getModule();
-        if (jvmci != otherModule) {
-            Set<String> packages = jvmci.getPackages();
-            for (String pkg : packages) {
-                boolean opened = jvmci.isOpen(pkg, otherModule);
-                if (!opened) {
-                    jvmci.addOpens(pkg, otherModule);
+        if (!IS_IN_NATIVE_IMAGE) {
+            Module jvmci = HotSpotJVMCICompilerConfig.class.getModule();
+            if (jvmci != otherModule) {
+                Set<String> packages = jvmci.getPackages();
+                for (String pkg : packages) {
+                    boolean opened = jvmci.isOpen(pkg, otherModule);
+                    if (!opened) {
+                        jvmci.addOpens(pkg, otherModule);
+                    }
                 }
             }
         }
     }
+
+    private static List<JVMCICompilerFactory> getJVMCICompilerFactories() {
+        return JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class);
+    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Wed May 01 12:41:26 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-package jdk.vm.ci.hotspot;
-
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.Iterator;
-
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.ResolvedJavaType;
-
-/**
- * This class manages the set of metadata roots that must be scanned during garbage collection.
- * Because of class redefinition Method* and ConstantPool* can be freed if they don't appear to be
- * in use so they must be tracked when there are live references to them from Java.
- *
- * The general theory of operation is that all {@link MetaspaceWrapperObject}s are created by
- * calling into the VM which calls back out to actually create the wrapper instance. During the call
- * the VM keeps the metadata reference alive through the use of metadata handles. Once the call
- * completes the wrapper object is registered here and will be scanned during metadata scanning. The
- * weakness of the reference to the wrapper object allows them to be reclaimed when they are no
- * longer used.
- *
- */
-class HotSpotJVMCIMetaAccessContext {
-
-    /**
-     * The set of currently live contexts used for tracking of live metadata. Examined from the VM
-     * during garbage collection.
-     */
-    private static WeakReference<?>[] allContexts = new WeakReference<?>[0];
-
-    /**
-     * This is a chunked list of metadata roots. It can be read from VM native code so it's been
-     * marked volatile to ensure the order of updates are respected.
-     */
-    private volatile Object[] metadataRoots;
-
-    private ChunkedList<WeakReference<MetaspaceWrapperObject>> list = new ChunkedList<>();
-
-    /**
-     * The number of weak references freed since the last time the list was shrunk.
-     */
-    private int freed;
-
-    /**
-     * The {@link ReferenceQueue} tracking the weak references created by this context.
-     */
-    private final ReferenceQueue<MetaspaceWrapperObject> queue = new ReferenceQueue<>();
-
-    static synchronized void add(HotSpotJVMCIMetaAccessContext context) {
-        for (int i = 0; i < allContexts.length; i++) {
-            if (allContexts[i] == null || allContexts[i].get() == null) {
-                allContexts[i] = new WeakReference<>(context);
-                return;
-            }
-        }
-        int index = allContexts.length;
-        allContexts = Arrays.copyOf(allContexts, index + 2);
-        allContexts[index] = new WeakReference<>(context);
-    }
-
-    HotSpotJVMCIMetaAccessContext() {
-        add(this);
-    }
-
-    /**
-     * Periodically trim the list of tracked metadata. A new list is created to replace the old to
-     * avoid concurrent scanning issues.
-     */
-    private void clean() {
-        Reference<?> ref = queue.poll();
-        if (ref == null) {
-            return;
-        }
-        while (ref != null) {
-            freed++;
-            ref = queue.poll();
-        }
-        if (freed > list.size() / 2) {
-            ChunkedList<WeakReference<MetaspaceWrapperObject>> newList = new ChunkedList<>();
-            for (WeakReference<MetaspaceWrapperObject> element : list) {
-                /*
-                 * The referent could become null anywhere in here but it doesn't matter. It will
-                 * get cleaned up next time.
-                 */
-                if (element != null && element.get() != null) {
-                    newList.add(element);
-                }
-            }
-            list = newList;
-            metadataRoots = list.getHead();
-            freed = 0;
-        }
-    }
-
-    /**
-     * Add a {@link MetaspaceWrapperObject} to tracked by the GC. It's assumed that the caller is
-     * responsible for keeping the reference alive for the duration of the call. Once registration
-     * is complete then the VM will ensure it's kept alive.
-     *
-     * @param metaspaceObject
-     */
-
-    public synchronized void add(MetaspaceWrapperObject metaspaceObject) {
-        clean();
-        list.add(new WeakReference<>(metaspaceObject, queue));
-        if (list.getHead() != metadataRoots) {
-            /*
-             * The list enlarged so update the head.
-             */
-            metadataRoots = list.getHead();
-        }
-        assert isRegistered(metaspaceObject);
-    }
-
-    protected ResolvedJavaType createClass(Class<?> javaClass) {
-        if (javaClass.isPrimitive()) {
-            JavaKind kind = JavaKind.fromJavaClass(javaClass);
-            return new HotSpotResolvedPrimitiveType(kind);
-        } else {
-            return new HotSpotResolvedObjectTypeImpl(javaClass, this);
-        }
-    }
-
-    private final ClassValue<WeakReference<ResolvedJavaType>> resolvedJavaType = new ClassValue<>() {
-        @Override
-        protected WeakReference<ResolvedJavaType> computeValue(Class<?> type) {
-            return new WeakReference<>(createClass(type));
-        }
-    };
-
-    /**
-     * Gets the JVMCI mirror for a {@link Class} object.
-     *
-     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
-     */
-    public ResolvedJavaType fromClass(Class<?> javaClass) {
-        ResolvedJavaType javaType = null;
-        while (javaType == null) {
-            WeakReference<ResolvedJavaType> type = resolvedJavaType.get(javaClass);
-            javaType = type.get();
-            if (javaType == null) {
-                /*
-                 * If the referent has become null, clear out the current value and let computeValue
-                 * above create a new value. Reload the value in a loop because in theory the
-                 * WeakReference referent can be reclaimed at any point.
-                 */
-                resolvedJavaType.remove(javaClass);
-            }
-        }
-        return javaType;
-    }
-
-    /**
-     * A very simple append only chunked list implementation.
-     */
-    static class ChunkedList<T> implements Iterable<T> {
-        private static final int CHUNK_SIZE = 32;
-
-        private static final int NEXT_CHUNK_INDEX = CHUNK_SIZE - 1;
-
-        private Object[] head;
-        private int index;
-        private int size;
-
-        ChunkedList() {
-            head = new Object[CHUNK_SIZE];
-            index = 0;
-        }
-
-        void add(T element) {
-            if (index == NEXT_CHUNK_INDEX) {
-                Object[] newHead = new Object[CHUNK_SIZE];
-                newHead[index] = head;
-                head = newHead;
-                index = 0;
-            }
-            head[index++] = element;
-            size++;
-        }
-
-        Object[] getHead() {
-            return head;
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return new ChunkIterator<>();
-        }
-
-        int size() {
-            return size;
-        }
-
-        class ChunkIterator<V> implements Iterator<V> {
-
-            ChunkIterator() {
-                currentChunk = head;
-                currentIndex = -1;
-                next = findNext();
-            }
-
-            Object[] currentChunk;
-            int currentIndex;
-            V next;
-
-            @SuppressWarnings("unchecked")
-            V findNext() {
-                V result;
-                do {
-                    currentIndex++;
-                    if (currentIndex == NEXT_CHUNK_INDEX) {
-                        currentChunk = (Object[]) currentChunk[currentIndex];
-                        currentIndex = 0;
-                        if (currentChunk == null) {
-                            return null;
-                        }
-                    }
-                    result = (V) currentChunk[currentIndex];
-                } while (result == null);
-                return result;
-            }
-
-            @Override
-            public boolean hasNext() {
-                return next != null;
-            }
-
-            @Override
-            public V next() {
-                V result = next;
-                next = findNext();
-                return result;
-            }
-
-        }
-
-    }
-
-    synchronized boolean isRegistered(MetaspaceWrapperObject wrapper) {
-        for (WeakReference<MetaspaceWrapperObject> m : list) {
-            if (m != null && m.get() == wrapper) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Reflection interface for reflecting on the internals of HotSpot JVMCI types and objects.
+ */
+abstract class HotSpotJVMCIReflection {
+
+    abstract boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj);
+
+    abstract boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType);
+
+    abstract Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass);
+
+    abstract boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder);
+
+    abstract JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    abstract JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile);
+
+    abstract boolean equals(HotSpotObjectConstantImpl hotSpotResolvedJavaType, HotSpotObjectConstantImpl that);
+
+    abstract JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedJavaType);
+
+    abstract ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaMethod);
+
+    abstract Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaField);
+
+    abstract Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod);
+
+    abstract Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaMethod);
+
+    abstract <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass);
+
+    abstract HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object);
+
+    abstract String asString(HotSpotObjectConstantImpl object);
+
+    /**
+     * Given a {@link java.lang.Class} instance, return the corresponding ResolvedJavaType.
+     */
+    abstract ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object);
+
+    abstract <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type);
+
+    abstract Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type);
+
+    abstract String formatString(HotSpotObjectConstantImpl object);
+
+    abstract Integer getLength(HotSpotObjectConstantImpl arrayObject);
+
+    abstract JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index);
+
+    abstract JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source);
+
+    abstract JavaConstant forObject(Object value);
+
+    abstract JavaConstant boxPrimitive(JavaConstant source);
+
+    abstract int getInt(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract byte getByte(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract short getShort(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract long getLong(HotSpotObjectConstantImpl object, long displacement);
+
+    abstract void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type);
+
+    abstract <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass);
+
+    /**
+     * Resolves {@code objectHandle} to a raw object if possible.
+     *
+     * @throws HotSpotJVMCIUnsupportedOperationError if {@code objectHandle} refers to an object in
+     *             another heap
+     */
+    abstract Object resolveObject(HotSpotObjectConstantImpl objectHandle);
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Wed May 01 12:31:29 2019 -0700
@@ -23,11 +23,22 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.common.InitTimer.timer;
+import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
 
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.io.Serializable;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
 import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.ref.WeakReference;
+
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -35,11 +46,11 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.ServiceLoader;
-import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.Predicate;
 
-import jdk.internal.misc.VM;
 import jdk.internal.misc.Unsafe;
+
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.CompilationRequestResult;
 import jdk.vm.ci.code.CompiledCode;
@@ -57,44 +68,144 @@
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.runtime.JVMCIRuntime;
 import jdk.vm.ci.services.JVMCIServiceLocator;
-
-import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None;
+import jdk.vm.ci.services.Services;
 
 /**
  * HotSpot implementation of a JVMCI runtime.
- *
- * The initialization of this class is very fragile since it's initialized both through
- * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
- * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
- * can't have a static initializer and any required initialization must be done as part of
- * {@link #runtime()}. This allows the initialization to funnel back through
- * {@link JVMCI#initialize()} without deadlocking.
  */
 public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
 
-    @SuppressWarnings("try")
-    static class DelayedInit {
-        private static final HotSpotJVMCIRuntime instance;
+    /**
+     * Singleton instance lazily initialized via double-checked locking.
+     */
+    @NativeImageReinitialize private static volatile HotSpotJVMCIRuntime instance;
+
+    private HotSpotResolvedObjectTypeImpl javaLangObject;
+    private HotSpotResolvedObjectTypeImpl javaLangInvokeMethodHandle;
+    private HotSpotResolvedObjectTypeImpl constantCallSiteType;
+    private HotSpotResolvedObjectTypeImpl callSiteType;
+    private HotSpotResolvedObjectTypeImpl javaLangString;
+    private HotSpotResolvedObjectTypeImpl javaLangClass;
+    private HotSpotResolvedObjectTypeImpl throwableType;
+    private HotSpotResolvedObjectTypeImpl serializableType;
+    private HotSpotResolvedObjectTypeImpl cloneableType;
+    private HotSpotResolvedObjectTypeImpl enumType;
 
-        static {
-            try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
-                instance = new HotSpotJVMCIRuntime();
+    HotSpotResolvedObjectTypeImpl getJavaLangObject() {
+        if (javaLangObject == null) {
+            javaLangObject = (HotSpotResolvedObjectTypeImpl) fromClass(Object.class);
+        }
+        return javaLangObject;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangString() {
+        if (javaLangString == null) {
+            javaLangString = (HotSpotResolvedObjectTypeImpl) fromClass(String.class);
+        }
+        return javaLangString;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangClass() {
+        if (javaLangClass == null) {
+            javaLangClass = (HotSpotResolvedObjectTypeImpl) fromClass(Class.class);
+        }
+        return javaLangClass;
+    }
 
-                // Can only do eager initialization of the JVMCI compiler
-                // once the singleton instance is available.
-                if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
-                    instance.getCompiler();
-                }
-            }
+    HotSpotResolvedObjectTypeImpl getJavaLangCloneable() {
+        if (cloneableType == null) {
+            cloneableType = (HotSpotResolvedObjectTypeImpl) fromClass(Cloneable.class);
+        }
+        return cloneableType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangSerializable() {
+        if (serializableType == null) {
+            serializableType = (HotSpotResolvedObjectTypeImpl) fromClass(Serializable.class);
+        }
+        return serializableType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangThrowable() {
+        if (throwableType == null) {
+            throwableType = (HotSpotResolvedObjectTypeImpl) fromClass(Throwable.class);
         }
+        return throwableType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getJavaLangEnum() {
+        if (enumType == null) {
+            enumType = (HotSpotResolvedObjectTypeImpl) fromClass(Enum.class);
+        }
+        return enumType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getConstantCallSite() {
+        if (constantCallSiteType == null) {
+            constantCallSiteType = (HotSpotResolvedObjectTypeImpl) fromClass(ConstantCallSite.class);
+        }
+        return constantCallSiteType;
+    }
+
+    HotSpotResolvedObjectTypeImpl getCallSite() {
+        if (callSiteType == null) {
+            callSiteType = (HotSpotResolvedObjectTypeImpl) fromClass(CallSite.class);
+        }
+        return callSiteType;
+    }
+
+    HotSpotResolvedObjectType getMethodHandleClass() {
+        if (javaLangInvokeMethodHandle == null) {
+            javaLangInvokeMethodHandle = (HotSpotResolvedObjectTypeImpl) fromClass(MethodHandle.class);
+        }
+        return javaLangInvokeMethodHandle;
     }
 
     /**
      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
      */
+    @VMEntryPoint
+    @SuppressWarnings("try")
     public static HotSpotJVMCIRuntime runtime() {
-        JVMCI.initialize();
-        return DelayedInit.instance;
+        HotSpotJVMCIRuntime result = instance;
+        if (result == null) {
+            // Synchronize on JVMCI.class to avoid deadlock
+            // between the two JVMCI initialization paths:
+            // HotSpotJVMCIRuntime.runtime() and JVMCI.getRuntime().
+            synchronized (JVMCI.class) {
+                result = instance;
+                if (result == null) {
+                    try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
+                        instance = result = new HotSpotJVMCIRuntime();
+
+                        // Can only do eager initialization of the JVMCI compiler
+                        // once the singleton instance is available.
+                        if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
+                            instance.getCompiler();
+                        }
+                    }
+                    // Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
+                    // initialized.
+                    JVMCI.getRuntime();
+                }
+            }
+        }
+        return result;
+    }
+
+    @VMEntryPoint
+    static Throwable decodeThrowable(String encodedThrowable) throws Throwable {
+        return TranslatedException.decodeThrowable(encodedThrowable);
+    }
+
+    @VMEntryPoint
+    static String encodeThrowable(Throwable throwable) throws Throwable {
+        return TranslatedException.encodeThrowable(throwable);
+    }
+
+    @VMEntryPoint
+    static String callToString(Object o) {
+        return o.toString();
     }
 
     /**
@@ -103,17 +214,17 @@
     public enum Option {
         // @formatter:off
         Compiler(String.class, null, "Selects the system compiler. This must match the getCompilerName() value returned " +
-                                     "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
-                                     "An empty string or the value \"null\" selects a compiler " +
-                                     "that will raise an exception upon receiving a compilation request."),
+                "by a jdk.vm.ci.runtime.JVMCICompilerFactory provider. " +
+                "An empty string or the value \"null\" selects a compiler " +
+                "that will raise an exception upon receiving a compilation request."),
         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
         // so that -XX:+JVMCIPrintProperties shows the option.
         InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
         PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
         TraceMethodDataFilter(String.class, null,
-                        "Enables tracing of profiling info when read by JVMCI.",
-                        "Empty value: trace all methods",
-                        "Non-empty value: trace methods whose fully qualified name contains the value."),
+                "Enables tracing of profiling info when read by JVMCI.",
+                "Empty value: trace all methods",
+                "Non-empty value: trace methods whose fully qualified name contains the value."),
         UseProfilingInformation(Boolean.class, true, "");
         // @formatter:on
 
@@ -123,12 +234,12 @@
         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
 
         /**
-         * Marker for uninitialized flags.
+         * Sentinel for value initialized to {@code null} since {@code null} means uninitialized.
          */
-        private static final String UNINITIALIZED = "UNINITIALIZED";
+        private static final String NULL_VALUE = "NULL";
 
         private final Class<?> type;
-        private Object value;
+        @NativeImageReinitialize private Object value;
         private final Object defaultValue;
         private boolean isDefault;
         private final String[] helpLines;
@@ -136,17 +247,16 @@
         Option(Class<?> type, Object defaultValue, String... helpLines) {
             assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name();
             this.type = type;
-            this.value = UNINITIALIZED;
             this.defaultValue = defaultValue;
             this.helpLines = helpLines;
         }
 
         @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
         private Object getValue() {
-            if (value == UNINITIALIZED) {
-                String propertyValue = VM.getSavedProperty(getPropertyName());
+            if (value == null) {
+                String propertyValue = Services.getSavedProperty(getPropertyName());
                 if (propertyValue == null) {
-                    this.value = defaultValue;
+                    this.value = defaultValue == null ? NULL_VALUE : defaultValue;
                     this.isDefault = true;
                 } else {
                     if (type == Boolean.class) {
@@ -158,10 +268,8 @@
                     }
                     this.isDefault = false;
                 }
-                // Saved properties should not be interned - let's be sure
-                assert value != UNINITIALIZED;
             }
-            return value;
+            return value == NULL_VALUE ? null : value;
         }
 
         /**
@@ -224,8 +332,10 @@
         }
     }
 
-    static HotSpotJVMCIBackendFactory findFactory(String architecture) {
-        for (HotSpotJVMCIBackendFactory factory : ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader())) {
+    private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
+        Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
+assert factories != null : "sanity";
+        for (HotSpotJVMCIBackendFactory factory : factories) {
             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
                 return factory;
             }
@@ -234,6 +344,23 @@
         throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
     }
 
+    private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
+
+    @SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
+    private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
+        if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
+            return cachedHotSpotJVMCIBackendFactories;
+        }
+        Iterable<HotSpotJVMCIBackendFactory> result = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader());
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            cachedHotSpotJVMCIBackendFactories = new ArrayList<>();
+            for (HotSpotJVMCIBackendFactory factory : result) {
+                cachedHotSpotJVMCIBackendFactories.add(factory);
+            }
+        }
+        return result;
+    }
+
     /**
      * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
      */
@@ -241,22 +368,32 @@
         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
     }
 
-    final CompilerToVM compilerToVm;
+    protected final CompilerToVM compilerToVm;
 
     protected final HotSpotVMConfigStore configStore;
-    private final HotSpotVMConfig config;
+    protected final HotSpotVMConfig config;
     private final JVMCIBackend hostBackend;
 
     private final JVMCICompilerFactory compilerFactory;
     private final HotSpotJVMCICompilerFactory hsCompilerFactory;
     private volatile JVMCICompiler compiler;
-    final HotSpotJVMCIMetaAccessContext metaAccessContext;
+    protected final HotSpotJVMCIReflection reflection;
+
+    @NativeImageReinitialize private volatile boolean creatingCompiler;
+
+    /**
+     * Cache for speeding up {@link #fromClass(Class)}.
+     */
+    @NativeImageReinitialize private volatile ClassValue<WeakReference<HotSpotResolvedJavaType>> resolvedJavaType;
+
+    @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes;
 
     /**
      * Stores the value set by {@link #excludeFromJVMCICompilation(Module...)} so that it can
      * be read from the VM.
      */
-    @SuppressWarnings("unused") @NativeImageReinitialize private Module[] excludeFromJVMCICompilation;
+    @SuppressWarnings("unused")//
+    @NativeImageReinitialize private Module[] excludeFromJVMCICompilation;
 
 
     private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
@@ -283,6 +420,16 @@
             config = new HotSpotVMConfig(configStore);
         }
 
+        reflection = IS_IN_NATIVE_IMAGE ? new SharedLibraryJVMCIReflection() : new HotSpotJDKReflection();
+
+        PrintStream vmLogStream = null;
+        if (IS_IN_NATIVE_IMAGE) {
+            // Redirect System.out and System.err to HotSpot's TTY stream
+            vmLogStream = new PrintStream(getLogStream());
+            System.setOut(vmLogStream);
+            System.setErr(vmLogStream);
+        }
+
         String hostArchitecture = config.getHostArchitectureName();
 
         HotSpotJVMCIBackendFactory factory;
@@ -294,8 +441,6 @@
             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
         }
 
-        metaAccessContext = new HotSpotJVMCIMetaAccessContext();
-
         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
@@ -310,15 +455,89 @@
         }
 
         if (config.getFlag("JVMCIPrintProperties", Boolean.class)) {
-            PrintStream out = new PrintStream(getLogStream());
-            Option.printProperties(out);
-            compilerFactory.printProperties(out);
+            if (vmLogStream == null) {
+                vmLogStream = new PrintStream(getLogStream());
+            }
+            Option.printProperties(vmLogStream);
+            compilerFactory.printProperties(vmLogStream);
             System.exit(0);
         }
 
         if (Option.PrintConfig.getBoolean()) {
-            configStore.printConfig();
+            printConfig(configStore, compilerToVm);
+        }
+    }
+
+    HotSpotResolvedJavaType createClass(Class<?> javaClass) {
+        if (javaClass.isPrimitive()) {
+            return HotSpotResolvedPrimitiveType.forKind(JavaKind.fromJavaClass(javaClass));
+        }
+        if (IS_IN_NATIVE_IMAGE) {
+            try {
+                return compilerToVm.lookupType(javaClass.getName().replace('.', '/'), null, true);
+            } catch (ClassNotFoundException e) {
+                throw new JVMCIError(e);
+            }
+        }
+        return compilerToVm.lookupClass(javaClass);
+    }
+
+    private HotSpotResolvedJavaType fromClass0(Class<?> javaClass) {
+        if (resolvedJavaType == null) {
+            synchronized (this) {
+                if (resolvedJavaType == null) {
+                    resolvedJavaType = new ClassValue<WeakReference<HotSpotResolvedJavaType>>() {
+                        @Override
+                        protected WeakReference<HotSpotResolvedJavaType> computeValue(Class<?> type) {
+                            return new WeakReference<>(createClass(type));
+                        }
+                    };
+                }
+            }
         }
+        HotSpotResolvedJavaType javaType = null;
+        while (javaType == null) {
+            WeakReference<HotSpotResolvedJavaType> type = resolvedJavaType.get(javaClass);
+            javaType = type.get();
+            if (javaType == null) {
+                /*
+                 * If the referent has become null, clear out the current value and let computeValue
+                 * above create a new value. Reload the value in a loop because in theory the
+                 * WeakReference referent can be reclaimed at any point.
+                 */
+                resolvedJavaType.remove(javaClass);
+            }
+        }
+        return javaType;
+    }
+
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
+     */
+    HotSpotResolvedJavaType fromClass(Class<?> javaClass) {
+        if (javaClass == null) {
+            return null;
+        }
+        return fromClass0(javaClass);
+    }
+
+    synchronized HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer, String signature) {
+        if (resolvedJavaTypes == null) {
+            resolvedJavaTypes = new HashMap<>();
+        }
+        assert klassPointer != 0;
+        WeakReference<ResolvedJavaType> klassReference = resolvedJavaTypes.get(klassPointer);
+        HotSpotResolvedObjectTypeImpl javaType = null;
+        if (klassReference != null) {
+            javaType = (HotSpotResolvedObjectTypeImpl) klassReference.get();
+        }
+        if (javaType == null) {
+            javaType = new HotSpotResolvedObjectTypeImpl(klassPointer, signature);
+            resolvedJavaTypes.put(klassPointer, new WeakReference<>(javaType));
+        }
+        return javaType;
     }
 
     private JVMCIBackend registerBackend(JVMCIBackend backend) {
@@ -328,24 +547,21 @@
         return backend;
     }
 
-    ResolvedJavaType fromClass(Class<?> javaClass) {
-        return metaAccessContext.fromClass(javaClass);
-    }
-
     public HotSpotVMConfigStore getConfigStore() {
         return configStore;
     }
 
-    HotSpotVMConfig getConfig() {
+    public HotSpotVMConfig getConfig() {
         return config;
     }
 
-    CompilerToVM getCompilerToVM() {
+    public CompilerToVM getCompilerToVM() {
         return compilerToVm;
     }
 
-    // Non-volatile since multi-initialization is harmless
-    private Predicate<ResolvedJavaType> intrinsificationTrustPredicate;
+    HotSpotJVMCIReflection getReflection() {
+        return reflection;
+    }
 
     /**
      * Gets a predicate that determines if a given type can be considered trusted for the purpose of
@@ -355,47 +571,17 @@
      *            compiler.
      */
     public Predicate<ResolvedJavaType> getIntrinsificationTrustPredicate(Class<?>... compilerLeafClasses) {
-        if (intrinsificationTrustPredicate == null) {
-            intrinsificationTrustPredicate = new Predicate<>() {
-                @Override
-                public boolean test(ResolvedJavaType type) {
-                    if (type instanceof HotSpotResolvedJavaType) {
-                        Class<?> mirror = getMirror(type);
-                        Module module = mirror.getModule();
-                        return getTrustedModules().contains(module);
-                    } else {
-                        return false;
-                    }
+        return new Predicate<ResolvedJavaType>() {
+            @Override
+            public boolean test(ResolvedJavaType type) {
+                if (type instanceof HotSpotResolvedObjectTypeImpl) {
+                    HotSpotResolvedObjectTypeImpl hsType = (HotSpotResolvedObjectTypeImpl) type;
+                    return compilerToVm.isTrustedForIntrinsics(hsType);
+                } else {
+                    return false;
                 }
-
-                private volatile Set<Module> trustedModules;
-
-                private Set<Module> getTrustedModules() {
-                    Set<Module> modules = trustedModules;
-                    if (modules == null) {
-                        modules = new HashSet<>();
-                        for (Class<?> compilerConfiguration : compilerLeafClasses) {
-                            Module compilerConfigurationModule = compilerConfiguration.getModule();
-                            if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
-                                throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
-                                                compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
-                            }
-                            modules.add(compilerConfigurationModule);
-                            for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
-                                for (Module module : compilerConfigurationModule.getLayer().modules()) {
-                                    if (module.getName().equals(require.name())) {
-                                        modules.add(module);
-                                    }
-                                }
-                            }
-                        }
-                        trustedModules = modules;
-                    }
-                    return modules;
-                }
-            };
-        }
-        return intrinsificationTrustPredicate;
+            }
+        };
     }
 
     /**
@@ -406,9 +592,11 @@
      *         does not support mapping {@link ResolvedJavaType} instances to {@link Class}
      *         instances
      */
-    @SuppressWarnings("static-method")
     public Class<?> getMirror(ResolvedJavaType type) {
-        return ((HotSpotResolvedJavaType) type).mirror();
+        if (type instanceof HotSpotResolvedJavaType && reflection instanceof HotSpotJDKReflection) {
+            return ((HotSpotJDKReflection) reflection).getMirror((HotSpotResolvedJavaType) type);
+        }
+        return null;
     }
 
     @Override
@@ -416,7 +604,10 @@
         if (compiler == null) {
             synchronized (this) {
                 if (compiler == null) {
+                    assert !creatingCompiler : "recursive compiler creation";
+                    creatingCompiler = true;
                     compiler = compilerFactory.createCompiler(this);
+                    creatingCompiler = false;
                 }
             }
         }
@@ -438,19 +629,23 @@
      */
     public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
         Objects.requireNonNull(accessingType, "cannot resolve type without an accessing class");
+        return lookupTypeInternal(name, accessingType, resolve);
+    }
+
+    JavaType lookupTypeInternal(String name, HotSpotResolvedObjectType accessingType, boolean resolve) {
         // If the name represents a primitive type we can short-circuit the lookup.
         if (name.length() == 1) {
             JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
-            return fromClass(kind.toJavaClass());
+            return HotSpotResolvedPrimitiveType.forKind(kind);
         }
 
         // Resolve non-primitive types in the VM.
         HotSpotResolvedObjectTypeImpl hsAccessingType = (HotSpotResolvedObjectTypeImpl) accessingType;
         try {
-            final HotSpotResolvedObjectTypeImpl klass = compilerToVm.lookupType(name, hsAccessingType.mirror(), resolve);
+            final HotSpotResolvedJavaType klass = compilerToVm.lookupType(name, hsAccessingType, resolve);
 
             if (klass == null) {
-                assert resolve == false;
+                assert resolve == false : name;
                 return UnresolvedJavaType.create(name);
             }
             return klass;
@@ -474,12 +669,9 @@
         return Collections.unmodifiableMap(backends);
     }
 
-    /**
-     * Called from the VM.
-     */
-    @SuppressWarnings({"unused"})
-    private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
-        CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
+    @VMEntryPoint
+    private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
+        CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, compileState, id));
         assert result != null : "compileMethod must always return something";
         HotSpotCompilationRequestResult hsResult;
         if (result instanceof HotSpotCompilationRequestResult) {
@@ -500,11 +692,13 @@
 
     /**
      * Shuts down the runtime.
-     *
-     * Called from the VM.
      */
-    @SuppressWarnings({"unused"})
+    @VMEntryPoint
     private void shutdown() throws Exception {
+        // Cleaners are normally only processed when a new Cleaner is
+        // instantiated so process all remaining cleaners now.
+        Cleaner.clean();
+
         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
             vmEventListener.notifyShutdown();
         }
@@ -512,10 +706,8 @@
 
     /**
      * Notify on completion of a bootstrap.
-     *
-     * Called from the VM.
      */
-    @SuppressWarnings({"unused"})
+    @VMEntryPoint
     private void bootstrapFinished() throws Exception {
         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
             vmEventListener.notifyBootstrapFinished();
@@ -535,6 +727,41 @@
         }
     }
 
+    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
+    private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
+        String line = String.format(format, args);
+        byte[] lineBytes = line.getBytes();
+        vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
+        vm.flushDebugOutput();
+    }
+
+    private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
+        TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
+        for (VMField field : fields.values()) {
+            if (!field.isStatic()) {
+                printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
+            } else {
+                String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value);
+                printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
+            }
+        }
+        TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
+        for (VMFlag flag : flags.values()) {
+            printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
+        }
+        TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
+        for (Map.Entry<String, Long> e : addresses.entrySet()) {
+            printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
+        for (Map.Entry<String, Long> e : constants.entrySet()) {
+            printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        for (VMIntrinsicMethod e : store.getIntrinsics()) {
+            printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
+        }
+    }
+
     /**
      * Gets an output stream that writes to HotSpot's {@code tty} stream.
      */
@@ -577,27 +804,26 @@
      *
      * @return the offset in bytes
      */
-    @SuppressWarnings("static-method")
     public int getArrayBaseOffset(JavaKind kind) {
         switch (kind) {
             case Boolean:
-                return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
+                return compilerToVm.ARRAY_BOOLEAN_BASE_OFFSET;
             case Byte:
-                return Unsafe.ARRAY_BYTE_BASE_OFFSET;
+                return compilerToVm.ARRAY_BYTE_BASE_OFFSET;
             case Char:
-                return Unsafe.ARRAY_CHAR_BASE_OFFSET;
+                return compilerToVm.ARRAY_CHAR_BASE_OFFSET;
             case Short:
-                return Unsafe.ARRAY_SHORT_BASE_OFFSET;
+                return compilerToVm.ARRAY_SHORT_BASE_OFFSET;
             case Int:
-                return Unsafe.ARRAY_INT_BASE_OFFSET;
+                return compilerToVm.ARRAY_INT_BASE_OFFSET;
             case Long:
-                return Unsafe.ARRAY_LONG_BASE_OFFSET;
+                return compilerToVm.ARRAY_LONG_BASE_OFFSET;
             case Float:
-                return Unsafe.ARRAY_FLOAT_BASE_OFFSET;
+                return compilerToVm.ARRAY_FLOAT_BASE_OFFSET;
             case Double:
-                return Unsafe.ARRAY_DOUBLE_BASE_OFFSET;
+                return compilerToVm.ARRAY_DOUBLE_BASE_OFFSET;
             case Object:
-                return Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+                return compilerToVm.ARRAY_OBJECT_BASE_OFFSET;
             default:
                 throw new JVMCIError("%s", kind);
         }
@@ -609,27 +835,26 @@
      *
      * @return the scale in order to convert the index into a byte offset
      */
-    @SuppressWarnings("static-method")
     public int getArrayIndexScale(JavaKind kind) {
         switch (kind) {
             case Boolean:
-                return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
+                return compilerToVm.ARRAY_BOOLEAN_INDEX_SCALE;
             case Byte:
-                return Unsafe.ARRAY_BYTE_INDEX_SCALE;
+                return compilerToVm.ARRAY_BYTE_INDEX_SCALE;
             case Char:
-                return Unsafe.ARRAY_CHAR_INDEX_SCALE;
+                return compilerToVm.ARRAY_CHAR_INDEX_SCALE;
             case Short:
-                return Unsafe.ARRAY_SHORT_INDEX_SCALE;
+                return compilerToVm.ARRAY_SHORT_INDEX_SCALE;
             case Int:
-                return Unsafe.ARRAY_INT_INDEX_SCALE;
+                return compilerToVm.ARRAY_INT_INDEX_SCALE;
             case Long:
-                return Unsafe.ARRAY_LONG_INDEX_SCALE;
+                return compilerToVm.ARRAY_LONG_INDEX_SCALE;
             case Float:
-                return Unsafe.ARRAY_FLOAT_INDEX_SCALE;
+                return compilerToVm.ARRAY_FLOAT_INDEX_SCALE;
             case Double:
-                return Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
+                return compilerToVm.ARRAY_DOUBLE_INDEX_SCALE;
             case Object:
-                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+                return compilerToVm.ARRAY_OBJECT_INDEX_SCALE;
             default:
                 throw new JVMCIError("%s", kind);
 
@@ -637,10 +862,10 @@
     }
 
     /**
-     * Links each native method in {@code clazz} to an implementation in the JVMCI SVM library.
+     * Links each native method in {@code clazz} to an implementation in the JVMCI shared library.
      * <p>
      * A use case for this is a JVMCI compiler implementation that offers an API to Java code
-     * executing in HotSpot to exercise functionality (mostly) in the JVMCI SVM library. For
+     * executing in HotSpot to exercise functionality (mostly) in the JVMCI shared library. For
      * example:
      *
      * <pre>
@@ -665,28 +890,73 @@
      * }
      * </pre>
      *
-     * The implementation of the native {@code JCompile.compile0} method would be in the SVM library
-     * that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0} implementation
-     * will be exported as the following JNI-compliant symbol:
+     * The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
+     * shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0}
+     * implementation will be exported as the following JNI-compatible symbol:
      *
      * <pre>
      * Java_com_jcompile_JCompile_compile0
      * </pre>
      *
-     * How the JVMCI compiler SVM library is built is outside the scope of this document.
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names"
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#creating_the_vm"
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
      *
-     * @see "https://docs.oracle.com/javase/10/docs/specs/jni/design.html#resolving-native-method-names"
      *
+     * @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
+     *         the Java VM in the JVMCI shared library, and the remaining values are the first 3
+     *         pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
      * @throws NullPointerException if {@code clazz == null}
-     * @throws IllegalArgumentException if the current execution context is SVM or if {@code clazz}
-     *             is {@link Class#isPrimitive()}
-     * @throws UnsatisfiedLinkError if the JVMCI SVM library is not available, a native method in
-     *             {@code clazz} is already linked or the SVM JVMCI library does not contain a
-     *             JNI-compliant symbol for a native method in {@code clazz}
+     * @throws IllegalArgumentException if the current execution context is the JVMCI shared library
+     *             or if {@code clazz} is {@link Class#isPrimitive()}
+     * @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in
+     *             {@code clazz} is already linked or the JVMCI shared library does not contain a
+     *             JNI-compatible symbol for a native method in {@code clazz}
      */
-    @SuppressWarnings({"static-method", "unused"})
-    public void registerNativeMethods(Class<?> clazz) {
-        throw new UnsatisfiedLinkError("SVM library is not available");
+    public long[] registerNativeMethods(Class<?> clazz) {
+        return compilerToVm.registerNativeMethods(clazz);
+    }
+
+    /**
+     * Creates or retrieves an object in the peer runtime that mirrors {@code obj}. The types whose
+     * objects can be translated are:
+     * <ul>
+     * <li>{@link HotSpotResolvedJavaMethodImpl},</li>
+     * <li>{@link HotSpotResolvedObjectTypeImpl},</li>
+     * <li>{@link HotSpotResolvedPrimitiveType},</li>
+     * <li>{@link IndirectHotSpotObjectConstantImpl},</li>
+     * <li>{@link DirectHotSpotObjectConstantImpl} and</li>
+     * <li>{@link HotSpotNmethod}</li>
+     * </ul>
+     *
+     * This mechanism can be used to pass and return values between the HotSpot and JVMCI shared
+     * library runtimes. In the receiving runtime, the value can be converted back to an object with
+     * {@link #unhand(Class, long)}.
+     *
+     * @param obj an object for which an equivalent instance in the peer runtime is requested
+     * @return a JNI global reference to the mirror of {@code obj} in the peer runtime
+     * @throws IllegalArgumentException if {@code obj} is not of a translatable type
+     *
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
+     */
+    public long translate(Object obj) {
+        return compilerToVm.translate(obj);
+    }
+
+    /**
+     * Dereferences and returns the object referred to by the JNI global reference {@code handle}.
+     * The global reference is deleted prior to returning. Any further use of {@code handle} is
+     * invalid.
+     *
+     * @param handle a JNI global reference to an object in the current runtime
+     * @return the object referred to by {@code handle}
+     * @throws ClassCastException if the returned object cannot be case to {@code type}
+     *
+     * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
+     *
+     */
+    public <T> T unhand(Class<T> type, long handle) {
+        return type.cast(compilerToVm.unhand(handle));
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIUnsupportedOperationError.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.services.Services;
+
+/**
+ * Indicates a path in HotSpot JVMCI related code that is unsupported in the current execution
+ * environment. For example, certain operations are not supported by JVMCI code running in an ahead
+ * of time compiled {@linkplain Services#IS_IN_NATIVE_IMAGE native image}. This usually reflects
+ * functionality only needed in non-native image execution that would require a more complex
+ * implementation to support in a native image.
+ *
+ * An example of such functionality is {@link ResolvedJavaType#isLocal()}. This can be conveniently
+ * implemented when JVMCI is running on the HotSpot heap as we can obtain the {@link Class} mirror
+ * for the {@link ResolvedJavaType} and call {@link Class#isLocalClass()}. In a native image, there
+ * is no {@link Class} mirror available in the native image heap so implementing this would involve
+ * a call into VM native code that in turn would make an upcall into Java code executing on the
+ * HotSpot heap. We have opted to defer implementing functionality such as this until there's a
+ * demonstrated need for it.
+ */
+public class HotSpotJVMCIUnsupportedOperationError extends Error {
+
+    public HotSpotJVMCIUnsupportedOperationError(String reason) {
+        super(reason);
+    }
+
+    public HotSpotJVMCIUnsupportedOperationError(String reason, Throwable cause) {
+        super(reason, cause);
+    }
+
+    private static final long serialVersionUID = 7782431672678016392L;
+
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -22,19 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.reflect.Array;
-
-import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MemoryAccessProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.PrimitiveConstant;
-import jdk.vm.ci.meta.ResolvedJavaField;
-import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * HotSpot implementation of {@link MemoryAccessProvider}.
@@ -55,89 +50,34 @@
      * @return {@code null} if {@code base} does not box an object otherwise the object boxed in
      *         {@code base}
      */
-    private Object asObject(Constant base, JavaKind kind, long displacement) {
+    private static HotSpotObjectConstantImpl asObject(Constant base, JavaKind kind, long displacement) {
         if (base instanceof HotSpotObjectConstantImpl) {
             HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base;
             HotSpotResolvedObjectType type = constant.getType();
-            Object object = constant.object();
-            checkRead(kind, displacement, type, object, runtime.getHostJVMCIBackend().getMetaAccess());
-            return object;
+            runtime().reflection.checkRead(constant, kind, displacement, type);
+            return constant;
         }
         return null;
     }
 
-    /**
-     * Offset of injected {@code java.lang.Class::oop_size} field. No need to make {@code volatile}
-     * as initialization is idempotent.
-     */
-    private long oopSizeOffset;
-
-    private static int computeOopSizeOffset(HotSpotJVMCIRuntime runtime) {
-        MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
-        ResolvedJavaType staticType = metaAccess.lookupJavaType(Class.class);
-        for (ResolvedJavaField f : staticType.getInstanceFields(false)) {
-            if (f.getName().equals("oop_size")) {
-                int offset = ((HotSpotResolvedJavaField) f).getOffset();
-                assert offset != 0 : "not expecting offset of java.lang.Class::oop_size to be 0";
-                return offset;
+    private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
+        if (base instanceof HotSpotMetaspaceConstant) {
+            MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
+                if (displacement == runtime.getConfig().javaMirrorOffset) {
+                    // Klass::_java_mirror is valid for all Klass* values
+                    return true;
+                }
+            } else {
+                throw new IllegalArgumentException(String.valueOf(metaspaceObject));
             }
         }
-        throw new JVMCIError("Could not find injected java.lang.Class::oop_size field");
-    }
-
-    private boolean checkRead(JavaKind kind, long displacement, HotSpotResolvedObjectType type, Object object, MetaAccessProvider metaAccess) {
-        if (type.isArray()) {
-            ResolvedJavaType componentType = type.getComponentType();
-            JavaKind componentKind = componentType.getJavaKind();
-            final int headerSize = metaAccess.getArrayBaseOffset(componentKind);
-            int sizeOfElement = metaAccess.getArrayIndexScale(componentKind);
-            int length = Array.getLength(object);
-            long arrayEnd = headerSize + (sizeOfElement * length);
-            boolean aligned = ((displacement - headerSize) % sizeOfElement) == 0;
-            if (displacement < 0 || displacement > (arrayEnd - sizeOfElement) || (kind == JavaKind.Object && !aligned)) {
-                int index = (int) ((displacement - headerSize) / sizeOfElement);
-                throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind +
-                                " at offset " + displacement + " (index ~ " + index + ") in " +
-                                type.toJavaName() + " object of length " + length);
-            }
-        } else if (kind != JavaKind.Object) {
-            long size;
-            if (object instanceof Class) {
-                if (oopSizeOffset == 0) {
-                    oopSizeOffset = computeOopSizeOffset(runtime);
-                }
-                int wordSize = runtime.getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
-                size = UNSAFE.getInt(object, oopSizeOffset) * wordSize;
-            } else {
-                size = Math.abs(type.instanceSize());
-            }
-            int bytesToRead = kind.getByteCount();
-            if (displacement + bytesToRead > size || displacement < 0) {
-                throw new IllegalArgumentException("Unsafe access: reading " + bytesToRead + " bytes at offset " + displacement + " in " +
-                                type.toJavaName() + " object of size " + size);
-            }
-        } else {
-            ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, JavaKind.Object);
-            if (field == null && object instanceof Class) {
-                // Read of a static field
-                HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object);
-                field = staticFieldsHolder.findStaticFieldWithOffset(displacement, JavaKind.Object);
-            }
-            if (field == null) {
-                throw new IllegalArgumentException("Unsafe object access: field not found for read of kind Object" +
-                                " at offset " + displacement + " in " + type.toJavaName() + " object");
-            }
-            if (field.getJavaKind() != JavaKind.Object) {
-                throw new IllegalArgumentException("Unsafe object access: field " + field.format("%H.%n:%T") + " not of expected kind Object" +
-                                " at offset " + displacement + " in " + type.toJavaName() + " object");
-            }
-        }
-        return true;
+        return false;
     }
 
     private static long asRawPointer(Constant base) {
         if (base instanceof HotSpotMetaspaceConstantImpl) {
-            MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            MetaspaceObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
             return meta.getMetaspacePointer();
         } else if (base instanceof PrimitiveConstant) {
             PrimitiveConstant prim = (PrimitiveConstant) base;
@@ -148,18 +88,18 @@
         throw new IllegalArgumentException(String.valueOf(base));
     }
 
-    private long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
-        Object base = asObject(baseConstant, kind, displacement);
+    private static long readRawValue(Constant baseConstant, long displacement, JavaKind kind, int bits) {
+        HotSpotObjectConstantImpl base = asObject(baseConstant, kind, displacement);
         if (base != null) {
             switch (bits) {
                 case Byte.SIZE:
-                    return UNSAFE.getByte(base, displacement);
+                    return runtime().reflection.getByte(base, displacement);
                 case Short.SIZE:
-                    return UNSAFE.getShort(base, displacement);
+                    return runtime().reflection.getShort(base, displacement);
                 case Integer.SIZE:
-                    return UNSAFE.getInt(base, displacement);
+                    return runtime().reflection.getInt(base, displacement);
                 case Long.SIZE:
-                    return UNSAFE.getLong(base, displacement);
+                    return runtime().reflection.getLong(base, displacement);
                 default:
                     throw new IllegalArgumentException(String.valueOf(bits));
             }
@@ -180,63 +120,33 @@
         }
     }
 
-    private boolean verifyReadRawObject(Object expected, Constant base, long displacement) {
+    private boolean verifyReadRawObject(JavaConstant expected, Constant base, long displacement) {
         if (base instanceof HotSpotMetaspaceConstant) {
-            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
-                if (displacement == runtime.getConfig().classMirrorHandleOffset) {
-                    assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
+                if (displacement == runtime.getConfig().javaMirrorOffset) {
+                    HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) metaspaceObject;
+                    assert expected.equals(type.getJavaMirror());
                 }
             }
         }
         return true;
     }
 
-    private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
+    private JavaConstant readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) {
         long displacement = initialDisplacement;
-        Object ret;
-        Object base = asObject(baseConstant, JavaKind.Object, displacement);
+        JavaConstant ret;
+        HotSpotObjectConstantImpl base = asObject(baseConstant, JavaKind.Object, displacement);
         if (base == null) {
             assert !compressed;
             displacement += asRawPointer(baseConstant);
-            ret = UNSAFE.getUncompressedObject(displacement);
+            ret = runtime.getCompilerToVM().readUncompressedOop(displacement);
             assert verifyReadRawObject(ret, baseConstant, initialDisplacement);
         } else {
             assert runtime.getConfig().useCompressedOops == compressed;
-            ret = UNSAFE.getReference(base, displacement);
+            ret = runtime.getCompilerToVM().getObject(base, displacement);
         }
-        return ret;
-    }
-
-    JavaConstant readFieldValue(HotSpotResolvedJavaField field, Object obj, boolean isVolatile) {
-        assert obj != null;
-        assert !field.isStatic() || obj instanceof Class;
-        long displacement = field.getOffset();
-        assert checkRead(field.getJavaKind(), displacement, (HotSpotResolvedObjectType) runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(obj.getClass()), obj,
-                        runtime.getHostJVMCIBackend().getMetaAccess());
-        JavaKind kind = field.getJavaKind();
-        switch (kind) {
-            case Boolean:
-                return JavaConstant.forBoolean(isVolatile ? UNSAFE.getBooleanVolatile(obj, displacement) : UNSAFE.getBoolean(obj, displacement));
-            case Byte:
-                return JavaConstant.forByte(isVolatile ? UNSAFE.getByteVolatile(obj, displacement) : UNSAFE.getByte(obj, displacement));
-            case Char:
-                return JavaConstant.forChar(isVolatile ? UNSAFE.getCharVolatile(obj, displacement) : UNSAFE.getChar(obj, displacement));
-            case Short:
-                return JavaConstant.forShort(isVolatile ? UNSAFE.getShortVolatile(obj, displacement) : UNSAFE.getShort(obj, displacement));
-            case Int:
-                return JavaConstant.forInt(isVolatile ? UNSAFE.getIntVolatile(obj, displacement) : UNSAFE.getInt(obj, displacement));
-            case Long:
-                return JavaConstant.forLong(isVolatile ? UNSAFE.getLongVolatile(obj, displacement) : UNSAFE.getLong(obj, displacement));
-            case Float:
-                return JavaConstant.forFloat(isVolatile ? UNSAFE.getFloatVolatile(obj, displacement) : UNSAFE.getFloat(obj, displacement));
-            case Double:
-                return JavaConstant.forDouble(isVolatile ? UNSAFE.getDoubleVolatile(obj, displacement) : UNSAFE.getDouble(obj, displacement));
-            case Object:
-                return HotSpotObjectConstantImpl.forObject(isVolatile ? UNSAFE.getReferenceVolatile(obj, displacement) : UNSAFE.getReference(obj, displacement));
-            default:
-                throw new IllegalArgumentException("Unsupported kind: " + kind);
-        }
+        return ret == null ? JavaConstant.NULL_POINTER : ret;
     }
 
     @Override
@@ -271,34 +181,35 @@
     @Override
     public JavaConstant readObjectConstant(Constant base, long displacement) {
         if (base instanceof HotSpotObjectConstantImpl) {
-            Object o = readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
-            return HotSpotObjectConstantImpl.forObject(o);
+            return readRawObject(base, displacement, runtime.getConfig().useCompressedOops);
+        }
+        if (!isValidObjectFieldDisplacement(base, displacement)) {
+            return null;
         }
-        if (base instanceof HotSpotMetaspaceConstant) {
-            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
-            if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
-                 if (displacement == runtime.getConfig().classMirrorHandleOffset) {
-                    // Klass::_java_mirror is valid for all Klass* values
-                    return HotSpotObjectConstantImpl.forObject(((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror());
-                 }
-             } else {
-                 throw new IllegalArgumentException(String.valueOf(metaspaceObject));
-             }
+        if (base instanceof HotSpotMetaspaceConstant &&
+            displacement == runtime.getConfig().javaMirrorOffset) {
+            MetaspaceObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            return ((HotSpotResolvedObjectTypeImpl) metaspaceObject).getJavaMirror();
         }
-        return null;
+        return readRawObject(base, displacement, false);
     }
 
     @Override
     public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
-        return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
+        JavaConstant res = readRawObject(base, displacement, true);
+        return JavaConstant.NULL_POINTER.equals(res) ? HotSpotCompressedNullConstant.COMPRESSED_NULL : ((HotSpotObjectConstant) res).compress();
     }
 
     private HotSpotResolvedObjectTypeImpl readKlass(Constant base, long displacement, boolean compressed) {
         assert (base instanceof HotSpotMetaspaceConstantImpl) || (base instanceof HotSpotObjectConstantImpl) : base.getClass();
-        Object baseObject = (base instanceof HotSpotMetaspaceConstantImpl) ? ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType() : ((HotSpotObjectConstantImpl) base).object();
-        return runtime.getCompilerToVM().getResolvedJavaType(baseObject, displacement, compressed);
+        if (base instanceof HotSpotMetaspaceConstantImpl) {
+            return runtime.getCompilerToVM().getResolvedJavaType((HotSpotResolvedObjectTypeImpl) ((HotSpotMetaspaceConstantImpl) base).asResolvedJavaType(), displacement, compressed);
+        } else {
+            return runtime.getCompilerToVM().getResolvedJavaType(((HotSpotObjectConstantImpl) base), displacement, compressed);
+        }
     }
 
+
     @Override
     public Constant readKlassPointerConstant(Constant base, long displacement) {
         HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, false);
@@ -320,8 +231,7 @@
     @Override
     public Constant readMethodPointerConstant(Constant base, long displacement) {
         assert (base instanceof HotSpotObjectConstantImpl);
-        Object baseObject = ((HotSpotObjectConstantImpl) base).object();
-        HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
+        HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) base, displacement);
         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -22,10 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
-import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-
-import java.lang.reflect.Array;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -43,6 +39,8 @@
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.Signature;
 import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.NoSpeculationReason;
+import jdk.vm.ci.meta.SpeculationLog.Speculation;
 
 // JaCoCo Exclude
 
@@ -87,20 +85,19 @@
     public ResolvedJavaField lookupJavaField(Field reflectionField) {
         Class<?> fieldHolder = reflectionField.getDeclaringClass();
 
-        HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder);
+        HotSpotResolvedJavaType holder = runtime.fromClass(fieldHolder);
+        assert holder != null : fieldHolder;
+        ResolvedJavaField[] fields;
         if (Modifier.isStatic(reflectionField.getModifiers())) {
-            final long offset = UNSAFE.staticFieldOffset(reflectionField);
-            for (ResolvedJavaField field : holder.getStaticFields()) {
-                if (offset == ((HotSpotResolvedJavaField) field).getOffset()) {
-                    return field;
-                }
-            }
+            fields = holder.getStaticFields();
         } else {
-            final long offset = UNSAFE.objectFieldOffset(reflectionField);
-            for (ResolvedJavaField field : holder.getInstanceFields(false)) {
-                if (offset == ((HotSpotResolvedJavaField) field).getOffset()) {
-                    return field;
-                }
+            fields = holder.getInstanceFields(false);
+        }
+        ResolvedJavaType fieldType = lookupJavaType(reflectionField.getType());
+        for (ResolvedJavaField field : fields) {
+            if (reflectionField.getName().equals(field.getName()) && field.getType().equals(fieldType)) {
+                assert Modifier.isStatic(reflectionField.getModifiers()) == field.isStatic();
+                return field;
             }
         }
 
@@ -147,19 +144,21 @@
     }
 
     @Override
-    public JavaConstant encodeSpeculation(SpeculationLog.Speculation speculation) {
-        if (speculation.getReason() instanceof SpeculationLog.NoSpeculationReason) {
+    public JavaConstant encodeSpeculation(Speculation speculation) {
+        if (speculation.getReason() instanceof NoSpeculationReason) {
             return JavaConstant.LONG_0;
         }
         return ((HotSpotSpeculationLog.HotSpotSpeculation) speculation).getEncoding();
     }
 
     @Override
-    public SpeculationLog.Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog) {
+    public Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog) {
         if (constant.equals(JavaConstant.LONG_0)) {
             return SpeculationLog.NO_SPECULATION;
         }
-        assert speculationLog != null : "Must have a speculation log";
+        if (speculationLog == null) {
+            throw new IllegalArgumentException("A speculation log is required to decode the speculation denoted by " + constant);
+        }
         return speculationLog.lookupSpeculation(constant);
     }
 
@@ -303,11 +302,11 @@
                 return 0;
             } else {
                 if (lookupJavaType.isArray()) {
-                    int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object());
+                    int length = runtime.getHostJVMCIBackend().getConstantReflection().readArrayLength(constant);
                     ResolvedJavaType elementType = lookupJavaType.getComponentType();
                     JavaKind elementKind = elementType.getJavaKind();
-                    final int headerSize = getArrayBaseOffset(elementKind);
-                    int sizeOfElement = getArrayIndexScale(elementKind);
+                    final int headerSize = runtime.getArrayBaseOffset(elementKind);
+                    int sizeOfElement = runtime.getArrayIndexScale(elementKind);
                     int log2ElementSize = CodeUtil.log2(sizeOfElement);
                     return computeArrayAllocationSize(length, headerSize, log2ElementSize);
                 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -29,18 +29,18 @@
 
 final class HotSpotMetaspaceConstantImpl implements HotSpotMetaspaceConstant, VMConstant {
 
-    static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+    static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceObject metaspaceObject, boolean compressed) {
         return new HotSpotMetaspaceConstantImpl(metaspaceObject, compressed);
     }
 
-    static MetaspaceWrapperObject getMetaspaceObject(Constant constant) {
+    static MetaspaceObject getMetaspaceObject(Constant constant) {
         return ((HotSpotMetaspaceConstantImpl) constant).metaspaceObject;
     }
 
-    private final MetaspaceWrapperObject metaspaceObject;
+    private final MetaspaceObject metaspaceObject;
     private final boolean compressed;
 
-    private HotSpotMetaspaceConstantImpl(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+    private HotSpotMetaspaceConstantImpl(MetaspaceObject metaspaceObject, boolean compressed) {
         this.metaspaceObject = metaspaceObject;
         this.compressed = compressed;
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -78,8 +78,4 @@
         String base = (flags & ALTERNATE) == ALTERNATE ? getName() : toString();
         formatter.format(applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width));
     }
-
-    public JavaMethod asJavaMethod() {
-        return this;
-    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -30,6 +30,7 @@
 
 import java.util.Arrays;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.internal.misc.Unsafe;
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.JavaMethodProfile;
@@ -45,26 +46,139 @@
  */
 final class HotSpotMethodData {
 
-    static final HotSpotVMConfig config = config();
-    static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.FALSE);
-    static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.UNKNOWN);
+    /**
+     * VM state that can be reset when building an AOT image.
+     */
+    static final class VMState {
+        final HotSpotVMConfig config = config();
+        final HotSpotMethodDataAccessor noDataNoExceptionAccessor = new NoMethodData(this, config.dataLayoutNoTag, TriState.FALSE);
+        final HotSpotMethodDataAccessor noDataExceptionPossiblyNotRecordedAccessor = new NoMethodData(this, config.dataLayoutNoTag, TriState.UNKNOWN);
+        final int noDataSize = cellIndexToOffset(0);
+        final int bitDataSize = cellIndexToOffset(0);
+        final int bitDataNullSeenFlag = 1 << config.bitDataNullSeenFlag;
+        final int counterDataSize = cellIndexToOffset(1);
+        final int counterDataCountOffset = cellIndexToOffset(config.methodDataCountOffset);
+        final int jumpDataSize = cellIndexToOffset(2);
+        final int takenCountOffset = cellIndexToOffset(config.jumpDataTakenOffset);
+        final int takenDisplacementOffset = cellIndexToOffset(config.jumpDataDisplacementOffset);
+        final int typeDataRowSize = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
+
+        final int nonprofiledCountOffset = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
+        final int typeDataFirstTypeOffset = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
+        final int typeDataFirstTypeCountOffset = cellIndexToOffset(config.receiverTypeDataCount0Offset);
+
+        final int typeCheckDataSize = cellIndexToOffset(2) + typeDataRowSize * config.typeProfileWidth;
+        final int virtualCallDataSize = cellIndexToOffset(2) + typeDataRowSize * (config.typeProfileWidth + config.methodProfileWidth);
+        final int virtualCallDataFirstMethodOffset = typeDataFirstTypeOffset + typeDataRowSize * config.typeProfileWidth;
+        final int virtualCallDataFirstMethodCountOffset = typeDataFirstTypeCountOffset + typeDataRowSize * config.typeProfileWidth;
+
+        final int retDataRowSize = cellsToBytes(3);
+        final int retDataSize = cellIndexToOffset(1) + retDataRowSize * config.bciProfileWidth;
+
+        final int branchDataSize = cellIndexToOffset(3);
+        final int notTakenCountOffset = cellIndexToOffset(config.branchDataNotTakenOffset);
+
+        final int arrayDataLengthOffset = cellIndexToOffset(config.arrayDataArrayLenOffset);
+        final int arrayDataStartOffset = cellIndexToOffset(config.arrayDataArrayStartOffset);
+
+        final int multiBranchDataSize = cellIndexToOffset(1);
+        final int multiBranchDataRowSizeInCells = config.multiBranchDataPerCaseCellCount;
+        final int multiBranchDataRowSize = cellsToBytes(multiBranchDataRowSizeInCells);
+        final int multiBranchDataFirstCountOffset = arrayDataStartOffset + cellsToBytes(0);
+        final int multiBranchDataFirstDisplacementOffset = arrayDataStartOffset + cellsToBytes(1);
+
+        final int argInfoDataSize = cellIndexToOffset(1);
+
+        // sorted by tag
+        // @formatter:off
+        final HotSpotMethodDataAccessor[] profileDataAccessors = {
+            null,
+            new BitData(this, config.dataLayoutBitDataTag),
+            new CounterData(this, config.dataLayoutCounterDataTag),
+            new JumpData(this, config.dataLayoutJumpDataTag),
+            new ReceiverTypeData(this, config.dataLayoutReceiverTypeDataTag),
+            new VirtualCallData(this, config.dataLayoutVirtualCallDataTag),
+            new RetData(this, config.dataLayoutRetDataTag),
+            new BranchData(this, config.dataLayoutBranchDataTag),
+            new MultiBranchData(this, config.dataLayoutMultiBranchDataTag),
+            new ArgInfoData(this, config.dataLayoutArgInfoDataTag),
+            new UnknownProfileData(this, config.dataLayoutCallTypeDataTag),
+            new VirtualCallTypeData(this, config.dataLayoutVirtualCallTypeDataTag),
+            new UnknownProfileData(this, config.dataLayoutParametersTypeDataTag),
+            new UnknownProfileData(this, config.dataLayoutSpeculativeTrapDataTag),
+        };
+        // @formatter:on
+
+        private boolean checkAccessorTags() {
+            int expectedTag = 0;
+            for (HotSpotMethodDataAccessor accessor : profileDataAccessors) {
+                if (expectedTag == 0) {
+                    assert accessor == null;
+                } else {
+                    assert accessor.tag == expectedTag : expectedTag + " != " + accessor.tag + " " + accessor;
+                }
+                expectedTag++;
+            }
+            return true;
+        }
+
+        private VMState() {
+            assert checkAccessorTags();
+        }
+
+        private static int truncateLongToInt(long value) {
+            return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
+        }
+
+        private int computeFullOffset(int position, int offsetInBytes) {
+            return config.methodDataOopDataOffset + position + offsetInBytes;
+        }
+
+        private int cellIndexToOffset(int cells) {
+            return config.dataLayoutHeaderSize + cellsToBytes(cells);
+        }
+
+        private int cellsToBytes(int cells) {
+            return cells * config.dataLayoutCellSize;
+        }
+
+        /**
+         * Singleton instance lazily initialized via double-checked locking.
+         */
+        @NativeImageReinitialize private static volatile VMState instance;
+
+        static VMState instance() {
+            VMState result = instance;
+            if (result == null) {
+                synchronized (VMState.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new VMState();
+                    }
+                }
+            }
+            return result;
+        }
+    }
 
     /**
      * Reference to the C++ MethodData object.
      */
     final long metaspaceMethodData;
     private final HotSpotResolvedJavaMethodImpl method;
+    private final VMState state;
 
     HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
         this.metaspaceMethodData = metaspaceMethodData;
         this.method = method;
+        this.state = VMState.instance();
     }
 
     /**
      * @return value of the MethodData::_data_size field
      */
     private int normalDataSize() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataDataSize);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataDataSize);
     }
 
     /**
@@ -74,8 +188,8 @@
      * @return size of extra data records
      */
     private int extraDataSize() {
-        final int extraDataBase = config.methodDataOopDataOffset + normalDataSize();
-        final int extraDataLimit = UNSAFE.getInt(metaspaceMethodData + config.methodDataSize);
+        final int extraDataBase = state.config.methodDataOopDataOffset + normalDataSize();
+        final int extraDataLimit = UNSAFE.getInt(metaspaceMethodData + state.config.methodDataSize);
         return extraDataLimit - extraDataBase;
     }
 
@@ -98,25 +212,25 @@
     public int getDeoptimizationCount(DeoptimizationReason reason) {
         HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
         int reasonIndex = metaAccess.convertDeoptReason(reason);
-        return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
+        return UNSAFE.getByte(metaspaceMethodData + state.config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
     }
 
     public int getOSRDeoptimizationCount(DeoptimizationReason reason) {
         HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
         int reasonIndex = metaAccess.convertDeoptReason(reason);
-        return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + config.deoptReasonOSROffset + reasonIndex) & 0xFF;
+        return UNSAFE.getByte(metaspaceMethodData + state.config.methodDataOopTrapHistoryOffset + state.config.deoptReasonOSROffset + reasonIndex) & 0xFF;
     }
 
     public int getDecompileCount() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataDecompiles);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataDecompiles);
     }
 
     public int getOverflowRecompileCount() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataOverflowRecompiles);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataOverflowRecompiles);
     }
 
     public int getOverflowTrapCount() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataOverflowTraps);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataOverflowTraps);
     }
 
     public HotSpotMethodDataAccessor getNormalData(int position) {
@@ -140,27 +254,27 @@
 
     public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
         if (exceptionPossiblyNotRecorded) {
-            return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
+            return VMState.instance().noDataExceptionPossiblyNotRecordedAccessor;
         } else {
-            return NO_DATA_NO_EXCEPTION_ACCESSOR;
+            return VMState.instance().noDataNoExceptionAccessor;
         }
     }
 
     private HotSpotMethodDataAccessor getData(int position) {
         assert position >= 0 : "out of bounds";
-        final int tag = HotSpotMethodDataAccessor.readTag(config, this, position);
-        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag];
+        final int tag = HotSpotMethodDataAccessor.readTag(state.config, this, position);
+        HotSpotMethodDataAccessor accessor = state.profileDataAccessors[tag];
         assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
         return accessor;
     }
 
     int readUnsignedByte(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return UNSAFE.getByte(metaspaceMethodData + fullOffsetInBytes) & 0xFF;
     }
 
     int readUnsignedShort(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return UNSAFE.getShort(metaspaceMethodData + fullOffsetInBytes) & 0xFFFF;
     }
 
@@ -169,13 +283,13 @@
      * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
      */
     private long readUnsignedInt(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes) & 0xFFFFFFFFL;
     }
 
     private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) {
         long value = readUnsignedInt(position, offsetInBytes);
-        return truncateLongToInt(value);
+        return VMState.truncateLongToInt(value);
     }
 
     /**
@@ -183,34 +297,18 @@
      * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
      */
     private int readInt(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return (int) UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes);
     }
 
     private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
         return compilerToVM().getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
     }
 
     private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
-        long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
-        return compilerToVM().getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
-    }
-
-    private static int truncateLongToInt(long value) {
-        return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
-    }
-
-    private static int computeFullOffset(int position, int offsetInBytes) {
-        return config.methodDataOopDataOffset + position + offsetInBytes;
-    }
-
-    private static int cellIndexToOffset(int cells) {
-        return config.dataLayoutHeaderSize + cellsToBytes(cells);
-    }
-
-    private static int cellsToBytes(int cells) {
-        return cells * config.dataLayoutCellSize;
+        long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
+        return compilerToVM().getResolvedJavaType(metaspaceMethodData + fullOffsetInBytes, false);
     }
 
     /**
@@ -263,14 +361,12 @@
         return sb.toString();
     }
 
-    static final int NO_DATA_SIZE = cellIndexToOffset(0);
-
     static class NoMethodData extends HotSpotMethodDataAccessor {
 
         private final TriState exceptionSeen;
 
-        protected NoMethodData(HotSpotVMConfig config, int tag, TriState exceptionSeen) {
-            super(config, tag, NO_DATA_SIZE);
+        protected NoMethodData(VMState state, int tag, TriState exceptionSeen) {
+            super(state, tag, state.noDataSize);
             this.exceptionSeen = exceptionSeen;
         }
 
@@ -290,22 +386,19 @@
         }
     }
 
-    static final int BIT_DATA_SIZE = cellIndexToOffset(0);
-    static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
-
     static class BitData extends HotSpotMethodDataAccessor {
 
-        private BitData(HotSpotVMConfig config, int tag) {
-            super(config, tag, BIT_DATA_SIZE);
+        private BitData(VMState state, int tag) {
+            super(state, tag, state.bitDataSize);
         }
 
-        protected BitData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected BitData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
         public TriState getNullSeen(HotSpotMethodData data, int position) {
-            return TriState.get((getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0);
+            return TriState.get((getFlags(data, position) & state.bitDataNullSeenFlag) != 0);
         }
 
         @Override
@@ -314,17 +407,14 @@
         }
     }
 
-    static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
-    static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
-
     static class CounterData extends BitData {
 
-        CounterData(HotSpotVMConfig config, int tag) {
-            super(config, tag, COUNTER_DATA_SIZE);
+        CounterData(VMState state, int tag) {
+            super(state, tag, state.counterDataSize);
         }
 
-        protected CounterData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected CounterData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -333,7 +423,7 @@
         }
 
         protected int getCounterValue(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, state.counterDataCountOffset);
         }
 
         @Override
@@ -342,18 +432,14 @@
         }
     }
 
-    static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
-    static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
-    static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
-
     static class JumpData extends HotSpotMethodDataAccessor {
 
-        JumpData(HotSpotVMConfig config, int tag) {
-            super(config, tag, JUMP_DATA_SIZE);
+        JumpData(VMState state, int tag) {
+            super(state, tag, state.jumpDataSize);
         }
 
-        protected JumpData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected JumpData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -363,11 +449,11 @@
 
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, state.takenCountOffset);
         }
 
         public int getTakenDisplacement(HotSpotMethodData data, int position) {
-            return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET);
+            return data.readInt(position, state.takenDisplacementOffset);
         }
 
         @Override
@@ -390,16 +476,10 @@
         }
     }
 
-    static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
-
-    static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
-    static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
-    static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
-
     abstract static class AbstractTypeData extends CounterData {
 
-        protected AbstractTypeData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected AbstractTypeData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -446,7 +526,7 @@
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
         public int getNonprofiledCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+            return data.readUnsignedIntAsSignedInt(position, state.nonprofiledCountOffset);
         }
 
         private JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
@@ -470,12 +550,12 @@
             return new JavaTypeProfile(nullSeen, notRecordedTypeProbability, ptypes);
         }
 
-        private static int getTypeOffset(int row) {
-            return TYPE_DATA_FIRST_TYPE_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        private int getTypeOffset(int row) {
+            return state.typeDataFirstTypeOffset + row * state.typeDataRowSize;
         }
 
-        protected static int getTypeCountOffset(int row) {
-            return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        protected int getTypeCountOffset(int row) {
+            return state.typeDataFirstTypeCountOffset + row * state.typeDataRowSize;
         }
 
         @Override
@@ -493,16 +573,14 @@
         }
     }
 
-    static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-
     static class ReceiverTypeData extends AbstractTypeData {
 
-        ReceiverTypeData(HotSpotVMConfig config, int tag) {
-            super(config, tag, TYPE_CHECK_DATA_SIZE);
+        ReceiverTypeData(VMState state, int tag) {
+            super(state, tag, state.typeCheckDataSize);
         }
 
-        protected ReceiverTypeData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected ReceiverTypeData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -516,18 +594,14 @@
         }
     }
 
-    static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
-    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-
     static class VirtualCallData extends ReceiverTypeData {
 
-        VirtualCallData(HotSpotVMConfig config, int tag) {
-            super(config, tag, VIRTUAL_CALL_DATA_SIZE);
+        VirtualCallData(VMState state, int tag) {
+            super(state, tag, state.virtualCallDataSize);
         }
 
-        protected VirtualCallData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        protected VirtualCallData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
@@ -540,7 +614,7 @@
             }
 
             total += getCounterValue(data, position);
-            return truncateLongToInt(total);
+            return VMState.truncateLongToInt(total);
         }
 
         @Override
@@ -548,8 +622,8 @@
             return getCounterValue(data, position);
         }
 
-        private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
+        private long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, state.nonprofiledCountOffset);
         }
 
         @Override
@@ -610,12 +684,12 @@
             return new JavaMethodProfile(notRecordedMethodProbability, pmethods);
         }
 
-        private static int getMethodOffset(int row) {
-            return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        private int getMethodOffset(int row) {
+            return state.virtualCallDataFirstMethodOffset + row * state.typeDataRowSize;
         }
 
-        private static int getMethodCountOffset(int row) {
-            return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
+        private int getMethodCountOffset(int row) {
+            return state.virtualCallDataFirstMethodCountOffset + row * state.typeDataRowSize;
         }
 
         @Override
@@ -632,8 +706,8 @@
 
     static class VirtualCallTypeData extends VirtualCallData {
 
-        VirtualCallTypeData(HotSpotVMConfig config, int tag) {
-            super(config, tag, 0);
+        VirtualCallTypeData(VMState state, int tag) {
+            super(state, tag, 0);
         }
 
         @Override
@@ -643,29 +717,23 @@
         }
     }
 
-    static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
-    static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
-
     static class RetData extends CounterData {
 
-        RetData(HotSpotVMConfig config, int tag) {
-            super(config, tag, RET_DATA_SIZE);
+        RetData(VMState state, int tag) {
+            super(state, tag, state.retDataSize);
         }
     }
 
-    static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
-    static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
-
     static class BranchData extends JumpData {
 
-        BranchData(HotSpotVMConfig config, int tag) {
-            super(config, tag, BRANCH_DATA_SIZE);
+        BranchData(VMState state, int tag) {
+            super(state, tag, state.branchDataSize);
         }
 
         @Override
         public double getBranchTakenProbability(HotSpotMethodData data, int position) {
-            long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
-            long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+            long takenCount = data.readUnsignedInt(position, state.takenCountOffset);
+            long notTakenCount = data.readUnsignedInt(position, state.notTakenCountOffset);
             long total = takenCount + notTakenCount;
 
             return total <= 0 ? -1 : takenCount / (double) total;
@@ -673,35 +741,32 @@
 
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
-            long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
-            return truncateLongToInt(count);
+            long count = data.readUnsignedInt(position, state.takenCountOffset) + data.readUnsignedInt(position, state.notTakenCountOffset);
+            return VMState.truncateLongToInt(count);
         }
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            long taken = data.readUnsignedInt(pos, TAKEN_COUNT_OFFSET);
-            long notTaken = data.readUnsignedInt(pos, NOT_TAKEN_COUNT_OFFSET);
+            long taken = data.readUnsignedInt(pos, state.takenCountOffset);
+            long notTaken = data.readUnsignedInt(pos, state.notTakenCountOffset);
             double takenProbability = getBranchTakenProbability(data, pos);
             return sb.append(format("taken(%d, %4.2f) not_taken(%d, %4.2f) displacement(%d)", taken, takenProbability, notTaken, 1.0D - takenProbability, getTakenDisplacement(data, pos)));
         }
     }
 
-    static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
-    static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
-
     static class ArrayData extends HotSpotMethodDataAccessor {
 
-        ArrayData(HotSpotVMConfig config, int tag, int staticSize) {
-            super(config, tag, staticSize);
+        ArrayData(VMState state, int tag, int staticSize) {
+            super(state, tag, staticSize);
         }
 
         @Override
         protected int getDynamicSize(HotSpotMethodData data, int position) {
-            return cellsToBytes(getLength(data, position));
+            return state.cellsToBytes(getLength(data, position));
         }
 
-        protected static int getLength(HotSpotMethodData data, int position) {
-            return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
+        protected int getLength(HotSpotMethodData data, int position) {
+            return data.readInt(position, state.arrayDataLengthOffset);
         }
 
         @Override
@@ -710,25 +775,19 @@
         }
     }
 
-    static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
-    static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
-    static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
-    static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
-    static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
-
     static class MultiBranchData extends ArrayData {
 
-        MultiBranchData(HotSpotVMConfig config, int tag) {
-            super(config, tag, MULTI_BRANCH_DATA_SIZE);
+        MultiBranchData(VMState state, int tag) {
+            super(state, tag, state.multiBranchDataSize);
         }
 
         @Override
         public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
             int arrayLength = getLength(data, position);
             assert arrayLength > 0 : "switch must have at least the default case";
-            assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+            assert arrayLength % state.multiBranchDataRowSizeInCells == 0 : "array must have full rows";
 
-            int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            int length = arrayLength / state.multiBranchDataRowSizeInCells;
             long totalCount = 0;
             double[] result = new double[length];
 
@@ -753,7 +812,7 @@
             }
         }
 
-        private static long readCount(HotSpotMethodData data, int position, int i) {
+        private long readCount(HotSpotMethodData data, int position, int i) {
             int offset;
             long count;
             offset = getCountOffset(i);
@@ -765,29 +824,29 @@
         public int getExecutionCount(HotSpotMethodData data, int position) {
             int arrayLength = getLength(data, position);
             assert arrayLength > 0 : "switch must have at least the default case";
-            assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
+            assert arrayLength % state.multiBranchDataRowSizeInCells == 0 : "array must have full rows";
 
-            int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            int length = arrayLength / state.multiBranchDataRowSizeInCells;
             long totalCount = 0;
             for (int i = 0; i < length; i++) {
                 int offset = getCountOffset(i);
                 totalCount += data.readUnsignedInt(position, offset);
             }
 
-            return truncateLongToInt(totalCount);
+            return VMState.truncateLongToInt(totalCount);
         }
 
-        private static int getCountOffset(int index) {
-            return MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+        private int getCountOffset(int index) {
+            return state.multiBranchDataFirstCountOffset + index * state.multiBranchDataRowSize;
         }
 
-        private static int getDisplacementOffset(int index) {
-            return MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE;
+        private int getDisplacementOffset(int index) {
+            return state.multiBranchDataFirstDisplacementOffset + index * state.multiBranchDataRowSize;
         }
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            int entries = getLength(data, pos) / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
+            int entries = getLength(data, pos) / state.multiBranchDataRowSizeInCells;
             sb.append(format("entries(%d)", entries));
             for (int i = 0; i < entries; i++) {
                 sb.append(format("%n  %d: count(%d) displacement(%d)", i, data.readUnsignedInt(pos, getCountOffset(i)), data.readUnsignedInt(pos, getDisplacementOffset(i))));
@@ -796,18 +855,16 @@
         }
     }
 
-    static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
-
     static class ArgInfoData extends ArrayData {
 
-        ArgInfoData(HotSpotVMConfig config, int tag) {
-            super(config, tag, ARG_INFO_DATA_SIZE);
+        ArgInfoData(VMState state, int tag) {
+            super(state, tag, state.argInfoDataSize);
         }
     }
 
     static class UnknownProfileData extends HotSpotMethodDataAccessor {
-        UnknownProfileData(HotSpotVMConfig config, int tag) {
-            super(config, tag, 0);
+        UnknownProfileData(VMState state, int tag) {
+            super(state, tag, 0);
         }
 
         @Override
@@ -824,47 +881,10 @@
     }
 
     public void setCompiledIRSize(int size) {
-        UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
+        UNSAFE.putInt(metaspaceMethodData + state.config.methodDataIRSizeOffset, size);
     }
 
     public int getCompiledIRSize() {
-        return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
+        return UNSAFE.getInt(metaspaceMethodData + state.config.methodDataIRSizeOffset);
     }
-
-    // sorted by tag
-    // @formatter:off
-    static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
-        null,
-        new BitData(config, config.dataLayoutBitDataTag),
-        new CounterData(config, config.dataLayoutCounterDataTag),
-        new JumpData(config, config.dataLayoutJumpDataTag),
-        new ReceiverTypeData(config, config.dataLayoutReceiverTypeDataTag),
-        new VirtualCallData(config, config.dataLayoutVirtualCallDataTag),
-        new RetData(config, config.dataLayoutRetDataTag),
-        new BranchData(config, config.dataLayoutBranchDataTag),
-        new MultiBranchData(config, config.dataLayoutMultiBranchDataTag),
-        new ArgInfoData(config, config.dataLayoutArgInfoDataTag),
-        new UnknownProfileData(config, config.dataLayoutCallTypeDataTag),
-        new VirtualCallTypeData(config, config.dataLayoutVirtualCallTypeDataTag),
-        new UnknownProfileData(config, config.dataLayoutParametersTypeDataTag),
-        new UnknownProfileData(config, config.dataLayoutSpeculativeTrapDataTag),
-    };
-
-    private static boolean checkAccessorTags() {
-        int expectedTag = 0;
-        for (HotSpotMethodDataAccessor accessor : PROFILE_DATA_ACCESSORS) {
-            if (expectedTag == 0) {
-                assert accessor == null;
-            } else {
-                assert accessor.tag == expectedTag : expectedTag + " != " + accessor.tag + " " + accessor;
-            }
-            expectedTag++;
-        }
-        return true;
-    }
-
-    static {
-        assert checkAccessorTags();
-    }
-    // @formatter:on
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -36,10 +36,12 @@
 
     final int tag;
     final int staticSize;
+    final HotSpotMethodData.VMState state;
     final HotSpotVMConfig config;
 
-    protected HotSpotMethodDataAccessor(HotSpotVMConfig config, int tag, int staticSize) {
-        this.config = config;
+    protected HotSpotMethodDataAccessor(HotSpotMethodData.VMState state, int tag, int staticSize) {
+        this.state = state;
+        this.config = state.config;
         this.tag = tag;
         this.staticSize = staticSize;
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -26,9 +26,10 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import java.lang.invoke.MethodHandle;
-import java.util.Objects;
 
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.hotspot.HotSpotMethodData.VMState;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.MethodHandleAccessProvider;
@@ -45,15 +46,16 @@
     }
 
     /**
-     * Lazy initialization to break class initialization cycle. Field and method lookup is only
-     * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
+     * Lazy initialized reflection on {@link MethodHandle} internals. Field and method lookup is
+     * only possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
      */
-    static class LazyInitialization {
-        static final ResolvedJavaType lambdaFormType;
-        static final ResolvedJavaField methodHandleFormField;
-        static final ResolvedJavaField lambdaFormVmentryField;
-        static final ResolvedJavaField methodField;
-        static final HotSpotResolvedJavaField vmtargetField;
+    static final class Internals {
+        final ResolvedJavaType lambdaFormType;
+        final ResolvedJavaField methodHandleFormField;
+        final ResolvedJavaField lambdaFormVmentryField;
+        final HotSpotResolvedJavaField callSiteTargetField;
+        final ResolvedJavaField methodField;
+        final HotSpotResolvedJavaField vmtargetField;
 
         /**
          * Search for an instance field with the given name in a class.
@@ -71,34 +73,53 @@
                     return field;
                 }
             }
-            throw new NoSuchFieldError(fieldType.getName() + " " + declaringType + "." + fieldName);
+            throw new NoSuchFieldError(declaringType + "." + fieldName);
         }
 
-        private static ResolvedJavaType resolveType(Class<?> c) {
-            return runtime().fromClass(c);
-        }
-
-        private static ResolvedJavaType resolveType(String className) throws ClassNotFoundException {
-            return resolveType(Class.forName(className));
+        private static ResolvedJavaType resolveType(String className) {
+            return (ResolvedJavaType) runtime().lookupTypeInternal(className, null, true);
         }
 
-        static {
+        private Internals() {
             try {
-                ResolvedJavaType methodHandleType = resolveType(MethodHandle.class);
-                ResolvedJavaType memberNameType = resolveType("java.lang.invoke.MemberName");
-                lambdaFormType = resolveType("java.lang.invoke.LambdaForm");
+                ResolvedJavaType methodHandleType = resolveType("Ljava/lang/invoke/MethodHandle;");
+                ResolvedJavaType memberNameType = resolveType("Ljava/lang/invoke/MemberName;");
+                lambdaFormType = resolveType("Ljava/lang/invoke/LambdaForm;");
                 methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
                 lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
-                ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName");
+
+                ResolvedJavaType methodType = resolveType("Ljava/lang/invoke/ResolvedMethodName;");
                 methodField = findFieldInClass(memberNameType, "method", methodType);
-                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass()));
+                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(Character.toString(HotSpotJVMCIRuntime.getHostWordKind().getTypeChar())));
 
+                ResolvedJavaType callSiteType = resolveType("Ljava/lang/invoke/CallSite;");
+                callSiteTargetField = (HotSpotResolvedJavaField) findFieldInClass(callSiteType, "target", methodHandleType);
             } catch (Throwable ex) {
                 throw new JVMCIError(ex);
             }
         }
+
+        /**
+         * Singleton instance lazily initialized via double-checked locking.
+         */
+        @NativeImageReinitialize private static volatile Internals instance;
+
+        static Internals instance() {
+            Internals result = instance;
+            if (result == null) {
+                synchronized (VMState.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new Internals();
+                    }
+                }
+            }
+            return result;
+        }
+
     }
 
+
     @Override
     public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
         int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
@@ -131,19 +152,19 @@
         }
 
         /* Load non-public field: LambdaForm MethodHandle.form */
-        JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
+        Internals internals = Internals.instance();
+        JavaConstant lambdaForm = constantReflection.readFieldValue(internals.methodHandleFormField, methodHandle);
         if (lambdaForm == null || lambdaForm.isNull()) {
             return null;
         }
 
-        JavaConstant memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+        JavaConstant memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
         if (memberName.isNull() && forceBytecodeGeneration) {
-            Object lf = ((HotSpotObjectConstant) lambdaForm).asObject(LazyInitialization.lambdaFormType);
-            compilerToVM().compileToBytecode(Objects.requireNonNull(lf));
-            memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+            compilerToVM().compileToBytecode((HotSpotObjectConstantImpl) lambdaForm);
+            memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
             assert memberName.isNonNull();
         }
-        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        JavaConstant method = constantReflection.readFieldValue(internals.methodField, memberName);
         return getTargetMethod(method);
     }
 
@@ -152,7 +173,7 @@
         if (memberName.isNull()) {
             return null;
         }
-        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        JavaConstant method = constantReflection.readFieldValue(Internals.instance().methodField, memberName);
         return getTargetMethod(method);
     }
 
@@ -165,8 +186,7 @@
             throw new IllegalArgumentException("unexpected type for memberName");
         }
 
-        Object object = ((HotSpotObjectConstantImpl) method).object();
         /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */
-        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.getOffset());
+        return compilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) method, Internals.instance().vmtargetField.getOffset());
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -23,6 +23,8 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.code.InvalidInstalledCodeException;
 import jdk.vm.ci.meta.JavaKind;
@@ -30,56 +32,104 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
- * Implementation of {@link InstalledCode} for code installed as an nmethod.
- *
- * When a {@link HotSpotNmethod} dies, it triggers unloading of the nmethod unless
- * {@link #isDefault() == true}.
+ * Implementation of {@link InstalledCode} for code installed as an {@code nmethod}. The address of
+ * the {@code nmethod} is stored in {@link InstalledCode#address} and the value of
+ * {@code nmethod::verified_entry_point()} is in {@link InstalledCode#entryPoint}.
  */
 public class HotSpotNmethod extends HotSpotInstalledCode {
 
     /**
-     * This (indirect) Method* reference is safe since class redefinition preserves all methods
-     * associated with nmethods in the code cache.
+     * This (indirect) {@code Method*} reference is safe since class redefinition preserves all
+     * methods associated with nmethods in the code cache.
      */
-    private final HotSpotResolvedJavaMethod method;
+    private final HotSpotResolvedJavaMethodImpl method;
 
+    /**
+     * Specifies whether the {@code nmethod} associated with this object is the code executed by
+     * default HotSpot linkage when a normal Java call to {@link #method} is made. That is, does
+     * {@code this.method.metadataHandle->_code} == {@code this.address}. If not, then the
+     * {@code nmethod} can only be invoked via a reference to this object. An example of this is the
+     * trampoline mechanism used by Truffle: https://goo.gl/LX88rZ.
+     */
     private final boolean isDefault;
 
-    public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) {
+    /**
+     * Determines whether this object is in the oops table of the nmethod.
+     * <p>
+     * If this object is in the oops table, the VM uses the oops table entry to update this object's
+     * {@link #address} and {@link #entryPoint} fields when the state of the nmethod changes. The
+     * nmethod will be unloadable when this object dies.
+     * <p>
+     * Otherwise, the nmethod's unloadability is not changed when this object dies.
+     */
+    boolean inOopsTable() {
+        return compileIdSnapshot != 0;
+    }
+
+    /**
+     * If this field is 0, this object is in the oops table of the nmethod. Otherwise, the value of
+     * the field records the nmethod's compile identifier. This value is used to confirm an entry in
+     * the code cache retrieved by {@link #address} is indeed the nmethod represented by this
+     * object.
+     *
+     * @see #inOopsTable
+     */
+    private final long compileIdSnapshot;
+
+    HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) {
         super(name);
         this.method = method;
         this.isDefault = isDefault;
+        boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault;
+        this.compileIdSnapshot = inOopsTable ? 0L : compileId;
+        assert inOopsTable || compileId != 0L : this;
     }
 
     /**
      * Determines if the nmethod associated with this object is the compiled entry point for
-     * {@link #getMethod()}. If {@code false}, then the nmethod is unloaded when the VM determines
-     * this object has died.
+     * {@link #getMethod()}.
      */
     public boolean isDefault() {
         return isDefault;
     }
 
+    @Override
+    public boolean isValid() {
+        if (compileIdSnapshot != 0L) {
+            compilerToVM().updateHotSpotNmethod(this);
+        }
+        return super.isValid();
+    }
+
     public ResolvedJavaMethod getMethod() {
         return method;
     }
 
     @Override
     public void invalidate() {
-        compilerToVM().invalidateInstalledCode(this);
+        compilerToVM().invalidateHotSpotNmethod(this);
+    }
+
+    @Override
+    public long getAddress() {
+        if (compileIdSnapshot != 0L) {
+            compilerToVM().updateHotSpotNmethod(this);
+        }
+        return super.getAddress();
+    }
+
+    @Override
+    public long getEntryPoint() {
+        if (compileIdSnapshot != 0L) {
+            return 0;
+        }
+        return super.getEntryPoint();
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
-    }
-
-    protected boolean checkThreeObjectArgs() {
-        assert method.getSignature().getParameterCount(!method.isStatic()) == 3;
-        assert method.getSignature().getParameterKind(0) == JavaKind.Object;
-        assert method.getSignature().getParameterKind(1) == JavaKind.Object;
-        assert !method.isStatic() || method.getSignature().getParameterKind(2) == JavaKind.Object;
-        return true;
+        return String.format("HotSpotNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s, inOopsTable=%s]",
+                        method, getAddress(), isDefault, name, inOopsTable());
     }
 
     private boolean checkArgs(Object... args) {
@@ -98,8 +148,11 @@
 
     @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        if (IS_IN_NATIVE_IMAGE) {
+            throw new HotSpotJVMCIUnsupportedOperationError("Cannot execute nmethod via mirror in native image");
+        }
         assert checkArgs(args);
-        return compilerToVM().executeInstalledCode(args, this);
+        return compilerToVM().executeHotSpotNmethod(args, this);
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -22,14 +22,9 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.ConstantCallSite;
-import java.lang.invoke.MethodHandle;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import jdk.vm.ci.meta.Assumptions;
-import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaType;
@@ -38,45 +33,12 @@
  * Represents a constant non-{@code null} object reference, within the compiler and across the
  * compiler/runtime interface.
  */
-class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
-
-    static JavaConstant forObject(Object object) {
-        return forObject(object, false);
-    }
-
-    static JavaConstant forObject(Object object, boolean compressed) {
-        if (object == null) {
-            return compressed ? HotSpotCompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER;
-        } else {
-            return new HotSpotObjectConstantImpl(object, compressed);
-        }
-    }
+abstract class HotSpotObjectConstantImpl implements HotSpotObjectConstant {
 
-    public static JavaConstant forBoxedValue(JavaKind kind, Object value) {
-        if (kind == JavaKind.Object) {
-            return HotSpotObjectConstantImpl.forObject(value);
-        } else {
-            return JavaConstant.forBoxedPrimitive(value);
-        }
-    }
+    protected final boolean compressed;
 
-    static Object asBoxedValue(Constant constant) {
-        if (JavaConstant.isNull(constant)) {
-            return null;
-        } else if (constant instanceof HotSpotObjectConstantImpl) {
-            return ((HotSpotObjectConstantImpl) constant).object;
-        } else {
-            return ((JavaConstant) constant).asBoxedPrimitive();
-        }
-    }
-
-    private final Object object;
-    private final boolean compressed;
-
-    protected HotSpotObjectConstantImpl(Object object, boolean compressed) {
-        this.object = object;
+    HotSpotObjectConstantImpl(boolean compressed) {
         this.compressed = compressed;
-        assert object != null;
     }
 
     @Override
@@ -84,82 +46,54 @@
         return JavaKind.Object;
     }
 
-    /**
-     * Package-private accessor for the object represented by this constant.
-     */
-    Object object() {
-        return object;
-    }
-
     @Override
     public boolean isCompressed() {
         return compressed;
     }
 
     @Override
-    public JavaConstant compress() {
-        assert !compressed;
-        return new HotSpotObjectConstantImpl(object, true);
-    }
+    public abstract JavaConstant compress();
 
     @Override
-    public JavaConstant uncompress() {
-        assert compressed;
-        return new HotSpotObjectConstantImpl(object, false);
-    }
+    public abstract JavaConstant uncompress();
 
     @Override
     public HotSpotResolvedObjectType getType() {
-        return fromObjectClass(object.getClass());
+        return runtime().reflection.getType(this);
     }
 
     @Override
-    public int getIdentityHashCode() {
-        return System.identityHashCode(object);
-    }
+    public abstract int getIdentityHashCode();
 
     @Override
     public JavaConstant getCallSiteTarget(Assumptions assumptions) {
-        if (object instanceof CallSite) {
-            CallSite callSite = (CallSite) object;
-            MethodHandle target = callSite.getTarget();
-            JavaConstant targetConstant = HotSpotObjectConstantImpl.forObject(target);
-            if (!(callSite instanceof ConstantCallSite)) {
+        if (runtime().getCallSite().isInstance(this)) {
+            HotSpotObjectConstantImpl target = (HotSpotObjectConstantImpl) runtime().getHostJVMCIBackend().getConstantReflection().readFieldValue(
+                            HotSpotMethodHandleAccessProvider.Internals.instance().callSiteTargetField, this);
+            if (!runtime().getConstantCallSite().isInstance(this)) {
                 if (assumptions == null) {
                     return null;
                 }
-                assumptions.record(new Assumptions.CallSiteTargetValue(this, targetConstant));
+                assumptions.record(new Assumptions.CallSiteTargetValue(this, target));
             }
-
-            return targetConstant;
+            return target;
         }
         return null;
     }
 
     @Override
-    @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want")
     public boolean isInternedString() {
-        if (object instanceof String) {
-            String s = (String) object;
-            return s.intern() == s;
-        }
-        return false;
+        return runtime().compilerToVm.isInternedString(this);
     }
 
     @Override
     public <T> T asObject(Class<T> type) {
-        if (type.isInstance(object)) {
-            return type.cast(object);
-        }
-        return null;
+        return runtime().reflection.asObject(this, type);
     }
 
     @Override
     public Object asObject(ResolvedJavaType type) {
-        if (type.isInstance(this)) {
-            return object;
-        }
-        return null;
+        return runtime().reflection.asObject(this, (HotSpotResolvedJavaType) type);
     }
 
     @Override
@@ -203,32 +137,40 @@
     }
 
     @Override
-    public int hashCode() {
-        return System.identityHashCode(object);
-    }
-
-    @Override
     public boolean equals(Object o) {
         if (o == this) {
             return true;
         } else if (o instanceof HotSpotObjectConstantImpl) {
             HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o;
-            return object == other.object && compressed == other.compressed;
+            return runtime().reflection.equals(this, other);
         }
         return false;
     }
 
     @Override
+    public int hashCode() {
+        return getIdentityHashCode();
+    }
+
+    @Override
     public String toValueString() {
-        if (object instanceof String) {
-            return "\"" + (String) object + "\"";
+        if (runtime().getJavaLangString().isInstance(this)) {
+            return "\"" + runtime().reflection.asString(this) + "\"";
         } else {
-            return JavaKind.Object.format(object);
+            return runtime().reflection.formatString(this);
         }
     }
 
     @Override
     public String toString() {
-        return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + JavaKind.Object.format(object) + "]";
+        return (compressed ? "NarrowOop" : getJavaKind().getJavaName()) + "[" + runtime().reflection.formatString(this) + "]";
+    }
+
+    public JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
+        return runtime().reflection.readFieldValue(this, field, isVolatile);
+    }
+
+    public ResolvedJavaType asJavaType() {
+        return runtime().reflection.asJavaType(this);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -22,15 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
-import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
-import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.util.HashMap;
+
+import jdk.internal.vm.annotation.Stable;
 
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaType;
@@ -44,7 +43,15 @@
 
     private final HotSpotResolvedObjectTypeImpl holder;
     private JavaType type;
+
+    /**
+     * Value of {@code fieldDescriptor::access_flags()}.
+     */
     private final int offset;
+
+    /**
+     * Value of {@code fieldDescriptor::index()}.
+     */
     private final short index;
 
     /**
@@ -68,7 +75,7 @@
         if (this == obj) {
             return true;
         }
-        if (obj instanceof HotSpotResolvedJavaField) {
+        if (obj instanceof HotSpotResolvedJavaFieldImpl) {
             HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj;
             if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
                 return false;
@@ -86,7 +93,7 @@
 
     @Override
     public int getModifiers() {
-        return modifiers & jvmFieldModifiers();
+        return modifiers & HotSpotModifiers.jvmFieldModifiers();
     }
 
     @Override
@@ -101,12 +108,12 @@
      *         {@code object}'s class
      */
     @Override
-    public boolean isInObject(JavaConstant constant) {
+    public boolean isInObject(JavaConstant object) {
         if (isStatic()) {
             return false;
         }
-        Object object = ((HotSpotObjectConstantImpl) constant).object();
-        return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass()));
+        HotSpotObjectConstant constant = (HotSpotObjectConstant) object;
+        return getDeclaringClass().isAssignableFrom(constant.getType());
     }
 
     @Override
@@ -127,12 +134,13 @@
         if (currentType instanceof UnresolvedJavaType) {
             // Don't allow unresolved types to hang around forever
             UnresolvedJavaType unresolvedType = (UnresolvedJavaType) currentType;
-            ResolvedJavaType resolved = holder.lookupType(unresolvedType, false);
-            if (resolved != null) {
+            JavaType resolved = HotSpotJVMCIRuntime.runtime().lookupType(unresolvedType.getName(), holder, false);
+            if (resolved instanceof ResolvedJavaType) {
                 type = resolved;
             }
         }
         return type;
+
     }
 
     @Override
@@ -140,9 +148,17 @@
         return offset;
     }
 
+    /**
+     * Gets the value of this field's index (i.e. {@code fieldDescriptor::index()} in the encoded
+     * fields of the declaring class.
+     */
+    int getIndex() {
+        return index;
+    }
+
     @Override
     public String toString() {
-        return format("HotSpotField<%H.%n %t:") + offset + ">";
+        return format("HotSpotResolvedJavaFieldImpl<%H.%n %t:") + offset + ">";
     }
 
     @Override
@@ -151,9 +167,9 @@
     }
 
     /**
-     * Checks if this field has the {@code Stable} annotation.
+     * Checks if this field has the {@link Stable} annotation.
      *
-     * @return true if field has {@code Stable} annotation, false otherwise
+     * @return true if field has {@link Stable} annotation, false otherwise
      */
     @Override
     public boolean isStable() {
@@ -180,7 +196,7 @@
         if (!hasAnnotations()) {
             return new Annotation[0];
         }
-        return toJava().getAnnotations();
+        return runtime().reflection.getFieldAnnotations(this);
     }
 
     @Override
@@ -188,7 +204,7 @@
         if (!hasAnnotations()) {
             return new Annotation[0];
         }
-        return toJava().getDeclaredAnnotations();
+        return runtime().reflection.getFieldDeclaredAnnotations(this);
     }
 
     @Override
@@ -196,29 +212,6 @@
         if (!hasAnnotations()) {
             return null;
         }
-        return toJava().getAnnotation(annotationClass);
-    }
-
-    /**
-     * Gets a {@link Field} object corresponding to this object. This method always returns the same
-     * {@link Field} object for a given {@link HotSpotResolvedJavaFieldImpl}. This ensures
-     * {@link #getDeclaredAnnotations()}, {@link #getAnnotations()} and
-     * {@link #getAnnotation(Class)} are stable with respect to the identity of the
-     * {@link Annotation} objects they return.
-     */
-    private Field toJava() {
-        synchronized (holder) {
-            HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = holder.reflectionFieldCache;
-            if (cache == null) {
-                cache = new HashMap<>();
-                holder.reflectionFieldCache = cache;
-            }
-            Field reflect = cache.get(this);
-            if (reflect == null) {
-                reflect = compilerToVM().asReflectionField(holder, index);
-                cache.put(this, reflect);
-            }
-            return reflect;
-        }
+        return runtime().reflection.getFieldAnnotation(this, annotationClass);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -35,8 +35,6 @@
 import java.lang.reflect.Executable;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
 
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
@@ -58,23 +56,24 @@
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
  */
-final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceWrapperObject {
+final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, MetaspaceHandleObject {
 
     /**
-     * Reference to metaspace Method object.
+     * Handle to the metaspace {@code Method} object. The handle is in
+     * {@code JVMCI::_metadata_handles}.
      */
-    private final long metaspaceMethod;
+    private final long metadataHandle;
 
     private final HotSpotResolvedObjectTypeImpl holder;
     private final HotSpotConstantPool constantPool;
-    private final HotSpotSignature signature;
+    final HotSpotSignature signature;
     private HotSpotMethodData methodData;
     private byte[] code;
 
     /**
-     * Cache for {@link #toJava()}.
+     * Cache for {@link HotSpotJDKReflection#getMethod}.
      */
-    private volatile Executable toJavaCache;
+    volatile Executable toJavaCache;
 
     /**
      * Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
@@ -85,35 +84,40 @@
     /**
      * Gets the holder of a HotSpot metaspace method native object.
      *
-     * @param metaspaceMethod a metaspace Method object
+     * @param metaspaceHandle a handle to a metaspace Method object
      * @return the {@link ResolvedJavaType} corresponding to the holder of the
      *         {@code metaspaceMethod}
      */
-    private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) {
+    private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceHandle) {
         HotSpotVMConfig config = config();
+        long metaspaceMethod = UNSAFE.getLong(metaspaceHandle);
+        assert metaspaceMethod != 0 : metaspaceHandle;
         final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset);
         final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset);
-        return compilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false);
+        HotSpotResolvedObjectTypeImpl result = compilerToVM().getResolvedJavaType(metaspaceConstantPool + config.constantPoolHolderOffset, false);
+        assert result != null;
+        return result;
     }
 
     /**
      * Gets the JVMCI mirror from a HotSpot method. The VM is responsible for ensuring that the
-     * Method* is kept alive for the duration of this call and the
-     * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that.
-     *
+     * Method* is kept alive for the duration of this call and the {@link HotSpotJVMCIRuntime} keeps
+     * it alive after that.
+     * <p>
      * Called from the VM.
      *
-     * @param metaspaceMethod a metaspace Method object
+     * @param metaspaceHandle a handle to metaspace Method object
      * @return the {@link ResolvedJavaMethod} corresponding to {@code metaspaceMethod}
      */
     @SuppressWarnings("unused")
-    private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceMethod) {
-        HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceMethod);
-        return holder.createMethod(metaspaceMethod);
+    @VMEntryPoint
+    private static HotSpotResolvedJavaMethod fromMetaspace(long metaspaceHandle) {
+        HotSpotResolvedObjectTypeImpl holder = getHolder(metaspaceHandle);
+        return holder.createMethod(metaspaceHandle);
     }
 
-    HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) {
-        this.metaspaceMethod = metaspaceMethod;
+    HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceHandle) {
+        this.metadataHandle = metaspaceHandle;
         this.holder = holder;
 
         HotSpotVMConfig config = config();
@@ -133,6 +137,7 @@
 
         final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset);
         this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
+        HandleCleaner.create(this, metaspaceHandle);
     }
 
     /**
@@ -144,8 +149,7 @@
      * @return pointer to this method's ConstMethod
      */
     private long getConstMethod() {
-        assert metaspaceMethod != 0;
-        return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset);
+        return UNSAFE.getAddress(getMetaspaceMethod() + config().methodConstMethodOffset);
     }
 
     @Override
@@ -164,14 +168,14 @@
         }
         if (obj instanceof HotSpotResolvedJavaMethodImpl) {
             HotSpotResolvedJavaMethodImpl that = (HotSpotResolvedJavaMethodImpl) obj;
-            return that.metaspaceMethod == metaspaceMethod;
+            return that.getMetaspaceMethod() == getMetaspaceMethod();
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        return (int) metaspaceMethod;
+        return (int) getMetaspaceMethod();
     }
 
     /**
@@ -180,7 +184,7 @@
      * @return flags of this method
      */
     private int getFlags() {
-        return UNSAFE.getShort(metaspaceMethod + config().methodFlagsOffset);
+        return UNSAFE.getShort(getMetaspaceMethod() + config().methodFlagsOffset);
     }
 
     /**
@@ -204,9 +208,17 @@
         return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
     }
 
+    long getMetaspaceMethod() {
+        long metaspacePointer = getMetaspacePointer();
+        if (metaspacePointer == 0) {
+            throw new NullPointerException("Method* is null");
+        }
+        return metaspacePointer;
+    }
+
     @Override
-    public long getMetaspacePointer() {
-        return metaspaceMethod;
+    public long getMetadataHandle() {
+        return metadataHandle;
     }
 
     @Override
@@ -219,7 +231,7 @@
      * modifiers as well as the HotSpot internal modifiers.
      */
     public int getAllModifiers() {
-        return UNSAFE.getInt(metaspaceMethod + config().methodAccessFlagsOffset);
+        return UNSAFE.getInt(getMetaspaceMethod() + config().methodAccessFlagsOffset);
     }
 
     @Override
@@ -277,7 +289,7 @@
                 // Check for Throwable which catches everything.
                 if (catchType instanceof HotSpotResolvedObjectTypeImpl) {
                     HotSpotResolvedObjectTypeImpl resolvedType = (HotSpotResolvedObjectTypeImpl) catchType;
-                    if (resolvedType.mirror() == Throwable.class) {
+                    if (resolvedType.equals(runtime().getJavaLangThrowable())) {
                         catchTypeIndex = 0;
                         catchType = null;
                     }
@@ -424,7 +436,7 @@
      */
     private long getCompiledCode() {
         HotSpotVMConfig config = config();
-        return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset);
+        return UNSAFE.getAddress(getMetaspaceMethod() + config.methodCodeOffset);
     }
 
     /**
@@ -455,7 +467,7 @@
         ProfilingInfo info;
 
         if (Option.UseProfilingInformation.getBoolean() && methodData == null) {
-            long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset);
+            long metaspaceMethodData = UNSAFE.getAddress(getMetaspaceMethod() + config().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData, this);
                 String methodDataFilter = Option.TraceMethodDataFilter.getString();
@@ -490,14 +502,7 @@
         if (signature.getParameterCount(false) == 0) {
             return new ResolvedJavaMethod.Parameter[0];
         }
-        java.lang.reflect.Parameter[] javaParameters = toJava().getParameters();
-        Parameter[] res = new Parameter[javaParameters.length];
-        for (int i = 0; i < res.length; i++) {
-            java.lang.reflect.Parameter src = javaParameters[i];
-            String paramName = src.isNamePresent() ? src.getName() : null;
-            res[i] = new Parameter(paramName, src.getModifiers(), this, i);
-        }
-        return res;
+        return runtime().reflection.getParameters(this);
     }
 
     @Override
@@ -505,7 +510,7 @@
         if ((getConstMethodFlags() & config().constMethodHasParameterAnnotations) == 0) {
             return new Annotation[signature.getParameterCount(false)][0];
         }
-        return toJava().getParameterAnnotations();
+        return runtime().reflection.getParameterAnnotations(this);
     }
 
     @Override
@@ -513,7 +518,7 @@
         if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
             return new Annotation[0];
         }
-        return toJava().getAnnotations();
+        return runtime().reflection.getMethodAnnotations(this);
     }
 
     @Override
@@ -521,7 +526,7 @@
         if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
             return new Annotation[0];
         }
-        return toJava().getDeclaredAnnotations();
+        return runtime().reflection.getMethodDeclaredAnnotations(this);
     }
 
     @Override
@@ -529,7 +534,7 @@
         if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
             return null;
         }
-        return toJava().getAnnotation(annotationClass);
+        return runtime().reflection.getMethodAnnotation(this, annotationClass);
     }
 
     @Override
@@ -559,19 +564,7 @@
         if (isClassInitializer()) {
             return new Type[0];
         }
-        return toJava().getGenericParameterTypes();
-    }
-
-    private Executable toJava() {
-        if (toJavaCache == null) {
-            assert !isClassInitializer() : this;
-            synchronized (this) {
-                if (toJavaCache == null) {
-                    toJavaCache = compilerToVM().asReflectionExecutable(this);
-                }
-            }
-        }
-        return toJavaCache;
+        return runtime().reflection.getGenericParameterTypes(this);
     }
 
     @Override
@@ -698,7 +691,7 @@
     private int getVtableIndex() {
         assert !holder.isInterface();
         HotSpotVMConfig config = config();
-        int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        int result = UNSAFE.getInt(getMetaspaceMethod() + config.methodVtableIndexOffset);
         assert result >= config.nonvirtualVtableIndex : "must be linked";
         return result;
     }
@@ -708,40 +701,16 @@
         return compilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this);
     }
 
-    /**
-     * The {@link SpeculationLog} for methods compiled by JVMCI hang off this per-declaring-type
-     * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is
-     * never moves and b) we never read from it.
-     * <p>
-     * One implication is that we will preserve {@link SpeculationLog}s for methods that have been
-     * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot
-     * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods
-     * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal).
-     */
-    private static final ClassValue<Map<Long, SpeculationLog>> SpeculationLogs = new ClassValue<>() {
-        @Override
-        protected Map<Long, SpeculationLog> computeValue(java.lang.Class<?> type) {
-            return new HashMap<>(4);
-        }
-    };
-
     @Override
     public SpeculationLog getSpeculationLog() {
-        Map<Long, SpeculationLog> map = SpeculationLogs.get(holder.mirror());
-        synchronized (map) {
-            SpeculationLog log = map.get(this.metaspaceMethod);
-            if (log == null) {
-                log = new HotSpotSpeculationLog();
-                map.put(metaspaceMethod, log);
-            }
-            return log;
-        }
+        long address = compilerToVM().getFailedSpeculationsAddress(this);
+        return new HotSpotSpeculationLog(address);
     }
 
     @Override
     public int intrinsicId() {
         HotSpotVMConfig config = config();
-        return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset);
+        return UNSAFE.getChar(getMetaspaceMethod() + config.methodIntrinsicIdOffset);
     }
 
     @Override
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -22,6 +22,7 @@
  */
 package jdk.vm.ci.hotspot;
 
+import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
 public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
@@ -30,20 +31,13 @@
         super(name);
     }
 
-    abstract Class<?> mirror();
-
     @Override
-    public final boolean equals(Object obj) {
-        if (!(obj instanceof HotSpotResolvedJavaType)) {
-            return false;
-        }
-        HotSpotResolvedJavaType that = (HotSpotResolvedJavaType) obj;
-        return this.mirror().equals(that.mirror());
-    }
+    public abstract boolean equals(Object obj);
 
     @Override
     public final int hashCode() {
         return getName().hashCode();
     }
 
+    abstract JavaConstant getJavaMirror();
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -31,10 +31,7 @@
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.nio.ByteOrder;
 import java.util.HashMap;
@@ -56,9 +53,11 @@
 import jdk.vm.ci.meta.UnresolvedJavaType;
 
 /**
- * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
+ * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. This class is not
+ * an {@link MetaspaceHandleObject} because it doesn't have to be scanned for GC. It's liveness is
+ * maintained by a reference to the {@link Class} instance.
  */
-final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceWrapperObject {
+final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceObject {
 
     private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
     private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
@@ -66,94 +65,71 @@
     /**
      * The Java class this type represents.
      */
-    private final Class<?> javaClass;
+    private final long metadataPointer;
+
     private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
     private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
-    private HotSpotResolvedJavaField[] instanceFields;
-    private HotSpotResolvedObjectTypeImpl[] interfaces;
+    private volatile HotSpotResolvedJavaField[] instanceFields;
+    private volatile HotSpotResolvedObjectTypeImpl[] interfaces;
     private HotSpotConstantPool constantPool;
-    final HotSpotJVMCIMetaAccessContext context;
     private HotSpotResolvedObjectType arrayOfType;
+    private final JavaConstant mirror;
+    private HotSpotResolvedObjectTypeImpl superClass;
 
     /**
-     * Managed exclusively by {@link HotSpotResolvedJavaFieldImpl#toJava}.
+     * Managed exclusively by {@link HotSpotJDKReflection#getField}.
      */
     HashMap<HotSpotResolvedJavaFieldImpl, Field> reflectionFieldCache;
 
-    /**
-     * Gets the JVMCI mirror for a {@link Class} object.
-     *
-     * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
-     */
-    static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
-        return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
+    static HotSpotResolvedObjectTypeImpl getJavaLangObject() {
+        return runtime().getJavaLangObject();
     }
 
     /**
-     * Gets the JVMCI mirror from a HotSpot type. Since {@link Class} is already a proxy for the
-     * underlying Klass*, it is used instead of the raw Klass*.
+     * Gets the JVMCI mirror from a HotSpot type.
      *
      * Called from the VM.
      *
-     * @param javaClass a {@link Class} object
+     * @param klassPointer a native pointer to the Klass*
      * @return the {@link ResolvedJavaType} corresponding to {@code javaClass}
      */
     @SuppressWarnings("unused")
-    private static HotSpotResolvedObjectTypeImpl fromMetaspace(Class<?> javaClass) {
-        return fromObjectClass(javaClass);
+    @VMEntryPoint
+    private static HotSpotResolvedObjectTypeImpl fromMetaspace(long klassPointer, String signature) {
+        return runtime().fromMetaspace(klassPointer, signature);
     }
 
     /**
      * Creates the JVMCI mirror for a {@link Class} object.
      *
-     * <p>
      * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
-     * {@link Class} type. Use {@link #fromObjectClass(Class)} or {@link #fromMetaspace(Class)}
-     * instead.
+     * {@link Class} type. {@link #fromMetaspace} instead.
      * </p>
      *
-     * @param javaClass the Class to create the mirror for
-     * @param context
+     * @param metadataPointer the Klass* to create the mirror for
      */
-    HotSpotResolvedObjectTypeImpl(Class<?> javaClass, HotSpotJVMCIMetaAccessContext context) {
-        super(getSignatureName(javaClass));
-        this.javaClass = javaClass;
-        this.context = context;
+    HotSpotResolvedObjectTypeImpl(long metadataPointer, String name) {
+        super(name);
+        this.metadataPointer = metadataPointer;
+        this.mirror = runtime().compilerToVm.getJavaMirror(this);
+        assert metadataPointer != 0;
         assert getName().charAt(0) != '[' || isArray() : getName();
     }
 
     /**
-     * Returns the name of this type as it would appear in a signature.
-     */
-    private static String getSignatureName(Class<?> javaClass) {
-        if (javaClass.isArray()) {
-            return javaClass.getName().replace('.', '/');
-        }
-        return "L" + javaClass.getName().replace('.', '/') + ";";
-    }
-
-    /**
      * Gets the metaspace Klass for this type.
      */
     long getMetaspaceKlass() {
-        if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
-            return UNSAFE.getLong(javaClass, config().klassOffset);
+        long metaspacePointer = getMetaspacePointer();
+        if (metaspacePointer == 0) {
+            throw new NullPointerException("Klass* is null");
         }
-        return UNSAFE.getInt(javaClass, config().klassOffset) & 0xFFFFFFFFL;
+        return metaspacePointer;
     }
 
     @Override
     public long getMetaspacePointer() {
-        return getMetaspaceKlass();
-    }
-
-    /**
-     * The Klass* for this object is kept alive by the direct reference to {@link #javaClass} so no
-     * extra work is required.
-     */
-    @Override
-    public boolean isRegistered() {
-        return true;
+        return metadataPointer;
     }
 
     @Override
@@ -173,15 +149,18 @@
     @Override
     public HotSpotResolvedObjectType getArrayClass() {
         if (arrayOfType == null) {
-            arrayOfType = fromObjectClass(Array.newInstance(mirror(), 0).getClass());
+            try {
+                arrayOfType = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + getName(), this, true);
+            } catch (ClassNotFoundException e) {
+                throw new JVMCIError(e);
+            }
         }
         return arrayOfType;
     }
 
     @Override
     public ResolvedJavaType getComponentType() {
-        Class<?> javaComponentType = mirror().getComponentType();
-        return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
+        return runtime().compilerToVm.getComponentType(this);
     }
 
     @Override
@@ -279,19 +258,35 @@
 
     @Override
     public HotSpotResolvedObjectTypeImpl getSuperclass() {
-        Class<?> javaSuperclass = mirror().getSuperclass();
-        return javaSuperclass == null ? null : fromObjectClass(javaSuperclass);
+        if (isInterface()) {
+            return null;
+        }
+        HotSpotResolvedObjectTypeImpl javaLangObject = runtime().getJavaLangObject();
+        if (this.equals(javaLangObject)) {
+            return null;
+        }
+        if (isArray()) {
+            return javaLangObject;
+        }
+
+        // Cache result of native call
+        if (superClass == null) {
+            superClass = compilerToVM().getResolvedJavaType(this, config().superOffset, false);
+        }
+        return superClass;
     }
 
     @Override
     public HotSpotResolvedObjectTypeImpl[] getInterfaces() {
         if (interfaces == null) {
-            Class<?>[] javaInterfaces = mirror().getInterfaces();
-            HotSpotResolvedObjectTypeImpl[] result = new HotSpotResolvedObjectTypeImpl[javaInterfaces.length];
-            for (int i = 0; i < javaInterfaces.length; i++) {
-                result[i] = fromObjectClass(javaInterfaces[i]);
+            if (isArray()) {
+                HotSpotResolvedObjectTypeImpl[] types = new HotSpotResolvedObjectTypeImpl[2];
+                types[0] = runtime().getJavaLangCloneable();
+                types[1] = runtime().getJavaLangSerializable();
+                this.interfaces = types;
+            } else {
+                interfaces = runtime().compilerToVm.getInterfaces(this);
             }
-            interfaces = result;
         }
         return interfaces;
     }
@@ -308,13 +303,14 @@
     public HotSpotResolvedObjectTypeImpl getSupertype() {
         if (isArray()) {
             ResolvedJavaType componentType = getComponentType();
-            if (mirror() == Object[].class || componentType.isPrimitive()) {
-                return fromObjectClass(Object.class);
+            if (componentType.equals(getJavaLangObject()) || componentType.isPrimitive()) {
+                return getJavaLangObject();
             }
-            return (HotSpotResolvedObjectTypeImpl) ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype().getArrayClass();
+            HotSpotResolvedObjectTypeImpl supertype = ((HotSpotResolvedObjectTypeImpl) componentType).getSupertype();
+            return (HotSpotResolvedObjectTypeImpl) supertype.getArrayClass();
         }
         if (isInterface()) {
-            return fromObjectClass(Object.class);
+            return getJavaLangObject();
         }
         return getSuperclass();
     }
@@ -354,18 +350,14 @@
     }
 
     @Override
-    public boolean isPrimitive() {
-        return false;
-    }
-
-    @Override
     public boolean isArray() {
-        return mirror().isArray();
+        return layoutHelper() < config().klassLayoutHelperNeutralValue;
     }
 
     @Override
     public boolean isEnum() {
-        return mirror().isEnum();
+        HotSpotResolvedObjectTypeImpl superclass = getSuperclass();
+        return superclass != null && superclass.equals(runtime().getJavaLangEnum());
     }
 
     @Override
@@ -392,7 +384,7 @@
     @Override
     public void initialize() {
         if (!isInitialized()) {
-            UNSAFE.ensureClassInitialized(mirror());
+            runtime().compilerToVm.ensureInitialized(this);
             assert isInitialized();
         }
     }
@@ -400,7 +392,7 @@
     @Override
     public boolean isInstance(JavaConstant obj) {
         if (obj.getJavaKind() == JavaKind.Object && !obj.isNull()) {
-            return mirror().isInstance(((HotSpotObjectConstantImpl) obj).object());
+            return runtime().reflection.isInstance(this, (HotSpotObjectConstantImpl) obj);
         }
         return false;
     }
@@ -412,7 +404,7 @@
 
     @Override
     public boolean isInterface() {
-        return mirror().isInterface();
+        return (getAccessFlags() & config().jvmAccInterface) != 0;
     }
 
     @Override
@@ -420,7 +412,7 @@
         assert other != null;
         if (other instanceof HotSpotResolvedObjectTypeImpl) {
             HotSpotResolvedObjectTypeImpl otherType = (HotSpotResolvedObjectTypeImpl) other;
-            return mirror().isAssignableFrom(otherType.mirror());
+            return runtime().reflection.isAssignableFrom(this, otherType);
         }
         return false;
     }
@@ -435,7 +427,7 @@
 
     @Override
     public boolean isJavaLangObject() {
-        return javaClass.equals(Object.class);
+        return getName().equals("Ljava/lang/Object;");
     }
 
     @Override
@@ -501,6 +493,7 @@
     @Override
     public int layoutHelper() {
         HotSpotVMConfig config = config();
+        assert getMetaspaceKlass() != 0 : getName();
         return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
     }
 
@@ -509,7 +502,8 @@
         return compilerToVM().getFingerprint(getMetaspaceKlass());
     }
 
-    synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
+    synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceHandle) {
+        long metaspaceMethod = UNSAFE.getLong(metaspaceHandle);
         // Maintain cache as array.
         if (methodCacheArray == null) {
             methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
@@ -519,11 +513,10 @@
         for (; i < methodCacheArray.length; ++i) {
             HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i];
             if (curMethod == null) {
-                HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+                HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceHandle);
                 methodCacheArray[i] = newMethod;
-                context.add(newMethod);
                 return newMethod;
-            } else if (curMethod.getMetaspacePointer() == metaspaceMethod) {
+            } else if (curMethod.getMetaspaceMethod() == metaspaceMethod) {
                 return curMethod;
             }
         }
@@ -535,9 +528,8 @@
 
         HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod);
         if (lookupResult == null) {
-            HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
+            HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceHandle);
             methodCacheHashMap.put(metaspaceMethod, newMethod);
-            context.add(lookupResult);
             return newMethod;
         } else {
             return lookupResult;
@@ -599,6 +591,27 @@
         return new FieldInfo(index);
     }
 
+    public void ensureInitialized() {
+        runtime().compilerToVm.ensureInitialized(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof HotSpotResolvedObjectTypeImpl)) {
+            return false;
+        }
+        HotSpotResolvedObjectTypeImpl that = (HotSpotResolvedObjectTypeImpl) obj;
+        return getMetaspaceKlass() == that.getMetaspaceKlass();
+    }
+
+    @Override
+    JavaConstant getJavaMirror() {
+        return mirror;
+    }
+
     /**
      * This class represents the field information for one field contained in the fields array of an
      * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
@@ -782,11 +795,6 @@
     }
 
     @Override
-    public Class<?> mirror() {
-        return javaClass;
-    }
-
-    @Override
     public String getSourceFileName() {
         HotSpotVMConfig config = config();
         final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
@@ -798,17 +806,17 @@
 
     @Override
     public Annotation[] getAnnotations() {
-        return mirror().getAnnotations();
+        return runtime().reflection.getAnnotations(this);
     }
 
     @Override
     public Annotation[] getDeclaredAnnotations() {
-        return mirror().getDeclaredAnnotations();
+        return runtime().reflection.getDeclaredAnnotations(this);
     }
 
     @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        return mirror().getAnnotation(annotationClass);
+        return runtime().reflection.getAnnotation(this, annotationClass);
     }
 
     /**
@@ -828,12 +836,17 @@
         }
         if (elementType.getName().startsWith("Ljava/")) {
             // Classes in a java.* package can only be defined by the
-            // boot or platform class loader.
+            // boot class loader. This is enforced by ClassLoader.preDefineClass()
+            assert hasSameClassLoader(runtime().getJavaLangObject());
             return true;
         }
-        ClassLoader thisCl = mirror().getClassLoader();
-        ClassLoader accessingClassCl = ((HotSpotResolvedObjectTypeImpl) accessingClass).mirror().getClassLoader();
-        return thisCl == accessingClassCl;
+        HotSpotResolvedObjectTypeImpl otherMirror = ((HotSpotResolvedObjectTypeImpl) accessingClass);
+        return hasSameClassLoader(otherMirror);
+    }
+
+    private boolean hasSameClassLoader(HotSpotResolvedObjectTypeImpl otherMirror) {
+        return UnsafeAccess.UNSAFE.getAddress(getMetaspaceKlass() + config().classLoaderDataOffset) == UnsafeAccess.UNSAFE.getAddress(
+                        otherMirror.getMetaspaceKlass() + config().classLoaderDataOffset);
     }
 
     @Override
@@ -887,16 +900,15 @@
 
     private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) {
         for (ResolvedJavaField field : declaredFields) {
-            HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field;
-            long resolvedFieldOffset = resolvedField.getOffset();
+            long resolvedFieldOffset = field.getOffset();
             // @formatter:off
-            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN  &&
-                            expectedEntryKind.isPrimitive() &&
-                            !expectedEntryKind.equals(JavaKind.Void) &&
-                            resolvedField.getJavaKind().isPrimitive()) {
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
+                    expectedEntryKind.isPrimitive() &&
+                    !expectedEntryKind.equals(JavaKind.Void) &&
+                    field.getJavaKind().isPrimitive()) {
                 resolvedFieldOffset +=
-                                resolvedField.getJavaKind().getByteCount() -
-                                Math.min(resolvedField.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
+                        field.getJavaKind().getByteCount() -
+                                Math.min(field.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
             }
             if (resolvedFieldOffset == offset) {
                 return field;
@@ -908,40 +920,27 @@
 
     @Override
     public boolean isLocal() {
-        return mirror().isLocalClass();
+        return runtime().reflection.isLocalClass(this);
     }
 
     @Override
     public boolean isMember() {
-        return mirror().isMemberClass();
+        return runtime().reflection.isMemberClass(this);
     }
 
     @Override
-    public HotSpotResolvedObjectTypeImpl getEnclosingType() {
-        final Class<?> encl = mirror().getEnclosingClass();
-        return encl == null ? null : fromObjectClass(encl);
+    public HotSpotResolvedObjectType getEnclosingType() {
+        return runtime().reflection.getEnclosingClass(this);
     }
 
     @Override
     public ResolvedJavaMethod[] getDeclaredConstructors() {
-        Constructor<?>[] constructors = mirror().getDeclaredConstructors();
-        ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length];
-        for (int i = 0; i < constructors.length; i++) {
-            result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(constructors[i]);
-            assert result[i].isConstructor();
-        }
-        return result;
+        return runtime().compilerToVm.getDeclaredConstructors(this);
     }
 
     @Override
     public ResolvedJavaMethod[] getDeclaredMethods() {
-        Method[] methods = mirror().getDeclaredMethods();
-        ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length];
-        for (int i = 0; i < methods.length; i++) {
-            result[i] = runtime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(methods[i]);
-            assert !result[i].isConstructor();
-        }
-        return result;
+        return runtime().compilerToVm.getDeclaredMethods(this);
     }
 
     @Override
@@ -986,6 +985,10 @@
         return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
     }
 
+    JavaConstant readFieldValue(HotSpotResolvedJavaField field, boolean isVolatile) {
+        return runtime().reflection.readFieldValue(this, field, isVolatile);
+    }
+
     private int getMiscFlags() {
         return UNSAFE.getInt(getMetaspaceKlass() + config().instanceKlassMiscFlagsOffset);
     }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -23,12 +23,13 @@
 package jdk.vm.ci.hotspot;
 
 import static java.util.Objects.requireNonNull;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
 import java.lang.reflect.Modifier;
 
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
@@ -42,22 +43,38 @@
  */
 public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType {
 
-    private final JavaKind kind;
+    @NativeImageReinitialize static HotSpotResolvedPrimitiveType[] primitives;
+
+    private JavaKind kind;
+    private HotSpotResolvedObjectType arrayClass;
+    HotSpotObjectConstantImpl mirror;
 
     /**
      * Creates the JVMCI mirror for a primitive {@link JavaKind}.
      *
-     * <p>
-     * <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
-     * {@link Class} type. Use {@link HotSpotJVMCIRuntime#fromClass(Class)} instead.
-     * </p>
-     *
      * @param kind the Kind to create the mirror for
      */
-    HotSpotResolvedPrimitiveType(JavaKind kind) {
+    private HotSpotResolvedPrimitiveType(JavaKind kind, HotSpotObjectConstantImpl mirror) {
         super(String.valueOf(kind.getTypeChar()));
+        this.mirror = mirror;
         this.kind = kind;
-        assert mirror().isPrimitive() : mirror() + " not a primitive type";
+    }
+
+    static HotSpotResolvedPrimitiveType forKind(JavaKind kind) {
+        HotSpotResolvedPrimitiveType primitive = primitives[kind.getBasicType()];
+        assert primitive != null : kind;
+        return primitive;
+    }
+
+    @VMEntryPoint
+    static HotSpotResolvedPrimitiveType fromMetaspace(HotSpotObjectConstantImpl mirror, char typeChar) {
+        JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(typeChar);
+        if (primitives == null) {
+            primitives = new HotSpotResolvedPrimitiveType[JavaKind.Void.getBasicType() + 1];
+        }
+        HotSpotResolvedPrimitiveType result = new HotSpotResolvedPrimitiveType(kind, mirror);
+        primitives[kind.getBasicType()] = result;
+        return result;
     }
 
     @Override
@@ -70,8 +87,14 @@
         if (kind == JavaKind.Void) {
             return null;
         }
-        Class<?> javaArrayMirror = Array.newInstance(mirror(), 0).getClass();
-        return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaArrayMirror);
+        if (arrayClass == null) {
+            try {
+                arrayClass = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + kind.getTypeChar(), null, true);
+            } catch (ClassNotFoundException e) {
+                throw new JVMCIError(e);
+            }
+        }
+        return arrayClass;
     }
 
     @Override
@@ -241,11 +264,6 @@
     }
 
     @Override
-    Class<?> mirror() {
-        return kind.toJavaClass();
-    }
-
-    @Override
     public boolean isLocal() {
         return false;
     }
@@ -279,4 +297,18 @@
     public boolean isCloneableWithAllocation() {
         return false;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof HotSpotResolvedPrimitiveType)) {
+            return false;
+        }
+        HotSpotResolvedPrimitiveType that = (HotSpotResolvedPrimitiveType) obj;
+        return that.kind == kind;
+    }
+
+    @Override
+    JavaConstant getJavaMirror() {
+        return runtime().reflection.getJavaMirror(this);
+    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -27,7 +27,9 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
- * Implementation of {@link InstalledCode} for code installed as a RuntimeStub.
+ * Implementation of {@link InstalledCode} for code installed as a {@code RuntimeStub}. The address
+ * of the {@code RuntimeStub} is stored in {@link InstalledCode#address} and the value of
+ * {@code RuntimeStub::entry_point()} is in {@link InstalledCode#entryPoint}.
  */
 public class HotSpotRuntimeStub extends HotSpotInstalledCode {
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -168,15 +168,17 @@
                 type = (ResolvedJavaType) result;
                 parameterTypes[index] = type;
             } else {
+                assert result != null;
                 return result;
             }
         }
+        assert type != null;
         return type;
     }
 
     @Override
     public String toMethodDescriptor() {
-        assert originalString.equals(Signature.super.toMethodDescriptor());
+        assert originalString.equals(Signature.super.toMethodDescriptor()) : originalString + " != " + Signature.super.toMethodDescriptor();
         return originalString;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationEncoding.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
+
+/**
+ * Implements a {@link SpeculationReasonEncoding} that {@linkplain #getByteArray() produces} a byte
+ * array. Data is added via a {@link DataOutputStream}. When producing the final byte array, if the
+ * total length of data exceeds the length of a SHA-1 digest, then a SHA-1 digest of the data is
+ * produced instead.
+ */
+final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements SpeculationReasonEncoding {
+
+    private DataOutputStream dos = new DataOutputStream(this);
+    private byte[] result;
+
+    HotSpotSpeculationEncoding() {
+        super(SHA1_LENGTH);
+    }
+
+    private void checkOpen() {
+        if (result != null) {
+            throw new IllegalArgumentException("Cannot update closed speculation encoding");
+        }
+    }
+
+    private static final int NULL_METHOD = -1;
+    private static final int NULL_TYPE = -2;
+    private static final int NULL_STRING = -3;
+
+    @Override
+    public void addByte(int value) {
+        checkOpen();
+        try {
+            dos.writeByte(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public void addShort(int value) {
+        checkOpen();
+        try {
+            dos.writeShort(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public void addMethod(ResolvedJavaMethod method) {
+        if (!addNull(method, NULL_METHOD)) {
+            checkOpen();
+            if (method instanceof HotSpotResolvedJavaMethodImpl) {
+                try {
+                    dos.writeLong(((HotSpotResolvedJavaMethodImpl) method).getMetaspaceMethod());
+                } catch (IOException e) {
+                    throw new InternalError(e);
+                }
+            } else {
+                throw new IllegalArgumentException("Cannot encode unsupported type " + method.getClass().getName() + ": " + method.format("%H.%n(%p)"));
+            }
+        }
+    }
+
+    @Override
+    public void addType(ResolvedJavaType type) {
+        if (!addNull(type, NULL_TYPE)) {
+            checkOpen();
+            if (type instanceof HotSpotResolvedObjectTypeImpl) {
+                try {
+                    dos.writeLong(((HotSpotResolvedObjectTypeImpl) type).getMetaspaceKlass());
+                } catch (IOException e) {
+                    throw new InternalError(e);
+                }
+            } else {
+                throw new IllegalArgumentException("Cannot encode unsupported type " + type.getClass().getName() + ": " + type.toClassName());
+            }
+        }
+    }
+
+    @Override
+    public void addString(String value) {
+        if (!addNull(value, NULL_STRING)) {
+            checkOpen();
+            try {
+                dos.writeChars(value);
+            } catch (IOException e) {
+                throw new InternalError(e);
+            }
+        }
+    }
+
+    @Override
+    public void addInt(int value) {
+        checkOpen();
+        try {
+            dos.writeInt(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public void addLong(long value) {
+        checkOpen();
+        try {
+            dos.writeLong(value);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private boolean addNull(Object o, int nullValue) {
+        if (o == null) {
+            addInt(nullValue);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Prototype SHA1 digest that is cloned before use.
+     */
+    private static final MessageDigest SHA1 = getSHA1();
+    private static final int SHA1_LENGTH = SHA1.getDigestLength();
+
+    private static MessageDigest getSHA1() {
+        try {
+            MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
+            sha1.clone();
+            return sha1;
+        } catch (CloneNotSupportedException | NoSuchAlgorithmException e) {
+            // Should never happen given that SHA-1 is mandated in a
+            // compliant Java platform implementation.
+            throw new JVMCIError("Expect a cloneable implementation of a SHA-1 message digest to be available", e);
+        }
+    }
+
+    /**
+     * Gets the final encoded byte array and closes this encoding such that any further attempts to
+     * update it result in an {@link IllegalArgumentException}.
+     */
+    byte[] getByteArray() {
+        if (result == null) {
+            if (count > SHA1_LENGTH) {
+                try {
+                    MessageDigest md = (MessageDigest) SHA1.clone();
+                    md.update(buf, 0, count);
+                    result = md.digest();
+                } catch (CloneNotSupportedException e) {
+                    throw new InternalError(e);
+                }
+            } else {
+                if (buf.length == count) {
+                    // No need to copy the byte array
+                    return buf;
+                }
+                result = Arrays.copyOf(buf, count);
+            }
+            dos = null;
+        }
+        return result;
+    }
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -22,98 +22,340 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.List;
+
+import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.SpeculationLog;
 
+/**
+ * Implements a {@link SpeculationLog} that can be used to:
+ * <ul>
+ * <li>Query failed speculations recorded in a native linked list of {@code FailedSpeculation}s (see
+ * methodData.hpp).</li>
+ * <li>Make speculations during compilation and record them in compiled code. This must only be done
+ * on compilation-local {@link HotSpotSpeculationLog} objects.</li>
+ * </ul>
+ *
+ * The choice of constructor determines whether the native failed speculations list is
+ * {@linkplain #managesFailedSpeculations() managed} by a {@link HotSpotSpeculationLog} object.
+ */
 public class HotSpotSpeculationLog implements SpeculationLog {
+
+    private static final byte[] NO_FLATTENED_SPECULATIONS = {};
+
+    /**
+     * Creates a speculation log that manages a failed speculation list. That is, when this object
+     * dies, the native resources of the list are freed.
+     *
+     * @see #managesFailedSpeculations()
+     * @see #getFailedSpeculationsAddress()
+     */
+    public HotSpotSpeculationLog() {
+        managesFailedSpeculations = true;
+    }
+
+    /**
+     * Creates a speculation log that reads from an externally managed failed speculation list. That
+     * is, the lifetime of the list is independent of this object.
+     *
+     * @param failedSpeculationsAddress an address in native memory at which the pointer to the
+     *            externally managed sailed speculation list resides
+     */
+    public HotSpotSpeculationLog(long failedSpeculationsAddress) {
+        if (failedSpeculationsAddress == 0) {
+            throw new IllegalArgumentException("failedSpeculationsAddress cannot be 0");
+        }
+        this.failedSpeculationsAddress = failedSpeculationsAddress;
+        managesFailedSpeculations = false;
+    }
+
+    /**
+     * Gets the address of the pointer to the native failed speculations list.
+     *
+     * @see #managesFailedSpeculations()
+     */
+    public long getFailedSpeculationsAddress() {
+        if (managesFailedSpeculations) {
+            synchronized (this) {
+                if (failedSpeculationsAddress == 0L) {
+                    failedSpeculationsAddress = UnsafeAccess.UNSAFE.allocateMemory(HotSpotJVMCIRuntime.getHostWordKind().getByteCount());
+                    UnsafeAccess.UNSAFE.putAddress(failedSpeculationsAddress, 0L);
+                    LogCleaner c = new LogCleaner(this, failedSpeculationsAddress);
+                    assert c.address == failedSpeculationsAddress;
+                }
+            }
+        }
+        return failedSpeculationsAddress;
+    }
+
+    /**
+     * Adds {@code speculation} to the native list of failed speculations. To update this object's
+     * view of the failed speculations, {@link #collectFailedSpeculations()} must be called after
+     * this method returns.
+     *
+     * This method exists primarily for testing purposes. Speculations are normally only added to
+     * the list by HotSpot during deoptimization.
+     *
+     * @return {@code false} if the speculation could not be appended to the list
+     */
+    public boolean addFailedSpeculation(Speculation speculation) {
+        return compilerToVM().addFailedSpeculation(getFailedSpeculationsAddress(), ((HotSpotSpeculation) speculation).encoding);
+    }
+
+    /**
+     * Returns {@code true} if the value returned by {@link #getFailedSpeculationsAddress()} is only
+     * valid only as long as this object is alive, {@code false} otherwise.
+     */
+    public boolean managesFailedSpeculations() {
+        return managesFailedSpeculations;
+    }
+
     public static final class HotSpotSpeculation extends Speculation {
-        private JavaConstant encoding;
 
-        HotSpotSpeculation(SpeculationReason reason, JavaConstant encoding) {
+        /**
+         * A speculation id is a long encoding an offset (high 32 bits) and a length (low 32 bts).
+         * Combined, the index and length denote where the {@linkplain #encoding encoded
+         * speculation} is in a {@linkplain HotSpotSpeculationLog#getFlattenedSpeculations
+         * flattened} speculations array.
+         */
+        private final JavaConstant id;
+
+        private final byte[] encoding;
+
+        HotSpotSpeculation(SpeculationReason reason, JavaConstant id, byte[] encoding) {
             super(reason);
+            this.id = id;
             this.encoding = encoding;
         }
 
         public JavaConstant getEncoding() {
-            return encoding;
+            return id;
+        }
+
+        @Override
+        public String toString() {
+            long indexAndLength = id.asLong();
+            int index = decodeIndex(indexAndLength);
+            int length = decodeLength(indexAndLength);
+            return String.format("{0x%016x[index: %d, len: %d, hash: 0x%x]: %s}", indexAndLength, index, length, Arrays.hashCode(encoding), getReason());
         }
     }
 
-    /** Written by the C++ code that performs deoptimization. */
-    private volatile long lastFailed;
+    /**
+     * Address of a pointer to a set of failed speculations. The address is recorded in the nmethod
+     * compiled with this speculation log such that when it fails a speculation, the speculation is
+     * added to the list.
+     */
+    private long failedSpeculationsAddress;
+
+    private final boolean managesFailedSpeculations;
 
-    /** All speculations that have caused a deoptimization. */
-    private Set<SpeculationReason> failedSpeculations;
+    /**
+     * The list of failed speculations read from native memory via
+     * {@link CompilerToVM#getFailedSpeculations}.
+     */
+    private byte[][] failedSpeculations;
 
-    /** Strong references to all reasons embedded in the current nmethod. */
-    private HashMap<SpeculationReason, JavaConstant> speculations;
-
-    private long currentSpeculationID;
+    /**
+     * Speculations made during the compilation associated with this log.
+     */
+    private List<byte[]> speculations;
+    private List<SpeculationReason> speculationReasons;
 
     @Override
-    public synchronized void collectFailedSpeculations() {
-        if (lastFailed != 0) {
-            if (failedSpeculations == null) {
-                failedSpeculations = new HashSet<>(2);
-            }
-            if (speculations != null) {
-                SpeculationReason lastFailedSpeculation = lookupSpeculation(this.lastFailed);
-                if (lastFailedSpeculation != null) {
-                    failedSpeculations.add(lastFailedSpeculation);
-                }
-                lastFailed = 0;
-                speculations = null;
-            }
+    public void collectFailedSpeculations() {
+        if (failedSpeculationsAddress != 0 && UnsafeAccess.UNSAFE.getLong(failedSpeculationsAddress) != 0) {
+            failedSpeculations = compilerToVM().getFailedSpeculations(failedSpeculationsAddress, failedSpeculations);
+            assert failedSpeculations.getClass() == byte[][].class;
         }
     }
 
-    private SpeculationReason lookupSpeculation(long value) {
-        for (Map.Entry<SpeculationReason, JavaConstant> entry : speculations.entrySet()) {
-            if (value == entry.getValue().asLong()) {
-                return entry.getKey();
+    byte[] getFlattenedSpeculations(boolean validate) {
+        if (speculations == null) {
+            return NO_FLATTENED_SPECULATIONS;
+        }
+        if (validate) {
+            int newFailuresStart = failedSpeculations == null ? 0 : failedSpeculations.length;
+            collectFailedSpeculations();
+            if (failedSpeculations != null && failedSpeculations.length != newFailuresStart) {
+                for (SpeculationReason reason : speculationReasons) {
+                    byte[] encoding = encode(reason);
+                    // Only check against new failures
+                    if (contains(failedSpeculations, newFailuresStart, encoding)) {
+                        throw new BailoutException(false, "Speculation failed: " + reason);
+                    }
+                }
             }
         }
-        return null;
+        int size = 0;
+        for (byte[] s : speculations) {
+            size += s.length;
+        }
+        byte[] result = new byte[size];
+        size = 0;
+        for (byte[] s : speculations) {
+            System.arraycopy(s, 0, result, size, s.length);
+            size += s.length;
+        }
+        return result;
     }
 
     @Override
-    public synchronized boolean maySpeculate(SpeculationReason reason) {
-        if (failedSpeculations != null && failedSpeculations.contains(reason)) {
-            return false;
+    public boolean maySpeculate(SpeculationReason reason) {
+        if (failedSpeculations == null) {
+            collectFailedSpeculations();
+        }
+        if (failedSpeculations != null && failedSpeculations.length != 0) {
+            byte[] encoding = encode(reason);
+            return !contains(failedSpeculations, 0, encoding);
         }
         return true;
     }
 
-    @Override
-    public synchronized Speculation speculate(SpeculationReason reason) {
-        if (speculations == null) {
-            speculations = new HashMap<>();
+    /**
+     * @return {@code true} if {@code needle} is in {@code haystack[fromIndex..haystack.length-1]}
+     */
+    private static boolean contains(byte[][] haystack, int fromIndex, byte[] needle) {
+        for (int i = fromIndex; i < haystack.length; i++) {
+            byte[] fs = haystack[i];
+
+            if (Arrays.equals(fs, needle)) {
+                return true;
+            }
         }
-        JavaConstant id = speculations.get(reason);
-        if (id == null) {
-            id = JavaConstant.forLong(++currentSpeculationID);
-            speculations.put(reason, id);
+        return false;
+    }
+
+    private static long encodeIndexAndLength(int index, int length) {
+        return ((long) index) << 32 | length;
+    }
+
+    private static int decodeIndex(long indexAndLength) {
+        return (int) (indexAndLength >>> 32);
+    }
+
+    private static int decodeLength(long indexAndLength) {
+        return (int) indexAndLength & 0xFFFFFFFF;
+    }
+
+    @Override
+    public Speculation speculate(SpeculationReason reason) {
+        byte[] encoding = encode(reason);
+        JavaConstant id;
+        if (speculations == null) {
+            speculations = new ArrayList<>();
+            speculationReasons = new ArrayList<>();
+            id = JavaConstant.forLong(encodeIndexAndLength(0, encoding.length));
+            speculations.add(encoding);
+            speculationReasons.add(reason);
+        } else {
+            id = null;
+            int flattenedIndex = 0;
+            for (byte[] fs : speculations) {
+                if (Arrays.equals(fs, encoding)) {
+                    id = JavaConstant.forLong(encodeIndexAndLength(flattenedIndex, fs.length));
+                    break;
+                }
+                flattenedIndex += fs.length;
+            }
+            if (id == null) {
+                id = JavaConstant.forLong(encodeIndexAndLength(flattenedIndex, encoding.length));
+                speculations.add(encoding);
+                speculationReasons.add(reason);
+            }
         }
-        return new HotSpotSpeculation(reason, id);
+
+        return new HotSpotSpeculation(reason, id, encoding);
+    }
+
+    private static byte[] encode(SpeculationReason reason) {
+        HotSpotSpeculationEncoding encoding = (HotSpotSpeculationEncoding) reason.encode(HotSpotSpeculationEncoding::new);
+        byte[] result = encoding == null ? null : encoding.getByteArray();
+        if (result == null) {
+            throw new IllegalArgumentException(HotSpotSpeculationLog.class.getName() + " expects " + reason.getClass().getName() + ".encode() to return a non-empty encoding");
+        }
+        return result;
+    }
+
+    @Override
+    public boolean hasSpeculations() {
+        return speculations != null;
     }
 
     @Override
-    public synchronized boolean hasSpeculations() {
-        return speculations != null && !speculations.isEmpty();
+    public Speculation lookupSpeculation(JavaConstant constant) {
+        if (constant.isDefaultForKind()) {
+            return NO_SPECULATION;
+        }
+        int flattenedIndex = decodeIndex(constant.asLong());
+        int index = 0;
+        for (byte[] s : speculations) {
+            if (flattenedIndex == 0) {
+                SpeculationReason reason = speculationReasons.get(index);
+                return new HotSpotSpeculation(reason, constant, s);
+            }
+            index++;
+            flattenedIndex -= s.length;
+        }
+        throw new IllegalArgumentException("Unknown encoded speculation: " + constant);
     }
 
     @Override
-    public synchronized Speculation lookupSpeculation(JavaConstant constant) {
-        if (constant.isDefaultForKind()) {
-            return NO_SPECULATION;
+    public String toString() {
+        Formatter buf = new Formatter();
+        buf.format("{managed:%s, failedSpeculationsAddress:0x%x, failedSpeculations:[", managesFailedSpeculations, failedSpeculationsAddress);
+
+        String sep = "";
+        if (failedSpeculations != null) {
+            for (int i = 0; i < failedSpeculations.length; i++) {
+                buf.format("%s{len:%d, hash:0x%x}", sep, failedSpeculations[i].length, Arrays.hashCode(failedSpeculations[i]));
+                sep = ", ";
+            }
+        }
+
+        buf.format("], speculations:[");
+
+        int size = 0;
+        if (speculations != null) {
+            sep = "";
+            for (int i = 0; i < speculations.size(); i++) {
+                byte[] s = speculations.get(i);
+                size += s.length;
+                buf.format("%s{len:%d, hash:0x%x, reason:{%s}}", sep, s.length, Arrays.hashCode(s), speculationReasons.get(i));
+                sep = ", ";
+            }
         }
-        SpeculationReason reason = lookupSpeculation(constant.asLong());
-        assert reason != null : "Speculation should have been registered";
-        return new HotSpotSpeculation(reason, constant);
+        buf.format("], len:%d, hash:0x%x}", size, Arrays.hashCode(getFlattenedSpeculations(false)));
+        return buf.toString();
+    }
+
+    /**
+     * Frees the native memory resources associated with {@link HotSpotSpeculationLog}s once they
+     * become reclaimable.
+     */
+    private static final class LogCleaner extends Cleaner {
+
+        LogCleaner(HotSpotSpeculationLog referent, long address) {
+            super(referent);
+            this.address = address;
+        }
+
+        @Override
+        void doCleanup() {
+            long pointer = UnsafeAccess.UNSAFE.getAddress(address);
+            if (pointer != 0) {
+                compilerToVM().releaseFailedSpeculations(address);
+            }
+            UnsafeAccess.UNSAFE.freeMemory(address);
+        }
+
+        final long address;
     }
 }
+
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -25,6 +25,7 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
+import jdk.vm.ci.services.Services;
 import jdk.internal.misc.Unsafe;
 
 /**
@@ -52,7 +53,7 @@
      * {@linkplain HotSpotJVMCIBackendFactory backend}.
      */
     String getHostArchitectureName() {
-        String arch = System.getProperty("os.arch");
+        String arch = Services.getSavedProperty("os.arch");
         switch (arch) {
             case "x86_64":
                 return "amd64";
@@ -70,16 +71,21 @@
 
     final int objectAlignment = getFlag("ObjectAlignmentInBytes", Integer.class);
 
+    final int hubOffset = getFieldOffset("oopDesc::_metadata._klass", Integer.class, "Klass*");
+
     final int prototypeMarkWordOffset = getFieldOffset("Klass::_prototype_header", Integer.class, "markOop");
     final int subklassOffset = getFieldOffset("Klass::_subklass", Integer.class, "Klass*");
+    final int superOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*");
     final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*");
     final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint");
     final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*");
 
+    final int classLoaderDataOffset = getFieldOffset("Klass::_class_loader_data", Integer.class, "ClassLoaderData*");
+
     /**
      * The offset of the _java_mirror field (of type {@link Class}) in a Klass.
      */
-    final int classMirrorHandleOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "OopHandle");
+    final int javaMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "OopHandle");
 
     final int klassAccessFlagsOffset = getFieldOffset("Klass::_access_flags", Integer.class, "AccessFlags");
     final int klassLayoutHelperOffset = getFieldOffset("Klass::_layout_helper", Integer.class, "jint");
@@ -131,6 +137,7 @@
     final int jvmAccBridge = getConstant("JVM_ACC_BRIDGE", Integer.class);
     final int jvmAccVarargs = getConstant("JVM_ACC_VARARGS", Integer.class);
     final int jvmAccEnum = getConstant("JVM_ACC_ENUM", Integer.class);
+    final int jvmAccInterface = getConstant("JVM_ACC_INTERFACE", Integer.class);
 
     // This is only valid on AMD64.
     final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, osArch.equals("amd64") ? null : 0);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -22,6 +22,9 @@
  */
 package jdk.vm.ci.hotspot;
 
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import jdk.vm.ci.common.JVMCIError;
 
 /**
@@ -50,8 +53,8 @@
             if (notPresent != null) {
                 return notPresent;
             }
-            store.printConfig();
-            throw new JVMCIError("expected VM symbol not found in " + store + ": " + name);
+            throw missingEntry("address", name, store.vmFlags.keySet());
+
         }
         return entry;
     }
@@ -82,8 +85,7 @@
             if (notPresent != null) {
                 return notPresent;
             }
-            store.printConfig();
-            throw new JVMCIError("expected VM constant not found in " + store + ": " + name);
+            throw missingEntry("constant", name, store.vmConstants.keySet());
         }
         return type.cast(convertValue(name, type, c, null));
     }
@@ -112,15 +114,23 @@
      * @throws JVMCIError if the field is static or not present and {@code notPresent} is null
      */
     public <T> T getFieldOffset(String name, Class<T> type, String cppType, T notPresent) {
-        assert type == Integer.class || type == Long.class;
-        VMField entry = getField(name, cppType, notPresent == null);
-        if (entry == null) {
-            return notPresent;
-        }
-        if (entry.address != 0) {
-            throw new JVMCIError("cannot get offset of static field " + name);
-        }
-        return type.cast(convertValue(name, type, entry.offset, cppType));
+        return getFieldOffset0(name, type, notPresent, cppType, null);
+    }
+
+    /**
+     * Gets the offset of a non-static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the offset value will be converted (must be
+     *            {@link Integer} or {@link Long})
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is
+     *            returned in element 0 of this array
+     * @return the offset in bytes of the requested field
+     * @throws JVMCIError if the field is static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldOffset(String name, Class<T> type, T notPresent, String[] outCppType) {
+        return getFieldOffset0(name, type, notPresent, null, outCppType);
     }
 
     /**
@@ -134,7 +144,7 @@
      * @throws JVMCIError if the field is static or not present
      */
     public <T> T getFieldOffset(String name, Class<T> type, String cppType) {
-        return getFieldOffset(name, type, cppType, null);
+        return getFieldOffset0(name, type, null, cppType, null);
     }
 
     /**
@@ -147,7 +157,22 @@
      * @throws JVMCIError if the field is static or not present
      */
     public <T> T getFieldOffset(String name, Class<T> type) {
-        return getFieldOffset(name, type, null, null);
+        return getFieldOffset0(name, type, null, null, null);
+    }
+
+    private <T> T getFieldOffset0(String name, Class<T> type, T notPresent, String inCppType, String[] outCppType) {
+        assert type == Integer.class || type == Long.class;
+        VMField entry = getField(name, inCppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address != 0) {
+            throw new JVMCIError("cannot get offset of static field " + name);
+        }
+        if (outCppType != null) {
+            outCppType[0] = entry.type;
+        }
+        return type.cast(convertValue(name, type, entry.offset, inCppType));
     }
 
     /**
@@ -160,14 +185,21 @@
      * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
      */
     public long getFieldAddress(String name, String cppType, Long notPresent) {
-        VMField entry = getField(name, cppType, notPresent == null);
-        if (entry == null) {
-            return notPresent;
-        }
-        if (entry.address == 0) {
-            throw new JVMCIError(name + " is not a static field");
-        }
-        return entry.address;
+        return getFieldAddress0(name, notPresent, cppType, null);
+    }
+
+    /**
+     * Gets the address of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is
+     *            returned in element 0 of this array
+     * @return the address of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public long getFieldAddress(String name, Long notPresent, String[] outCppType) {
+        return getFieldAddress0(name, notPresent, null, outCppType);
     }
 
     /**
@@ -179,7 +211,21 @@
      * @throws JVMCIError if the field is not static or not present
      */
     public long getFieldAddress(String name, String cppType) {
-        return getFieldAddress(name, cppType, null);
+        return getFieldAddress0(name, null, cppType, null);
+    }
+
+    private long getFieldAddress0(String name, Long notPresent, String inCppType, String[] outCppType) {
+        VMField entry = getField(name, inCppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.address == 0) {
+            throw new JVMCIError(name + " is not a static field");
+        }
+        if (outCppType != null) {
+            outCppType[0] = entry.type;
+        }
+        return entry.address;
     }
 
     /**
@@ -193,14 +239,7 @@
      * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
      */
     public <T> T getFieldValue(String name, Class<T> type, String cppType, T notPresent) {
-        VMField entry = getField(name, cppType, notPresent == null);
-        if (entry == null) {
-            return notPresent;
-        }
-        if (entry.value == null) {
-            throw new JVMCIError(name + " is not a static field");
-        }
-        return type.cast(convertValue(name, type, entry.value, cppType));
+        return getFieldValue0(name, type, notPresent, cppType, null);
     }
 
     /**
@@ -213,7 +252,22 @@
      * @throws JVMCIError if the field is not static or not present
      */
     public <T> T getFieldValue(String name, Class<T> type, String cppType) {
-        return getFieldValue(name, type, cppType, null);
+        return getFieldValue0(name, type, null, cppType, null);
+    }
+
+    /**
+     * Gets the value of a static C++ field.
+     *
+     * @param name fully qualified name of the field
+     * @param type the boxed type to which the constant value will be converted
+     * @param notPresent if non-null and the field is not present then this value is returned
+     * @param outCppType if non-null, the C++ type of the field (e.g., {@code "HeapWord*"}) is
+     *            returned in element 0 of this array
+     * @return the value of the requested field
+     * @throws JVMCIError if the field is not static or not present and {@code notPresent} is null
+     */
+    public <T> T getFieldValue(String name, Class<T> type, T notPresent, String[] outCppType) {
+        return getFieldValue0(name, type, notPresent, null, outCppType);
     }
 
     /**
@@ -225,7 +279,21 @@
      * @throws JVMCIError if the field is not static or not present
      */
     public <T> T getFieldValue(String name, Class<T> type) {
-        return getFieldValue(name, type, null, null);
+        return getFieldValue0(name, type, null, null, null);
+    }
+
+    private <T> T getFieldValue0(String name, Class<T> type, T notPresent, String inCppType, String[] outCppType) {
+        VMField entry = getField(name, inCppType, notPresent == null);
+        if (entry == null) {
+            return notPresent;
+        }
+        if (entry.value == null) {
+            throw new JVMCIError(name + " is not a static field ");
+        }
+        if (outCppType != null) {
+            outCppType[0] = entry.type;
+        }
+        return type.cast(convertValue(name, type, entry.value, inCppType));
     }
 
     /**
@@ -243,8 +311,7 @@
             if (!required) {
                 return null;
             }
-            store.printConfig();
-            throw new JVMCIError("expected VM field not found in " + store + ": " + name);
+            throw missingEntry("field", name, store.vmFields.keySet());
         }
 
         // Make sure the native type is still the type we expect.
@@ -288,8 +355,7 @@
                 if (notPresent != null) {
                     return notPresent;
                 }
-                store.printConfig();
-                throw new JVMCIError("expected VM flag not found in " + store + ": " + name);
+                throw missingEntry("flag", name, store.vmFlags.keySet());
             } else {
                 cppType = null;
             }
@@ -300,6 +366,11 @@
         return type.cast(convertValue(name, type, value, cppType));
     }
 
+    private JVMCIError missingEntry(String category, String name, Set<String> keys) {
+        throw new JVMCIError("expected VM %s not found in %s: %s%nAvailable values:%n    %s", category, store, name,
+                        keys.stream().sorted().collect(Collectors.joining(System.lineSeparator() + "    ")));
+    }
+
     private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
         if (toType == Boolean.class) {
             if (value instanceof String) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl {
+    /**
+     * An object handle in {@code JVMCI::_jvmci_handles}.
+     */
+    final long objectHandle;
+    private int hashCode;
+
+    final IndirectHotSpotObjectConstantImpl base;
+
+    @VMEntryPoint
+    private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) {
+        super(compressed);
+        assert objectHandle != 0 && UnsafeAccess.UNSAFE.getLong(objectHandle) != 0;
+        this.objectHandle = objectHandle;
+        this.base = null;
+        if (!skipRegister) {
+            HandleCleaner.create(this, objectHandle);
+        }
+    }
+
+    private IndirectHotSpotObjectConstantImpl(IndirectHotSpotObjectConstantImpl base, boolean compressed) {
+        super(compressed);
+        // This is a variant of an original object that only varies in compress vs uncompressed.
+        // Instead of creating a new handle, reference that object and objectHandle.
+        this.objectHandle = base.objectHandle;
+        // There should only be on level of indirection to the base object.
+        assert base.base == null || base.base.base == null;
+        this.base = base.base != null ? base.base : base;
+    }
+
+    @Override
+    public JavaConstant compress() {
+        assert !compressed;
+        return new IndirectHotSpotObjectConstantImpl(this, true);
+    }
+
+    @Override
+    public JavaConstant uncompress() {
+        assert compressed;
+        return new IndirectHotSpotObjectConstantImpl(this, false);
+    }
+
+    @Override
+    public int getIdentityHashCode() {
+        int hash = hashCode;
+        if (hash == 0) {
+            hash = runtime().compilerToVm.getIdentityHashCode(this);
+            if (hash == 0) {
+                hash = 31;
+            }
+            hashCode = hash;
+        }
+        return hash;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceHandleObject.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * A tag interface indicating that this type is a handledized wrapper around a HotSpot metaspace
+ * object that requires GC interaction to keep alive.
+ *
+ * It would preferable if this were the base class containing the pointer but that would require
+ * mixins since most of the wrapper types have complex supertype hierarchies.
+ */
+interface MetaspaceHandleObject extends MetaspaceObject {
+
+    long getMetadataHandle();
+
+    @Override
+    default long getMetaspacePointer() {
+        return UnsafeAccess.UNSAFE.getLong(getMetadataHandle());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceObject.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * The marker interface for an object which wraps HotSpot Metadata.
+ */
+interface MetaspaceObject {
+    long getMetaspacePointer();
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Wed May 01 12:41:26 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-package jdk.vm.ci.hotspot;
-
-/**
- * A tag interface indicating that this type is a wrapper around a HotSpot metaspace object that
- * requires GC interaction to keep alive.
- *
- * It would preferable if this were the base class containing the pointer but that would require
- * mixins since most of the wrapper types have complex supertype hierarchies.
- */
-interface MetaspaceWrapperObject {
-
-    long getMetaspacePointer();
-
-    /**
-     * Check if this object is properly registered for metadata tracking. All classes which
-     * implement this interface must be registered with the
-     * {@link HotSpotJVMCIMetaAccessContext#add} unless they are kept alive through other means.
-     * Currently the only type which doesn't require explicit registration is
-     * {@link HotSpotResolvedObjectTypeImpl} since it's kept alive by references to the
-     * {@link Class}.
-     *
-     * @return true if this object is properly registered for meta data tracking.
-     */
-    default boolean isRegistered() {
-        return HotSpotJVMCIRuntime.runtime().metaAccessContext.isRegistered(this);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * Implementation of {@link HotSpotJVMCIReflection} when running in a JVMCI shared library.
+ */
+class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
+
+    @Override
+    Object resolveObject(HotSpotObjectConstantImpl objectHandle) {
+        throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve handle in a JVMCI shared library to a raw object: " + objectHandle);
+    }
+
+    @Override
+    boolean isInstance(HotSpotResolvedObjectTypeImpl holder, HotSpotObjectConstantImpl obj) {
+        if (obj instanceof DirectHotSpotObjectConstantImpl) {
+            ResolvedJavaType type = getType(obj);
+            return holder.isAssignableFrom(type);
+        }
+        return runtime().compilerToVm.isInstance(holder, obj);
+    }
+
+    @Override
+    boolean isAssignableFrom(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedObjectTypeImpl otherType) {
+        return runtime().compilerToVm.isAssignableFrom(holder, otherType);
+    }
+
+    @Override
+    boolean isLocalClass(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.isLocalClass()");
+    }
+
+    @Override
+    boolean isMemberClass(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.isMemberClass()");
+    }
+
+    @Override
+    HotSpotResolvedObjectType getEnclosingClass(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("requires a call Class.getEnclosingClass()");
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotResolvedObjectTypeImpl holder, HotSpotResolvedJavaField field, boolean isVolatile) {
+        JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(holder, field, isVolatile);
+        if (javaConstant == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return javaConstant;
+    }
+
+    @Override
+    JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedJavaField field, boolean isVolatile) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            // cannot read fields from objects due to lack of
+            // general reflection support in native image
+            return null;
+        }
+        JavaConstant javaConstant = runtime().compilerToVm.readFieldValue(object, field, isVolatile);
+        if (javaConstant == null) {
+            return JavaConstant.NULL_POINTER;
+        }
+        return javaConstant;
+    }
+
+    @Override
+    boolean equals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) {
+        if (x == y) {
+            return true;
+        }
+        if (x.compressed != y.compressed) {
+            return false;
+        }
+        if (x instanceof DirectHotSpotObjectConstantImpl && y instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl xd = (DirectHotSpotObjectConstantImpl) x;
+            DirectHotSpotObjectConstantImpl yd = (DirectHotSpotObjectConstantImpl) y;
+            return (xd.object == yd.object);
+        }
+        if (x instanceof DirectHotSpotObjectConstantImpl || y instanceof DirectHotSpotObjectConstantImpl) {
+            // Mixing of constant types is always inequal
+            return false;
+        }
+        IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x;
+        IndirectHotSpotObjectConstantImpl indirectY = (IndirectHotSpotObjectConstantImpl) y;
+        return runtime().compilerToVm.equals(x, indirectX.objectHandle, y, indirectY.objectHandle);
+    }
+
+    @Override
+    JavaConstant getJavaMirror(HotSpotResolvedPrimitiveType hotSpotResolvedPrimitiveType) {
+        return runtime().compilerToVm.getJavaMirror(hotSpotResolvedPrimitiveType);
+    }
+
+    @Override
+    ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) {
+        // ResolvedJavaMethod.getParameters allows a return value of null
+        return null;
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    static Annotation[] getClassAnnotations(String className) {
+        throw new InternalError("missing substitution: " + className);
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    static Annotation[][] getParameterAnnotations(String className, String methodName) {
+        throw new InternalError("missing substitution: " + className + " " + methodName);
+    }
+
+    @Override
+    Annotation[] getAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        return getClassAnnotations(holder.getName());
+    }
+
+    @Override
+    Annotation[] getDeclaredAnnotations(HotSpotResolvedObjectTypeImpl holder) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    <T extends Annotation> T getAnnotation(HotSpotResolvedObjectTypeImpl holder, Class<T> annotationClass) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getParameterAnnotations(javaMethod.getDeclaringClass().getName(), javaMethod.getName());
+    }
+
+    @Override
+    Type[] getGenericParameterTypes(HotSpotResolvedJavaMethodImpl javaMethod) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[] getFieldAnnotations(HotSpotResolvedJavaFieldImpl javaField) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[] getMethodAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        return getMethodAnnotationsInternal(javaMethod);
+    }
+
+    @Override
+    <T extends Annotation> T getMethodAnnotation(HotSpotResolvedJavaMethodImpl javaMethod, Class<T> annotationClass) {
+        Annotation[] methodAnnotations = getMethodAnnotations(javaMethod);
+        if (methodAnnotations != null) {
+            for (Annotation ann : methodAnnotations) {
+                if (annotationClass.isInstance(ann)) {
+                    return annotationClass.cast(ann);
+                }
+            }
+        }
+        return null;
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    @SuppressWarnings("unused")
+    private static Annotation[] getMethodAnnotationsInternal(ResolvedJavaMethod javaMethod) {
+        throw new InternalError("missing substitution");
+    }
+
+    @Override
+    Annotation[] getMethodDeclaredAnnotations(HotSpotResolvedJavaMethodImpl javaMethod) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    Annotation[] getFieldDeclaredAnnotations(HotSpotResolvedJavaFieldImpl javaMethod) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    <T extends Annotation> T getFieldAnnotation(HotSpotResolvedJavaFieldImpl javaField, Class<T> annotationClass) {
+        throw new HotSpotJVMCIUnsupportedOperationError("unimplemented");
+    }
+
+    @Override
+    HotSpotResolvedObjectTypeImpl getType(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            Class<?> theClass = ((DirectHotSpotObjectConstantImpl) object).object.getClass();
+            try {
+                String name = theClass.getName().replace('.', '/');
+                HotSpotResolvedObjectTypeImpl type = (HotSpotResolvedObjectTypeImpl) runtime().compilerToVm.lookupType(name, null, true);
+                if (type == null) {
+                    throw new InternalError(name);
+                }
+                return type;
+            } catch (ClassNotFoundException e) {
+                throw new InternalError(e);
+            }
+        }
+        return runtime().compilerToVm.getResolvedJavaType(object, runtime().getConfig().hubOffset, false);
+    }
+
+    @Override
+    String asString(HotSpotObjectConstantImpl object) {
+        if (object instanceof IndirectHotSpotObjectConstantImpl) {
+            return runtime().compilerToVm.asString(object);
+        }
+        Object value = ((DirectHotSpotObjectConstantImpl) object).object;
+        if (value instanceof String) {
+            return (String) value;
+        }
+        return null;
+    }
+
+    @Override
+    ResolvedJavaType asJavaType(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
+            if (direct.object instanceof Class) {
+                Class<?> javaClass = (Class<?>) direct.object;
+                return runtime().fromClass(javaClass);
+            }
+            if (direct.object instanceof ResolvedJavaType) {
+                return (ResolvedJavaType) convertUnknownValue(direct.object);
+            }
+            return null;
+        }
+        return runtime().compilerToVm.asJavaType(object);
+    }
+
+    // Substituted by Target_jdk_vm_ci_hotspot_SharedLibraryJVMCIReflection
+    static Object convertUnknownValue(Object object) {
+        return object;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    <T> T asObject(HotSpotObjectConstantImpl object, Class<T> type) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            Object theObject = ((DirectHotSpotObjectConstantImpl) object).object;
+            if (type.isInstance(theObject)) {
+                return (T) convertUnknownValue(type.cast(theObject));
+            }
+        }
+        return null;
+    }
+
+    @Override
+    Object asObject(HotSpotObjectConstantImpl object, HotSpotResolvedJavaType type) {
+        throw new HotSpotJVMCIUnsupportedOperationError("cannot resolve a shared library JVMCI object handle to a " +
+                        "raw object as it may be in another runtime");
+    }
+
+    @Override
+    String formatString(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
+            return "CompilerObject<" + direct.object.getClass().getName() + ">";
+        }
+        return "Instance<" + object.getType().toJavaName() + ">";
+    }
+
+    @Override
+    Integer getLength(HotSpotObjectConstantImpl object) {
+        if (object instanceof DirectHotSpotObjectConstantImpl) {
+            DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
+            if (direct.object.getClass().isArray()) {
+                return Array.getLength(direct.object);
+            }
+            return null;
+        }
+        int length = runtime().compilerToVm.getArrayLength(object);
+        if (length >= 0) {
+            return length;
+        }
+        return null;
+    }
+
+    @Override
+    JavaConstant readArrayElement(HotSpotObjectConstantImpl arrayObject, int index) {
+        Object result = runtime().compilerToVm.readArrayElement(arrayObject, index);
+        if (result == null) {
+            return null;
+        }
+        if (result instanceof JavaConstant) {
+            return (JavaConstant) result;
+        }
+        JavaConstant constant = JavaConstant.forBoxedPrimitive(result);
+        if (constant == null) {
+            throw new InternalError("Unexpected value " + result);
+        }
+        return constant;
+    }
+
+    @Override
+    JavaConstant forObject(Object value) {
+        return DirectHotSpotObjectConstantImpl.forObject(value, false);
+    }
+
+    @Override
+    JavaConstant unboxPrimitive(HotSpotObjectConstantImpl source) {
+        Object box = runtime().compilerToVm.unboxPrimitive(source);
+        return JavaConstant.forBoxedPrimitive(box);
+    }
+
+    @Override
+    JavaConstant boxPrimitive(JavaConstant source) {
+        return runtime().compilerToVm.boxPrimitive(source.asBoxedPrimitive());
+    }
+
+    @Override
+    int getInt(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getInt(object, displacement);
+    }
+
+    @Override
+    byte getByte(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getByte(object, displacement);
+    }
+
+    @Override
+    short getShort(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getShort(object, displacement);
+    }
+
+    @Override
+    long getLong(HotSpotObjectConstantImpl object, long displacement) {
+        return runtime().compilerToVm.getLong(object, displacement);
+    }
+
+    @Override
+    void checkRead(HotSpotObjectConstantImpl constant, JavaKind kind, long displacement, HotSpotResolvedObjectType type) {
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.Objects;
+
+/**
+ * Support for translating exceptions between different runtime heaps.
+ */
+@SuppressWarnings("serial")
+final class TranslatedException extends Exception {
+
+    private TranslatedException(String message) {
+        super(message);
+    }
+
+    private TranslatedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * No need to record an initial stack trace since it will be manually overwritten.
+     */
+    @SuppressWarnings("sync-override")
+    @Override
+    public Throwable fillInStackTrace() {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return getMessage();
+    }
+
+    private static TranslatedException create(String className, String message) {
+        if (className.equals(TranslatedException.class.getName())) {
+            // Chop the class name when boxing another TranslatedException
+            return new TranslatedException(message);
+        }
+        if (message == null) {
+            return new TranslatedException(className);
+        }
+        return new TranslatedException(className + ": " + message);
+    }
+
+    private static String encodedString(String value) {
+        return Objects.toString(value, "").replace('|', '_');
+    }
+
+    /**
+     * Encodes {@code throwable} including its stack and causes as a string. The encoding format of
+     * a single exception with its cause is:
+     *
+     * <pre>
+     * <exception class name> '|' <exception message> '|' <stack size> '|' [<class> '|' <method> '|' <file> '|' <line> '|' ]*
+     * </pre>
+     *
+     * Each cause is appended after the exception is it the cause of.
+     */
+    @VMEntryPoint
+    static String encodeThrowable(Throwable throwable) throws Throwable {
+        try {
+            Formatter enc = new Formatter();
+            Throwable current = throwable;
+            do {
+                enc.format("%s|%s|", current.getClass().getName(), encodedString(current.getMessage()));
+                StackTraceElement[] stackTrace = current.getStackTrace();
+                if (stackTrace == null) {
+                    stackTrace = new StackTraceElement[0];
+                }
+                enc.format("%d|", stackTrace.length);
+                for (int i = 0; i < stackTrace.length; i++) {
+                    StackTraceElement frame = stackTrace[i];
+                    if (frame != null) {
+                        enc.format("%s|%s|%s|%d|", frame.getClassName(), frame.getMethodName(),
+                                        encodedString(frame.getFileName()), frame.getLineNumber());
+                    }
+                }
+                current = current.getCause();
+            } while (current != null);
+            return enc.toString();
+        } catch (Throwable e) {
+            try {
+                return e.getClass().getName() + "|" + encodedString(e.getMessage()) + "|0|";
+            } catch (Throwable e2) {
+                return "java.lang.Throwable|too many errors during encoding|0|";
+            }
+        }
+    }
+
+    /**
+     * Gets the stack of the current thread without the frames between this call and the one just
+     * below the frame of the first method in {@link CompilerToVM}. The chopped frames are specific
+     * to the implementation of {@link HotSpotJVMCIRuntime#decodeThrowable(String)}.
+     */
+    private static StackTraceElement[] getStackTraceSuffix() {
+        StackTraceElement[] stack = new Exception().getStackTrace();
+        for (int i = 0; i < stack.length; i++) {
+            StackTraceElement e = stack[i];
+            if (e.getClassName().equals(CompilerToVM.class.getName())) {
+                return Arrays.copyOfRange(stack, i, stack.length);
+            }
+        }
+        // This should never happen but since we're in exception handling
+        // code, just return a safe value instead raising a nested exception.
+        return new StackTraceElement[0];
+    }
+
+    /**
+     * Decodes {@code encodedThrowable} into a {@link TranslatedException}.
+     *
+     * @param encodedThrowable an encoded exception in the format specified by
+     *            {@link #encodeThrowable}
+     */
+    @VMEntryPoint
+    static Throwable decodeThrowable(String encodedThrowable) {
+        try {
+            int i = 0;
+            String[] parts = encodedThrowable.split("\\|");
+            Throwable parent = null;
+            Throwable result = null;
+            while (i != parts.length) {
+                String exceptionClassName = parts[i++];
+                String exceptionMessage = parts[i++];
+                Throwable throwable = create(exceptionClassName, exceptionMessage);
+                int stackTraceDepth = Integer.parseInt(parts[i++]);
+
+                StackTraceElement[] suffix = parent == null ? new StackTraceElement[0] : getStackTraceSuffix();
+                StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length];
+                for (int j = 0; j < stackTraceDepth; j++) {
+                    String className = parts[i++];
+                    String methodName = parts[i++];
+                    String fileName = parts[i++];
+                    int lineNumber = Integer.parseInt(parts[i++]);
+                    if (fileName.isEmpty()) {
+                        fileName = null;
+                    }
+                    stackTrace[j] = new StackTraceElement(className, methodName, fileName, lineNumber);
+                }
+                System.arraycopy(suffix, 0, stackTrace, stackTraceDepth, suffix.length);
+                throwable.setStackTrace(stackTrace);
+                if (parent != null) {
+                    parent.initCause(throwable);
+                } else {
+                    result = throwable;
+                }
+                parent = throwable;
+            }
+            return result;
+        } catch (Throwable t) {
+            return new TranslatedException("Error decoding exception: " + encodedThrowable, t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMEntryPoint.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot;
+
+/**
+ * Marker interface for methods which are called from the JVM.
+ */
+@interface VMEntryPoint {
+    /**
+     * An optional comment describing the caller.
+     */
+    String value() default "";
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMField.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -63,19 +63,20 @@
     }
 
     /**
-     * Creates a description of a field.
+     * Creates a description of a non-static field.
      */
-    VMField(String name, String type, long address, Object value) {
+    @VMEntryPoint
+    VMField(String name, String type, long offset, long address, Object value) {
         this.name = name;
         this.type = type;
-        this.offset = 0;
+        this.offset = offset;
         this.address = address;
         this.value = value;
     }
 
     @Override
     public String toString() {
-        String val = value == null ? "null" : String.format("0x%x", value);
+        String val = value == null ? "null" : (type.contains("*") ? String.format("0x%x", value) : String.format("%s", value));
         return String.format("Field[name=%s, type=%s, offset=%d, address=0x%x, value=%s]", name, type, offset, address, val);
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMFlag.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -42,6 +42,7 @@
      */
     public final Object value;
 
+    @VMEntryPoint
     VMFlag(String name, String type, Object value) {
         this.name = name;
         this.type = type;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/VMIntrinsicMethod.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -54,6 +54,7 @@
      */
     public final int id;
 
+    @VMEntryPoint
     VMIntrinsicMethod(String declaringClass, String name, String descriptor, int id) {
         this.declaringClass = declaringClass;
         this.name = name;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -22,6 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 
 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
@@ -146,7 +147,7 @@
 
         public ProfiledType(ResolvedJavaType type, double probability) {
             super(type, probability);
-            assert type.isArray() || type.isConcrete() : type;
+            assert type.isArray() || type.isConcrete() : type + " " + Modifier.toString(type.getModifiers());
         }
 
         /**
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -102,14 +102,25 @@
      */
     JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId);
 
+    /**
+     * Gets a constant that denotes {@code speculation}. The constant can passed to the
+     * deoptimization handler (e.g., through a thread local) to indicate a failed speculation.
+     */
     JavaConstant encodeSpeculation(Speculation speculation);
 
+    /**
+     * Decodes {@code constant} back to a {@link Speculation} object.
+     *
+     * @throws IllegalArgumentException if {@code constant} can only be decoded through a
+     *             {@link SpeculationLog} and {@code speculationLog} does not contain the
+     *             speculation denoted by {@code constant}
+     */
+    Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog);
+
     DeoptimizationReason decodeDeoptReason(JavaConstant constant);
 
     DeoptimizationAction decodeDeoptAction(JavaConstant constant);
 
-    Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog);
-
     int decodeDebugId(JavaConstant constant);
 
     int getArrayBaseOffset(JavaKind elementKind);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -46,6 +46,10 @@
         assert kind.isPrimitive() || kind == JavaKind.Illegal;
     }
 
+    static PrimitiveConstant forTypeChar(char kind, long i) {
+        return JavaConstant.forIntegerKind(JavaKind.fromPrimitiveOrVoidTypeChar(kind), i);
+    }
+
     @Override
     public JavaKind getJavaKind() {
         return kind;
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -25,7 +25,6 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
@@ -39,7 +38,8 @@
     /**
      * Returns the bytecode of this method, if the method has code. The returned byte array does not
      * contain breakpoints or non-Java bytecodes. This may return null if the
-     * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
+     * {@linkplain #getDeclaringClass() declaring class} is not
+     * {@linkplain ResolvedJavaType#isLinked() linked}.
      *
      * The contained constant pool indices may not be the ones found in the original class file but
      * they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
@@ -439,13 +439,15 @@
     }
 
     /**
-     * Checks whether the method has bytecodes associated with it. Methods without bytecodes are
-     * either abstract or native methods.
+     * Checks whether the method has bytecodes associated with it. Note that even if this method
+     * returns {@code true}, {@link #getCode} can return {@code null} if
+     * {@linkplain #getDeclaringClass() declaring class} is not
+     * {@linkplain ResolvedJavaType#isLinked() linked}.
      *
-     * @return whether the definition of this method is Java bytecodes
+     * @return {@code this.getCodeSize() != 0}
      */
     default boolean hasBytecodes() {
-        return isConcrete() && !isNative();
+        return getCodeSize() != 0;
     }
 
     /**
@@ -464,16 +466,11 @@
         return getDeclaringClass().isJavaLangObject() && getName().equals("<init>");
     }
 
+    /**
+     * Gets a speculation log that can be used when compiling this method to make new speculations
+     * and query previously failed speculations. The implementation may return a new
+     * {@link SpeculationLog} object each time this method is called so its the caller's
+     * responsibility to ensure the same speculation log is used throughout a compilation.
+     */
     SpeculationLog getSpeculationLog();
-
-    /**
-     *
-     * @param object
-     * @param args
-     * @throws InvocationTargetException
-     * @throws IllegalAccessException
-     */
-    default JavaConstant invoke(JavaConstant object, JavaConstant... args) throws InvocationTargetException, IllegalAccessException {
-        throw new InternalError("unimplemented");
-    }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -22,19 +22,72 @@
  */
 package jdk.vm.ci.meta;
 
+import java.util.Map;
+import java.util.function.Supplier;
+
 /**
- * Manages unique deoptimization reasons. Reasons are embedded in compiled code and can be
- * invalidated at run time. Subsequent compilations then should not speculate again on such
- * invalidated reasons to avoid repeated deoptimization.
- *
- * All methods of this interface are called by the compiler. There is no need for API to register
- * failed speculations during deoptimization, since every VM has different needs there.
+ * Manages unique {@link SpeculationReason} objects that denote why a deoptimization occurred.
+ * Reasons are embedded in compiled code for a method. If the compiled code deoptimizes at a
+ * position associated with a {@link SpeculationReason}, the reason is added to a set of failed
+ * speculations associated with the method. A subsequent compilation of the method can query the
+ * failed speculations via a {@link SpeculationLog} to avoid making a speculation based on
+ * invalidated reasons. This avoids repeated deoptimizations.
  */
 public interface SpeculationLog {
     /**
-     * Marker interface for speculation objects that can be added to the speculation log.
+     * The specific attributes of a speculation that a compiler uses to denote a speculation in a
+     * compiled method. Typical attributes of a speculation are a bytecode position, type
+     * information about a variable being speculated on and an enum denoting the type of operation
+     * to which the speculation applies. A {@link SpeculationReason} is used as a key in a
+     * {@link Map} and so it must implement {@link Object#equals(Object)} and
+     * {@link Object#hashCode()} in terms of its attributes.
+     *
+     * A JVMCI implementation may serialize speculations for storage off heap (e.g. in native memory
+     * associated with an nmethod). For this reason, the attributes of a {@link SpeculationReason}
+     * are restricted to those supported by the {@code add...} methods of
+     * {@link SpeculationReasonEncoding}.
      */
     public interface SpeculationReason {
+
+        /**
+         * Encodes the attributes of this reason using a {@link SpeculationReasonEncoding}. For
+         * efficiency, a {@link SpeculationReason} implementation should cache the returned value
+         * and return it for all subsequent calls to this method. This also underlines the
+         * requirement that the encoding for a specific reason instance should be stable.
+         *
+         * @param encodingSupplier source of a {@link SpeculationReasonEncoding}
+         * @return a {@link SpeculationReasonEncoding} that encodes all the attributes that uniquely
+         *         identify this reason
+         */
+        default SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            return null;
+        }
+    }
+
+    /**
+     * Provides a facility for encoding the attributes of a {@link SpeculationReason}. The encoding
+     * format is determined by the implementation of this interface.
+     */
+    public interface SpeculationReasonEncoding {
+        void addByte(int value);
+
+        void addShort(int value);
+
+        void addInt(int value);
+
+        void addLong(long value);
+
+        void addMethod(ResolvedJavaMethod method);
+
+        void addType(ResolvedJavaType type);
+
+        void addString(String value);
+
+        default void addField(ResolvedJavaField field) {
+            addType(field.getDeclaringClass());
+            addInt(field.getModifiers());
+            addInt(field.getOffset());
+        }
     }
 
     /**
@@ -44,7 +97,7 @@
     }
 
     class Speculation {
-        private SpeculationReason reason;
+        private final SpeculationReason reason;
 
         public Speculation(SpeculationReason reason) {
             this.reason = reason;
@@ -77,7 +130,8 @@
     Speculation NO_SPECULATION = new Speculation(new NoSpeculationReason());
 
     /**
-     * Must be called before compilation, i.e., before a compiler calls {@link #maySpeculate}.
+     * Updates the set of failed speculations recorded in this log. This must be called before
+     * compilation.
      */
     void collectFailedSpeculations();
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -24,40 +24,57 @@
 
 import java.util.Formatter;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.services.Services;
+
 public class JVMCI {
 
-    private static final JVMCIRuntime runtime;
+    /**
+     * Singleton instance lazily initialized via double-checked locking.
+     */
+    @NativeImageReinitialize private static volatile JVMCIRuntime runtime;
 
-    private static native JVMCIRuntime initializeRuntime();
+    @NativeImageReinitialize private static boolean initializing;
 
     public static void initialize() {
         // force static initializer
     }
 
+    private static native JVMCIRuntime initializeRuntime();
+
     /**
      * Gets the singleton {@link JVMCIRuntime} instance available to the application.
      *
      * @throws UnsupportedOperationException if JVMCI is not supported
      */
     public static JVMCIRuntime getRuntime() {
-        if (runtime == null) {
-            String javaHome = System.getProperty("java.home");
-            String vmName = System.getProperty("java.vm.name");
-            Formatter errorMessage = new Formatter();
-            errorMessage.format("The VM does not support the JVMCI API.%n");
-            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
-            errorMessage.format("Currently used VM configuration is: %s", vmName);
-            throw new UnsupportedOperationException(errorMessage.toString());
+        JVMCIRuntime result = runtime;
+        if (result == null) {
+            synchronized (JVMCI.class) {
+                result = runtime;
+                if (result == null) {
+                    if (initializing) {
+                        // In recursive call from HotSpotJVMCIRuntime.runtime
+                        // so no need to re-enter initializeRuntime below. This
+                        // path is only entered if JVMCI initialization starts
+                        // with JVMCI.getRuntime().
+                        return null;
+                    }
+                    initializing = true;
+                    try {
+                        runtime = result = initializeRuntime();
+                    } catch (UnsatisfiedLinkError e) {
+                        String javaHome = Services.getSavedProperty("java.home");
+                        String vmName = Services.getSavedProperty("java.vm.name");
+                        Formatter errorMessage = new Formatter();
+                        errorMessage.format("The VM does not support the JVMCI API.%n");
+                        errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+                        errorMessage.format("Currently used VM configuration is: %s", vmName);
+                        throw new UnsupportedOperationException(errorMessage.toString());
+                    }
+                }
+            }
         }
-        return runtime;
-    }
-
-    static {
-        JVMCIRuntime rt = null;
-        try {
-            rt = initializeRuntime();
-        } catch (UnsatisfiedLinkError e) {
-        }
-        runtime = rt;
+        return result;
     }
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml	Wed May 01 12:41:26 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
-    Checkstyle-Configuration: Checks
-    Description: none
--->
-<module name="Checker">
-  <property name="severity" value="error"/>
-  <module name="TreeWalker">
-    <property name="tabWidth" value="4"/>
-    <module name="JavadocStyle">
-      <property name="checkHtml" value="false"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-    <module name="ParameterName"/>
-    <module name="TypeName">
-      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
-    </module>
-    <module name="RedundantImport"/>
-    <module name="LineLength">
-      <property name="max" value="250"/>
-    </module>
-    <module name="MethodParamPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <module name="AvoidStarImport">
-       <property name="allowClassImports" value="false"/>
-       <property name="allowStaticMemberImports" value="false"/>
-    </module>
-    <module name="NoWhitespaceBefore">
-      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
-    </module>
-    <module name="ParenPad"/>
-    <module name="TypecastParenPad">
-      <property name="tokens" value="RPAREN,TYPECAST"/>
-    </module>
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
-    </module>
-    <module name="RedundantModifier"/>
-    <module name="AvoidNestedBlocks">
-      <property name="allowInSwitchCase" value="true"/>
-    </module>
-    <module name="EmptyBlock">
-      <property name="option" value="text"/>
-      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly"/>
-    <module name="NeedBraces"/>
-    <module name="RightCurly"/>
-    <module name="EmptyStatement"/>
-    <module name="HiddenField">
-      <property name="severity" value="ignore"/>
-      <property name="ignoreConstructorParameter" value="true"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="FinalClass"/>
-    <module name="HideUtilityClassConstructor">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ArrayTypeStyle"/>
-    <module name="UpperEll"/>
-    <module name="FallThrough"/>
-    <module name="FinalLocalVariable">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="MultipleVariableDeclarations"/>
-    <module name="StringLiteralEquality">
-      <property name="severity" value="error"/>
-    </module>
-    <module name="SuperFinalize"/>
-    <module name="UnnecessaryParentheses">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="Indentation">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="StaticVariableName">
-      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="EmptyForInitializerPad"/>
-    <module name="EmptyForIteratorPad"/>
-    <module name="ModifierOrder"/>
-    <module name="DefaultComesLast"/>
-    <module name="InnerAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ModifiedControlVariable"/>
-    <module name="MutableException">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ParameterAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="format" value="\s$"/>
-      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
-      <property name="format" value=" ,"/>
-      <property name="message" value="illegal space before a comma"/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="[^\x00-\x7F]"/>
-      <property name="message" value="Only use ASCII characters."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
-      <property name="message" value="Don't use old synchronized collection classes"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
-      <property name="checkFormat" value="ConstantNameCheck"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
-      <property name="checkFormat" value="MethodName"/>
-      <property name="checkC" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
-      <property name="checkFormat" value="ParameterAssignment"/>
-      <property name="checkC" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
-      <property name="checkFormat" value="FinalLocalVariable"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop"/>
-      <property name="onCommentFormat" value="Checkstyle: resume"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
-      <property name="checkFormat" value="InnerAssignment"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
-      <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
-      <property name="checkFormat" value="MemberName"/>
-      <property name="checkC" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop header check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume header check"/>
-      <property name="checkFormat" value=".*Header"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
-      <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
-      <property name="checkFormat" value="LineLength"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="CheckStyle: start generated"/>
-      <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-      <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="Checkstyle: stop"/>
-      <property name="onCommentFormat" value="Checkstyle: resume"/>
-      <property name="checkFormat" value=".*"/>
-    </module>
-    <module name="SuppressionCommentFilter">
-      <property name="offCommentFormat" value="@formatter:off"/>
-      <property name="onCommentFormat" value="@formatter:on"/>
-      <property name="checkFormat" value=".*"/>
-    </module>
-  </module>
-  <module name="RegexpHeader">
-    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="FileTabCharacter">
-    <property name="severity" value="error"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="NewlineAtEndOfFile">
-    <property name="lineSeparator" value="lf"/>
-  </module>
-  <module name="Translation"/>
-  <module name="RegexpMultiline">
-    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
-    <property name="format" value="\r\n"/>
-    <property name="message" value="illegal Windows line ending"/>
-  </module>
-</module>
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/JVMCIServiceLocator.java	Wed May 01 12:31:29 2019 -0700
@@ -22,6 +22,9 @@
  */
 package jdk.vm.ci.services;
 
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.ServiceLoader;
@@ -68,6 +71,26 @@
      */
     protected abstract <S> S getProvider(Class<S> service);
 
+    private static volatile List<JVMCIServiceLocator> cachedLocators;
+
+    private static Iterable<JVMCIServiceLocator> getJVMCIServiceLocators() {
+        Iterable<JVMCIServiceLocator> result = cachedLocators;
+        if (result != null) {
+            return result;
+        }
+        result = ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader());
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            ArrayList<JVMCIServiceLocator> l = new ArrayList<>();
+            for (JVMCIServiceLocator locator: result) {
+                l.add(locator);
+            }
+            l.trimToSize();
+            cachedLocators = l;
+            return l;
+        }
+        return result;
+    }
+
     /**
      * Gets the providers of the service defined by {@code service} by querying the available
      * {@link JVMCIServiceLocator} providers.
@@ -82,7 +105,7 @@
             sm.checkPermission(new JVMCIPermission());
         }
         List<S> providers = new ArrayList<>();
-        for (JVMCIServiceLocator access : ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader())) {
+        for (JVMCIServiceLocator access : getJVMCIServiceLocators()) {
             S provider = access.getProvider(service);
             if (provider != null) {
                 providers.add(provider);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -22,10 +22,23 @@
  */
 package jdk.vm.ci.services;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Properties;
+import java.util.ServiceLoader;
 import java.util.Set;
 
 import jdk.internal.misc.VM;
+import jdk.internal.reflect.Reflection;
 
 /**
  * Provides utilities needed by JVMCI clients.
@@ -36,35 +49,32 @@
     // processors while building JDK 9 so use of API added in JDK 9 is made via reflection.
 
     /**
-     * Guards code that should be run when building a native image but should be excluded from
-     * (being compiled into) the image. Such code must be directly guarded by an {@code if}
+     * Guards code that should be run when building an JVMCI shared library but should be excluded
+     * from (being compiled into) the library. Such code must be directly guarded by an {@code if}
      * statement on this field - the guard cannot be behind a method call.
      */
-    public static final boolean IS_BUILDING_NATIVE_IMAGE;
+    public static final boolean IS_BUILDING_NATIVE_IMAGE = Boolean.parseBoolean(VM.getSavedProperty("jdk.vm.ci.services.aot"));
 
     /**
-     * Guards code that should only be run in native image. Such code must be directly guarded by an
-     * {@code if} statement on this field - the guard cannot be behind a method call.
+     * Guards code that should only be run in a JVMCI shared library. Such code must be directly
+     * guarded by an {@code if} statement on this field - the guard cannot be behind a method call.
      *
-     * The value of this field seen during analysis and compilation of an SVM image must be
-     * {@code true}.
+     * The value of this field in a JVMCI shared library runtime must be {@code true}.
      */
     public static final boolean IS_IN_NATIVE_IMAGE;
-
     static {
         /*
-         * Prevents javac from constant folding use of this field. It is set to true in the SVM
-         * image via substitution during image building.
+         * Prevents javac from constant folding use of this field. It is set to true by the process
+         * that builds the shared library.
          */
         IS_IN_NATIVE_IMAGE = false;
-        IS_BUILDING_NATIVE_IMAGE = false;
     }
 
     private Services() {
     }
 
-    static final Map<String, String> SAVED_PROPERTIES = VM.getSavedProperties();
-    static final boolean JVMCI_ENABLED = Boolean.parseBoolean(SAVED_PROPERTIES.get("jdk.internal.vm.ci.enabled"));
+    private static volatile Map<String, String> savedProperties = VM.getSavedProperties();
+    static final boolean JVMCI_ENABLED = Boolean.parseBoolean(savedProperties.get("jdk.internal.vm.ci.enabled"));
 
     /**
      * Checks that JVMCI is enabled in the VM and throws an error if it isn't.
@@ -84,7 +94,21 @@
         if (sm != null) {
             sm.checkPermission(new JVMCIPermission());
         }
-        return SAVED_PROPERTIES;
+        return savedProperties;
+    }
+
+    /**
+     * Helper method equivalent to {@link #getSavedProperties()}{@code .getOrDefault(name, def)}.
+     */
+    public static String getSavedProperty(String name, String def) {
+        return Services.getSavedProperties().getOrDefault(name, def);
+    }
+
+    /**
+     * Helper method equivalent to {@link #getSavedProperties()}{@code .get(name)}.
+     */
+    public static String getSavedProperty(String name) {
+        return Services.getSavedProperties().get(name);
     }
 
     /**
@@ -99,6 +123,83 @@
         }
     }
 
+    private static boolean jvmciEnabled = true;
+
+    /**
+     * When {@code -XX:-UseJVMCIClassLoader} is in use, JVMCI classes are loaded via the boot class
+     * loader. When {@code null} is the second argument to
+     * {@link ServiceLoader#load(Class, ClassLoader)}, service lookup will use the system class
+     * loader and thus find application classes which violates the API of {@link #load} and
+     * {@link #loadSingle}. To avoid this, a class loader that simply delegates to the boot class
+     * loader is used.
+     */
+    static class LazyBootClassPath {
+        static final ClassLoader bootClassPath = new ClassLoader(null) {
+        };
+    }
+
+    private static ClassLoader findBootClassLoaderChild(ClassLoader start) {
+        ClassLoader cl = start;
+        while (cl.getParent() != null) {
+            cl = cl.getParent();
+        }
+        return cl;
+    }
+
+    private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
+
+    @SuppressWarnings("unchecked")
+    private static <S> Iterable<S> load0(Class<S> service) {
+        if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
+            List<?> list = servicesCache.get(service);
+            if (list != null) {
+                return (Iterable<S>) list;
+            }
+            if (IS_IN_NATIVE_IMAGE) {
+                throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
+            }
+        }
+
+        Iterable<S> providers = Collections.emptyList();
+        if (jvmciEnabled) {
+            ClassLoader cl = null;
+            try {
+                cl = getJVMCIClassLoader();
+                if (cl == null) {
+                    cl = LazyBootClassPath.bootClassPath;
+                    // JVMCI classes are loaded via the boot class loader.
+                    // If we use null as the second argument to ServiceLoader.load,
+                    // service loading will use the system class loader
+                    // and find classes on the application class path. Since we
+                    // don't want this, we use a loader that is as close to the
+                    // boot class loader as possible (since it is impossible
+                    // to force service loading to use only the boot class loader).
+                    cl = findBootClassLoaderChild(ClassLoader.getSystemClassLoader());
+                }
+                providers = ServiceLoader.load(service, cl);
+            } catch (UnsatisfiedLinkError e) {
+                jvmciEnabled = false;
+            } catch (InternalError e) {
+                if (e.getMessage().equals("JVMCI is not enabled")) {
+                    jvmciEnabled = false;
+                } else {
+                    throw e;
+                }
+            }
+        }
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            synchronized (servicesCache) {
+                ArrayList<S> providersList = new ArrayList<>();
+                for (S provider : providers) {
+                    providersList.add(provider);
+                }
+                servicesCache.put(service, providersList);
+                providers = providersList;
+            }
+        }
+        return providers;
+    }
+
     /**
      * Opens all JVMCI packages to {@code otherModule}.
      */
@@ -114,4 +215,123 @@
             }
         }
     }
+
+    /**
+     * Gets an {@link Iterable} of the JVMCI providers available for a given service.
+     *
+     * @throws SecurityException if a security manager is present and it denies <tt>
+     *             {@link RuntimePermission}("jvmci")</tt>
+     */
+    public static <S> Iterable<S> load(Class<S> service) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        return load0(service);
+    }
+
+    /**
+     * Gets the JVMCI provider for a given service for which at most one provider must be available.
+     *
+     * @param service the service whose provider is being requested
+     * @param required specifies if an {@link InternalError} should be thrown if no provider of
+     *            {@code service} is available
+     * @throws SecurityException if a security manager is present and it denies <tt>
+     *             {@link RuntimePermission}("jvmci")</tt>
+     */
+    public static <S> S loadSingle(Class<S> service, boolean required) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new JVMCIPermission());
+        }
+        Iterable<S> providers = load0(service);
+
+        S singleProvider = null;
+        for (S provider : providers) {
+            if (singleProvider != null) {
+                throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), provider.getClass().getName()));
+            }
+            singleProvider = provider;
+        }
+        if (singleProvider == null && required) {
+            String javaHome = Services.getSavedProperty("java.home");
+            String vmName = Services.getSavedProperty("java.vm.name");
+            Formatter errorMessage = new Formatter();
+            errorMessage.format("The VM does not expose required service %s.%n", service.getName());
+            errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
+            errorMessage.format("Currently used VM configuration is: %s", vmName);
+            throw new UnsupportedOperationException(errorMessage.toString());
+        }
+        return singleProvider;
+    }
+
+    static {
+        Reflection.registerMethodsToFilter(Services.class, Set.of("getJVMCIClassLoader"));
+    }
+
+    /**
+     * Gets the JVMCI class loader.
+     *
+     * @throws InternalError with the {@linkplain Throwable#getMessage() message}
+     *             {@code "JVMCI is not enabled"} iff JVMCI is not enabled
+     */
+    private static ClassLoader getJVMCIClassLoader() {
+        if (IS_IN_NATIVE_IMAGE) {
+            return null;
+        }
+        return ClassLoader.getSystemClassLoader();
+    }
+
+    /**
+     * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for
+     * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial
+     * properties in the JVMCI shared library.
+     */
+    @VMEntryPoint
+    private static byte[] serializeSavedProperties() throws IOException {
+        if (IS_IN_NATIVE_IMAGE) {
+            throw new InternalError("Can only serialize saved properties in HotSpot runtime");
+        }
+        Map<String, String> props = Services.getSavedProperties();
+
+        // Compute size of output on the assumption that
+        // all system properties have ASCII names and values
+        int estimate = 4;
+        for (Map.Entry<String, String> e : props.entrySet()) {
+            String name = e.getKey();
+            String value = e.getValue();
+            estimate += (2 + (name.length())) + (2 + (value.length()));
+        }
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate);
+        DataOutputStream out = new DataOutputStream(baos);
+        out.writeInt(props.size());
+        for (Map.Entry<String, String> e : props.entrySet()) {
+            String name = e.getKey();
+            String value = e.getValue();
+            out.writeUTF(name);
+            out.writeUTF(value);
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * Initialized the {@linkplain #getSavedProperties() saved system properties} in the JVMCI
+     * shared library from the {@linkplain #serializeSavedProperties() serialized saved properties}
+     * in the HotSpot runtime.
+     */
+    @VMEntryPoint
+    private static void initializeSavedProperties(byte[] serializedProperties) throws IOException {
+        if (!IS_IN_NATIVE_IMAGE) {
+            throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime");
+        }
+        DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties));
+        Map<String, String> props = new HashMap<>(in.readInt());
+        while (in.available() != 0) {
+            String name = in.readUTF();
+            String value = in.readUTF();
+            props.put(name, value);
+        }
+        savedProperties = Collections.unmodifiableMap(props);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/VMEntryPoint.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.services;
+
+/**
+ * Marker interface for methods which are called from the JVM.
+ */
+@interface VMEntryPoint {
+    /**
+     * An optional comment describing the caller.
+     */
+    String value() default "";
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -313,7 +313,7 @@
             case Double:
                 return SPARCKind.DOUBLE;
             default:
-                throw new IllegalArgumentException("Unknown JavaKind: " + javaKind);
+                return null;
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
 
 import org.graalvm.compiler.api.replacements.Snippet;
@@ -66,7 +67,7 @@
     @Override
     public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
         convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
-        profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier
+        profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)
                         ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
                         : null;
         mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -26,6 +26,7 @@
 
 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
 import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs;
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs;
 import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace;
 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
@@ -227,7 +228,7 @@
         stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target);
         hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target);
         resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
-        if (!JavaVersionUtil.Java8OrEarlier) {
+        if (!JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)) {
             profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
         }
         objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -29,22 +29,38 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
 
+import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject;
+
+import jdk.vm.ci.code.BytecodePosition;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.Services;
 
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+
 /**
- * JDK 9+ version of {@link GraalServices}.
+ * JDK 13+ version of {@link GraalServices}.
  */
 public final class GraalServices {
 
+    private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
+
     private GraalServices() {
     }
 
@@ -54,8 +70,37 @@
      * @throws SecurityException if on JDK8 and a security manager is present and it denies
      *             {@link JVMCIPermission}
      */
+    @SuppressWarnings("unchecked")
     public static <S> Iterable<S> load(Class<S> service) {
-        Iterable<S> iterable = ServiceLoader.load(service);
+        if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
+            List<?> list = servicesCache.get(service);
+            if (list != null) {
+                return (Iterable<S>) list;
+            }
+            if (IS_IN_NATIVE_IMAGE) {
+                throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
+            }
+        }
+
+        Iterable<S> providers = load0(service);
+
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            synchronized (servicesCache) {
+                ArrayList<S> providersList = new ArrayList<>();
+                for (S provider : providers) {
+                    providersList.add(provider);
+                }
+                providers = providersList;
+                servicesCache.put(service, providersList);
+                return providers;
+            }
+        }
+
+        return providers;
+    }
+
+    protected static <S> Iterable<S> load0(Class<S> service) {
+        Iterable<S> iterable = ServiceLoader.load(service, GraalServices.class.getClassLoader());
         return new Iterable<>() {
             @Override
             public Iterator<S> iterator() {
@@ -90,6 +135,8 @@
      * @param other all JVMCI packages will be opened to the module defining this class
      */
     static void openJVMCITo(Class<?> other) {
+        if (IS_IN_NATIVE_IMAGE) return;
+
         Module jvmciModule = JVMCI_MODULE;
         Module otherModule = other.getModule();
         if (jvmciModule != otherModule) {
@@ -98,7 +145,7 @@
                     // JVMCI initialization opens all JVMCI packages
                     // to Graal which is a prerequisite for Graal to
                     // open JVMCI packages to other modules.
-                    JVMCI.initialize();
+                    JVMCI.getRuntime();
 
                     jvmciModule.addOpens(pkg, otherModule);
                 }
@@ -179,6 +226,7 @@
         final int groupId;
         final String groupName;
         final Object[] context;
+        private SpeculationReasonEncoding encoding;
 
         DirectSpeculationReason(int groupId, String groupName, Object[] context) {
             this.groupId = groupId;
@@ -204,6 +252,123 @@
         public String toString() {
             return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context));
         }
+
+        @Override
+        public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            if (encoding == null) {
+                encoding = encodingSupplier.get();
+                encoding.addInt(groupId);
+                for (Object o : context) {
+                    if (o == null) {
+                        encoding.addInt(0);
+                    } else {
+                        addNonNullObject(encoding, o);
+                    }
+                }
+            }
+            return encoding;
+        }
+
+        static void addNonNullObject(SpeculationReasonEncoding encoding, Object o) {
+            Class<? extends Object> c = o.getClass();
+            if (c == String.class) {
+                encoding.addString((String) o);
+            } else if (c == Byte.class) {
+                encoding.addByte((Byte) o);
+            } else if (c == Short.class) {
+                encoding.addShort((Short) o);
+            } else if (c == Character.class) {
+                encoding.addShort((Character) o);
+            } else if (c == Integer.class) {
+                encoding.addInt((Integer) o);
+            } else if (c == Long.class) {
+                encoding.addLong((Long) o);
+            } else if (c == Float.class) {
+                encoding.addInt(Float.floatToRawIntBits((Float) o));
+            } else if (c == Double.class) {
+                encoding.addLong(Double.doubleToRawLongBits((Double) o));
+            } else if (o instanceof Enum) {
+                encoding.addInt(((Enum<?>) o).ordinal());
+            } else if (o instanceof ResolvedJavaMethod) {
+                encoding.addMethod((ResolvedJavaMethod) o);
+            } else if (o instanceof ResolvedJavaType) {
+                encoding.addType((ResolvedJavaType) o);
+            } else if (o instanceof ResolvedJavaField) {
+                encoding.addField((ResolvedJavaField) o);
+            } else if (o instanceof SpeculationContextObject) {
+                SpeculationContextObject sco = (SpeculationContextObject) o;
+                // These are compiler objects which all have the same class
+                // loader so the class name uniquely identifies the class.
+                encoding.addString(o.getClass().getName());
+                sco.accept(new EncodingAdapter(encoding));
+            } else if (o.getClass() == BytecodePosition.class) {
+                BytecodePosition p = (BytecodePosition) o;
+                while (p != null) {
+                    encoding.addInt(p.getBCI());
+                    encoding.addMethod(p.getMethod());
+                    p = p.getCaller();
+                }
+            } else {
+                throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName());
+            }
+        }
+    }
+
+    static class EncodingAdapter implements SpeculationContextObject.Visitor {
+        private final SpeculationReasonEncoding encoding;
+
+        EncodingAdapter(SpeculationReasonEncoding encoding) {
+            this.encoding = encoding;
+        }
+
+        @Override
+        public void visitBoolean(boolean v) {
+            encoding.addByte(v ? 1 : 0);
+        }
+
+        @Override
+        public void visitByte(byte v) {
+            encoding.addByte(v);
+        }
+
+        @Override
+        public void visitChar(char v) {
+            encoding.addShort(v);
+        }
+
+        @Override
+        public void visitShort(short v) {
+            encoding.addInt(v);
+        }
+
+        @Override
+        public void visitInt(int v) {
+            encoding.addInt(v);
+        }
+
+        @Override
+        public void visitLong(long v) {
+            encoding.addLong(v);
+        }
+
+        @Override
+        public void visitFloat(float v) {
+            encoding.addInt(Float.floatToRawIntBits(v));
+        }
+
+        @Override
+        public void visitDouble(double v) {
+            encoding.addLong(Double.doubleToRawLongBits(v));
+        }
+
+        @Override
+        public void visitObject(Object v) {
+            if (v == null) {
+                encoding.addInt(0);
+            } else {
+                DirectSpeculationReason.addNonNullObject(encoding, v);
+            }
+        }
     }
 
     static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) {
--- a/test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/SecurityRestrictionsTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -84,7 +84,7 @@
         NO_JVMCI {
             @Override
             public Class<? extends Throwable> getExpectedException() {
-                return InternalError.class;
+                return Error.class;
             }
         },
         ALL_PERM {
@@ -172,12 +172,8 @@
                 }
             };
             Utils.runAndCheckException(() -> {
-                try {
-                    // CompilerToVM::<cinit> provokes CompilerToVM::<init>
-                    Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper");
-                } catch (ClassNotFoundException e) {
-                    throw new Error("TESTBUG : " + e, e);
-                }
+                // CompilerToVM::<cinit> provokes CompilerToVM::<init>
+                Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper");
             }, exceptionCheck);
         }
 
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -28,7 +28,10 @@
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.code.stack.InspectedFrameVisitor;
 import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.runtime.JVMCI;
 import java.lang.reflect.Executable;
 
 /**
@@ -36,6 +39,7 @@
  */
 public class CompilerToVMHelper {
     public static final CompilerToVM CTVM = new CompilerToVM();
+    private static final MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
 
     public static byte[] getBytecode(HotSpotResolvedJavaMethod method) {
         return CTVM.getBytecode((HotSpotResolvedJavaMethodImpl)method);
@@ -80,8 +84,12 @@
     }
 
     public static HotSpotResolvedObjectType lookupType(String name,
-            Class<?> accessingClass, boolean resolve) throws ClassNotFoundException {
-        return CTVM.lookupType(name, accessingClass, resolve);
+            Class<?> accessClass, boolean resolve) throws ClassNotFoundException {
+        if (accessClass == null) {
+            throw new NullPointerException();
+        }
+        HotSpotResolvedObjectTypeImpl accessingClass = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType(accessClass);
+        return (HotSpotResolvedObjectType) CTVM.lookupType(name, accessingClass, resolve);
     }
 
     public static HotSpotResolvedObjectType lookupTypeHelper(String name,
@@ -94,11 +102,13 @@
     }
 
     public static Object resolveConstantInPool(ConstantPool constantPool, int cpi) {
-        return CTVM.resolveConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        DirectHotSpotObjectConstantImpl obj = (DirectHotSpotObjectConstantImpl) CTVM.resolveConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        return obj.object;
     }
 
     public static Object resolvePossiblyCachedConstantInPool(ConstantPool constantPool, int cpi) {
-        return CTVM.resolvePossiblyCachedConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        DirectHotSpotObjectConstantImpl obj = (DirectHotSpotObjectConstantImpl) CTVM.resolvePossiblyCachedConstantInPool((HotSpotConstantPool) constantPool, cpi);
+        return obj.object;
     }
 
     public static int lookupNameAndTypeRefIndexInPool(ConstantPool constantPool, int cpi) {
@@ -158,7 +168,16 @@
 
     public static int installCode(TargetDescription target,
             HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog) {
-        return CTVM.installCode(target, compiledCode, code, speculationLog);
+        byte[] speculations;
+        long failedSpeculationsAddress;
+        if (speculationLog != null) {
+            speculations = speculationLog.getFlattenedSpeculations(true);
+            failedSpeculationsAddress = speculationLog.getFailedSpeculationsAddress();
+        } else {
+            speculations = new byte[0];
+            failedSpeculationsAddress = 0L;
+        }
+        return CTVM.installCode(target, compiledCode, code, failedSpeculationsAddress, speculations);
     }
 
     public static int getMetadata(TargetDescription target,
@@ -208,9 +227,9 @@
         return CTVM.getStackTraceElement((HotSpotResolvedJavaMethodImpl)method, bci);
     }
 
-    public static Object executeInstalledCode(Object[] args,
-            InstalledCode installedCode) throws InvalidInstalledCodeException {
-        return CTVM.executeInstalledCode(args, installedCode);
+    public static Object executeHotSpotNmethod(Object[] args,
+            HotSpotNmethod nmethodMirror) throws InvalidInstalledCodeException {
+        return CTVM.executeHotSpotNmethod(args, nmethodMirror);
     }
 
     public static long[] getLineNumberTable(HotSpotResolvedJavaMethod method) {
@@ -233,8 +252,8 @@
         CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static void invalidateInstalledCode(InstalledCode installedCode) {
-        CTVM.invalidateInstalledCode(installedCode);
+    public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror) {
+        CTVM.invalidateHotSpotNmethod(nmethodMirror);
     }
 
     public static long[] collectCounters() {
@@ -289,33 +308,33 @@
         CTVM.flushDebugOutput();
     }
 
-    public static HotSpotResolvedJavaMethod getResolvedJavaMethod(Object base,
+    public static HotSpotResolvedJavaMethod getResolvedJavaMethod(HotSpotObjectConstantImpl base,
             long displacement) {
         return CTVM.getResolvedJavaMethod(base, displacement);
     }
 
-    public static HotSpotConstantPool getConstantPool(Object object) {
+    public static HotSpotConstantPool getConstantPool(MetaspaceObject object) {
         return CTVM.getConstantPool(object);
     }
 
-    public static HotSpotResolvedObjectType getResolvedJavaType(Object base,
+    public static HotSpotResolvedObjectType getResolvedJavaType(MetaspaceObject base,
             long displacement, boolean compressed) {
         return CTVM.getResolvedJavaType(base, displacement, compressed);
     }
 
     public static long getMetaspacePointer(Object o) {
-        return ((MetaspaceWrapperObject) o).getMetaspacePointer();
+        return ((MetaspaceObject) o).getMetaspacePointer();
     }
 
     public static Class<?> CompilerToVMClass() {
         return CompilerToVM.class;
     }
 
-    public static Class<?> getMirror(HotSpotResolvedObjectType type) {
-        return ((HotSpotResolvedJavaType) type).mirror();
+    public static JavaConstant getJavaMirror(HotSpotResolvedObjectType type) {
+        return ((HotSpotResolvedJavaType) type).getJavaMirror();
     }
 
     public static HotSpotResolvedObjectType fromObjectClass(Class<?> theClass) {
-        return HotSpotResolvedObjectTypeImpl.fromObjectClass(theClass);
+          return (HotSpotResolvedObjectType) metaAccess.lookupJavaType(theClass);
     }
 }
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -26,4 +26,4 @@
 /**
  * A public available version of MetaspaceWrapperObject interface.
  */
-public interface PublicMetaspaceWrapperObject extends MetaspaceWrapperObject { }
+public interface PublicMetaspaceWrapperObject extends MetaspaceHandleObject { }
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -69,7 +69,7 @@
 
     private void checkNull() {
         Utils.runAndCheckException(
-                () -> CompilerToVMHelper.disassembleCodeBlob(null),
+                () -> { CompilerToVMHelper.disassembleCodeBlob(null); },
                 NullPointerException.class);
     }
 
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -27,6 +27,7 @@
  * @requires vm.jvmci
  * @library /test/lib /
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -27,6 +27,7 @@
  * @requires vm.jvmci
  * @library /test/lib /
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -27,6 +27,7 @@
  * @requires vm.jvmci
  * @library / /test/lib
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc:+open
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:+open
  *
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -27,6 +27,7 @@
  * @requires vm.jvmci
  * @library / /test/lib
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
  *          jdk.internal.vm.ci/jdk.vm.ci.meta
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -27,6 +27,7 @@
  * @requires vm.jvmci
  * @library /test/lib /
  * @library ../common/patches
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -26,6 +26,7 @@
  * @bug 8136421
  * @requires vm.jvmci
  * @library /test/lib /
+ * @ignore Not supported JVMCI API
  * @modules java.base/jdk.internal.misc:open
  * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:open
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
--- a/test/hotspot/jtreg/compiler/jvmci/errors/CodeInstallerTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/errors/CodeInstallerTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -32,7 +32,9 @@
 import jdk.vm.ci.code.site.Site;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
+import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.meta.Assumptions.Assumption;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.PlatformKind;
@@ -50,7 +52,7 @@
     protected final MetaAccessProvider metaAccess;
     protected final HotSpotConstantReflectionProvider constantReflection;
 
-    protected final ResolvedJavaMethod dummyMethod;
+    protected final HotSpotResolvedJavaMethod dummyMethod;
 
     public static void dummyMethod() {
     }
@@ -69,12 +71,13 @@
             Assert.fail();
         }
 
-        dummyMethod = metaAccess.lookupJavaMethod(method);
+        dummyMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
     }
 
     protected void installEmptyCode(Site[] sites, Assumption[] assumptions, Comment[] comments, int dataSectionAlignment, DataPatch[] dataSectionPatches, StackSlot deoptRescueSlot) {
-        HotSpotCompiledCode code = new HotSpotCompiledCode("dummyMethod", new byte[0], 0, sites, assumptions, new ResolvedJavaMethod[]{dummyMethod}, comments, new byte[8], dataSectionAlignment,
-                        dataSectionPatches, false, 0, deoptRescueSlot);
+        HotSpotCompiledCode code = new HotSpotCompiledNmethod("dummyMethod", new byte[0], 0, sites, assumptions, new ResolvedJavaMethod[]{dummyMethod}, comments, new byte[8], dataSectionAlignment,
+                        dataSectionPatches, false, 0, deoptRescueSlot,
+                        dummyMethod, 0, 1, 0L, false);
         codeCache.addCode(dummyMethod, code, null, null);
     }
 
--- a/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -74,6 +74,7 @@
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
+import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.HotSpotVMEventListener;
@@ -118,10 +119,11 @@
         }
         HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(SimpleClass.class, testMethod);
-        HotSpotCompiledCode compiledCode = new HotSpotCompiledCode(METHOD_NAME,
+        HotSpotCompiledCode compiledCode = new HotSpotCompiledNmethod(METHOD_NAME,
                 new byte[0], 0, new Site[0], new Assumption[0],
                 new ResolvedJavaMethod[]{method}, new Comment[0], new byte[0],
-                16, new DataPatch[0], false, 0, null);
+                16, new DataPatch[0], false, 0, null,
+                method, 0, 1, 0L, false);
         codeCache.installCode(method, compiledCode, /* installedCode = */ null,
                 /* speculationLog = */ null, /* isDefault = */ false);
         Asserts.assertEQ(gotInstallNotification, 1,
--- a/test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -34,7 +34,7 @@
     public static void main(String args[]) {
         try {
             HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
-        } catch (InternalError e) {
+        } catch (Error e) {
             System.out.println(GOT_INTERNAL_ERROR);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotSpeculationLog.java	Wed May 01 12:31:29 2019 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.vm.ci.hotspot.test;
+
+import java.util.function.Supplier;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+import jdk.vm.ci.hotspot.HotSpotSpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
+
+public class TestHotSpotSpeculationLog {
+
+    static final class DummyReason implements SpeculationLog.SpeculationReason {
+
+        final String name;
+        private SpeculationReasonEncoding cachedEncoding;
+
+        DummyReason(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            SpeculationReasonEncoding encoding = cachedEncoding;
+            if (encoding == null) {
+                encoding = encodingSupplier.get();
+                encoding.addString(name);
+            }
+            cachedEncoding = encoding;
+            return encoding;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof DummyReason) {
+                DummyReason that = (DummyReason) obj;
+                return this.name.equals(that.name);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+
+    @Test
+    public synchronized void testFailedSpeculations() {
+        HotSpotSpeculationLog log = new HotSpotSpeculationLog();
+        DummyReason reason1 = new DummyReason("dummy1");
+        DummyReason reason2 = new DummyReason("dummy2");
+        Assert.assertTrue(log.maySpeculate(reason1));
+        Assert.assertTrue(log.maySpeculate(reason2));
+
+        SpeculationLog.Speculation s1 = log.speculate(reason1);
+        SpeculationLog.Speculation s2 = log.speculate(reason2);
+
+        boolean added = log.addFailedSpeculation(s1);
+        Assume.assumeTrue(added);
+        log.collectFailedSpeculations();
+        Assert.assertFalse(log.maySpeculate(reason1));
+        Assert.assertTrue(log.maySpeculate(reason2));
+
+        added = log.addFailedSpeculation(s2);
+        Assume.assumeTrue(added);
+        log.collectFailedSpeculations();
+        Assume.assumeTrue(added);
+        Assert.assertFalse(log.maySpeculate(reason1));
+        Assert.assertFalse(log.toString(), log.maySpeculate(reason2));
+    }
+}
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -25,6 +25,7 @@
  * @test
  * @requires vm.jvmci
  * @library ../../../../../
+ * @ignore Not supported JVMCI API
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -25,6 +25,7 @@
  * @test
  * @requires vm.jvmci
  * @library ../../../../../
+ * @ignore Not supported JVMCI API
  * @modules jdk.internal.vm.ci/jdk.vm.ci.meta
  *          jdk.internal.vm.ci/jdk.vm.ci.runtime
  *          java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestSpeculationLog.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestSpeculationLog.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -24,24 +24,107 @@
  */
 package jdk.vm.ci.runtime.test;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Supplier;
+
 import org.junit.Assert;
 import org.junit.Test;
 
+import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
+import jdk.vm.ci.runtime.JVMCI;
 
 public class TestSpeculationLog extends MethodUniverse {
 
-    static class Dummy implements SpeculationLog.SpeculationReason {
+    static final class Dummy implements SpeculationLog.SpeculationReason {
+
+        final int[] ints = {Integer.MIN_VALUE, -42, -1, 0, 1, 42, Integer.MAX_VALUE};
+        final long[] longs = {Long.MIN_VALUE, -42, -1, 0, 1, 42, Long.MAX_VALUE};
+        final String[] strings = {null, "non-empty string", ""};
+        final Collection<ResolvedJavaMethod> methods = new ArrayList<>(MethodUniverse.methods.values()).subList(0, 10);
+        final Collection<ResolvedJavaMethod> constructors = new ArrayList<>(MethodUniverse.constructors.values()).subList(0, 10);
+        final Collection<ResolvedJavaType> types = new ArrayList<>(TypeUniverse.javaTypes).subList(0, 10);
+
+        private final boolean useCache;
+        private SpeculationReasonEncoding cachedEncoding;
+
+        Dummy(boolean useCache) {
+            this.useCache = useCache;
+        }
 
+        @Override
+        public SpeculationReasonEncoding encode(Supplier<SpeculationReasonEncoding> encodingSupplier) {
+            SpeculationReasonEncoding encoding = cachedEncoding;
+            if (encoding == null) {
+                encoding = encodingSupplier.get();
+                for (int i : ints) {
+                    encoding.addInt(i);
+                }
+                for (long l : longs) {
+                    encoding.addLong(l);
+                }
+                for (String s : strings) {
+                    encoding.addString(s);
+                }
+                for (ResolvedJavaMethod m : methods) {
+                    encoding.addMethod(m);
+                }
+                for (ResolvedJavaMethod c : constructors) {
+                    encoding.addMethod(c);
+                }
+                for (ResolvedJavaType t : types) {
+                    encoding.addType(t);
+                }
+                encoding.addMethod(null);
+                encoding.addType(null);
+            }
+            if (useCache) {
+                cachedEncoding = encoding;
+            }
+            return encoding;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Dummy) {
+                Dummy that = (Dummy) obj;
+                return Arrays.equals(this.ints, that.ints) &&
+                                Arrays.equals(this.longs, that.longs) &&
+                                Arrays.equals(this.strings, that.strings) &&
+                                this.methods.equals(that.methods) &&
+                                this.constructors.equals(that.constructors) &&
+                                this.types.equals(that.types);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * Arrays.hashCode(ints) ^
+                            Arrays.hashCode(longs) ^
+                            Arrays.hashCode(strings) ^
+                            methods.hashCode() ^
+                            constructors.hashCode() ^
+                            types.hashCode();
+        }
     }
 
     @Test
-    public void testSpeculationIdentity() {
-        Dummy spec = new Dummy();
-        SpeculationLog log = methods.entrySet().iterator().next().getValue().getSpeculationLog();
-        SpeculationLog.Speculation s1 = log.speculate(spec);
-        SpeculationLog.Speculation s2 = log.speculate(spec);
+    public synchronized void testSpeculationIdentity() {
+        CodeCacheProvider codeCache = JVMCI.getRuntime().getHostJVMCIBackend().getCodeCache();
+        SpeculationLog log = codeCache.createSpeculationLog();
+        Dummy spec1 = new Dummy(true);
+        Dummy spec2 = new Dummy(false);
+        Assert.assertTrue(log.maySpeculate(spec1));
+        Assert.assertTrue(log.maySpeculate(spec2));
+        SpeculationLog.Speculation s1 = log.speculate(spec1);
+        SpeculationLog.Speculation s2 = log.speculate(spec2);
         Assert.assertTrue("Speculation should maintain identity", s1.equals(s2));
         JavaConstant e1 = metaAccess.encodeSpeculation(s1);
         JavaConstant e2 = metaAccess.encodeSpeculation(s2);
--- a/test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java	Wed May 01 12:41:26 2019 -0400
+++ b/test/hotspot/jtreg/runtime/NMT/MallocSiteTypeChange.java	Wed May 01 12:31:29 2019 -0700
@@ -60,7 +60,7 @@
         output.shouldContain("Baseline succeeded");
 
         wb.NMTFree(addr);
-        addr = wb.NMTMallocWithPseudoStackAndType(2 * 1024, pc, 7 /* mtInternal */ );
+        addr = wb.NMTMallocWithPseudoStackAndType(2 * 1024, pc, 8 /* mtInternal */ );
         pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff"});
         output = new OutputAnalyzer(pb.start());
         output.shouldContain("(malloc=0KB type=Test -4KB)");