1 | /* |
2 | * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | */ |
23 | |
24 | #include "precompiled.hpp" |
25 | #include "classfile/symbolTable.hpp" |
26 | #include "interpreter/linkResolver.hpp" |
27 | #include "jvmci/jniAccessMark.inline.hpp" |
28 | #include "jvmci/jvmciJavaClasses.hpp" |
29 | #include "jvmci/jvmciRuntime.hpp" |
30 | #include "memory/resourceArea.hpp" |
31 | #include "runtime/jniHandles.inline.hpp" |
32 | #include "runtime/fieldDescriptor.inline.hpp" |
33 | |
34 | // ------------------------------------------------------------------ |
35 | |
36 | oop HotSpotJVMCI::resolve(JVMCIObject obj) { |
37 | return JNIHandles::resolve(obj.as_jobject()); |
38 | } |
39 | |
40 | arrayOop HotSpotJVMCI::resolve(JVMCIArray obj) { |
41 | return (arrayOop) JNIHandles::resolve(obj.as_jobject()); |
42 | } |
43 | |
44 | objArrayOop HotSpotJVMCI::resolve(JVMCIObjectArray obj) { |
45 | return (objArrayOop) JNIHandles::resolve(obj.as_jobject()); |
46 | } |
47 | |
48 | typeArrayOop HotSpotJVMCI::resolve(JVMCIPrimitiveArray obj) { |
49 | return (typeArrayOop) JNIHandles::resolve(obj.as_jobject()); |
50 | } |
51 | |
52 | JVMCIObject HotSpotJVMCI::wrap(oop obj) { |
53 | assert(Thread::current()->is_Java_thread(), "must be" ); |
54 | return JVMCIObject(JNIHandles::make_local(obj), true); |
55 | } |
56 | |
57 | /** |
58 | * Computes the field offset of a static or instance field. |
59 | * It looks up the name and signature symbols without creating new ones; |
60 | * all the symbols of these classes need to be already loaded. |
61 | */ |
62 | void HotSpotJVMCI::compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field, TRAPS) { |
63 | InstanceKlass* ik = InstanceKlass::cast(klass); |
64 | Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name)); |
65 | Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature)); |
66 | if (name_symbol == NULL || signature_symbol == NULL) { |
67 | #ifndef PRODUCT |
68 | ik->print_on(tty); |
69 | #endif |
70 | fatal("symbol with name %s and signature %s was not found in symbol table (klass=%s)" , name, signature, klass->name()->as_C_string()); |
71 | } |
72 | |
73 | fieldDescriptor fd; |
74 | if (!ik->find_field(name_symbol, signature_symbol, &fd)) { |
75 | ResourceMark rm; |
76 | fatal("Could not find field %s.%s with signature %s" , ik->external_name(), name, signature); |
77 | } |
78 | guarantee(fd.is_static() == static_field, "static/instance mismatch" ); |
79 | dest_offset = fd.offset(); |
80 | assert(dest_offset != 0, "must be valid offset" ); |
81 | if (static_field) { |
82 | // Must ensure classes for static fields are initialized as the |
83 | // accessor itself does not include a class initialization check. |
84 | ik->initialize(CHECK); |
85 | } |
86 | } |
87 | |
88 | #ifndef PRODUCT |
89 | static void check_resolve_method(const char* call_type, Klass* resolved_klass, Symbol* method_name, Symbol* method_signature, TRAPS) { |
90 | methodHandle method; |
91 | LinkInfo link_info(resolved_klass, method_name, method_signature, NULL, LinkInfo::skip_access_check); |
92 | if (strcmp(call_type, "call_static" ) == 0) { |
93 | method = LinkResolver::resolve_static_call_or_null(link_info); |
94 | } else if (strcmp(call_type, "call_virtual" ) == 0) { |
95 | method = LinkResolver::resolve_virtual_call_or_null(resolved_klass, link_info); |
96 | } else if (strcmp(call_type, "call_special" ) == 0) { |
97 | method = LinkResolver::resolve_special_call_or_null(link_info); |
98 | } else { |
99 | fatal("Unknown or unsupported call type: %s" , call_type); |
100 | } |
101 | if (method.is_null()) { |
102 | fatal("Could not resolve %s.%s%s" , resolved_klass->external_name(), method_name->as_C_string(), method_signature->as_C_string()); |
103 | } |
104 | } |
105 | #endif |
106 | |
107 | jclass JNIJVMCI::_box_classes[T_CONFLICT+1]; |
108 | jclass JNIJVMCI::_byte_array; |
109 | jfieldID JNIJVMCI::_box_fields[T_CONFLICT+1]; |
110 | jmethodID JNIJVMCI::_box_constructors[T_CONFLICT+1]; |
111 | jmethodID JNIJVMCI::_Class_getName_method; |
112 | |
113 | jmethodID JNIJVMCI::_HotSpotResolvedJavaMethodImpl_fromMetaspace_method; |
114 | jmethodID JNIJVMCI::_HotSpotConstantPool_fromMetaspace_method; |
115 | jmethodID JNIJVMCI::_HotSpotResolvedObjectTypeImpl_fromMetaspace_method; |
116 | jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method; |
117 | |
118 | #define START_CLASS(className, fullClassName) { \ |
119 | Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::fullClassName(), true, CHECK); \ |
120 | className::_klass = InstanceKlass::cast(k); \ |
121 | className::_klass->initialize(CHECK); |
122 | |
123 | #define END_CLASS } |
124 | |
125 | #define FIELD(className, name, signature, static_field) compute_offset(className::_##name##_offset, className::_klass, #name, signature, static_field, CHECK); |
126 | #define CHAR_FIELD(className, name) FIELD(className, name, "C", false) |
127 | #define INT_FIELD(className, name) FIELD(className, name, "I", false) |
128 | #define BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", false) |
129 | #define LONG_FIELD(className, name) FIELD(className, name, "J", false) |
130 | #define FLOAT_FIELD(className, name) FIELD(className, name, "F", false) |
131 | #define OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, false) |
132 | #define STATIC_OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, true) |
133 | #define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true) |
134 | #define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true) |
135 | #ifdef PRODUCT |
136 | #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) |
137 | #define CONSTRUCTOR(className, signature) |
138 | #else |
139 | #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \ |
140 | check_resolve_method(#hsCallType, k, vmSymbols::methodName##_name(), vmSymbols::signatureSymbolName(), CHECK); |
141 | #define CONSTRUCTOR(className, signature) { \ |
142 | TempNewSymbol sig = SymbolTable::new_symbol(signature); \ |
143 | check_resolve_method("call_special", k, vmSymbols::object_initializer_name(), sig, CHECK); \ |
144 | } |
145 | #endif |
146 | /** |
147 | * Computes and initializes the offsets used by HotSpotJVMCI. |
148 | */ |
149 | void HotSpotJVMCI::compute_offsets(TRAPS) { |
150 | 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) |
151 | } |
152 | |
153 | #undef START_CLASS |
154 | #undef END_CLASS |
155 | #undef METHOD |
156 | #undef CONSTRUCTOR |
157 | #undef FIELD |
158 | #undef CHAR_FIELD |
159 | #undef INT_FIELD |
160 | #undef BOOLEAN_FIELD |
161 | #undef LONG_FIELD |
162 | #undef FLOAT_FIELD |
163 | #undef OBJECT_FIELD |
164 | #undef PRIMARRAY_FIELD |
165 | #undef OBJECTARRAY_FIELD |
166 | #undef STATIC_FIELD |
167 | #undef STATIC_OBJECT_FIELD |
168 | #undef STATIC_OBJECTARRAY_FIELD |
169 | #undef STATIC_INT_FIELD |
170 | #undef STATIC_BOOLEAN_FIELD |
171 | #undef EMPTY_CAST |
172 | |
173 | // ------------------------------------------------------------------ |
174 | |
175 | #define START_CLASS(className, fullClassName) \ |
176 | void HotSpotJVMCI::className::(JVMCI_TRAPS) { \ |
177 | Thread* THREAD = Thread::current(); \ |
178 | className::klass()->initialize(CHECK); \ |
179 | } \ |
180 | bool HotSpotJVMCI::className::(JVMCIEnv* env, JVMCIObject object) { \ |
181 | return resolve(object)->is_a(className::klass()); \ |
182 | } \ |
183 | void HotSpotJVMCI::className::(oop obj, const char* field_name, int offset) { \ |
184 | assert(obj != NULL, "NULL field access of %s.%s", #className, field_name); \ |
185 | assert(obj->is_a(className::klass()), "wrong class, " #className " expected, found %s", obj->klass()->external_name()); \ |
186 | assert(offset != 0, "must be valid offset"); \ |
187 | } \ |
188 | InstanceKlass* HotSpotJVMCI::className:: = NULL; |
189 | |
190 | #define END_CLASS |
191 | |
192 | #define FIELD(className, name, type, accessor, cast) \ |
193 | type HotSpotJVMCI::className::name(JVMCIEnv* env, oop obj) { className::check(obj, #name, className::_##name##_offset); return cast obj->accessor(className::_##name##_offset); } \ |
194 | 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); } |
195 | |
196 | #define EMPTY_CAST |
197 | #define CHAR_FIELD(className, name) FIELD(className, name, jchar, char_field, EMPTY_CAST) |
198 | #define INT_FIELD(className, name) FIELD(className, name, jint, int_field, EMPTY_CAST) |
199 | #define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, bool_field, EMPTY_CAST) |
200 | #define LONG_FIELD(className, name) FIELD(className, name, jlong, long_field, EMPTY_CAST) |
201 | #define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, float_field, EMPTY_CAST) |
202 | |
203 | #define OBJECT_FIELD(className, name, signature) FIELD(className, name, oop, obj_field, EMPTY_CAST) |
204 | #define OBJECTARRAY_FIELD(className, name, signature) FIELD(className, name, objArrayOop, obj_field, (objArrayOop)) |
205 | #define PRIMARRAY_FIELD(className, name, signature) FIELD(className, name, typeArrayOop, obj_field, (typeArrayOop)) |
206 | #define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, oop) |
207 | #define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, objArrayOop) |
208 | #define STATIC_OOPISH_FIELD(className, name, type) \ |
209 | type HotSpotJVMCI::className::name(JVMCIEnv* env) { \ |
210 | assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className); \ |
211 | InstanceKlass* ik = className::klass(); \ |
212 | oop base = ik->static_field_base_raw(); \ |
213 | oop result = HeapAccess<>::oop_load_at(base, className::_##name##_offset); \ |
214 | return type(result); \ |
215 | } \ |
216 | void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, type x) { \ |
217 | assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className); \ |
218 | assert(className::klass() != NULL, "Class not yet loaded: " #className); \ |
219 | InstanceKlass* ik = className::klass(); \ |
220 | oop base = ik->static_field_base_raw(); \ |
221 | HeapAccess<>::oop_store_at(base, className::_##name##_offset, x); \ |
222 | } |
223 | #define STATIC_PRIMITIVE_FIELD(className, name, jtypename) \ |
224 | jtypename HotSpotJVMCI::className::get_##name(JVMCIEnv* env) { \ |
225 | assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className); \ |
226 | InstanceKlass* ik = className::klass(); \ |
227 | oop base = ik->static_field_base_raw(); \ |
228 | return HeapAccess<>::load_at(base, className::_##name##_offset); \ |
229 | } \ |
230 | void HotSpotJVMCI::className::set_##name(JVMCIEnv* env, jtypename x) { \ |
231 | assert(className::klass() != NULL && className::klass()->is_linked(), "Class not yet linked: " #className); \ |
232 | InstanceKlass* ik = className::klass(); \ |
233 | oop base = ik->static_field_base_raw(); \ |
234 | HeapAccess<>::store_at(base, _##name##_offset, x); \ |
235 | } |
236 | |
237 | #define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint) |
238 | #define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean) |
239 | #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) |
240 | #define CONSTRUCTOR(className, signature) |
241 | |
242 | /** |
243 | * Generates the method and field definitions for the classes in HotSpotJVMCI. For example: |
244 | * |
245 | * void HotSpotJVMCI::Architecture::initialize(JVMCIEnv* env) { ... } |
246 | * bool HotSpotJVMCI::Architecture::is_instance(JVMCIEnv* env, JVMCIObject object) { ... } |
247 | * void HotSpotJVMCI::Architecture::check(oop obj, const char* field_name, int offset) { ... } |
248 | * oop HotSpotJVMCI::Architecture::wordKind(JVMCIEnv* env, oop obj) { ... } |
249 | * void HotSpotJVMCI::Architecture::set_wordKind(JVMCIEnv* env, oop obj, oop x) { ... } |
250 | * |
251 | * InstanceKlass *HotSpotJVMCI::Architecture::_klass = NULL; |
252 | */ |
253 | 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) |
254 | |
255 | #undef START_CLASS |
256 | #undef END_CLASS |
257 | #undef METHOD |
258 | #undef CONSTRUCTOR |
259 | #undef FIELD |
260 | #undef CHAR_FIELD |
261 | #undef INT_FIELD |
262 | #undef BOOLEAN_FIELD |
263 | #undef LONG_FIELD |
264 | #undef FLOAT_FIELD |
265 | #undef OBJECT_FIELD |
266 | #undef PRIMARRAY_FIELD |
267 | #undef OBJECTARRAY_FIELD |
268 | #undef STATIC_OOPISH_FIELD |
269 | #undef STATIC_OBJECT_FIELD |
270 | #undef STATIC_OBJECTARRAY_FIELD |
271 | #undef STATIC_INT_FIELD |
272 | #undef STATIC_BOOLEAN_FIELD |
273 | #undef STATIC_PRIMITIVE_FIELD |
274 | #undef EMPTY_CAST |
275 | |
276 | /** |
277 | * Initializes the JNI id of a field. As per the JNI specification, |
278 | * this ensures the declaring class is initialized. |
279 | */ |
280 | void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, const char* class_name, const char* name, const char* signature, bool static_field) { |
281 | if (JVMCILibDumpJNIConfig != NULL) { |
282 | fileStream* st = JVMCIGlobals::get_jni_config_file(); |
283 | st->print_cr("field %s %s %s" , class_name, name, signature); |
284 | return; |
285 | } |
286 | if (env->ExceptionCheck()) { |
287 | return; |
288 | } |
289 | if (static_field) { |
290 | // Class initialization barrier |
291 | fieldid = env->GetStaticFieldID(clazz, name, signature); |
292 | } else { |
293 | // Class initialization barrier |
294 | fieldid = env->GetFieldID(clazz, name, signature); |
295 | } |
296 | |
297 | if (env->ExceptionCheck()) { |
298 | env->ExceptionDescribe(); |
299 | env->ExceptionClear(); |
300 | ResourceMark rm; |
301 | Thread* THREAD = Thread::current(); |
302 | fatal("Could not find field %s.%s with signature %s" , class_name, name, signature); |
303 | } |
304 | } |
305 | |
306 | #define START_CLASS(className, fullClassName) { \ |
307 | current_class_name = vmSymbols::fullClassName()->as_C_string(); \ |
308 | if (JVMCILibDumpJNIConfig != NULL) { \ |
309 | fileStream* st = JVMCIGlobals::get_jni_config_file(); \ |
310 | st->print_cr("class %s", current_class_name); \ |
311 | } else { \ |
312 | jclass k = env->FindClass(current_class_name); \ |
313 | JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", current_class_name); \ |
314 | assert(k != NULL, #fullClassName " not initialized"); \ |
315 | className::_class = (jclass) env->NewGlobalRef(k); \ |
316 | } |
317 | |
318 | #define END_CLASS current_class_name = NULL; } |
319 | |
320 | #define FIELD(className, name, signature, static_field) initialize_field_id(env, className::_##name##_field_id, className::_class, current_class_name, #name, signature, static_field); |
321 | #define CHAR_FIELD(className, name) FIELD(className, name, "C", false) |
322 | #define INT_FIELD(className, name) FIELD(className, name, "I", false) |
323 | #define BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", false) |
324 | #define LONG_FIELD(className, name) FIELD(className, name, "J", false) |
325 | #define FLOAT_FIELD(className, name) FIELD(className, name, "F", false) |
326 | #define OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, false) |
327 | #define STATIC_OBJECT_FIELD(className, name, signature) FIELD(className, name, signature, true) |
328 | #define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true) |
329 | #define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true) |
330 | |
331 | #define GET_JNI_METHOD(jniGetMethod, dst, clazz, methodName, signature) \ |
332 | if (JVMCILibDumpJNIConfig != NULL) { \ |
333 | fileStream* st = JVMCIGlobals::get_jni_config_file(); \ |
334 | st->print_cr("method %s %s %s", current_class_name, methodName, signature); \ |
335 | } else { \ |
336 | dst = env->jniGetMethod(clazz, methodName, signature); \ |
337 | JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", current_class_name, methodName, signature); \ |
338 | assert(dst != NULL, "uninitialized"); \ |
339 | } |
340 | |
341 | #define GET_JNI_CONSTRUCTOR(clazz, signature) \ |
342 | GET_JNI_METHOD(GetMethodID, JNIJVMCI::clazz::_constructor, clazz::_class, "<init>", signature) \ |
343 | |
344 | #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \ |
345 | GET_JNI_METHOD(jniGetMethod, \ |
346 | className::_##methodName##_method, \ |
347 | className::clazz(), \ |
348 | vmSymbols::methodName##_name()->as_C_string(), \ |
349 | vmSymbols::signatureSymbolName()->as_C_string()) |
350 | |
351 | #define CONSTRUCTOR(className, signature) \ |
352 | GET_JNI_CONSTRUCTOR(className, signature) |
353 | |
354 | extern "C" { |
355 | void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass); |
356 | jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c); |
357 | } |
358 | |
359 | // Dumps symbols for public <init>() and <init>(String) methods of |
360 | // non-abstract Throwable subtypes known by the VM. This is to |
361 | // support the use of reflection in jdk.vm.ci.hotspot.TranslatedException.create(). |
362 | class ThrowableInitDumper : public SymbolClosure { |
363 | private: |
364 | fileStream* _st; |
365 | public: |
366 | ThrowableInitDumper(fileStream* st) { _st = st; } |
367 | void do_symbol(Symbol** p) { |
368 | Thread* THREAD = Thread::current(); |
369 | Symbol* name = *p; |
370 | if (name == NULL) { |
371 | return; |
372 | } |
373 | Klass* k = SystemDictionary::resolve_or_null(name, CHECK_EXIT); |
374 | if (k != NULL && k->is_instance_klass()) { |
375 | InstanceKlass* iklass = InstanceKlass::cast(k); |
376 | if (iklass->is_subclass_of(SystemDictionary::Throwable_klass()) && iklass->is_public() && !iklass->is_abstract()) { |
377 | const char* class_name = NULL; |
378 | Array<Method*>* methods = iklass->methods(); |
379 | for (int i = 0; i < methods->length(); i++) { |
380 | Method* m = methods->at(i); |
381 | if (m->name() == vmSymbols::object_initializer_name() && |
382 | m->is_public() && |
383 | (m->signature() == vmSymbols::void_method_signature() || m->signature() == vmSymbols::string_void_signature())) { |
384 | if (class_name == NULL) { |
385 | class_name = name->as_C_string(); |
386 | _st->print_cr("class %s" , class_name); |
387 | } |
388 | _st->print_cr("method %s %s %s" , class_name, m->name()->as_C_string(), m->signature()->as_C_string()); |
389 | } |
390 | } |
391 | } |
392 | } |
393 | } |
394 | }; |
395 | |
396 | #define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string() |
397 | /** |
398 | * Initializes the JNI method and field ids used in JNIJVMCI. |
399 | */ |
400 | void JNIJVMCI::initialize_ids(JNIEnv* env) { |
401 | ResourceMark rm; |
402 | const char* current_class_name = NULL; |
403 | 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) |
404 | |
405 | IN_CLASS(java_lang_Class); |
406 | GET_JNI_METHOD(GetMethodID, _Class_getName_method, Class::_class, "getName" , "()Ljava/lang/String;" ); |
407 | |
408 | IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType); |
409 | GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedPrimitiveType_fromMetaspace_method, HotSpotResolvedPrimitiveType::_class, |
410 | vmSymbols::fromMetaspace_name()->as_C_string(), |
411 | vmSymbols::primitive_fromMetaspace_signature()->as_C_string()); |
412 | IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl); |
413 | GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedObjectTypeImpl_fromMetaspace_method, HotSpotResolvedObjectTypeImpl::_class, |
414 | vmSymbols::fromMetaspace_name()->as_C_string(), |
415 | vmSymbols::klass_fromMetaspace_signature()->as_C_string()); |
416 | IN_CLASS(jdk_vm_ci_hotspot_HotSpotConstantPool); |
417 | GET_JNI_METHOD(GetStaticMethodID, _HotSpotConstantPool_fromMetaspace_method, HotSpotConstantPool::_class, |
418 | vmSymbols::fromMetaspace_name()->as_C_string(), |
419 | vmSymbols::constantPool_fromMetaspace_signature()->as_C_string()); |
420 | IN_CLASS(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl); |
421 | GET_JNI_METHOD(GetStaticMethodID, _HotSpotResolvedJavaMethodImpl_fromMetaspace_method, HotSpotResolvedJavaMethodImpl::_class, |
422 | vmSymbols::fromMetaspace_name()->as_C_string(), |
423 | vmSymbols::method_fromMetaspace_signature()->as_C_string()); |
424 | |
425 | #define BOX_CLASSES(generate) \ |
426 | generate(Boolean, T_BOOLEAN, Z) \ |
427 | generate(Byte, T_BYTE, B) \ |
428 | generate(Character, T_CHAR, C) \ |
429 | generate(Short, T_SHORT, S) \ |
430 | generate(Integer, T_INT, I) \ |
431 | generate(Long, T_LONG, J) \ |
432 | generate(Float, T_FLOAT, F) \ |
433 | generate(Double, T_DOUBLE, D) \ |
434 | |
435 | #define DO_BOX_CLASS(klass, basicType, type) \ |
436 | current_class_name = "java/lang/" #klass; \ |
437 | if (JVMCILibDumpJNIConfig == NULL) { \ |
438 | _box_classes[basicType] = env->FindClass("java/lang/" #klass); \ |
439 | JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", #klass); \ |
440 | _box_classes[basicType] = (jclass) env->NewGlobalRef(_box_classes[basicType]); \ |
441 | assert(_box_classes[basicType] != NULL, "uninitialized"); \ |
442 | _box_fields[basicType] = env->GetFieldID(_box_classes[basicType], "value", #type); \ |
443 | JVMCI_EXCEPTION_CHECK(env, "GetFieldID(%s, value, %s)", #klass, #type); \ |
444 | GET_JNI_METHOD(GetMethodID, _box_constructors[basicType], _box_classes[basicType], "<init>", "(" #type ")V"); \ |
445 | } else { \ |
446 | fileStream* st = JVMCIGlobals::get_jni_config_file(); \ |
447 | st->print_cr("field %s value %s", current_class_name, #type); \ |
448 | st->print_cr("method %s <init> (%s)V", current_class_name, #type); \ |
449 | } |
450 | |
451 | BOX_CLASSES(DO_BOX_CLASS); |
452 | |
453 | if (JVMCILibDumpJNIConfig == NULL) { |
454 | _byte_array = env->FindClass("[B" ); |
455 | JVMCI_EXCEPTION_CHECK(env, "FindClass([B)" ); |
456 | _byte_array = (jclass) env->NewGlobalRef(_byte_array); |
457 | assert(_byte_array != NULL, "uninitialized" ); |
458 | } else { |
459 | fileStream* st = JVMCIGlobals::get_jni_config_file(); |
460 | st->print_cr("class [B" ); |
461 | } |
462 | |
463 | #define DUMP_ALL_NATIVE_METHODS(class_symbol) do { \ |
464 | current_class_name = class_symbol->as_C_string(); \ |
465 | Klass* k = SystemDictionary::resolve_or_fail(class_symbol, true, CHECK_EXIT); \ |
466 | InstanceKlass* iklass = InstanceKlass::cast(k); \ |
467 | Array<Method*>* methods = iklass->methods(); \ |
468 | for (int i = 0; i < methods->length(); i++) { \ |
469 | Method* m = methods->at(i); \ |
470 | if (m->is_native()) { \ |
471 | st->print_cr("method %s %s %s", current_class_name, m->name()->as_C_string(), m->signature()->as_C_string()); \ |
472 | } \ |
473 | } \ |
474 | } while(0) |
475 | |
476 | if (JVMCILibDumpJNIConfig != NULL) { |
477 | Thread* THREAD = Thread::current(); |
478 | fileStream* st = JVMCIGlobals::get_jni_config_file(); |
479 | |
480 | DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM()); |
481 | ThrowableInitDumper dumper(st); |
482 | vmSymbols::symbols_do(&dumper); |
483 | |
484 | st->flush(); |
485 | tty->print_cr("Dumped JVMCI shared library JNI configuration to %s" , JVMCILibDumpJNIConfig); |
486 | vm_exit(0); |
487 | } |
488 | |
489 | #undef DUMP_ALL_NATIVE_METHODS |
490 | #undef DO_BOX_CLASS |
491 | #undef BOX_CLASSES |
492 | #undef IN_CLASS |
493 | |
494 | #define CC (char*) /*cast a literal from (const char*)*/ |
495 | #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f)) |
496 | |
497 | if (env != JavaThread::current()->jni_environment()) { |
498 | jclass clazz = env->FindClass("jdk/vm/ci/hotspot/CompilerToVM" ); |
499 | if (env->ExceptionCheck()) { |
500 | env->ExceptionDescribe(); |
501 | guarantee(false, "Could not find class jdk/vm/ci/hotspot/CompilerToVM" ); |
502 | } |
503 | JNINativeMethod CompilerToVM_native_methods[] = { |
504 | { CC"registerNatives" , CC"()V" , FN_PTR(JVM_RegisterJVMCINatives) }, |
505 | }; |
506 | env->RegisterNatives(clazz, CompilerToVM_native_methods, 1); |
507 | if (env->ExceptionCheck()) { |
508 | env->ExceptionDescribe(); |
509 | guarantee(false, "" ); |
510 | } |
511 | |
512 | JNINativeMethod JVMCI_native_methods[] = { |
513 | { CC"initializeRuntime" , CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;" , FN_PTR(JVM_GetJVMCIRuntime) }, |
514 | }; |
515 | env->RegisterNatives(JVMCI::clazz(), JVMCI_native_methods, 1); |
516 | if (env->ExceptionCheck()) { |
517 | env->ExceptionDescribe(); |
518 | guarantee(false, "" ); |
519 | } |
520 | } |
521 | } |
522 | |
523 | #undef METHOD |
524 | #undef CONSTRUCTOR |
525 | #undef FIELD2 |
526 | |
527 | #define EMPTY0 |
528 | #define EMPTY1(x) |
529 | #define EMPTY2(x,y) |
530 | #define FIELD3(className, name, sig) FIELD2(className, name) |
531 | #define FIELD2(className, name) \ |
532 | jfieldID JNIJVMCI::className::_##name##_field_id = 0; \ |
533 | int HotSpotJVMCI::className::_##name##_offset = 0; |
534 | #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) |
535 | #define CONSTRUCTOR(className, signature) |
536 | |
537 | // Generates the definitions of static fields used by the accessors. For example: |
538 | // jfieldID JNIJVMCI::Architecture::_wordKind_field_id = 0; |
539 | // jfieldID HotSpotJVMCI::Architecture::_wordKind_offset = 0; |
540 | JVMCI_CLASSES_DO(EMPTY2, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD3, FIELD3, FIELD3, FIELD2, FIELD2, METHOD, CONSTRUCTOR) |
541 | |
542 | #undef START_CLASS |
543 | #undef END_CLASS |
544 | #undef METHOD |
545 | #undef CONSTRUCTOR |
546 | #undef FIELD |
547 | #undef CHAR_FIELD |
548 | #undef INT_FIELD |
549 | #undef BOOLEAN_FIELD |
550 | #undef LONG_FIELD |
551 | #undef FLOAT_FIELD |
552 | #undef OBJECT_FIELD |
553 | #undef PRIMARRAY_FIELD |
554 | #undef OBJECTARRAY_FIELD |
555 | #undef STATIC_FIELD |
556 | #undef STATIC_OBJECT_FIELD |
557 | #undef STATIC_OBJECTARRAY_FIELD |
558 | #undef STATIC_INT_FIELD |
559 | #undef STATIC_BOOLEAN_FIELD |
560 | #undef EMPTY_CAST |
561 | |
562 | |
563 | #define START_CLASS(className, fullClassName) \ |
564 | void JNIJVMCI::className::(JVMCI_TRAPS) { \ |
565 | /* should already be initialized */ \ |
566 | } \ |
567 | bool JNIJVMCI::className::(JVMCIEnv* jvmciEnv, JVMCIObject object) { \ |
568 | JNIAccessMark jni(jvmciEnv); \ |
569 | return jni()->IsInstanceOf(object.as_jobject(), className::clazz()) != 0; \ |
570 | } \ |
571 | void JNIJVMCI::className::(JVMCIEnv* jvmciEnv, JVMCIObject obj, const char* field_name, jfieldID offset) { \ |
572 | assert(obj.is_non_null(), "NULL field access of %s.%s", #className, field_name); \ |
573 | assert(jvmciEnv->isa_##className(obj), "wrong class, " #className " expected, found %s", jvmciEnv->klass_name(obj)); \ |
574 | assert(offset != 0, "must be valid offset"); \ |
575 | } \ |
576 | jclass JNIJVMCI::className:: = NULL; |
577 | |
578 | #define END_CLASS |
579 | |
580 | #define FIELD(className, name, type, accessor, cast) \ |
581 | type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj) { \ |
582 | className::check(jvmciEnv, obj, #name, className::_##name##_field_id); \ |
583 | JNIAccessMark jni(jvmciEnv); \ |
584 | return cast jni()->Get##accessor##Field(resolve_handle(obj), className::_##name##_field_id); \ |
585 | } \ |
586 | void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x) { \ |
587 | className::check(jvmciEnv, obj, #name, className::_##name##_field_id); \ |
588 | JNIAccessMark jni(jvmciEnv); \ |
589 | jni()->Set##accessor##Field(resolve_handle(obj), className::_##name##_field_id, x); \ |
590 | } \ |
591 | |
592 | #define EMPTY_CAST |
593 | #define CHAR_FIELD(className, name) FIELD(className, name, jchar, Char, EMPTY_CAST) |
594 | #define INT_FIELD(className, name) FIELD(className, name, jint, Int, EMPTY_CAST) |
595 | #define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, Boolean, EMPTY_CAST) |
596 | #define LONG_FIELD(className, name) FIELD(className, name, jlong, Long, EMPTY_CAST) |
597 | #define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, Float, EMPTY_CAST) |
598 | |
599 | #define OBJECT_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST) |
600 | #define OBJECTARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray)) |
601 | #define PRIMARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray)) |
602 | |
603 | #define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject)) |
604 | #define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray)) |
605 | |
606 | #define OOPISH_FIELD(className, name, type, accessor, cast) \ |
607 | type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj) { \ |
608 | className::check(jvmciEnv, obj, #name, className::_##name##_field_id); \ |
609 | JNIAccessMark jni(jvmciEnv); \ |
610 | return cast wrap(jni()->Get##accessor##Field(resolve_handle(obj), className::_##name##_field_id)); \ |
611 | } \ |
612 | void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, JVMCIObject obj, type x) { \ |
613 | className::check(jvmciEnv, obj, #name, className::_##name##_field_id); \ |
614 | JNIAccessMark jni(jvmciEnv); \ |
615 | jni()->Set##accessor##Field(resolve_handle(obj), className::_##name##_field_id, resolve_handle(x)); \ |
616 | } |
617 | |
618 | #define STATIC_OOPISH_FIELD(className, name, type, accessor, cast) \ |
619 | type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv) { \ |
620 | JNIAccessMark jni(jvmciEnv); \ |
621 | return cast wrap(jni()->GetStatic##accessor##Field(className::clazz(), className::_##name##_field_id)); \ |
622 | } \ |
623 | void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, type x) { \ |
624 | JNIAccessMark jni(jvmciEnv); \ |
625 | jni()->SetStatic##accessor##Field(className::clazz(), className::_##name##_field_id, resolve_handle(x)); \ |
626 | } |
627 | |
628 | #define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast) \ |
629 | type JNIJVMCI::className::get_##name(JVMCIEnv* jvmciEnv) { \ |
630 | JNIAccessMark jni(jvmciEnv); \ |
631 | return cast jni()->GetStatic##accessor##Field(className::clazz(), className::_##name##_field_id); \ |
632 | } \ |
633 | void JNIJVMCI::className::set_##name(JVMCIEnv* jvmciEnv, type x) { \ |
634 | JNIAccessMark jni(jvmciEnv); \ |
635 | jni()->SetStatic##accessor##Field(className::clazz(), className::_##name##_field_id, x); \ |
636 | } |
637 | |
638 | #define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST) |
639 | #define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST) |
640 | #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \ |
641 | jmethodID JNIJVMCI::className::_##methodName##_method; |
642 | |
643 | #define CONSTRUCTOR(className, signature) \ |
644 | jmethodID JNIJVMCI::className::_constructor; |
645 | |
646 | /** |
647 | * Generates the method definitions for the classes in HotSpotJVMCI. |
648 | */ |
649 | 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) |
650 | |
651 | #undef METHOD |
652 | #undef CONSTRUCTOR |
653 | #undef START_CLASS |
654 | #undef END_CLASS |
655 | #undef FIELD |
656 | #undef CHAR_FIELD |
657 | #undef INT_FIELD |
658 | #undef BOOLEAN_FIELD |
659 | #undef LONG_FIELD |
660 | #undef FLOAT_FIELD |
661 | #undef OBJECT_FIELD |
662 | #undef PRIMARRAY_FIELD |
663 | #undef OBJECTARRAY_FIELD |
664 | #undef STATIC_OOPISH_FIELD |
665 | #undef STATIC_OBJECT_FIELD |
666 | #undef STATIC_OBJECTARRAY_FIELD |
667 | #undef STATIC_INT_FIELD |
668 | #undef STATIC_BOOLEAN_FIELD |
669 | #undef STATIC_PRIMITIVE_FIELD |
670 | #undef OOPISH_FIELD |
671 | #undef EMPTY_CAST |
672 | |