Mercurial > hg > graal-jvmci-8
comparison 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 |
comparison
equal
deleted
inserted
replaced
13818:d2f520f46180 | 13819:49db2c1e3bee |
---|---|
27 #include "runtime/gpu.hpp" | 27 #include "runtime/gpu.hpp" |
28 #include "utilities/globalDefinitions.hpp" | 28 #include "utilities/globalDefinitions.hpp" |
29 #include "utilities/ostream.hpp" | 29 #include "utilities/ostream.hpp" |
30 #include "memory/allocation.hpp" | 30 #include "memory/allocation.hpp" |
31 #include "memory/allocation.inline.hpp" | 31 #include "memory/allocation.inline.hpp" |
32 #include "graal/graalEnv.hpp" | |
33 #include "graal/graalCompiler.hpp" | |
34 #include "graal/graalJavaAccess.hpp" | |
32 #include "hsailKernelArguments.hpp" | 35 #include "hsailKernelArguments.hpp" |
33 | 36 |
34 void * gpu::Hsail::_device_context; | 37 // Entry to GPU native method implementation that transitions current thread to '_thread_in_vm'. |
38 #define GPU_VMENTRY(result_type, name, signature) \ | |
39 JNIEXPORT result_type JNICALL name signature { \ | |
40 GRAAL_VM_ENTRY_MARK; \ | |
41 | |
42 // Entry to GPU native method implementation that calls a JNI function | |
43 // and hence cannot transition current thread to '_thread_in_vm'. | |
44 #define GPU_ENTRY(result_type, name, signature) \ | |
45 JNIEXPORT result_type JNICALL name signature { \ | |
46 | |
47 #define GPU_END } | |
48 | |
49 #define CC (char*) /*cast a literal from (const char*)*/ | |
50 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f)) | |
51 | |
52 #define OBJECT "Ljava/lang/Object;" | |
53 #define STRING "Ljava/lang/String;" | |
54 #define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" | |
55 | |
56 // public native void executeKernel(HotSpotNmethod kernel, int jobSize, int i, int j, Object[] args) throws InvalidInstalledCodeException; | |
57 | |
58 JNINativeMethod gpu::Hsail::HSAIL_methods[] = { | |
59 {CC"initialize", CC"()Z", FN_PTR(gpu::Hsail::initialize)}, | |
60 {CC"generateKernel", CC"([B" STRING ")J", FN_PTR(gpu::Hsail::generate_kernel)}, | |
61 {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT")Z", FN_PTR(gpu::Hsail::execute_kernel_void_1d)}, | |
62 }; | |
63 | |
64 void * gpu::Hsail::_device_context = NULL; | |
35 | 65 |
36 gpu::Hsail::okra_create_context_func_t gpu::Hsail::_okra_create_context; | 66 gpu::Hsail::okra_create_context_func_t gpu::Hsail::_okra_create_context; |
37 gpu::Hsail::okra_create_kernel_func_t gpu::Hsail::_okra_create_kernel; | 67 gpu::Hsail::okra_create_kernel_func_t gpu::Hsail::_okra_create_kernel; |
38 gpu::Hsail::okra_push_object_func_t gpu::Hsail::_okra_push_object; | 68 gpu::Hsail::okra_push_object_func_t gpu::Hsail::_okra_push_object; |
39 gpu::Hsail::okra_push_boolean_func_t gpu::Hsail::_okra_push_boolean; | 69 gpu::Hsail::okra_push_boolean_func_t gpu::Hsail::_okra_push_boolean; |
45 gpu::Hsail::okra_execute_with_range_func_t gpu::Hsail::_okra_execute_with_range; | 75 gpu::Hsail::okra_execute_with_range_func_t gpu::Hsail::_okra_execute_with_range; |
46 gpu::Hsail::okra_clearargs_func_t gpu::Hsail::_okra_clearargs; | 76 gpu::Hsail::okra_clearargs_func_t gpu::Hsail::_okra_clearargs; |
47 gpu::Hsail::okra_register_heap_func_t gpu::Hsail::_okra_register_heap; | 77 gpu::Hsail::okra_register_heap_func_t gpu::Hsail::_okra_register_heap; |
48 | 78 |
49 | 79 |
50 bool gpu::Hsail::initialize_gpu() { | |
51 // All the initialization is done in the okra library so | |
52 // nothing to do here. | |
53 if (TraceGPUInteraction) { | |
54 tty->print_cr("[HSAIL] Simulator: initialize_gpu"); | |
55 } | |
56 return true; | |
57 } | |
58 | |
59 unsigned int gpu::Hsail::total_cores() { | |
60 // This is not important with simulator | |
61 return 1; | |
62 } | |
63 | |
64 void gpu::Hsail::register_heap() { | 80 void gpu::Hsail::register_heap() { |
65 // After the okra functions are set up and the heap is initialized, register the java heap with HSA | 81 // After the okra functions are set up and the heap is initialized, register the java heap with HSA |
66 guarantee(Universe::heap() != NULL, "heap should be there by now."); | 82 guarantee(Universe::heap() != NULL, "heap should be there by now."); |
67 if (TraceGPUInteraction) { | 83 if (TraceGPUInteraction) { |
68 tty->print_cr("[HSAIL] heap=" PTR_FORMAT, Universe::heap()); | 84 tty->print_cr("[HSAIL] heap=" PTR_FORMAT, Universe::heap()); |
69 tty->print_cr("[HSAIL] base=0x%08x, capacity=%ld", Universe::heap()->base(), Universe::heap()->capacity()); | 85 tty->print_cr("[HSAIL] base=0x%08x, capacity=%ld", Universe::heap()->base(), Universe::heap()->capacity()); |
70 } | 86 } |
71 _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity()); | 87 _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity()); |
72 } | 88 } |
73 | 89 |
74 bool gpu::Hsail::execute_kernel_void_1d(address kernel, int dimX, jobject args, methodHandle& mh) { | 90 GPU_VMENTRY(jboolean, gpu::Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args_handle)) |
75 objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args); | 91 |
92 ResourceMark rm; | |
93 jlong nmethodValue = HotSpotInstalledCode::codeBlob(kernel_handle); | |
94 if (nmethodValue == 0) { | |
95 SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); | |
96 } | |
97 nmethod* nm = (nmethod*) (address) nmethodValue; | |
98 methodHandle mh = nm->method(); | |
99 Symbol* signature = mh->signature(); | |
100 | |
101 void* kernel = (void*) HotSpotInstalledCode::codeStart(kernel_handle); | |
102 if (kernel == NULL) { | |
103 SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); | |
104 } | |
105 | |
106 objArrayOop args = (objArrayOop) JNIHandles::resolve(args_handle); | |
76 | 107 |
77 // Reset the kernel arguments | 108 // Reset the kernel arguments |
78 _okra_clearargs(kernel); | 109 _okra_clearargs(kernel); |
79 | 110 |
80 // This object sets up the kernel arguments | 111 // This object sets up the kernel arguments |
81 HSAILKernelArguments hka(kernel, mh->signature(), argsArray, mh->is_static()); | 112 HSAILKernelArguments hka((address) kernel, mh->signature(), args, mh->is_static()); |
82 | 113 |
83 // Run the kernel | 114 // Run the kernel |
84 bool success = _okra_execute_with_range(kernel, dimX); | 115 return _okra_execute_with_range(kernel, dimX); |
85 return success; | 116 GPU_END |
86 } | 117 |
87 | 118 GPU_ENTRY(jlong, gpu::Hsail::generate_kernel, (JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle)) |
88 void *gpu::Hsail::generate_kernel(unsigned char *code, int code_len, const char *name) { | 119 guarantee(_okra_create_kernel != NULL, "[HSAIL] Okra not linked"); |
89 | 120 ResourceMark rm; |
90 if (_okra_create_kernel == NULL) { | 121 jsize name_len = env->GetStringLength(name_handle); |
91 // probe linkage and we really need it to work this time | 122 jsize code_len = env->GetArrayLength(code_handle); |
92 bool success = probe_linkage_internal(true); | 123 |
93 guarantee(success, "[HSAIL] loading okra library"); | 124 char* name = NEW_RESOURCE_ARRAY(char, name_len + 1); |
94 } | 125 unsigned char *code = NEW_RESOURCE_ARRAY(unsigned char, code_len + 1); |
95 | 126 |
96 gpu::Hsail::register_heap(); | 127 code[code_len] = 0; |
128 name[name_len] = 0; | |
129 | |
130 env->GetByteArrayRegion(code_handle, 0, code_len, (jbyte*) code); | |
131 env->GetStringUTFRegion(name_handle, 0, name_len, name); | |
132 | |
133 register_heap(); | |
97 | 134 |
98 // The kernel entrypoint is always run for the time being | 135 // The kernel entrypoint is always run for the time being |
99 const char* entryPointName = "&run"; | 136 const char* entryPointName = "&run"; |
100 | 137 |
101 _device_context = _okra_create_context(); | 138 _device_context = _okra_create_context(); |
102 | 139 |
103 // code is not null terminated, must be a better way to do this | 140 return (jlong) _okra_create_kernel(_device_context, code, entryPointName); |
104 unsigned char* nullTerminatedCodeBuffer = (unsigned char*) malloc(code_len + 1); | 141 GPU_END |
105 memcpy(nullTerminatedCodeBuffer, code, code_len); | |
106 nullTerminatedCodeBuffer[code_len] = 0; | |
107 void* kernel = _okra_create_kernel(_device_context, nullTerminatedCodeBuffer, entryPointName); | |
108 free(nullTerminatedCodeBuffer); | |
109 return kernel; | |
110 } | |
111 | 142 |
112 #if defined(LINUX) | 143 #if defined(LINUX) |
113 static const char okra_library_name[] = "libokra_x86_64.so"; | 144 static const char okra_library_name[] = "libokra_x86_64.so"; |
114 #elif defined (_WINDOWS) | 145 #elif defined(_WINDOWS) |
115 static char const okra_library_name[] = "okra_x86_64.dll"; | 146 static char const okra_library_name[] = "okra_x86_64.dll"; |
116 #else | 147 #else |
117 static char const okra_library_name[] = ""; | 148 static char const okra_library_name[] = NULL; |
118 #endif | 149 #endif |
119 | |
120 #define STD_BUFFER_SIZE 1024 | |
121 | 150 |
122 #define STRINGIFY(x) #x | 151 #define STRINGIFY(x) #x |
123 | 152 |
124 #define LOOKUP_OKRA_FUNCTION(name, alias) \ | 153 #define LOOKUP_OKRA_FUNCTION(name, alias) \ |
125 _##alias = \ | 154 _##alias = \ |
126 CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \ | 155 CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \ |
127 if (_##alias == NULL) { \ | 156 if (_##alias == NULL) { \ |
128 tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \ | 157 tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \ |
129 return 0; \ | 158 return false; \ |
130 } \ | 159 } \ |
131 | 160 |
132 bool gpu::Hsail::probe_linkage() { | 161 GPU_ENTRY(jboolean, gpu::Hsail::initialize, (JNIEnv *env, jclass)) |
133 return probe_linkage_internal(false); | |
134 } | |
135 | |
136 | |
137 bool gpu::Hsail::probe_linkage_internal(bool isRequired) { | |
138 if (okra_library_name == NULL) { | 162 if (okra_library_name == NULL) { |
139 if (TraceGPUInteraction) { | 163 if (TraceGPUInteraction) { |
140 tty->print_cr("Unsupported HSAIL platform"); | 164 tty->print_cr("Unsupported HSAIL platform"); |
141 } | 165 } |
142 return false; | 166 return false; |
143 } | 167 } |
144 | 168 |
145 // here we know we have a valid okra_library_name to try to load | 169 // here we know we have a valid okra_library_name to try to load |
146 // the isRequired boolean specifies whether it is an error if the | 170 char ebuf[O_BUFLEN]; |
147 // probe does not find the okra library | |
148 char *buffer = (char*)malloc(STD_BUFFER_SIZE); | |
149 if (TraceGPUInteraction) { | 171 if (TraceGPUInteraction) { |
150 tty->print_cr("[HSAIL] library is %s", okra_library_name); | 172 tty->print_cr("[HSAIL] library is %s", okra_library_name); |
151 } | 173 } |
152 void *handle = os::dll_load(okra_library_name, buffer, STD_BUFFER_SIZE); | 174 void *handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN); |
153 // try alternate location if env variable set | 175 // try alternate location if env variable set |
154 char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); | 176 char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); |
155 if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) { | 177 if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) { |
156 handle = os::dll_load(okra_lib_name_from_env_var, buffer, STD_BUFFER_SIZE); | 178 handle = os::dll_load(okra_lib_name_from_env_var, ebuf, O_BUFLEN); |
157 if ((handle != NULL) && TraceGPUInteraction) { | 179 if ((handle != NULL) && TraceGPUInteraction) { |
158 tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_")); | 180 tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_")); |
159 } | 181 } |
160 } | 182 } |
161 free(buffer); | 183 |
162 | 184 if (handle == NULL) { |
163 if ((handle == NULL) && !isRequired) { | |
164 // return true for now but we will probe again later | |
165 if (TraceGPUInteraction) { | |
166 tty->print_cr("[HSAIL] library load not in PATH, waiting for Java to put in tmpdir."); | |
167 } | |
168 return true; | |
169 } | |
170 | |
171 if ((handle == NULL) && isRequired) { | |
172 // Unable to dlopen okra | 185 // Unable to dlopen okra |
173 if (TraceGPUInteraction) { | 186 if (TraceGPUInteraction) { |
174 tty->print_cr("[HSAIL] library load failed."); | 187 tty->print_cr("[HSAIL] library load failed."); |
175 } | 188 } |
176 return false; | 189 return false; |
177 } | 190 } |
178 | 191 |
192 guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization"); | |
193 | |
179 // at this point we know handle is valid and we can lookup the functions | 194 // at this point we know handle is valid and we can lookup the functions |
180 LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context); | 195 LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context); |
181 LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel); | 196 LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel); |
182 LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object); | 197 LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object); |
183 LOOKUP_OKRA_FUNCTION(okra_push_boolean, okra_push_boolean); | 198 LOOKUP_OKRA_FUNCTION(okra_push_boolean, okra_push_boolean); |
187 LOOKUP_OKRA_FUNCTION(okra_push_int, okra_push_int); | 202 LOOKUP_OKRA_FUNCTION(okra_push_int, okra_push_int); |
188 LOOKUP_OKRA_FUNCTION(okra_push_long, okra_push_long); | 203 LOOKUP_OKRA_FUNCTION(okra_push_long, okra_push_long); |
189 LOOKUP_OKRA_FUNCTION(okra_execute_with_range, okra_execute_with_range); | 204 LOOKUP_OKRA_FUNCTION(okra_execute_with_range, okra_execute_with_range); |
190 LOOKUP_OKRA_FUNCTION(okra_clearargs, okra_clearargs); | 205 LOOKUP_OKRA_FUNCTION(okra_clearargs, okra_clearargs); |
191 LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap); | 206 LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap); |
192 | |
193 // if we made it this far, real success | 207 // if we made it this far, real success |
208 | |
209 gpu::initialized_gpu("Okra"); | |
210 | |
211 return true; | |
212 GPU_END | |
213 | |
214 bool gpu::Hsail::register_natives(JNIEnv* env) { | |
215 jclass klass = env->FindClass("com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend"); | |
216 if (klass == NULL) { | |
217 if (TraceGPUInteraction) { | |
218 tty->print_cr("HSAILHotSpotBackend class not found"); | |
219 } | |
220 return false; | |
221 } | |
222 jint status = env->RegisterNatives(klass, HSAIL_methods, sizeof(HSAIL_methods) / sizeof(JNINativeMethod)); | |
223 if (status != JNI_OK) { | |
224 if (TraceGPUInteraction) { | |
225 tty->print_cr("Error registering natives for HSAILHotSpotBackend: %d", status); | |
226 } | |
227 return false; | |
228 } | |
194 return true; | 229 return true; |
195 } | 230 } |