diff src/gpu/hsail/vm/gpu_hsail.cpp @ 13819:49db2c1e3bee

added support for co-existing GPU backends (JBS:GRAAL-1)
author Doug Simon <doug.simon@oracle.com>
date Thu, 30 Jan 2014 00:52:33 +0100
parents bfd61161d752
children 35fc64972250
line wrap: on
line diff
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Thu Jan 30 00:48:41 2014 +0100
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Thu Jan 30 00:52:33 2014 +0100
@@ -29,9 +29,39 @@
 #include "utilities/ostream.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
+#include "graal/graalEnv.hpp"
+#include "graal/graalCompiler.hpp"
+#include "graal/graalJavaAccess.hpp"
 #include "hsailKernelArguments.hpp"
 
-void * gpu::Hsail::_device_context;
+// Entry to GPU native method implementation that transitions current thread to '_thread_in_vm'.
+#define GPU_VMENTRY(result_type, name, signature) \
+  JNIEXPORT result_type JNICALL name signature { \
+  GRAAL_VM_ENTRY_MARK; \
+
+// Entry to GPU native method implementation that calls a JNI function
+// and hence cannot transition current thread to '_thread_in_vm'.
+#define GPU_ENTRY(result_type, name, signature) \
+  JNIEXPORT result_type JNICALL name signature { \
+
+#define GPU_END }
+
+#define CC (char*)  /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f))
+
+#define OBJECT                "Ljava/lang/Object;"
+#define STRING                "Ljava/lang/String;"
+#define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
+
+//  public native void executeKernel(HotSpotNmethod kernel, int jobSize, int i, int j, Object[] args) throws InvalidInstalledCodeException;
+
+JNINativeMethod gpu::Hsail::HSAIL_methods[] = {
+  {CC"initialize",       CC"()Z",                               FN_PTR(gpu::Hsail::initialize)},
+  {CC"generateKernel",   CC"([B" STRING ")J",                   FN_PTR(gpu::Hsail::generate_kernel)},
+  {CC"executeKernel0",   CC"("HS_INSTALLED_CODE"I["OBJECT")Z",  FN_PTR(gpu::Hsail::execute_kernel_void_1d)},
+};
+
+void * gpu::Hsail::_device_context = NULL;
 
 gpu::Hsail::okra_create_context_func_t  gpu::Hsail::_okra_create_context;
 gpu::Hsail::okra_create_kernel_func_t   gpu::Hsail::_okra_create_kernel;
@@ -47,20 +77,6 @@
 gpu::Hsail::okra_register_heap_func_t   gpu::Hsail::_okra_register_heap;
 
 
-bool gpu::Hsail::initialize_gpu() {
-  // All the initialization is done in the okra library so
-  // nothing to do here.
-  if (TraceGPUInteraction) {
-    tty->print_cr("[HSAIL] Simulator: initialize_gpu");
-  }
-  return true;
-}
-
-unsigned int gpu::Hsail::total_cores() {
-  // This is not important with simulator
-  return 1;
-}
-
 void gpu::Hsail::register_heap() {
   // After the okra functions are set up and the heap is initialized, register the java heap with HSA
   guarantee(Universe::heap() != NULL, "heap should be there by now.");
@@ -71,54 +87,67 @@
   _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity());
 }
 
-bool  gpu::Hsail::execute_kernel_void_1d(address kernel, int dimX, jobject args, methodHandle& mh) {
-  objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args);
+GPU_VMENTRY(jboolean, gpu::Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args_handle))
+
+  ResourceMark rm;
+  jlong nmethodValue = HotSpotInstalledCode::codeBlob(kernel_handle);
+  if (nmethodValue == 0) {
+    SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
+  }
+  nmethod* nm = (nmethod*) (address) nmethodValue;
+  methodHandle mh = nm->method();
+  Symbol* signature = mh->signature();
+
+  void* kernel = (void*) HotSpotInstalledCode::codeStart(kernel_handle);
+  if (kernel == NULL) {
+    SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
+  }
+
+  objArrayOop args = (objArrayOop) JNIHandles::resolve(args_handle);
 
   // Reset the kernel arguments
   _okra_clearargs(kernel);
 
   // This object sets up the kernel arguments
-  HSAILKernelArguments hka(kernel, mh->signature(), argsArray, mh->is_static());
+  HSAILKernelArguments hka((address) kernel, mh->signature(), args, mh->is_static());
 
   // Run the kernel
-  bool success = _okra_execute_with_range(kernel, dimX);
-  return success;
-}
+  return _okra_execute_with_range(kernel, dimX);
+GPU_END
 
