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