jni.cc (add_char): Conditional on INTERPRETER.
[platform/upstream/gcc.git] / libjava / jni.cc
1 // jni.cc - JNI implementation, including the jump table.
2
3 /* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include <stddef.h>
14 #include <string.h>
15
16 // Define this before including jni.h.
17 #define __GCJ_JNI_IMPL__
18
19 #include <gcj/cni.h>
20 #include <jvm.h>
21 #include <java-assert.h>
22 #include <jni.h>
23
24 #include <java/lang/Class.h>
25 #include <java/lang/ClassLoader.h>
26 #include <java/lang/Throwable.h>
27 #include <java/lang/ArrayIndexOutOfBoundsException.h>
28 #include <java/lang/StringIndexOutOfBoundsException.h>
29 #include <java/lang/AbstractMethodError.h>
30 #include <java/lang/InstantiationException.h>
31 #include <java/lang/NoSuchFieldError.h>
32 #include <java/lang/NoSuchMethodError.h>
33 #include <java/lang/reflect/Constructor.h>
34 #include <java/lang/reflect/Method.h>
35 #include <java/lang/reflect/Modifier.h>
36 #include <java/lang/OutOfMemoryError.h>
37 #include <java/util/Hashtable.h>
38 #include <java/lang/Integer.h>
39
40 #include <gcj/method.h>
41 #include <gcj/field.h>
42
43 #include <java-interp.h>
44
45 #define ClassClass _CL_Q34java4lang5Class
46 extern java::lang::Class ClassClass;
47 #define ObjectClass _CL_Q34java4lang6Object
48 extern java::lang::Class ObjectClass;
49
50 #define MethodClass _CL_Q44java4lang7reflect6Method
51 extern java::lang::Class MethodClass;
52
53 // This enum is used to select different template instantiations in
54 // the invocation code.
55 enum invocation_type
56 {
57   normal,
58   nonvirtual,
59   static_type,
60   constructor
61 };
62
63 // Forward declaration.
64 extern struct JNINativeInterface _Jv_JNIFunctions;
65
66 // Number of slots in the default frame.  The VM must allow at least
67 // 16.
68 #define FRAME_SIZE 32
69
70 // This structure is used to keep track of local references.
71 struct _Jv_JNI_LocalFrame
72 {
73   // This is true if this frame object represents a pushed frame (eg
74   // from PushLocalFrame).
75   int marker :  1;
76
77   // Number of elements in frame.
78   int size   : 31;
79
80   // Next frame in chain.
81   _Jv_JNI_LocalFrame *next;
82
83   // The elements.  These are allocated using the C "struct hack".
84   jobject vec[0];
85 };
86
87 // This holds a reference count for all local and global references.
88 static java::util::Hashtable *ref_table;
89
90 \f
91
92 void
93 _Jv_JNI_Init (void)
94 {
95   ref_table = new java::util::Hashtable;
96 }
97
98 // Tell the GC that a certain pointer is live.
99 static void
100 mark_for_gc (jobject obj)
101 {
102   JvSynchronize sync (ref_table);
103
104   using namespace java::lang;
105   Integer *refcount = (Integer *) ref_table->get (obj);
106   jint val = (refcount == NULL) ? 0 : refcount->intValue ();
107   ref_table->put (obj, new Integer (val + 1));
108 }
109
110 // Unmark a pointer.
111 static void
112 unmark_for_gc (jobject obj)
113 {
114   JvSynchronize sync (ref_table);
115
116   using namespace java::lang;
117   Integer *refcount = (Integer *) ref_table->get (obj);
118   JvAssert (refcount);
119   jint val = refcount->intValue () - 1;
120   if (val == 0)
121     ref_table->remove (obj);
122   else
123     ref_table->put (obj, new Integer (val));
124 }
125
126 \f
127
128 static jobject
129 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
130 {
131   mark_for_gc (obj);
132   return obj;
133 }
134
135 static void
136 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
137 {
138   unmark_for_gc (obj);
139 }
140
141 static void
142 _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
143 {
144   _Jv_JNI_LocalFrame *frame;
145
146   for (frame = env->locals; frame != NULL; frame = frame->next)
147     {
148       for (int i = 0; i < FRAME_SIZE; ++i)
149         {
150           if (frame->vec[i] == obj)
151             {
152               frame->vec[i] = NULL;
153               unmark_for_gc (obj);
154               return;
155             }
156         }
157
158       // Don't go past a marked frame.
159       JvAssert (! frame->marker);
160     }
161
162   JvAssert (0);
163 }
164
165 static jint
166 _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
167 {
168   // It is easier to just always allocate a new frame of the requested
169   // size.  This isn't the most efficient thing, but for now we don't
170   // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
171
172   _Jv_JNI_LocalFrame *frame
173     = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
174                                                   + size * sizeof (jobject));
175   if (frame == NULL)
176     {
177       // FIXME: exception processing.
178       env->ex = new java::lang::OutOfMemoryError;
179       return -1;
180     }
181
182   frame->marker = true;
183   frame->size = size;
184   memset (&frame->vec[0], 0, size * sizeof (jobject));
185   frame->next = env->locals;
186   env->locals = frame;
187
188   return 0;
189 }
190
191 static jint
192 _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
193 {
194   jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
195   if (r < 0)
196     return r;
197
198   // The new frame is on top.
199   env->locals->marker = true;
200
201   return 0;
202 }
203
204 static jobject
205 _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
206 {
207   // Try to find an open slot somewhere in the topmost frame.
208   _Jv_JNI_LocalFrame *frame = env->locals;
209   bool done = false, set = false;
210   while (frame != NULL && ! done)
211     {
212       for (int i = 0; i < frame->size; ++i)
213         if (frame->vec[i] == NULL)
214           {
215             set = true;
216             done = true;
217             frame->vec[i] = obj;
218             break;
219           }
220     }
221
222   if (! set)
223     {
224       // No slots, so we allocate a new frame.  According to the spec
225       // we could just die here.  FIXME: return value.
226       _Jv_JNI_EnsureLocalCapacity (env, 16);
227       // We know the first element of the new frame will be ok.
228       env->locals->vec[0] = obj;
229     }
230
231   mark_for_gc (obj);
232   return obj;
233 }
234
235 static jobject
236 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
237 {
238   _Jv_JNI_LocalFrame *rf = env->locals;
239
240   bool done = false;
241   while (rf != NULL && ! done)
242     {  
243       for (int i = 0; i < rf->size; ++i)
244         if (rf->vec[i] != NULL)
245           unmark_for_gc (rf->vec[i]);
246
247       // If the frame we just freed is the marker frame, we are done.
248       done = rf->marker;
249
250       _Jv_JNI_LocalFrame *n = rf->next;
251       // When N==NULL, we've reached the stack-allocated frame, and we
252       // must not free it.  However, we must be sure to clear all its
253       // elements, since we might conceivably reuse it.
254       if (n == NULL)
255         {
256           memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
257           break;
258         }
259
260       _Jv_Free (rf);
261       rf = n;
262     }
263
264   return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
265 }
266
267 // This function is used from other template functions.  It wraps the
268 // return value appropriately; we specialize it so that object returns
269 // are turned into local references.
270 template<typename T>
271 static T
272 wrap_value (JNIEnv *, T value)
273 {
274   return value;
275 }
276
277 template<>
278 static jobject
279 wrap_value (JNIEnv *env, jobject value)
280 {
281   return _Jv_JNI_NewLocalRef (env, value);
282 }
283
284 \f
285
286 static jint
287 _Jv_JNI_GetVersion (JNIEnv *)
288 {
289   return JNI_VERSION_1_2;
290 }
291
292 static jclass
293 _Jv_JNI_DefineClass (JNIEnv *env, jobject loader, 
294                      const jbyte *buf, jsize bufLen)
295 {
296   jbyteArray bytes = JvNewByteArray (bufLen);
297   jbyte *elts = elements (bytes);
298   memcpy (elts, buf, bufLen * sizeof (jbyte));
299
300   java::lang::ClassLoader *l
301     = reinterpret_cast<java::lang::ClassLoader *> (loader);
302
303   // FIXME: exception processing.
304   jclass result = l->defineClass (bytes, 0, bufLen);
305   return (jclass) _Jv_JNI_NewLocalRef (env, result);
306 }
307
308 static jclass
309 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
310 {
311   // FIXME: assume that NAME isn't too long.
312   int len = strlen (name);
313   char s[len + 1];
314   for (int i = 0; i <= len; ++i)
315     s[i] = (name[i] == '/') ? '.' : name[i];
316   jstring n = JvNewStringUTF (s);
317
318   java::lang::ClassLoader *loader;
319   if (env->klass == NULL)
320     {
321       // FIXME: should use getBaseClassLoader, but we don't have that
322       // yet.
323       loader = java::lang::ClassLoader::getSystemClassLoader ();
324     }
325   else
326     loader = env->klass->getClassLoader ();
327
328   // FIXME: exception processing.
329   jclass r = loader->findClass (n);
330
331   return (jclass) _Jv_JNI_NewLocalRef (env, r);
332 }
333
334 static jclass
335 _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
336 {
337   return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ());
338 }
339
340 static jboolean
341 _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
342 {
343   return clazz1->isAssignableFrom (clazz2);
344 }
345
346 static jint
347 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
348 {
349   env->ex = obj;
350   return 0;
351 }
352
353 static jint
354 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
355 {
356   using namespace java::lang::reflect;
357
358   JArray<jclass> *argtypes
359     = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
360
361   jclass *elts = elements (argtypes);
362   elts[0] = &StringClass;
363
364   // FIXME: exception processing.
365   Constructor *cons = clazz->getConstructor (argtypes);
366
367   jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
368   jobject *velts = elements (values);
369   velts[0] = JvNewStringUTF (message);
370
371   // FIXME: exception processing.
372   jobject obj = cons->newInstance (values);
373
374   env->ex = reinterpret_cast<jthrowable> (obj);
375   return 0;
376 }
377
378 static jthrowable
379 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
380 {
381   return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex);
382 }
383
384 static void
385 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
386 {
387   if (env->ex != NULL)
388     env->ex->printStackTrace();
389 }
390
391 static void
392 _Jv_JNI_ExceptionClear (JNIEnv *env)
393 {
394   env->ex = NULL;
395 }
396
397 static jboolean
398 _Jv_JNI_ExceptionCheck (JNIEnv *env)
399 {
400   return env->ex != NULL;
401 }
402
403 static void
404 _Jv_JNI_FatalError (JNIEnv *, const char *message)
405 {
406   JvFail (message);
407 }
408
409 \f
410
411 static jboolean
412 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
413 {
414   return obj1 == obj2;
415 }
416
417 static jobject
418 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
419 {
420   jobject obj = NULL;
421   using namespace java::lang::reflect;
422   if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
423     env->ex = new java::lang::InstantiationException ();
424   else
425     {
426       // FIXME: exception processing.
427       // FIXME: will this work for String?
428       obj = JvAllocObject (clazz);
429     }
430
431   return _Jv_JNI_NewLocalRef (env, obj);
432 }
433
434 static jclass
435 _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
436 {
437   return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass());
438 }
439
440 static jboolean
441 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
442 {
443   return clazz->isInstance(obj);
444 }
445
446 \f
447
448 //
449 // This section concerns method invocation.
450 //
451
452 template<jboolean is_static>
453 static jmethodID
454 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
455                         const char *name, const char *sig)
456 {
457   // FIXME: exception processing.
458   _Jv_InitClass (clazz);
459
460   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
461   _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
462
463   JvAssert (! clazz->isPrimitive());
464
465   using namespace java::lang::reflect;
466
467   while (clazz != NULL)
468     {
469       jint count = JvNumMethods (clazz);
470       jmethodID meth = JvGetFirstMethod (clazz);
471
472       for (jint i = 0; i < count; ++i)
473         {
474           if (((is_static && Modifier::isStatic (meth->accflags))
475                || (! is_static && ! Modifier::isStatic (meth->accflags)))
476               && _Jv_equalUtf8Consts (meth->name, name_u)
477               && _Jv_equalUtf8Consts (meth->signature, sig_u))
478             return meth;
479
480           meth = meth->getNextMethod();
481         }
482
483       clazz = clazz->getSuperclass ();
484     }
485
486   env->ex = new java::lang::NoSuchMethodError ();
487   return NULL;
488 }
489
490 // This is a helper function which turns a va_list into an array of
491 // `jvalue's.  It needs signature information in order to do its work.
492 // The array of values must already be allocated.
493 static void
494 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
495 {
496   jclass *arg_elts = elements (arg_types);
497   for (int i = 0; i < arg_types->length; ++i)
498     {
499       if (arg_elts[i] == JvPrimClass (byte))
500         values[i].b = va_arg (vargs, jbyte);
501       else if (arg_elts[i] == JvPrimClass (short))
502         values[i].s = va_arg (vargs, jshort);
503       else if (arg_elts[i] == JvPrimClass (int))
504         values[i].i = va_arg (vargs, jint);
505       else if (arg_elts[i] == JvPrimClass (long))
506         values[i].j = va_arg (vargs, jlong);
507       else if (arg_elts[i] == JvPrimClass (float))
508         values[i].f = va_arg (vargs, jfloat);
509       else if (arg_elts[i] == JvPrimClass (double))
510         values[i].d = va_arg (vargs, jdouble);
511       else if (arg_elts[i] == JvPrimClass (boolean))
512         values[i].z = va_arg (vargs, jboolean);
513       else if (arg_elts[i] == JvPrimClass (char))
514         values[i].c = va_arg (vargs, jchar);
515       else
516         {
517           // An object.
518           values[i].l = va_arg (vargs, jobject);
519         }
520     }
521 }
522
523 // This can call any sort of method: virtual, "nonvirtual", static, or
524 // constructor.
525 template<typename T, invocation_type style>
526 static T
527 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
528                         jmethodID id, va_list vargs)
529 {
530   if (style == normal)
531     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
532
533   jclass decl_class = klass ? klass : obj->getClass ();
534   JvAssert (decl_class != NULL);
535
536   jclass return_type;
537   JArray<jclass> *arg_types;
538   // FIXME: exception processing.
539   _Jv_GetTypesFromSignature (id, decl_class,
540                              &arg_types, &return_type);
541
542   jvalue args[arg_types->length];
543   array_from_valist (args, arg_types, vargs);
544
545   jvalue result;
546   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
547                                       style == constructor,
548                                       arg_types, args, &result);
549
550   if (ex != NULL)
551     env->ex = ex;
552
553   // We cheat a little here.  FIXME.
554   return wrap_value (env, * (T *) &result);
555 }
556
557 template<typename T, invocation_type style>
558 static T
559 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
560                        jmethodID method, ...)
561 {
562   va_list args;
563   T result;
564
565   va_start (args, method);
566   result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
567   va_end (args);
568
569   return result;
570 }
571
572 template<typename T, invocation_type style>
573 static T
574 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
575                         jmethodID id, jvalue *args)
576 {
577   if (style == normal)
578     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
579
580   jclass decl_class = klass ? klass : obj->getClass ();
581   JvAssert (decl_class != NULL);
582
583   jclass return_type;
584   JArray<jclass> *arg_types;
585   // FIXME: exception processing.
586   _Jv_GetTypesFromSignature (id, decl_class,
587                              &arg_types, &return_type);
588
589   jvalue result;
590   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
591                                       style == constructor,
592                                       arg_types, args, &result);
593
594   if (ex != NULL)
595     env->ex = ex;
596
597   // We cheat a little here.  FIXME.
598   return wrap_value (env, * (T *) &result);
599 }
600
601 template<invocation_type style>
602 static void
603 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
604                             jmethodID id, va_list vargs)
605 {
606   if (style == normal)
607     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
608
609   jclass decl_class = klass ? klass : obj->getClass ();
610   JvAssert (decl_class != NULL);
611
612   jclass return_type;
613   JArray<jclass> *arg_types;
614   // FIXME: exception processing.
615   _Jv_GetTypesFromSignature (id, decl_class,
616                              &arg_types, &return_type);
617
618   jvalue args[arg_types->length];
619   array_from_valist (args, arg_types, vargs);
620
621   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
622                                       style == constructor,
623                                       arg_types, args, NULL);
624
625   if (ex != NULL)
626     env->ex = ex;
627 }
628
629 template<invocation_type style>
630 static void
631 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
632                            jmethodID method, ...)
633 {
634   va_list args;
635
636   va_start (args, method);
637   _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
638   va_end (args);
639 }
640
641 template<invocation_type style>
642 static void
643 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
644                             jmethodID id, jvalue *args)
645 {
646   if (style == normal)
647     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
648
649   jclass decl_class = klass ? klass : obj->getClass ();
650   JvAssert (decl_class != NULL);
651
652   jclass return_type;
653   JArray<jclass> *arg_types;
654   // FIXME: exception processing.
655   _Jv_GetTypesFromSignature (id, decl_class,
656                              &arg_types, &return_type);
657
658   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
659                                       style == constructor,
660                                       arg_types, args, NULL);
661
662   if (ex != NULL)
663     env->ex = ex;
664 }
665
666 // Functions with this signature are used to implement functions in
667 // the CallMethod family.
668 template<typename T>
669 static T
670 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
671 {
672   return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
673 }
674
675 // Functions with this signature are used to implement functions in
676 // the CallMethod family.
677 template<typename T>
678 static T
679 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
680 {
681   va_list args;
682   T result;
683
684   va_start (args, id);
685   result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
686   va_end (args);
687
688   return result;
689 }
690
691 // Functions with this signature are used to implement functions in
692 // the CallMethod family.
693 template<typename T>
694 static T
695 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
696 {
697   return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
698 }
699
700 static void
701 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
702 {
703   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
704 }
705
706 static void
707 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
708 {
709   va_list args;
710
711   va_start (args, id);
712   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
713   va_end (args);
714 }
715
716 static void
717 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
718 {
719   _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
720 }
721
722 // Functions with this signature are used to implement functions in
723 // the CallStaticMethod family.
724 template<typename T>
725 static T
726 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
727                            jmethodID id, va_list args)
728 {
729   return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
730 }
731
732 // Functions with this signature are used to implement functions in
733 // the CallStaticMethod family.
734 template<typename T>
735 static T
736 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
737 {
738   va_list args;
739   T result;
740
741   va_start (args, id);
742   result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
743                                                    id, args);
744   va_end (args);
745
746   return result;
747 }
748
749 // Functions with this signature are used to implement functions in
750 // the CallStaticMethod family.
751 template<typename T>
752 static T
753 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
754                            jvalue *args)
755 {
756   return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
757 }
758
759 static void
760 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
761                                va_list args)
762 {
763   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
764 }
765
766 static void
767 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
768 {
769   va_list args;
770
771   va_start (args, id);
772   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
773   va_end (args);
774 }
775
776 static void
777 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
778                                jvalue *args)
779 {
780   _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
781 }
782
783 static jobject
784 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
785                     jmethodID id, va_list args)
786 {
787   return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
788                                                        id, args);
789 }
790
791 static jobject
792 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
793 {
794   va_list args;
795   jobject result;
796
797   va_start (args, id);
798   result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
799                                                          id, args);
800   va_end (args);
801
802   return result;
803 }
804
805 static jobject
806 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
807                     jvalue *args)
808 {
809   return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
810                                                        id, args);
811 }
812
813 \f
814
815 template<typename T>
816 static T
817 _Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field) 
818 {
819   T *ptr = (T *) ((char *) obj + field->getOffset ());
820   return wrap_value (env, *ptr);
821 }
822
823 template<typename T>
824 static void
825 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
826 {
827   T *ptr = (T *) ((char *) obj + field->getOffset ());
828   *ptr = value;
829 }
830
831 template<jboolean is_static>
832 static jfieldID
833 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
834                        const char *name, const char *sig)
835 {
836   // FIXME: exception processing.
837   _Jv_InitClass (clazz);
838
839   _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
840
841   jclass field_class = NULL;
842   if (sig[0] == '[')
843     field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
844   else
845     {
846       _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
847       field_class = _Jv_FindClass (sig_u, NULL);
848     }
849
850   // FIXME: what if field_class == NULL?
851
852   while (clazz != NULL)
853     {
854       jint count = (is_static
855                     ? JvNumStaticFields (clazz)
856                     : JvNumInstanceFields (clazz));
857       jfieldID field = (is_static
858                         ? JvGetFirstStaticField (clazz)
859                         : JvGetFirstInstanceField (clazz));
860       for (jint i = 0; i < count; ++i)
861         {
862           // The field is resolved as a side effect of class
863           // initialization.
864           JvAssert (field->isResolved ());
865
866           _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
867
868           if (_Jv_equalUtf8Consts (f_name, a_name)
869               && field->getClass() == field_class)
870             return field;
871
872           field = field->getNextField ();
873         }
874
875       clazz = clazz->getSuperclass ();
876     }
877
878   env->ex = new java::lang::NoSuchFieldError ();
879   return NULL;
880 }
881
882 template<typename T>
883 static T
884 _Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
885 {
886   T *ptr = (T *) field->u.addr;
887   return wrap_value (env, *ptr);
888 }
889
890 template<typename T>
891 static void
892 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
893 {
894   T *ptr = (T *) field->u.addr;
895   *ptr = value;
896 }
897
898 static jstring
899 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
900 {
901   // FIXME: exception processing.
902   jstring r = _Jv_NewString (unichars, len);
903   return (jstring) _Jv_JNI_NewLocalRef (env, r);
904 }
905
906 static jsize
907 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
908 {
909   return string->length();
910 }
911
912 static const jchar *
913 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
914 {
915   jchar *result = _Jv_GetStringChars (string);
916   mark_for_gc (string);
917   if (isCopy)
918     *isCopy = false;
919   return (const jchar *) result;
920 }
921
922 static void
923 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
924 {
925   unmark_for_gc (string);
926 }
927
928 static jstring
929 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
930 {
931   // FIXME: exception processing.
932   jstring result = JvNewStringUTF (bytes);
933   return (jstring) _Jv_JNI_NewLocalRef (env, result);
934 }
935
936 static jsize
937 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
938 {
939   return JvGetStringUTFLength (string);
940 }
941
942 static const char *
943 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
944 {
945   jsize len = JvGetStringUTFLength (string);
946   // FIXME: exception processing.
947   char *r = (char *) _Jv_Malloc (len + 1);
948   JvGetStringUTFRegion (string, 0, len, r);
949   r[len] = '\0';
950
951   if (isCopy)
952     *isCopy = true;
953
954   return (const char *) r;
955 }
956
957 static void
958 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
959 {
960   _Jv_Free ((void *) utf);
961 }
962
963 static void
964 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
965                          jchar *buf)
966 {
967   jchar *result = _Jv_GetStringChars (string);
968   if (start < 0 || start > string->length ()
969       || len < 0 || start + len > string->length ())
970     env->ex = new java::lang::StringIndexOutOfBoundsException ();
971   else
972     memcpy (buf, &result[start], len * sizeof (jchar));
973 }
974
975 static void
976 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
977                             jsize len, char *buf)
978 {
979   if (start < 0 || start > str->length ()
980       || len < 0 || start + len > str->length ())
981     env->ex = new java::lang::StringIndexOutOfBoundsException ();
982   else
983     _Jv_GetStringUTFRegion (str, start, len, buf);
984 }
985
986 static const jchar *
987 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
988 {
989   jchar *result = _Jv_GetStringChars (str);
990   if (isCopy)
991     *isCopy = false;
992   return result;
993 }
994
995 static void
996 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
997 {
998   // Nothing.
999 }
1000
1001 static jsize
1002 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1003 {
1004   return array->length;
1005 }
1006
1007 static jarray
1008 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1009                         jobject init)
1010 {
1011   // FIXME: exception processing.
1012   jarray result = JvNewObjectArray (length, elementClass, init);
1013   return (jarray) _Jv_JNI_NewLocalRef (env, result);
1014 }
1015
1016 static jobject
1017 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1018 {
1019   jobject *elts = elements (array);
1020   return _Jv_JNI_NewLocalRef (env, elts[index]);
1021 }
1022
1023 static void
1024 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
1025                                jobject value)
1026 {
1027   // FIXME: exception processing.
1028   _Jv_CheckArrayStore (array, value);
1029   jobject *elts = elements (array);
1030   elts[index] = value;
1031 }
1032
1033 template<typename T, jclass K>
1034 static JArray<T> *
1035 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1036 {
1037   // FIXME: exception processing.
1038   return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
1039                                             _Jv_NewPrimArray (K, length));
1040 }
1041
1042 template<typename T>
1043 static T *
1044 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1045                                    jboolean *isCopy)
1046 {
1047   T *elts = elements (array);
1048   if (isCopy)
1049     {
1050       // We elect never to copy.
1051       *isCopy = false;
1052     }
1053   mark_for_gc (array);
1054   return elts;
1055 }
1056
1057 template<typename T>
1058 static void
1059 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1060                                        T *, jint /* mode */)
1061 {
1062   // Note that we ignore MODE.  We can do this because we never copy
1063   // the array elements.  My reading of the JNI documentation is that
1064   // this is an option for the implementor.
1065   unmark_for_gc (array);
1066 }
1067
1068 template<typename T>
1069 static void
1070 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1071                                  jsize start, jsize len,
1072                                  T *buf)
1073 {
1074   if (start < 0 || len >= array->length || start + len >= array->length)
1075     {
1076       // FIXME: index.
1077       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1078     }
1079   else
1080     {
1081       T *elts = elements (array) + start;
1082       memcpy (buf, elts, len * sizeof (T));
1083     }
1084 }
1085
1086 template<typename T>
1087 static void
1088 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array, 
1089                                  jsize start, jsize len, T *buf)
1090 {
1091   if (start < 0 || len >= array->length || start + len >= array->length)
1092     {
1093       // FIXME: index.
1094       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1095     }
1096   else
1097     {
1098       T *elts = elements (array) + start;
1099       memcpy (elts, buf, len * sizeof (T));
1100     }
1101 }
1102
1103 static void *
1104 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1105                                    jboolean *isCopy)
1106 {
1107   // FIXME: does this work?
1108   jclass klass = array->getClass()->getComponentType();
1109   JvAssert (klass->isPrimitive ());
1110   char *r = _Jv_GetArrayElementFromElementType (array, klass);
1111   if (isCopy)
1112     *isCopy = false;
1113   return r;
1114 }
1115
1116 static void
1117 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1118 {
1119   // Nothing.
1120 }
1121
1122 static jint
1123 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
1124 {
1125   // FIXME: exception processing.
1126   jint r = _Jv_MonitorEnter (obj);
1127   return r;
1128 }
1129
1130 static jint
1131 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
1132 {
1133   // FIXME: exception processing.
1134   jint r = _Jv_MonitorExit (obj);
1135   return r;
1136 }
1137
1138 // JDK 1.2
1139 jobject
1140 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1141                           jboolean)
1142 {
1143   // FIXME: exception processing.
1144   java::lang::reflect::Field *field = new java::lang::reflect::Field();
1145   field->declaringClass = cls;
1146   field->offset = (char*) fieldID - (char *) cls->fields;
1147   field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1148   return _Jv_JNI_NewLocalRef (env, field);
1149 }
1150
1151 // JDK 1.2
1152 static jfieldID
1153 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1154 {
1155   using namespace java::lang::reflect;
1156
1157   Field *field = reinterpret_cast<Field *> (f);
1158   return _Jv_FromReflectedField (field);
1159 }
1160
1161 jobject
1162 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1163                            jboolean)
1164 {
1165   using namespace java::lang::reflect;
1166
1167   // FIXME.
1168   static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
1169
1170   jobject result;
1171   if (_Jv_equalUtf8Consts (id->name, init_name))
1172     {
1173       // A constructor.
1174       Constructor *cons = new Constructor ();
1175       cons->offset = (char *) id - (char *) &klass->methods;
1176       cons->declaringClass = klass;
1177       result = cons;
1178     }
1179   else
1180     {
1181       Method *meth = new Method ();
1182       meth->offset = (char *) id - (char *) &klass->methods;
1183       meth->declaringClass = klass;
1184       result = meth;
1185     }
1186
1187   return _Jv_JNI_NewLocalRef (env, result);
1188 }
1189
1190 static jmethodID
1191 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1192 {
1193   using namespace java::lang::reflect;
1194   if ((&MethodClass)->isInstance (method))
1195     return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1196   return
1197     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1198 }
1199
1200 \f
1201
1202 #ifdef INTERPRETER
1203
1204 // Add a character to the buffer, encoding properly.
1205 static void
1206 add_char (char *buf, jchar c, int *here)
1207 {
1208   if (c == '_')
1209     {
1210       buf[(*here)++] = '_';
1211       buf[(*here)++] = '1';
1212     }
1213   else if (c == ';')
1214     {
1215       buf[(*here)++] = '_';
1216       buf[(*here)++] = '2';
1217     }
1218   else if (c == '[')
1219     {
1220       buf[(*here)++] = '_';
1221       buf[(*here)++] = '3';
1222     }
1223   else if (c == '/')
1224     buf[(*here)++] = '_';
1225   if ((c >= '0' && c <= '9')
1226       || (c >= 'a' && c <= 'z')
1227       || (c >= 'A' && c <= 'Z'))
1228     buf[(*here)++] = (char) c;
1229   else
1230     {
1231       // "Unicode" character.
1232       buf[(*here)++] = '_';
1233       buf[(*here)++] = '0';
1234       for (int i = 0; i < 4; ++i)
1235         {
1236           int val = c & 0x0f;
1237           buf[(*here) + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
1238           c >>= 4;
1239         }
1240       *here += 4;
1241     }
1242 }
1243
1244 // Compute a mangled name for a native function.  This computes the
1245 // long name, and also returns an index which indicates where a NUL
1246 // can be placed to create the short name.  This function assumes that
1247 // the buffer is large enough for its results.
1248 static void
1249 mangled_name (jclass klass, _Jv_Utf8Const *func_name,
1250               _Jv_Utf8Const *signature, char *buf, int *long_start)
1251 {
1252   strcpy (buf, "Java_");
1253   int here = 5;
1254
1255   // Add fully qualified class name.
1256   jchar *chars = _Jv_GetStringChars (klass->getName ());
1257   jint len = klass->getName ()->length ();
1258   for (int i = 0; i < len; ++i)
1259     add_char (buf, chars[i], &here);
1260
1261   // Don't use add_char because we need a literal `_'.
1262   buf[here++] = '_';
1263
1264   const unsigned char *fn = (const unsigned char *) func_name->data;
1265   const unsigned char *limit = fn + func_name->length;
1266   for (int i = 0; ; ++i)
1267     {
1268       int ch = UTF8_GET (fn, limit);
1269       if (ch < 0)
1270         break;
1271       add_char (buf, ch, &here);
1272     }
1273
1274   // This is where the long signature begins.
1275   *long_start = here;
1276   buf[here++] = '_';
1277   buf[here++] = '_';
1278
1279   const unsigned char *sig = (const unsigned char *) signature->data;
1280   limit = sig + signature->length;
1281   JvAssert (signature[0] == '(');
1282   for (int i = 1; ; ++i)
1283     {
1284       int ch = UTF8_GET (sig, limit);
1285       if (ch == ')' || ch < 0)
1286         break;
1287       add_char (buf, ch, &here);
1288     }
1289
1290   buf[here] = '\0';
1291 }
1292
1293 // This function is the stub which is used to turn an ordinary (CNI)
1294 // method call into a JNI call.
1295 void
1296 _Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this)
1297 {
1298   _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
1299
1300   JNIEnv env;
1301   _Jv_JNI_LocalFrame *frame
1302     = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
1303                                      + FRAME_SIZE * sizeof (jobject));
1304
1305   env.p = &_Jv_JNIFunctions;
1306   env.ex = NULL;
1307   env.klass = _this->defining_class;
1308   env.locals = frame;
1309
1310   frame->marker = true;
1311   frame->next = NULL;
1312   frame->size = FRAME_SIZE;
1313   for (int i = 0; i < frame->size; ++i)
1314     frame->vec[i] = NULL;
1315
1316   // FIXME: we should mark every reference parameter as a local.  For
1317   // now we assume a conservative GC, and we assume that the
1318   // references are on the stack somewhere.
1319
1320   // We cache the value that we find, of course, but if we don't find
1321   // a value we don't cache that fact -- we might subsequently load a
1322   // library which finds the function in question.
1323   if (_this->function == NULL)
1324     {
1325       char buf[10 + 6 * (_this->self->name->length
1326                          + _this->self->signature->length)];
1327       int long_start;
1328       mangled_name (_this->defining_class, _this->self->name,
1329                     _this->self->signature, buf, &long_start);
1330       char c = buf[long_start];
1331       buf[long_start] = '\0';
1332       _this->function = _Jv_FindSymbolInExecutable (buf);
1333       if (_this->function == NULL)
1334         {
1335           buf[long_start] = c;
1336           _this->function = _Jv_FindSymbolInExecutable (buf);
1337           if (_this->function == NULL)
1338             {
1339               jstring str = JvNewStringUTF (_this->self->name->data);
1340               JvThrow (new java::lang::AbstractMethodError (str));
1341             }
1342         }
1343     }
1344
1345   // The actual call to the JNI function.
1346   // FIXME: if this is a static function we must include the class!
1347   ffi_raw_call (cif, (void (*) (...)) _this->function, ret, args);
1348
1349   do
1350     {
1351       _Jv_JNI_PopLocalFrame (&env, NULL);
1352     }
1353   while (env.locals != frame);
1354
1355   if (env.ex)
1356     JvThrow (env.ex);
1357 }
1358
1359 #endif /* INTERPRETER */
1360
1361 \f
1362
1363 #define NOT_IMPL NULL
1364 #define RESERVED NULL
1365
1366 struct JNINativeInterface _Jv_JNIFunctions =
1367 {
1368   RESERVED,
1369   RESERVED,
1370   RESERVED,
1371   RESERVED,
1372   _Jv_JNI_GetVersion,
1373   _Jv_JNI_DefineClass,
1374   _Jv_JNI_FindClass,
1375   _Jv_JNI_FromReflectedMethod,
1376   _Jv_JNI_FromReflectedField,
1377   _Jv_JNI_ToReflectedMethod,
1378   _Jv_JNI_GetSuperclass,
1379   _Jv_JNI_IsAssignableFrom,
1380   _Jv_JNI_ToReflectedField,
1381   _Jv_JNI_Throw,
1382   _Jv_JNI_ThrowNew,
1383   _Jv_JNI_ExceptionOccurred,
1384   _Jv_JNI_ExceptionDescribe,
1385   _Jv_JNI_ExceptionClear,
1386   _Jv_JNI_FatalError,
1387
1388   _Jv_JNI_PushLocalFrame,
1389   _Jv_JNI_PopLocalFrame,
1390   _Jv_JNI_NewGlobalRef,
1391   _Jv_JNI_DeleteGlobalRef,
1392   _Jv_JNI_DeleteLocalRef,
1393
1394   _Jv_JNI_IsSameObject,
1395
1396   _Jv_JNI_NewLocalRef,
1397   _Jv_JNI_EnsureLocalCapacity,
1398
1399   _Jv_JNI_AllocObject,
1400   _Jv_JNI_NewObject,
1401   _Jv_JNI_NewObjectV,
1402   _Jv_JNI_NewObjectA,
1403   _Jv_JNI_GetObjectClass,
1404   _Jv_JNI_IsInstanceOf,
1405   _Jv_JNI_GetAnyMethodID<false>,
1406
1407   _Jv_JNI_CallMethod<jobject>,
1408   _Jv_JNI_CallMethodV<jobject>,
1409   _Jv_JNI_CallMethodA<jobject>,
1410   _Jv_JNI_CallMethod<jboolean>,
1411   _Jv_JNI_CallMethodV<jboolean>,
1412   _Jv_JNI_CallMethodA<jboolean>,
1413   _Jv_JNI_CallMethod<jbyte>,
1414   _Jv_JNI_CallMethodV<jbyte>,
1415   _Jv_JNI_CallMethodA<jbyte>,
1416   _Jv_JNI_CallMethod<jchar>,
1417   _Jv_JNI_CallMethodV<jchar>,
1418   _Jv_JNI_CallMethodA<jchar>,
1419   _Jv_JNI_CallMethod<jshort>,
1420   _Jv_JNI_CallMethodV<jshort>,
1421   _Jv_JNI_CallMethodA<jshort>,
1422   _Jv_JNI_CallMethod<jint>,
1423   _Jv_JNI_CallMethodV<jint>,
1424   _Jv_JNI_CallMethodA<jint>,
1425   _Jv_JNI_CallMethod<jlong>,
1426   _Jv_JNI_CallMethodV<jlong>,
1427   _Jv_JNI_CallMethodA<jlong>,
1428   _Jv_JNI_CallMethod<jfloat>,
1429   _Jv_JNI_CallMethodV<jfloat>,
1430   _Jv_JNI_CallMethodA<jfloat>,
1431   _Jv_JNI_CallMethod<jdouble>,
1432   _Jv_JNI_CallMethodV<jdouble>,
1433   _Jv_JNI_CallMethodA<jdouble>,
1434   _Jv_JNI_CallVoidMethod,
1435   _Jv_JNI_CallVoidMethodV,
1436   _Jv_JNI_CallVoidMethodA,
1437
1438   // Nonvirtual method invocation functions follow.
1439   _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1440   _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1441   _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1442   _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1443   _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1444   _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1445   _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1446   _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1447   _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1448   _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1449   _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1450   _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1451   _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1452   _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1453   _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1454   _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1455   _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1456   _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1457   _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1458   _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1459   _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1460   _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1461   _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1462   _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1463   _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1464   _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1465   _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1466   _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1467   _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1468   _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1469
1470   _Jv_JNI_GetAnyFieldID<false>,
1471   _Jv_JNI_GetField<jobject>,
1472   _Jv_JNI_GetField<jboolean>,
1473   _Jv_JNI_GetField<jbyte>,
1474   _Jv_JNI_GetField<jchar>,
1475   _Jv_JNI_GetField<jshort>,
1476   _Jv_JNI_GetField<jint>,
1477   _Jv_JNI_GetField<jlong>,
1478   _Jv_JNI_GetField<jfloat>,
1479   _Jv_JNI_GetField<jdouble>,
1480   _Jv_JNI_SetField,
1481   _Jv_JNI_SetField,
1482   _Jv_JNI_SetField,
1483   _Jv_JNI_SetField,
1484   _Jv_JNI_SetField,
1485   _Jv_JNI_SetField,
1486   _Jv_JNI_SetField,
1487   _Jv_JNI_SetField,
1488   _Jv_JNI_SetField,
1489   _Jv_JNI_GetAnyMethodID<true>,
1490
1491   _Jv_JNI_CallStaticMethod<jobject>,
1492   _Jv_JNI_CallStaticMethodV<jobject>,
1493   _Jv_JNI_CallStaticMethodA<jobject>,
1494   _Jv_JNI_CallStaticMethod<jboolean>,
1495   _Jv_JNI_CallStaticMethodV<jboolean>,
1496   _Jv_JNI_CallStaticMethodA<jboolean>,
1497   _Jv_JNI_CallStaticMethod<jbyte>,
1498   _Jv_JNI_CallStaticMethodV<jbyte>,
1499   _Jv_JNI_CallStaticMethodA<jbyte>,
1500   _Jv_JNI_CallStaticMethod<jchar>,
1501   _Jv_JNI_CallStaticMethodV<jchar>,
1502   _Jv_JNI_CallStaticMethodA<jchar>,
1503   _Jv_JNI_CallStaticMethod<jshort>,
1504   _Jv_JNI_CallStaticMethodV<jshort>,
1505   _Jv_JNI_CallStaticMethodA<jshort>,
1506   _Jv_JNI_CallStaticMethod<jint>,
1507   _Jv_JNI_CallStaticMethodV<jint>,
1508   _Jv_JNI_CallStaticMethodA<jint>,
1509   _Jv_JNI_CallStaticMethod<jlong>,
1510   _Jv_JNI_CallStaticMethodV<jlong>,
1511   _Jv_JNI_CallStaticMethodA<jlong>,
1512   _Jv_JNI_CallStaticMethod<jfloat>,
1513   _Jv_JNI_CallStaticMethodV<jfloat>,
1514   _Jv_JNI_CallStaticMethodA<jfloat>,
1515   _Jv_JNI_CallStaticMethod<jdouble>,
1516   _Jv_JNI_CallStaticMethodV<jdouble>,
1517   _Jv_JNI_CallStaticMethodA<jdouble>,
1518   _Jv_JNI_CallStaticVoidMethod,
1519   _Jv_JNI_CallStaticVoidMethodV,
1520   _Jv_JNI_CallStaticVoidMethodA,
1521
1522   _Jv_JNI_GetAnyFieldID<true>,
1523   _Jv_JNI_GetStaticField<jobject>,
1524   _Jv_JNI_GetStaticField<jboolean>,
1525   _Jv_JNI_GetStaticField<jbyte>,
1526   _Jv_JNI_GetStaticField<jchar>,
1527   _Jv_JNI_GetStaticField<jshort>,
1528   _Jv_JNI_GetStaticField<jint>,
1529   _Jv_JNI_GetStaticField<jlong>,
1530   _Jv_JNI_GetStaticField<jfloat>,
1531   _Jv_JNI_GetStaticField<jdouble>,
1532   _Jv_JNI_SetStaticField,
1533   _Jv_JNI_SetStaticField,
1534   _Jv_JNI_SetStaticField,
1535   _Jv_JNI_SetStaticField,
1536   _Jv_JNI_SetStaticField,
1537   _Jv_JNI_SetStaticField,
1538   _Jv_JNI_SetStaticField,
1539   _Jv_JNI_SetStaticField,
1540   _Jv_JNI_SetStaticField,
1541   _Jv_JNI_NewString,
1542   _Jv_JNI_GetStringLength,
1543   _Jv_JNI_GetStringChars,
1544   _Jv_JNI_ReleaseStringChars,
1545   _Jv_JNI_NewStringUTF,
1546   _Jv_JNI_GetStringUTFLength,
1547   _Jv_JNI_GetStringUTFChars,
1548   _Jv_JNI_ReleaseStringUTFChars,
1549   _Jv_JNI_GetArrayLength,
1550   _Jv_JNI_NewObjectArray,
1551   _Jv_JNI_GetObjectArrayElement,
1552   _Jv_JNI_SetObjectArrayElement,
1553   _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1554   _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1555   _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1556   _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1557   _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1558   _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1559   _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1560   _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
1561   _Jv_JNI_GetPrimitiveArrayElements,
1562   _Jv_JNI_GetPrimitiveArrayElements,
1563   _Jv_JNI_GetPrimitiveArrayElements,
1564   _Jv_JNI_GetPrimitiveArrayElements,
1565   _Jv_JNI_GetPrimitiveArrayElements,
1566   _Jv_JNI_GetPrimitiveArrayElements,
1567   _Jv_JNI_GetPrimitiveArrayElements,
1568   _Jv_JNI_GetPrimitiveArrayElements,
1569   _Jv_JNI_ReleasePrimitiveArrayElements,
1570   _Jv_JNI_ReleasePrimitiveArrayElements,
1571   _Jv_JNI_ReleasePrimitiveArrayElements,
1572   _Jv_JNI_ReleasePrimitiveArrayElements,
1573   _Jv_JNI_ReleasePrimitiveArrayElements,
1574   _Jv_JNI_ReleasePrimitiveArrayElements,
1575   _Jv_JNI_ReleasePrimitiveArrayElements,
1576   _Jv_JNI_ReleasePrimitiveArrayElements,
1577   _Jv_JNI_GetPrimitiveArrayRegion,
1578   _Jv_JNI_GetPrimitiveArrayRegion,
1579   _Jv_JNI_GetPrimitiveArrayRegion,
1580   _Jv_JNI_GetPrimitiveArrayRegion,
1581   _Jv_JNI_GetPrimitiveArrayRegion,
1582   _Jv_JNI_GetPrimitiveArrayRegion,
1583   _Jv_JNI_GetPrimitiveArrayRegion,
1584   _Jv_JNI_GetPrimitiveArrayRegion,
1585   _Jv_JNI_SetPrimitiveArrayRegion,
1586   _Jv_JNI_SetPrimitiveArrayRegion,
1587   _Jv_JNI_SetPrimitiveArrayRegion,
1588   _Jv_JNI_SetPrimitiveArrayRegion,
1589   _Jv_JNI_SetPrimitiveArrayRegion,
1590   _Jv_JNI_SetPrimitiveArrayRegion,
1591   _Jv_JNI_SetPrimitiveArrayRegion,
1592   _Jv_JNI_SetPrimitiveArrayRegion,
1593   NOT_IMPL /* RegisterNatives */,
1594   NOT_IMPL /* UnregisterNatives */,
1595   _Jv_JNI_MonitorEnter,
1596   _Jv_JNI_MonitorExit,
1597   NOT_IMPL /* GetJavaVM */,
1598
1599   _Jv_JNI_GetStringRegion,
1600   _Jv_JNI_GetStringUTFRegion,
1601   _Jv_JNI_GetPrimitiveArrayCritical,
1602   _Jv_JNI_ReleasePrimitiveArrayCritical,
1603   _Jv_JNI_GetStringCritical,
1604   _Jv_JNI_ReleaseStringCritical,
1605
1606   NOT_IMPL /* newweakglobalref */,
1607   NOT_IMPL /* deleteweakglobalref */,
1608
1609   _Jv_JNI_ExceptionCheck
1610 };