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