OSDN Git Service

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