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
36oop HotSpotJVMCI::resolve(JVMCIObject obj) {
37 return JNIHandles::resolve(obj.as_jobject());
38}
39
40arrayOop HotSpotJVMCI::resolve(JVMCIArray obj) {
41 return (arrayOop) JNIHandles::resolve(obj.as_jobject());
42}
43
44objArrayOop HotSpotJVMCI::resolve(JVMCIObjectArray obj) {
45 return (objArrayOop) JNIHandles::resolve(obj.as_jobject());
46}
47
48typeArrayOop HotSpotJVMCI::resolve(JVMCIPrimitiveArray obj) {
49 return (typeArrayOop) JNIHandles::resolve(obj.as_jobject());
50}
51
52JVMCIObject 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 */
62void 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
89static 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
107jclass JNIJVMCI::_box_classes[T_CONFLICT+1];
108jclass JNIJVMCI::_byte_array;
109jfieldID JNIJVMCI::_box_fields[T_CONFLICT+1];
110jmethodID JNIJVMCI::_box_constructors[T_CONFLICT+1];
111jmethodID JNIJVMCI::_Class_getName_method;
112
113jmethodID JNIJVMCI::_HotSpotResolvedJavaMethodImpl_fromMetaspace_method;
114jmethodID JNIJVMCI::_HotSpotConstantPool_fromMetaspace_method;
115jmethodID JNIJVMCI::_HotSpotResolvedObjectTypeImpl_fromMetaspace_method;
116jmethodID 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 */
149void 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::initialize(JVMCI_TRAPS) { \
177 Thread* THREAD = Thread::current(); \
178 className::klass()->initialize(CHECK); \
179 } \
180 bool HotSpotJVMCI::className::is_instance(JVMCIEnv* env, JVMCIObject object) { \
181 return resolve(object)->is_a(className::klass()); \
182 } \
183 void HotSpotJVMCI::className::check(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::_klass = 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 */
253JVMCI_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 */
280void 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
354extern "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().
362class 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 */
400void 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;
540JVMCI_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::initialize(JVMCI_TRAPS) { \
565 /* should already be initialized */ \
566 } \
567 bool JNIJVMCI::className::is_instance(JVMCIEnv* jvmciEnv, JVMCIObject object) { \
568 JNIAccessMark jni(jvmciEnv); \
569 return jni()->IsInstanceOf(object.as_jobject(), className::clazz()) != 0; \
570 } \
571 void JNIJVMCI::className::check(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::_class = 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 */
649JVMCI_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