-void *gpu::Hsail::generate_kernel(unsigned char *code, int code_len, const char *name) {
+GPU_ENTRY(jlong, gpu::Hsail::generate_kernel, (JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle))
+  guarantee(_okra_create_kernel != NULL, "[HSAIL] Okra not linked");
+  ResourceMark rm;
+  jsize name_len = env->GetStringLength(name_handle);
+  jsize code_len = env->GetArrayLength(code_handle);
 
-  if (_okra_create_kernel == NULL) {
-    // probe linkage and we really need it to work this time
-    bool success = probe_linkage_internal(true);
-    guarantee(success, "[HSAIL] loading okra library");
-  }
+  char* name = NEW_RESOURCE_ARRAY(char, name_len + 1);
+  unsigned char *code = NEW_RESOURCE_ARRAY(unsigned char, code_len + 1);
 
-  gpu::Hsail::register_heap();
+  code[code_len] = 0;
+  name[name_len] = 0;
+
+  env->GetByteArrayRegion(code_handle, 0, code_len, (jbyte*) code);
+  env->GetStringUTFRegion(name_handle, 0, name_len, name);
+
+  register_heap();
 
   // The kernel entrypoint is always run for the time being  
   const char* entryPointName = "&run";
 
   _device_context = _okra_create_context();
 
-  // code is not null terminated, must be a better way to do this
-  unsigned char* nullTerminatedCodeBuffer = (unsigned char*) malloc(code_len + 1);
-  memcpy(nullTerminatedCodeBuffer, code, code_len);
-  nullTerminatedCodeBuffer[code_len] = 0;
-  void* kernel = _okra_create_kernel(_device_context, nullTerminatedCodeBuffer, entryPointName);
-  free(nullTerminatedCodeBuffer);
-  return kernel;
-}
+  return (jlong) _okra_create_kernel(_device_context, code, entryPointName);
+GPU_END
 
 #if defined(LINUX)
 static const char okra_library_name[] = "libokra_x86_64.so";
-#elif defined (_WINDOWS)
+#elif defined(_WINDOWS)
 static char const okra_library_name[] = "okra_x86_64.dll";
 #else
-static char const okra_library_name[] = "";
+static char const okra_library_name[] = NULL;
 #endif
 
-#define STD_BUFFER_SIZE 1024
-
 #define STRINGIFY(x)     #x
 
 #define LOOKUP_OKRA_FUNCTION(name, alias)  \
@@ -126,15 +155,10 @@
     CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \
   if (_##alias == NULL) {      \
   tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \
-        return 0; \
+        return false; \
   } \
 
-bool gpu::Hsail::probe_linkage() {
-  return probe_linkage_internal(false);
-}
-
-
-bool gpu::Hsail::probe_linkage_internal(bool isRequired) {
+GPU_ENTRY(jboolean, gpu::Hsail::initialize, (JNIEnv *env, jclass))
   if (okra_library_name == NULL) {
     if (TraceGPUInteraction) {
       tty->print_cr("Unsupported HSAIL platform");
@@ -143,32 +167,21 @@
   }
 
   // here we know we have a valid okra_library_name to try to load
-  // the isRequired boolean specifies whether it is an error if the
-  // probe does not find the okra library
-  char *buffer = (char*)malloc(STD_BUFFER_SIZE);
+  char ebuf[O_BUFLEN];
   if (TraceGPUInteraction) {
       tty->print_cr("[HSAIL] library is %s", okra_library_name);
   }
-  void *handle = os::dll_load(okra_library_name, buffer, STD_BUFFER_SIZE);
+  void *handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN);
   // try alternate location if env variable set
   char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_");
   if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) {
-    handle = os::dll_load(okra_lib_name_from_env_var, buffer, STD_BUFFER_SIZE);
+    handle = os::dll_load(okra_lib_name_from_env_var, ebuf, O_BUFLEN);
     if ((handle != NULL) && TraceGPUInteraction) {
       tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_"));
     }
   }
-  free(buffer);
 
-  if ((handle == NULL) && !isRequired) {
-    // return true for now but we will probe again later
-    if (TraceGPUInteraction) {
-      tty->print_cr("[HSAIL] library load not in PATH, waiting for Java to put in tmpdir.");
-    }
-    return true;
-  }
-
-  if ((handle == NULL) && isRequired) {
+  if (handle == NULL) {
     // Unable to dlopen okra
     if (TraceGPUInteraction) {
       tty->print_cr("[HSAIL] library load failed.");
@@ -176,6 +189,8 @@
     return false;
   }
   
+  guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization");
+
   // at this point we know handle is valid and we can lookup the functions
   LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context);
   LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel);
@@ -189,7 +204,27 @@
   LOOKUP_OKRA_FUNCTION(okra_execute_with_range, okra_execute_with_range);
   LOOKUP_OKRA_FUNCTION(okra_clearargs, okra_clearargs);
   LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap);
-  
   // if we made it this far, real success
+
+  gpu::initialized_gpu("Okra");
+
+  return true;
+GPU_END
+
+bool gpu::Hsail::register_natives(JNIEnv* env) {
+  jclass klass = env->FindClass("com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend");
+  if (klass == NULL) {
+    if (TraceGPUInteraction) {
+      tty->print_cr("HSAILHotSpotBackend class not found");
+    }
+    return false;
+  }
+  jint status = env->RegisterNatives(klass, HSAIL_methods, sizeof(HSAIL_methods) / sizeof(JNINativeMethod));
+  if (status != JNI_OK) {
+    if (TraceGPUInteraction) {
+      tty->print_cr("Error registering natives for HSAILHotSpotBackend: %d", status);
+    }
+    return false;
+  }
   return true;
 }