src/hotspot/share/jvmci/jvmciEnv.hpp
changeset 54669 ad45b3802d4e
parent 53430 ccfd4e614bb8
child 54732 2d012a75d35c
--- 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