OSDN Git Service

2005-02-13 Anthony Green <green@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / jni.cc
1 // jni.cc - JNI implementation, including the jump table.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
4    Free Software Foundation
5
6    This file is part of libgcj.
7
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10 details.  */
11
12 #include <config.h>
13
14 #include <stdio.h>
15 #include <stddef.h>
16 #include <string.h>
17
18 #include <gcj/cni.h>
19 #include <jvm.h>
20 #include <java-assert.h>
21 #include <jni.h>
22 #ifdef ENABLE_JVMPI
23 #include <jvmpi.h>
24 #endif
25
26 #include <java/lang/Class.h>
27 #include <java/lang/ClassLoader.h>
28 #include <java/lang/Throwable.h>
29 #include <java/lang/ArrayIndexOutOfBoundsException.h>
30 #include <java/lang/StringIndexOutOfBoundsException.h>
31 #include <java/lang/StringBuffer.h>
32 #include <java/lang/UnsatisfiedLinkError.h>
33 #include <java/lang/InstantiationException.h>
34 #include <java/lang/NoSuchFieldError.h>
35 #include <java/lang/NoSuchMethodError.h>
36 #include <java/lang/reflect/Constructor.h>
37 #include <java/lang/reflect/Method.h>
38 #include <java/lang/reflect/Modifier.h>
39 #include <java/lang/OutOfMemoryError.h>
40 #include <java/lang/Integer.h>
41 #include <java/lang/ThreadGroup.h>
42 #include <java/lang/Thread.h>
43 #include <java/lang/IllegalAccessError.h>
44 #include <java/nio/Buffer.h>
45 #include <java/nio/DirectByteBufferImpl.h>
46 #include <java/nio/DirectByteBufferImpl$ReadWrite.h>
47 #include <java/util/IdentityHashMap.h>
48 #include <gnu/gcj/RawData.h>
49
50 #include <gcj/method.h>
51 #include <gcj/field.h>
52
53 #include <java-interp.h>
54 #include <java-threads.h>
55
56 using namespace gcj;
57
58 // This enum is used to select different template instantiations in
59 // the invocation code.
60 enum invocation_type
61 {
62   normal,
63   nonvirtual,
64   static_type,
65   constructor
66 };
67
68 // Forward declarations.
69 extern struct JNINativeInterface _Jv_JNIFunctions;
70 extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions;
71
72 // Number of slots in the default frame.  The VM must allow at least
73 // 16.
74 #define FRAME_SIZE 16
75
76 // Mark value indicating this is an overflow frame.
77 #define MARK_NONE    0
78 // Mark value indicating this is a user frame.
79 #define MARK_USER    1
80 // Mark value indicating this is a system frame.
81 #define MARK_SYSTEM  2
82
83 // This structure is used to keep track of local references.
84 struct _Jv_JNI_LocalFrame
85 {
86   // This is true if this frame object represents a pushed frame (eg
87   // from PushLocalFrame).
88   int marker;
89
90   // Flag to indicate some locals were allocated.
91   int allocated_p;
92
93   // Number of elements in frame.
94   int size;
95
96   // Next frame in chain.
97   _Jv_JNI_LocalFrame *next;
98
99   // The elements.  These are allocated using the C "struct hack".
100   jobject vec[0];
101 };
102
103 // This holds a reference count for all local references.
104 static java::util::IdentityHashMap *local_ref_table;
105 // This holds a reference count for all global references.
106 static java::util::IdentityHashMap *global_ref_table;
107
108 // The only VM.
109 static JavaVM *the_vm;
110
111 #ifdef ENABLE_JVMPI
112 // The only JVMPI interface description.
113 static JVMPI_Interface _Jv_JVMPI_Interface;
114
115 static jint
116 jvmpiEnableEvent (jint event_type, void *)
117 {
118   switch (event_type)
119     {
120     case JVMPI_EVENT_OBJECT_ALLOC:
121       _Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent;
122       break;
123
124     case JVMPI_EVENT_THREAD_START:
125       _Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent;
126       break;
127
128     case JVMPI_EVENT_THREAD_END:
129       _Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent;
130       break;
131
132     default:
133       return JVMPI_NOT_AVAILABLE;
134     }
135
136   return JVMPI_SUCCESS;
137 }
138
139 static jint
140 jvmpiDisableEvent (jint event_type, void *)
141 {
142   switch (event_type)
143     {
144     case JVMPI_EVENT_OBJECT_ALLOC:
145       _Jv_JVMPI_Notify_OBJECT_ALLOC = NULL;
146       break;
147
148     default:
149       return JVMPI_NOT_AVAILABLE;
150     }
151
152   return JVMPI_SUCCESS;
153 }
154 #endif
155
156 \f
157
158 void
159 _Jv_JNI_Init (void)
160 {
161   local_ref_table = new java::util::IdentityHashMap;
162   global_ref_table = new java::util::IdentityHashMap;
163
164 #ifdef ENABLE_JVMPI
165   _Jv_JVMPI_Interface.version = 1;
166   _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent;
167   _Jv_JVMPI_Interface.DisableEvent = &jvmpiDisableEvent;
168   _Jv_JVMPI_Interface.EnableGC = &_Jv_EnableGC;
169   _Jv_JVMPI_Interface.DisableGC = &_Jv_DisableGC;
170   _Jv_JVMPI_Interface.RunGC = &_Jv_RunGC;
171 #endif
172 }
173
174 // Tell the GC that a certain pointer is live.
175 static void
176 mark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
177 {
178   JvSynchronize sync (ref_table);
179
180   using namespace java::lang;
181   Integer *refcount = (Integer *) ref_table->get (obj);
182   jint val = (refcount == NULL) ? 0 : refcount->intValue ();
183   // FIXME: what about out of memory error?
184   ref_table->put (obj, new Integer (val + 1));
185 }
186
187 // Unmark a pointer.
188 static void
189 unmark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
190 {
191   JvSynchronize sync (ref_table);
192
193   using namespace java::lang;
194   Integer *refcount = (Integer *) ref_table->get (obj);
195   JvAssert (refcount);
196   jint val = refcount->intValue () - 1;
197   JvAssert (val >= 0);
198   if (val == 0)
199     ref_table->remove (obj);
200   else
201     // FIXME: what about out of memory error?
202     ref_table->put (obj, new Integer (val));
203 }
204
205 // "Unwrap" some random non-reference type.  This exists to simplify
206 // other template functions.
207 template<typename T>
208 static T
209 unwrap (T val)
210 {
211   return val;
212 }
213
214 // Unwrap a weak reference, if required.
215 template<typename T>
216 static T *
217 unwrap (T *obj)
218 {
219   using namespace gnu::gcj::runtime;
220   // We can compare the class directly because JNIWeakRef is `final'.
221   // Doing it this way is much faster.
222   if (obj == NULL || obj->getClass () != &JNIWeakRef::class$)
223     return obj;
224   JNIWeakRef *wr = reinterpret_cast<JNIWeakRef *> (obj);
225   return reinterpret_cast<T *> (wr->get ());
226 }
227
228 \f
229
230 static jobject JNICALL
231 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
232 {
233   // This seems weird but I think it is correct.
234   obj = unwrap (obj);
235   mark_for_gc (obj, global_ref_table);
236   return obj;
237 }
238
239 static void JNICALL
240 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
241 {
242   // This seems weird but I think it is correct.
243   obj = unwrap (obj);
244   unmark_for_gc (obj, global_ref_table);
245 }
246
247 static void JNICALL
248 _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
249 {
250   _Jv_JNI_LocalFrame *frame;
251
252   // This seems weird but I think it is correct.
253   obj = unwrap (obj);
254
255   for (frame = env->locals; frame != NULL; frame = frame->next)
256     {
257       for (int i = 0; i < frame->size; ++i)
258         {
259           if (frame->vec[i] == obj)
260             {
261               frame->vec[i] = NULL;
262               unmark_for_gc (obj, local_ref_table);
263               return;
264             }
265         }
266
267       // Don't go past a marked frame.
268       JvAssert (frame->marker == MARK_NONE);
269     }
270
271   JvAssert (0);
272 }
273
274 static jint JNICALL
275 _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
276 {
277   // It is easier to just always allocate a new frame of the requested
278   // size.  This isn't the most efficient thing, but for now we don't
279   // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
280
281   _Jv_JNI_LocalFrame *frame;
282   try
283     {
284       frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame)
285                                                  + size * sizeof (jobject));
286     }
287   catch (jthrowable t)
288     {
289       env->ex = t;
290       return JNI_ERR;
291     }
292
293   frame->marker = MARK_NONE;
294   frame->size = size;
295   frame->allocated_p = 0;
296   memset (&frame->vec[0], 0, size * sizeof (jobject));
297   frame->next = env->locals;
298   env->locals = frame;
299
300   return 0;
301 }
302
303 static jint JNICALL
304 _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
305 {
306   jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
307   if (r < 0)
308     return r;
309
310   // The new frame is on top.
311   env->locals->marker = MARK_USER;
312
313   return 0;
314 }
315
316 static jobject JNICALL
317 _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
318 {
319   // This seems weird but I think it is correct.
320   obj = unwrap (obj);
321
322   // Try to find an open slot somewhere in the topmost frame.
323   _Jv_JNI_LocalFrame *frame = env->locals;
324   bool done = false, set = false;
325   for (; frame != NULL && ! done; frame = frame->next)
326     {
327       for (int i = 0; i < frame->size; ++i)
328         {
329           if (frame->vec[i] == NULL)
330             {
331               set = true;
332               done = true;
333               frame->vec[i] = obj;
334               frame->allocated_p = 1;
335               break;
336             }
337         }
338
339       // If we found a slot, or if the frame we just searched is the
340       // mark frame, then we are done.
341       if (done || frame == NULL || frame->marker != MARK_NONE)
342         break;
343     }
344
345   if (! set)
346     {
347       // No slots, so we allocate a new frame.  According to the spec
348       // we could just die here.  FIXME: return value.
349       _Jv_JNI_EnsureLocalCapacity (env, 16);
350       // We know the first element of the new frame will be ok.
351       env->locals->vec[0] = obj;
352       env->locals->allocated_p = 1;
353     }
354
355   mark_for_gc (obj, local_ref_table);
356   return obj;
357 }
358
359 static jobject JNICALL
360 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
361 {
362   _Jv_JNI_LocalFrame *rf = env->locals;
363
364   bool done = false;
365   while (rf != NULL && ! done)
366     {
367       for (int i = 0; i < rf->size; ++i)
368         if (rf->vec[i] != NULL)
369           unmark_for_gc (rf->vec[i], local_ref_table);
370
371       // If the frame we just freed is the marker frame, we are done.
372       done = (rf->marker == stop);
373
374       _Jv_JNI_LocalFrame *n = rf->next;
375       // When N==NULL, we've reached the reusable bottom_locals, and we must
376       // not free it.  However, we must be sure to clear all its elements.
377       if (n == NULL)
378         {
379           if (rf->allocated_p)
380             memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
381           rf->allocated_p = 0;
382           rf = NULL;
383           break;
384         }
385
386       _Jv_Free (rf);
387       rf = n;
388     }
389
390   // Update the local frame information.
391   env->locals = rf;
392
393   return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
394 }
395
396 static jobject JNICALL
397 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
398 {
399   return _Jv_JNI_PopLocalFrame (env, result, MARK_USER);
400 }
401
402 // Make sure an array's type is compatible with the type of the
403 // destination.
404 template<typename T>
405 static bool
406 _Jv_JNI_check_types (JNIEnv *env, JArray<T> *array, jclass K)
407 {
408   jclass klass = array->getClass()->getComponentType();
409   if (__builtin_expect (klass != K, false))
410     {
411       env->ex = new java::lang::IllegalAccessError ();
412       return false;
413     }
414   else
415     return true;
416 }
417
418 // Pop a `system' frame from the stack.  This is `extern "C"' as it is
419 // used by the compiler.
420 extern "C" void
421 _Jv_JNI_PopSystemFrame (JNIEnv *env)
422 {
423   // Only enter slow path when we're not at the bottom, or there have been
424   // allocations. Usually this is false and we can just null out the locals
425   // field.
426
427   if (__builtin_expect ((env->locals->next 
428                          || env->locals->allocated_p), false))
429     _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
430   else
431     env->locals = NULL;
432   
433   if (__builtin_expect (env->ex != NULL, false))
434     {
435       jthrowable t = env->ex;
436       env->ex = NULL;
437       throw t;
438     }
439 }
440
441 template<typename T> T extract_from_jvalue(jvalue const & t);
442 template<> jboolean extract_from_jvalue(jvalue const & jv) { return jv.z; }
443 template<> jbyte    extract_from_jvalue(jvalue const & jv) { return jv.b; }
444 template<> jchar    extract_from_jvalue(jvalue const & jv) { return jv.c; }
445 template<> jshort   extract_from_jvalue(jvalue const & jv) { return jv.s; }
446 template<> jint     extract_from_jvalue(jvalue const & jv) { return jv.i; }
447 template<> jlong    extract_from_jvalue(jvalue const & jv) { return jv.j; }
448 template<> jfloat   extract_from_jvalue(jvalue const & jv) { return jv.f; }
449 template<> jdouble  extract_from_jvalue(jvalue const & jv) { return jv.d; }
450 template<> jobject  extract_from_jvalue(jvalue const & jv) { return jv.l; }
451
452
453 // This function is used from other template functions.  It wraps the
454 // return value appropriately; we specialize it so that object returns
455 // are turned into local references.
456 template<typename T>
457 static T
458 wrap_value (JNIEnv *, T value)
459 {
460   return value;
461 }
462
463 // This specialization is used for jobject, jclass, jstring, jarray,
464 // etc.
465 template<typename R, typename T>
466 static T *
467 wrap_value (JNIEnv *env, T *value)
468 {
469   return (value == NULL
470           ? value
471           : (T *) _Jv_JNI_NewLocalRef (env, (jobject) value));
472 }
473
474 \f
475
476 static jint JNICALL
477 _Jv_JNI_GetVersion (JNIEnv *)
478 {
479   return JNI_VERSION_1_4;
480 }
481
482 static jclass JNICALL
483 _Jv_JNI_DefineClass (JNIEnv *env, const char *name, jobject loader,
484                      const jbyte *buf, jsize bufLen)
485 {
486   try
487     {
488       loader = unwrap (loader);
489
490       jstring sname = JvNewStringUTF (name);
491       jbyteArray bytes = JvNewByteArray (bufLen);
492
493       jbyte *elts = elements (bytes);
494       memcpy (elts, buf, bufLen * sizeof (jbyte));
495
496       java::lang::ClassLoader *l
497         = reinterpret_cast<java::lang::ClassLoader *> (loader);
498
499       jclass result = l->defineClass (sname, bytes, 0, bufLen);
500       return (jclass) wrap_value (env, result);
501     }
502   catch (jthrowable t)
503     {
504       env->ex = t;
505       return NULL;
506     }
507 }
508
509 static jclass JNICALL
510 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
511 {
512   // FIXME: assume that NAME isn't too long.
513   int len = strlen (name);
514   char s[len + 1];
515   for (int i = 0; i <= len; ++i)
516     s[i] = (name[i] == '/') ? '.' : name[i];
517
518   jclass r = NULL;
519   try
520     {
521       // This might throw an out of memory exception.
522       jstring n = JvNewStringUTF (s);
523
524       java::lang::ClassLoader *loader = NULL;
525       if (env->klass != NULL)
526         loader = env->klass->getClassLoaderInternal ();
527
528       if (loader == NULL)
529         {
530           // FIXME: should use getBaseClassLoader, but we don't have that
531           // yet.
532           loader = java::lang::ClassLoader::getSystemClassLoader ();
533         }
534
535       r = loader->loadClass (n);
536     }
537   catch (jthrowable t)
538     {
539       env->ex = t;
540     }
541
542   return (jclass) wrap_value (env, r);
543 }
544
545 static jclass JNICALL
546 _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
547 {
548   return (jclass) wrap_value (env, unwrap (clazz)->getSuperclass ());
549 }
550
551 static jboolean JNICALL
552 _Jv_JNI_IsAssignableFrom (JNIEnv *, jclass clazz1, jclass clazz2)
553 {
554   return unwrap (clazz1)->isAssignableFrom (unwrap (clazz2));
555 }
556
557 static jint JNICALL
558 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
559 {
560   // We check in case the user did some funky cast.
561   obj = unwrap (obj);
562   JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
563   env->ex = obj;
564   return 0;
565 }
566
567 static jint JNICALL
568 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
569 {
570   using namespace java::lang::reflect;
571
572   clazz = unwrap (clazz);
573   JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
574
575   int r = JNI_OK;
576   try
577     {
578       JArray<jclass> *argtypes
579         = (JArray<jclass> *) JvNewObjectArray (1, &java::lang::Class::class$,
580                                                NULL);
581
582       jclass *elts = elements (argtypes);
583       elts[0] = &java::lang::String::class$;
584
585       Constructor *cons = clazz->getConstructor (argtypes);
586
587       jobjectArray values = JvNewObjectArray (1, &java::lang::String::class$,
588                                               NULL);
589       jobject *velts = elements (values);
590       velts[0] = JvNewStringUTF (message);
591
592       jobject obj = cons->newInstance (values);
593
594       env->ex = reinterpret_cast<jthrowable> (obj);
595     }
596   catch (jthrowable t)
597     {
598       env->ex = t;
599       r = JNI_ERR;
600     }
601
602   return r;
603 }
604
605 static jthrowable JNICALL
606 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
607 {
608   return (jthrowable) wrap_value (env, env->ex);
609 }
610
611 static void JNICALL
612 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
613 {
614   if (env->ex != NULL)
615     env->ex->printStackTrace();
616 }
617
618 static void JNICALL
619 _Jv_JNI_ExceptionClear (JNIEnv *env)
620 {
621   env->ex = NULL;
622 }
623
624 static jboolean JNICALL
625 _Jv_JNI_ExceptionCheck (JNIEnv *env)
626 {
627   return env->ex != NULL;
628 }
629
630 static void JNICALL
631 _Jv_JNI_FatalError (JNIEnv *, const char *message)
632 {
633   JvFail (message);
634 }
635
636 \f
637
638 static jboolean JNICALL
639 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
640 {
641   return unwrap (obj1) == unwrap (obj2);
642 }
643
644 static jobject JNICALL
645 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
646 {
647   jobject obj = NULL;
648   using namespace java::lang::reflect;
649
650   try
651     {
652       clazz = unwrap (clazz);
653       JvAssert (clazz && ! clazz->isArray ());
654       if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
655         env->ex = new java::lang::InstantiationException ();
656       else
657         obj = _Jv_AllocObject (clazz);
658     }
659   catch (jthrowable t)
660     {
661       env->ex = t;
662     }
663
664   return wrap_value (env, obj);
665 }
666
667 static jclass JNICALL
668 _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
669 {
670   obj = unwrap (obj);
671   JvAssert (obj);
672   return (jclass) wrap_value (env, obj->getClass());
673 }
674
675 static jboolean JNICALL
676 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
677 {
678   return unwrap (clazz)->isInstance(unwrap (obj));
679 }
680
681 \f
682
683 //
684 // This section concerns method invocation.
685 //
686
687 template<jboolean is_static>
688 static jmethodID JNICALL
689 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
690                         const char *name, const char *sig)
691 {
692   try
693     {
694       clazz = unwrap (clazz);
695       _Jv_InitClass (clazz);
696
697       _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
698
699       // FIXME: assume that SIG isn't too long.
700       int len = strlen (sig);
701       char s[len + 1];
702       for (int i = 0; i <= len; ++i)
703         s[i] = (sig[i] == '/') ? '.' : sig[i];
704       _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) s, -1);
705
706       JvAssert (! clazz->isPrimitive());
707
708       using namespace java::lang::reflect;
709
710       while (clazz != NULL)
711         {
712           jint count = JvNumMethods (clazz);
713           jmethodID meth = JvGetFirstMethod (clazz);
714
715           for (jint i = 0; i < count; ++i)
716             {
717               if (((is_static && Modifier::isStatic (meth->accflags))
718                    || (! is_static && ! Modifier::isStatic (meth->accflags)))
719                   && _Jv_equalUtf8Consts (meth->name, name_u)
720                   && _Jv_equalUtf8Consts (meth->signature, sig_u))
721                 return meth;
722
723               meth = meth->getNextMethod();
724             }
725
726           clazz = clazz->getSuperclass ();
727         }
728
729       java::lang::StringBuffer *name_sig =
730         new java::lang::StringBuffer (JvNewStringUTF (name));
731       name_sig->append ((jchar) ' ')->append (JvNewStringUTF (s));
732       env->ex = new java::lang::NoSuchMethodError (name_sig->toString ());
733     }
734   catch (jthrowable t)
735     {
736       env->ex = t;
737     }
738
739   return NULL;
740 }
741
742 // This is a helper function which turns a va_list into an array of
743 // `jvalue's.  It needs signature information in order to do its work.
744 // The array of values must already be allocated.
745 static void
746 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
747 {
748   jclass *arg_elts = elements (arg_types);
749   for (int i = 0; i < arg_types->length; ++i)
750     {
751       // Here we assume that sizeof(int) >= sizeof(jint), because we
752       // use `int' when decoding the varargs.  Likewise for
753       // float, and double.  Also we assume that sizeof(jlong) >=
754       // sizeof(int), i.e. that jlong values are not further
755       // promoted.
756       JvAssert (sizeof (int) >= sizeof (jint));
757       JvAssert (sizeof (jlong) >= sizeof (int));
758       JvAssert (sizeof (double) >= sizeof (jfloat));
759       JvAssert (sizeof (double) >= sizeof (jdouble));
760       if (arg_elts[i] == JvPrimClass (byte))
761         values[i].b = (jbyte) va_arg (vargs, int);
762       else if (arg_elts[i] == JvPrimClass (short))
763         values[i].s = (jshort) va_arg (vargs, int);
764       else if (arg_elts[i] == JvPrimClass (int))
765         values[i].i = (jint) va_arg (vargs, int);
766       else if (arg_elts[i] == JvPrimClass (long))
767         values[i].j = (jlong) va_arg (vargs, jlong);
768       else if (arg_elts[i] == JvPrimClass (float))
769         values[i].f = (jfloat) va_arg (vargs, double);
770       else if (arg_elts[i] == JvPrimClass (double))
771         values[i].d = (jdouble) va_arg (vargs, double);
772       else if (arg_elts[i] == JvPrimClass (boolean))
773         values[i].z = (jboolean) va_arg (vargs, int);
774       else if (arg_elts[i] == JvPrimClass (char))
775         values[i].c = (jchar) va_arg (vargs, int);
776       else
777         {
778           // An object.
779           values[i].l = unwrap (va_arg (vargs, jobject));
780         }
781     }
782 }
783
784 // This can call any sort of method: virtual, "nonvirtual", static, or
785 // constructor.
786 template<typename T, invocation_type style>
787 static T JNICALL
788 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
789                         jmethodID id, va_list vargs)
790 {
791   obj = unwrap (obj);
792   klass = unwrap (klass);
793
794   jclass decl_class = klass ? klass : obj->getClass ();
795   JvAssert (decl_class != NULL);
796
797   jclass return_type;
798   JArray<jclass> *arg_types;
799
800   try
801     {
802       _Jv_GetTypesFromSignature (id, decl_class,
803                                  &arg_types, &return_type);
804
805       jvalue args[arg_types->length];
806       array_from_valist (args, arg_types, vargs);
807
808       // For constructors we need to pass the Class we are instantiating.
809       if (style == constructor)
810         return_type = klass;
811
812       jvalue result;
813       _Jv_CallAnyMethodA (obj, return_type, id,
814                           style == constructor,
815                           style == normal,
816                           arg_types, args, &result);
817
818       return wrap_value (env, extract_from_jvalue<T>(result));
819     }
820   catch (jthrowable t)
821     {
822       env->ex = t;
823     }
824
825   return wrap_value (env, (T) 0);
826 }
827
828 template<typename T, invocation_type style>
829 static T JNICALL
830 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
831                        jmethodID method, ...)
832 {
833   va_list args;
834   T result;
835
836   va_start (args, method);
837   result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
838   va_end (args);
839
840   return result;
841 }
842
843 template<typename T, invocation_type style>
844 static T JNICALL
845 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
846                         jmethodID id, jvalue *args)
847 {
848   obj = unwrap (obj);
849   klass = unwrap (klass);
850
851   jclass decl_class = klass ? klass : obj->getClass ();
852   JvAssert (decl_class != NULL);
853
854   jclass return_type;
855   JArray<jclass> *arg_types;
856   try
857     {
858       _Jv_GetTypesFromSignature (id, decl_class,
859                                  &arg_types, &return_type);
860
861       // For constructors we need to pass the Class we are instantiating.
862       if (style == constructor)
863         return_type = klass;
864
865       // Unwrap arguments as required.  Eww.
866       jclass *type_elts = elements (arg_types);
867       jvalue arg_copy[arg_types->length];
868       for (int i = 0; i < arg_types->length; ++i)
869         {
870           if (type_elts[i]->isPrimitive ())
871             arg_copy[i] = args[i];
872           else
873             arg_copy[i].l = unwrap (args[i].l);
874         }
875
876       jvalue result;
877       _Jv_CallAnyMethodA (obj, return_type, id,
878                           style == constructor,
879                           style == normal,
880                           arg_types, arg_copy, &result);
881
882       return wrap_value (env, extract_from_jvalue<T>(result));
883     }
884   catch (jthrowable t)
885     {
886       env->ex = t;
887     }
888
889   return wrap_value (env, (T) 0);
890 }
891
892 template<invocation_type style>
893 static void JNICALL
894 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
895                             jmethodID id, va_list vargs)
896 {
897   obj = unwrap (obj);
898   klass = unwrap (klass);
899
900   jclass decl_class = klass ? klass : obj->getClass ();
901   JvAssert (decl_class != NULL);
902
903   jclass return_type;
904   JArray<jclass> *arg_types;
905   try
906     {
907       _Jv_GetTypesFromSignature (id, decl_class,
908                                  &arg_types, &return_type);
909
910       jvalue args[arg_types->length];
911       array_from_valist (args, arg_types, vargs);
912
913       // For constructors we need to pass the Class we are instantiating.
914       if (style == constructor)
915         return_type = klass;
916
917       _Jv_CallAnyMethodA (obj, return_type, id,
918                           style == constructor,
919                           style == normal,
920                           arg_types, args, NULL);
921     }
922   catch (jthrowable t)
923     {
924       env->ex = t;
925     }
926 }
927
928 template<invocation_type style>
929 static void JNICALL
930 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
931                            jmethodID method, ...)
932 {
933   va_list args;
934
935   va_start (args, method);
936   _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
937   va_end (args);
938 }
939
940 template<invocation_type style>
941 static void JNICALL
942 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
943                             jmethodID id, jvalue *args)
944 {
945   jclass decl_class = klass ? klass : obj->getClass ();
946   JvAssert (decl_class != NULL);
947
948   jclass return_type;
949   JArray<jclass> *arg_types;
950   try
951     {
952       _Jv_GetTypesFromSignature (id, decl_class,
953                                  &arg_types, &return_type);
954
955       // Unwrap arguments as required.  Eww.
956       jclass *type_elts = elements (arg_types);
957       jvalue arg_copy[arg_types->length];
958       for (int i = 0; i < arg_types->length; ++i)
959         {
960           if (type_elts[i]->isPrimitive ())
961             arg_copy[i] = args[i];
962           else
963             arg_copy[i].l = unwrap (args[i].l);
964         }
965
966       _Jv_CallAnyMethodA (obj, return_type, id,
967                           style == constructor,
968                           style == normal,
969                           arg_types, args, NULL);
970     }
971   catch (jthrowable t)
972     {
973       env->ex = t;
974     }
975 }
976
977 // Functions with this signature are used to implement functions in
978 // the CallMethod family.
979 template<typename T>
980 static T JNICALL
981 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, 
982                      jmethodID id, va_list args)
983 {
984   return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
985 }
986
987 // Functions with this signature are used to implement functions in
988 // the CallMethod family.
989 template<typename T>
990 static T JNICALL
991 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
992 {
993   va_list args;
994   T result;
995
996   va_start (args, id);
997   result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
998   va_end (args);
999
1000   return result;
1001 }
1002
1003 // Functions with this signature are used to implement functions in
1004 // the CallMethod family.
1005 template<typename T>
1006 static T JNICALL
1007 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, 
1008                      jmethodID id, jvalue *args)
1009 {
1010   return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
1011 }
1012
1013 static void JNICALL
1014 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, 
1015                          jmethodID id, va_list args)
1016 {
1017   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
1018 }
1019
1020 static void JNICALL
1021 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
1022 {
1023   va_list args;
1024
1025   va_start (args, id);
1026   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
1027   va_end (args);
1028 }
1029
1030 static void JNICALL
1031 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, 
1032                          jmethodID id, jvalue *args)
1033 {
1034   _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
1035 }
1036
1037 // Functions with this signature are used to implement functions in
1038 // the CallStaticMethod family.
1039 template<typename T>
1040 static T JNICALL
1041 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
1042                            jmethodID id, va_list args)
1043 {
1044   JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1045   JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1046
1047   return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
1048 }
1049
1050 // Functions with this signature are used to implement functions in
1051 // the CallStaticMethod family.
1052 template<typename T>
1053 static T JNICALL
1054 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, 
1055                           jmethodID id, ...)
1056 {
1057   va_list args;
1058   T result;
1059
1060   JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1061   JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1062
1063   va_start (args, id);
1064   result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
1065                                                    id, args);
1066   va_end (args);
1067
1068   return result;
1069 }
1070
1071 // Functions with this signature are used to implement functions in
1072 // the CallStaticMethod family.
1073 template<typename T>
1074 static T JNICALL
1075 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
1076                            jvalue *args)
1077 {
1078   JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1079   JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1080
1081   return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
1082 }
1083
1084 static void JNICALL
1085 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, 
1086                                jmethodID id, va_list args)
1087 {
1088   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
1089 }
1090
1091 static void JNICALL
1092 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, 
1093                               jmethodID id, ...)
1094 {
1095   va_list args;
1096
1097   va_start (args, id);
1098   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
1099   va_end (args);
1100 }
1101
1102 static void JNICALL
1103 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, 
1104                                jmethodID id, jvalue *args)
1105 {
1106   _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
1107 }
1108
1109 static jobject JNICALL
1110 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
1111                     jmethodID id, va_list args)
1112 {
1113   JvAssert (klass && ! klass->isArray ());
1114   JvAssert (! strcmp (id->name->data, "<init>")
1115             && id->signature->length > 2
1116             && id->signature->data[0] == '('
1117             && ! strcmp (&id->signature->data[id->signature->length - 2],
1118                          ")V"));
1119
1120   return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
1121                                                        id, args);
1122 }
1123
1124 static jobject JNICALL
1125 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
1126 {
1127   JvAssert (klass && ! klass->isArray ());
1128   JvAssert (! strcmp (id->name->data, "<init>")
1129             && id->signature->length > 2
1130             && id->signature->data[0] == '('
1131             && ! strcmp (&id->signature->data[id->signature->length - 2],
1132                          ")V"));
1133
1134   va_list args;
1135   jobject result;
1136
1137   va_start (args, id);
1138   result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
1139                                                          id, args);
1140   va_end (args);
1141
1142   return result;
1143 }
1144
1145 static jobject JNICALL
1146 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
1147                     jvalue *args)
1148 {
1149   JvAssert (klass && ! klass->isArray ());
1150   JvAssert (! strcmp (id->name->data, "<init>")
1151             && id->signature->length > 2
1152             && id->signature->data[0] == '('
1153             && ! strcmp (&id->signature->data[id->signature->length - 2],
1154                          ")V"));
1155
1156   return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
1157                                                        id, args);
1158 }
1159
1160 \f
1161
1162 template<typename T>
1163 static T JNICALL
1164 _Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
1165 {
1166   obj = unwrap (obj);
1167   JvAssert (obj);
1168   T *ptr = (T *) ((char *) obj + field->getOffset ());
1169   return wrap_value (env, *ptr);
1170 }
1171
1172 template<typename T>
1173 static void JNICALL
1174 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
1175 {
1176   obj = unwrap (obj);
1177   value = unwrap (value);
1178
1179   JvAssert (obj);
1180   T *ptr = (T *) ((char *) obj + field->getOffset ());
1181   *ptr = value;
1182 }
1183
1184 template<jboolean is_static>
1185 static jfieldID JNICALL
1186 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
1187                        const char *name, const char *sig)
1188 {
1189   try
1190     {
1191       clazz = unwrap (clazz);
1192
1193       _Jv_InitClass (clazz);
1194
1195       _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
1196
1197       // FIXME: assume that SIG isn't too long.
1198       int len = strlen (sig);
1199       char s[len + 1];
1200       for (int i = 0; i <= len; ++i)
1201         s[i] = (sig[i] == '/') ? '.' : sig[i];
1202       jclass field_class = _Jv_FindClassFromSignature ((char *) s, NULL);
1203
1204       // FIXME: what if field_class == NULL?
1205
1206       java::lang::ClassLoader *loader = clazz->getClassLoaderInternal ();
1207       while (clazz != NULL)
1208         {
1209           // We acquire the class lock so that fields aren't resolved
1210           // while we are running.
1211           JvSynchronize sync (clazz);
1212
1213           jint count = (is_static
1214                         ? JvNumStaticFields (clazz)
1215                         : JvNumInstanceFields (clazz));
1216           jfieldID field = (is_static
1217                             ? JvGetFirstStaticField (clazz)
1218                             : JvGetFirstInstanceField (clazz));
1219           for (jint i = 0; i < count; ++i)
1220             {
1221               _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
1222
1223               // The field might be resolved or it might not be.  It
1224               // is much simpler to always resolve it.
1225               _Jv_Linker::resolve_field (field, loader);
1226               if (_Jv_equalUtf8Consts (f_name, a_name)
1227                   && field->getClass() == field_class)
1228                 return field;
1229
1230               field = field->getNextField ();
1231             }
1232
1233           clazz = clazz->getSuperclass ();
1234         }
1235
1236       env->ex = new java::lang::NoSuchFieldError ();
1237     }
1238   catch (jthrowable t)
1239     {
1240       env->ex = t;
1241     }
1242   return NULL;
1243 }
1244
1245 template<typename T>
1246 static T JNICALL
1247 _Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
1248 {
1249   T *ptr = (T *) field->u.addr;
1250   return wrap_value (env, *ptr);
1251 }
1252
1253 template<typename T>
1254 static void JNICALL
1255 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
1256 {
1257   value = unwrap (value);
1258   T *ptr = (T *) field->u.addr;
1259   *ptr = value;
1260 }
1261
1262 static jstring JNICALL
1263 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
1264 {
1265   try
1266     {
1267       jstring r = _Jv_NewString (unichars, len);
1268       return (jstring) wrap_value (env, r);
1269     }
1270   catch (jthrowable t)
1271     {
1272       env->ex = t;
1273       return NULL;
1274     }
1275 }
1276
1277 static jsize JNICALL
1278 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
1279 {
1280   return unwrap (string)->length();
1281 }
1282
1283 static const jchar * JNICALL
1284 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
1285 {
1286   string = unwrap (string);
1287   jchar *result = _Jv_GetStringChars (string);
1288   mark_for_gc (string, global_ref_table);
1289   if (isCopy)
1290     *isCopy = false;
1291   return (const jchar *) result;
1292 }
1293
1294 static void JNICALL
1295 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
1296 {
1297   unmark_for_gc (unwrap (string), global_ref_table);
1298 }
1299
1300 static jstring JNICALL
1301 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
1302 {
1303   try
1304     {
1305       jstring result = JvNewStringUTF (bytes);
1306       return (jstring) wrap_value (env, result);
1307     }
1308   catch (jthrowable t)
1309     {
1310       env->ex = t;
1311       return NULL;
1312     }
1313 }
1314
1315 static jsize JNICALL
1316 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
1317 {
1318   return JvGetStringUTFLength (unwrap (string));
1319 }
1320
1321 static const char * JNICALL
1322 _Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string, 
1323                            jboolean *isCopy)
1324 {
1325   try
1326     {
1327       string = unwrap (string);
1328       if (string == NULL)
1329         return NULL;
1330       jsize len = JvGetStringUTFLength (string);
1331       char *r = (char *) _Jv_Malloc (len + 1);
1332       JvGetStringUTFRegion (string, 0, string->length(), r);
1333       r[len] = '\0';
1334
1335       if (isCopy)
1336         *isCopy = true;
1337
1338       return (const char *) r;
1339     }
1340   catch (jthrowable t)
1341     {
1342       env->ex = t;
1343       return NULL;
1344     }
1345 }
1346
1347 static void JNICALL
1348 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
1349 {
1350   _Jv_Free ((void *) utf);
1351 }
1352
1353 static void JNICALL
1354 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, 
1355                          jsize len, jchar *buf)
1356 {
1357   string = unwrap (string);
1358   jchar *result = _Jv_GetStringChars (string);
1359   if (start < 0 || start > string->length ()
1360       || len < 0 || start + len > string->length ())
1361     {
1362       try
1363         {
1364           env->ex = new java::lang::StringIndexOutOfBoundsException ();
1365         }
1366       catch (jthrowable t)
1367         {
1368           env->ex = t;
1369         }
1370     }
1371   else
1372     memcpy (buf, &result[start], len * sizeof (jchar));
1373 }
1374
1375 static void JNICALL
1376 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
1377                             jsize len, char *buf)
1378 {
1379   str = unwrap (str);
1380     
1381   if (start < 0 || start > str->length ()
1382       || len < 0 || start + len > str->length ())
1383     {
1384       try
1385         {
1386           env->ex = new java::lang::StringIndexOutOfBoundsException ();
1387         }
1388       catch (jthrowable t)
1389         {
1390           env->ex = t;
1391         }
1392     }
1393   else
1394     _Jv_GetStringUTFRegion (str, start, len, buf);
1395 }
1396
1397 static const jchar * JNICALL
1398 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
1399 {
1400   jchar *result = _Jv_GetStringChars (unwrap (str));
1401   if (isCopy)
1402     *isCopy = false;
1403   return result;
1404 }
1405
1406 static void JNICALL
1407 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1408 {
1409   // Nothing.
1410 }
1411
1412 static jsize JNICALL
1413 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1414 {
1415   return unwrap (array)->length;
1416 }
1417
1418 static jobjectArray JNICALL
1419 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, 
1420                         jclass elementClass, jobject init)
1421 {
1422   try
1423     {
1424       elementClass = unwrap (elementClass);
1425       init = unwrap (init);
1426
1427       _Jv_CheckCast (elementClass, init);
1428       jarray result = JvNewObjectArray (length, elementClass, init);
1429       return (jobjectArray) wrap_value (env, result);
1430     }
1431   catch (jthrowable t)
1432     {
1433       env->ex = t;
1434       return NULL;
1435     }
1436 }
1437
1438 static jobject JNICALL
1439 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, 
1440                                jsize index)
1441 {
1442   if ((unsigned) index >= (unsigned) array->length)
1443     _Jv_ThrowBadArrayIndex (index);
1444   jobject *elts = elements (unwrap (array));
1445   return wrap_value (env, elts[index]);
1446 }
1447
1448 static void JNICALL
1449 _Jv_JNI_SetObjectArrayElement (JNIEnv *env, jobjectArray array, 
1450                                jsize index, jobject value)
1451 {
1452   try
1453     {
1454       array = unwrap (array);
1455       value = unwrap (value);
1456
1457       _Jv_CheckArrayStore (array, value);
1458       if ((unsigned) index >= (unsigned) array->length)
1459         _Jv_ThrowBadArrayIndex (index);
1460       jobject *elts = elements (array);
1461       elts[index] = value;
1462     }
1463   catch (jthrowable t)
1464     {
1465       env->ex = t;
1466     }
1467 }
1468
1469 template<typename T, jclass K>
1470 static JArray<T> * JNICALL
1471 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1472 {
1473   try
1474     {
1475       return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
1476     }
1477   catch (jthrowable t)
1478     {
1479       env->ex = t;
1480       return NULL;
1481     }
1482 }
1483
1484 template<typename T, jclass K>
1485 static T * JNICALL
1486 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *env, JArray<T> *array,
1487                                    jboolean *isCopy)
1488 {
1489   array = unwrap (array);
1490   if (! _Jv_JNI_check_types (env, array, K))
1491     return NULL;
1492   T *elts = elements (array);
1493   if (isCopy)
1494     {
1495       // We elect never to copy.
1496       *isCopy = false;
1497     }
1498   mark_for_gc (array, global_ref_table);
1499   return elts;
1500 }
1501
1502 template<typename T, jclass K>
1503 static void JNICALL
1504 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *env, JArray<T> *array,
1505                                        T *, jint /* mode */)
1506 {
1507   array = unwrap (array);
1508   _Jv_JNI_check_types (env, array, K);
1509   // Note that we ignore MODE.  We can do this because we never copy
1510   // the array elements.  My reading of the JNI documentation is that
1511   // this is an option for the implementor.
1512   unmark_for_gc (array, global_ref_table);
1513 }
1514
1515 template<typename T, jclass K>
1516 static void JNICALL
1517 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1518                                  jsize start, jsize len,
1519                                  T *buf)
1520 {
1521   array = unwrap (array);
1522   if (! _Jv_JNI_check_types (env, array, K))
1523     return;
1524
1525   // The cast to unsigned lets us save a comparison.
1526   if (start < 0 || len < 0
1527       || (unsigned long) (start + len) > (unsigned long) array->length)
1528     {
1529       try
1530         {
1531           // FIXME: index.
1532           env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1533         }
1534       catch (jthrowable t)
1535         {
1536           // Could have thown out of memory error.
1537           env->ex = t;
1538         }
1539     }
1540   else
1541     {
1542       T *elts = elements (array) + start;
1543       memcpy (buf, elts, len * sizeof (T));
1544     }
1545 }
1546
1547 template<typename T, jclass K>
1548 static void JNICALL
1549 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1550                                  jsize start, jsize len, T *buf)
1551 {
1552   array = unwrap (array);
1553   if (! _Jv_JNI_check_types (env, array, K))
1554     return;
1555
1556   // The cast to unsigned lets us save a comparison.
1557   if (start < 0 || len < 0
1558       || (unsigned long) (start + len) > (unsigned long) array->length)
1559     {
1560       try
1561         {
1562           // FIXME: index.
1563           env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1564         }
1565       catch (jthrowable t)
1566         {
1567           env->ex = t;
1568         }
1569     }
1570   else
1571     {
1572       T *elts = elements (array) + start;
1573       memcpy (elts, buf, len * sizeof (T));
1574     }
1575 }
1576
1577 static void * JNICALL
1578 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1579                                    jboolean *isCopy)
1580 {
1581   array = unwrap (array);
1582   // FIXME: does this work?
1583   jclass klass = array->getClass()->getComponentType();
1584   JvAssert (klass->isPrimitive ());
1585   char *r = _Jv_GetArrayElementFromElementType (array, klass);
1586   if (isCopy)
1587     *isCopy = false;
1588   return r;
1589 }
1590
1591 static void JNICALL
1592 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1593 {
1594   // Nothing.
1595 }
1596
1597 static jint JNICALL
1598 _Jv_JNI_MonitorEnter (JNIEnv *env, jobject obj)
1599 {
1600   try
1601     {
1602       _Jv_MonitorEnter (unwrap (obj));
1603       return 0;
1604     }
1605   catch (jthrowable t)
1606     {
1607       env->ex = t;
1608     }
1609   return JNI_ERR;
1610 }
1611
1612 static jint JNICALL
1613 _Jv_JNI_MonitorExit (JNIEnv *env, jobject obj)
1614 {
1615   try
1616     {
1617       _Jv_MonitorExit (unwrap (obj));
1618       return 0;
1619     }
1620   catch (jthrowable t)
1621     {
1622       env->ex = t;
1623     }
1624   return JNI_ERR;
1625 }
1626
1627 // JDK 1.2
1628 jobject JNICALL
1629 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1630                           jboolean)
1631 {
1632   try
1633     {
1634       cls = unwrap (cls);
1635       java::lang::reflect::Field *field = new java::lang::reflect::Field();
1636       field->declaringClass = cls;
1637       field->offset = (char*) fieldID - (char *) cls->fields;
1638       field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1639       return wrap_value (env, field);
1640     }
1641   catch (jthrowable t)
1642     {
1643       env->ex = t;
1644     }
1645   return NULL;
1646 }
1647
1648 // JDK 1.2
1649 static jfieldID JNICALL
1650 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1651 {
1652   using namespace java::lang::reflect;
1653
1654   f = unwrap (f);
1655   Field *field = reinterpret_cast<Field *> (f);
1656   return _Jv_FromReflectedField (field);
1657 }
1658
1659 jobject JNICALL
1660 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1661                            jboolean)
1662 {
1663   using namespace java::lang::reflect;
1664
1665   jobject result = NULL;
1666   klass = unwrap (klass);
1667
1668   try
1669     {
1670       if (_Jv_equalUtf8Consts (id->name, init_name))
1671         {
1672           // A constructor.
1673           Constructor *cons = new Constructor ();
1674           cons->offset = (char *) id - (char *) &klass->methods;
1675           cons->declaringClass = klass;
1676           result = cons;
1677         }
1678       else
1679         {
1680           Method *meth = new Method ();
1681           meth->offset = (char *) id - (char *) &klass->methods;
1682           meth->declaringClass = klass;
1683           result = meth;
1684         }
1685     }
1686   catch (jthrowable t)
1687     {
1688       env->ex = t;
1689     }
1690
1691   return wrap_value (env, result);
1692 }
1693
1694 static jmethodID JNICALL
1695 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1696 {
1697   using namespace java::lang::reflect;
1698   method = unwrap (method);
1699   if (Method::class$.isInstance (method))
1700     return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1701   return
1702     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1703 }
1704
1705 // JDK 1.2.
1706 jweak JNICALL
1707 _Jv_JNI_NewWeakGlobalRef (JNIEnv *env, jobject obj)
1708 {
1709   using namespace gnu::gcj::runtime;
1710   JNIWeakRef *ref = NULL;
1711
1712   try
1713     {
1714       // This seems weird but I think it is correct.
1715       obj = unwrap (obj);
1716       ref = new JNIWeakRef (obj);
1717       mark_for_gc (ref, global_ref_table);
1718     }
1719   catch (jthrowable t)
1720     {
1721       env->ex = t;
1722     }
1723
1724   return reinterpret_cast<jweak> (ref);
1725 }
1726
1727 void JNICALL
1728 _Jv_JNI_DeleteWeakGlobalRef (JNIEnv *, jweak obj)
1729 {
1730   using namespace gnu::gcj::runtime;
1731   JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
1732   unmark_for_gc (ref, global_ref_table);
1733   ref->clear ();
1734 }
1735
1736 \f
1737
1738 // Direct byte buffers.
1739
1740 static jobject JNICALL
1741 _Jv_JNI_NewDirectByteBuffer (JNIEnv *, void *address, jlong length)
1742 {
1743   using namespace gnu::gcj;
1744   using namespace java::nio;
1745   return new DirectByteBufferImpl$ReadWrite
1746     (reinterpret_cast<RawData *> (address), length);
1747 }
1748
1749 static void * JNICALL
1750 _Jv_JNI_GetDirectBufferAddress (JNIEnv *, jobject buffer)
1751 {
1752   using namespace java::nio;
1753   if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
1754     return NULL;
1755   Buffer *tmp = static_cast<Buffer *> (buffer);
1756   return reinterpret_cast<void *> (tmp->address);
1757 }
1758
1759 static jlong JNICALL
1760 _Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
1761 {
1762   using namespace java::nio;
1763   if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
1764     return -1;
1765   Buffer *tmp = static_cast<Buffer *> (buffer);
1766   if (tmp->address == NULL)
1767     return -1;
1768   return tmp->capacity();
1769 }
1770
1771 \f
1772
1773 // Hash table of native methods.
1774 static JNINativeMethod *nathash;
1775 // Number of slots used.
1776 static int nathash_count = 0;
1777 // Number of slots available.  Must be power of 2.
1778 static int nathash_size = 0;
1779
1780 #define DELETED_ENTRY ((char *) (~0))
1781
1782 // Compute a hash value for a native method descriptor.
1783 static int
1784 hash (const JNINativeMethod *method)
1785 {
1786   char *ptr;
1787   int hash = 0;
1788
1789   ptr = method->name;
1790   while (*ptr)
1791     hash = (31 * hash) + *ptr++;
1792
1793   ptr = method->signature;
1794   while (*ptr)
1795     hash = (31 * hash) + *ptr++;
1796
1797   return hash;
1798 }
1799
1800 // Find the slot where a native method goes.
1801 static JNINativeMethod *
1802 nathash_find_slot (const JNINativeMethod *method)
1803 {
1804   jint h = hash (method);
1805   int step = (h ^ (h >> 16)) | 1;
1806   int w = h & (nathash_size - 1);
1807   int del = -1;
1808
1809   for (;;)
1810     {
1811       JNINativeMethod *slotp = &nathash[w];
1812       if (slotp->name == NULL)
1813         {
1814           if (del >= 0)
1815             return &nathash[del];
1816           else
1817             return slotp;
1818         }
1819       else if (slotp->name == DELETED_ENTRY)
1820         del = w;
1821       else if (! strcmp (slotp->name, method->name)
1822                && ! strcmp (slotp->signature, method->signature))
1823         return slotp;
1824       w = (w + step) & (nathash_size - 1);
1825     }
1826 }
1827
1828 // Find a method.  Return NULL if it isn't in the hash table.
1829 static void *
1830 nathash_find (JNINativeMethod *method)
1831 {
1832   if (nathash == NULL)
1833     return NULL;
1834   JNINativeMethod *slot = nathash_find_slot (method);
1835   if (slot->name == NULL || slot->name == DELETED_ENTRY)
1836     return NULL;
1837   return slot->fnPtr;
1838 }
1839
1840 static void
1841 natrehash ()
1842 {
1843   if (nathash == NULL)
1844     {
1845       nathash_size = 1024;
1846       nathash =
1847         (JNINativeMethod *) _Jv_AllocBytes (nathash_size
1848                                             * sizeof (JNINativeMethod));
1849       memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
1850     }
1851   else
1852     {
1853       int savesize = nathash_size;
1854       JNINativeMethod *savehash = nathash;
1855       nathash_size *= 2;
1856       nathash =
1857         (JNINativeMethod *) _Jv_AllocBytes (nathash_size
1858                                             * sizeof (JNINativeMethod));
1859       memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
1860
1861       for (int i = 0; i < savesize; ++i)
1862         {
1863           if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
1864             {
1865               JNINativeMethod *slot = nathash_find_slot (&savehash[i]);
1866               *slot = savehash[i];
1867             }
1868         }
1869     }
1870 }
1871
1872 static void
1873 nathash_add (const JNINativeMethod *method)
1874 {
1875   if (3 * nathash_count >= 2 * nathash_size)
1876     natrehash ();
1877   JNINativeMethod *slot = nathash_find_slot (method);
1878   // If the slot has a real entry in it, then there is no work to do.
1879   if (slot->name != NULL && slot->name != DELETED_ENTRY)
1880     return;
1881   // FIXME
1882   slot->name = strdup (method->name);
1883   // This was already strduped in _Jv_JNI_RegisterNatives.
1884   slot->signature = method->signature;
1885   slot->fnPtr = method->fnPtr;
1886 }
1887
1888 static jint JNICALL
1889 _Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
1890                          const JNINativeMethod *methods,
1891                          jint nMethods)
1892 {
1893   // Synchronize while we do the work.  This must match
1894   // synchronization in some other functions that manipulate or use
1895   // the nathash table.
1896   JvSynchronize sync (global_ref_table);
1897
1898   JNINativeMethod dottedMethod;
1899
1900   // Look at each descriptor given us, and find the corresponding
1901   // method in the class.
1902   for (int j = 0; j < nMethods; ++j)
1903     {
1904       bool found = false;
1905
1906       _Jv_Method *imeths = JvGetFirstMethod (klass);
1907       for (int i = 0; i < JvNumMethods (klass); ++i)
1908         {
1909           _Jv_Method *self = &imeths[i];
1910
1911           // Copy this JNINativeMethod and do a slash to dot
1912           // conversion on the signature.
1913           dottedMethod.name = methods[j].name;
1914           dottedMethod.signature = strdup (methods[j].signature);
1915           dottedMethod.fnPtr = methods[j].fnPtr;
1916           char *c = dottedMethod.signature;
1917           while (*c)
1918             {
1919               if (*c == '/')
1920                 *c = '.';
1921               c++;
1922             }
1923
1924           if (! strcmp (self->name->chars (), dottedMethod.name)
1925               && ! strcmp (self->signature->chars (), dottedMethod.signature))
1926             {
1927               if (! (self->accflags & java::lang::reflect::Modifier::NATIVE))
1928                 break;
1929
1930               // Found a match that is native.
1931               found = true;
1932               nathash_add (&dottedMethod);
1933
1934               break;
1935             }
1936         }
1937
1938       if (! found)
1939         {
1940           jstring m = JvNewStringUTF (methods[j].name);
1941           try
1942             {
1943               env->ex = new java::lang::NoSuchMethodError (m);
1944             }
1945           catch (jthrowable t)
1946             {
1947               env->ex = t;
1948             }
1949           return JNI_ERR;
1950         }
1951     }
1952
1953   return JNI_OK;
1954 }
1955
1956 static jint JNICALL
1957 _Jv_JNI_UnregisterNatives (JNIEnv *, jclass)
1958 {
1959   // FIXME -- we could implement this.
1960   return JNI_ERR;
1961 }
1962
1963 \f
1964
1965 // Add a character to the buffer, encoding properly.
1966 static void
1967 add_char (char *buf, jchar c, int *here)
1968 {
1969   if (c == '_')
1970     {
1971       buf[(*here)++] = '_';
1972       buf[(*here)++] = '1';
1973     }
1974   else if (c == ';')
1975     {
1976       buf[(*here)++] = '_';
1977       buf[(*here)++] = '2';
1978     }
1979   else if (c == '[')
1980     {
1981       buf[(*here)++] = '_';
1982       buf[(*here)++] = '3';
1983     }
1984
1985   // Also check for `.' here because we might be passed an internal
1986   // qualified class name like `foo.bar'.
1987   else if (c == '/' || c == '.')
1988     buf[(*here)++] = '_';
1989   else if ((c >= '0' && c <= '9')
1990            || (c >= 'a' && c <= 'z')
1991            || (c >= 'A' && c <= 'Z'))
1992     buf[(*here)++] = (char) c;
1993   else
1994     {
1995       // "Unicode" character.
1996       buf[(*here)++] = '_';
1997       buf[(*here)++] = '0';
1998       for (int i = 0; i < 4; ++i)
1999         {
2000           int val = c & 0x0f;
2001           buf[(*here) + 3 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
2002           c >>= 4;
2003         }
2004       *here += 4;
2005     }
2006 }
2007
2008 // Compute a mangled name for a native function.  This computes the
2009 // long name, and also returns an index which indicates where a NUL
2010 // can be placed to create the short name.  This function assumes that
2011 // the buffer is large enough for its results.
2012 static void
2013 mangled_name (jclass klass, _Jv_Utf8Const *func_name,
2014               _Jv_Utf8Const *signature, char *buf, int *long_start)
2015 {
2016   strcpy (buf, "Java_");
2017   int here = 5;
2018
2019   // Add fully qualified class name.
2020   jchar *chars = _Jv_GetStringChars (klass->getName ());
2021   jint len = klass->getName ()->length ();
2022   for (int i = 0; i < len; ++i)
2023     add_char (buf, chars[i], &here);
2024
2025   // Don't use add_char because we need a literal `_'.
2026   buf[here++] = '_';
2027
2028   const unsigned char *fn = (const unsigned char *) func_name->chars ();
2029   const unsigned char *limit = fn + func_name->len ();
2030   for (int i = 0; ; ++i)
2031     {
2032       int ch = UTF8_GET (fn, limit);
2033       if (ch < 0)
2034         break;
2035       add_char (buf, ch, &here);
2036     }
2037
2038   // This is where the long signature begins.
2039   *long_start = here;
2040   buf[here++] = '_';
2041   buf[here++] = '_';
2042
2043   const unsigned char *sig = (const unsigned char *) signature->chars ();
2044   limit = sig + signature->len ();
2045   JvAssert (sig[0] == '(');
2046   ++sig;
2047   while (1)
2048     {
2049       int ch = UTF8_GET (sig, limit);
2050       if (ch == ')' || ch < 0)
2051         break;
2052       add_char (buf, ch, &here);
2053     }
2054
2055   buf[here] = '\0';
2056 }
2057
2058 // Return the current thread's JNIEnv; if one does not exist, create
2059 // it.  Also create a new system frame for use.  This is `extern "C"'
2060 // because the compiler calls it.
2061 extern "C" JNIEnv *
2062 _Jv_GetJNIEnvNewFrame (jclass klass)
2063 {
2064   JNIEnv *env = _Jv_GetCurrentJNIEnv ();
2065   if (__builtin_expect (env == NULL, false))
2066     {
2067       env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
2068       env->p = &_Jv_JNIFunctions;
2069       env->klass = klass;
2070       env->locals = NULL;
2071       // We set env->ex below.
2072
2073       // Set up the bottom, reusable frame.
2074       env->bottom_locals = (_Jv_JNI_LocalFrame *) 
2075         _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
2076                              + (FRAME_SIZE
2077                                 * sizeof (jobject)));
2078       
2079       env->bottom_locals->marker = MARK_SYSTEM;
2080       env->bottom_locals->size = FRAME_SIZE;
2081       env->bottom_locals->next = NULL;
2082       env->bottom_locals->allocated_p = 0;
2083       memset (&env->bottom_locals->vec[0], 0, 
2084               env->bottom_locals->size * sizeof (jobject));
2085
2086       _Jv_SetCurrentJNIEnv (env);
2087     }
2088
2089   // If we're in a simple JNI call (non-nested), we can just reuse the
2090   // locals frame we allocated many calls ago, back when the env was first
2091   // built, above.
2092
2093   if (__builtin_expect (env->locals == NULL, true))
2094     env->locals = env->bottom_locals;
2095
2096   else
2097     {
2098       // Alternatively, we might be re-entering JNI, in which case we can't
2099       // reuse the bottom_locals frame, because it is already underneath
2100       // us. So we need to make a new one.
2101
2102       _Jv_JNI_LocalFrame *frame
2103         = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
2104                                                       + (FRAME_SIZE
2105                                                          * sizeof (jobject)));
2106       
2107       frame->marker = MARK_SYSTEM;
2108       frame->size = FRAME_SIZE;
2109       frame->allocated_p = 0;
2110       frame->next = env->locals;
2111
2112       memset (&frame->vec[0], 0, 
2113               frame->size * sizeof (jobject));
2114
2115       env->locals = frame;
2116     }
2117
2118   env->ex = NULL;
2119
2120   return env;
2121 }
2122
2123 // Destroy the env's reusable resources. This is called from the thread
2124 // destructor "finalize_native" in natThread.cc
2125 void 
2126 _Jv_FreeJNIEnv (_Jv_JNIEnv *env)
2127 {
2128   if (env == NULL)
2129     return;
2130
2131   if (env->bottom_locals != NULL)
2132     _Jv_Free (env->bottom_locals);
2133
2134   _Jv_Free (env);
2135 }
2136
2137 // Return the function which implements a particular JNI method.  If
2138 // we can't find the function, we throw the appropriate exception.
2139 // This is `extern "C"' because the compiler uses it.
2140 extern "C" void *
2141 _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
2142                      _Jv_Utf8Const *signature, MAYBE_UNUSED int args_size)
2143 {
2144   int name_length = name->len();
2145   int sig_length = signature->len();
2146   char buf[10 + 6 * (name_length + sig_length) + 12];
2147   int long_start;
2148   void *function;
2149
2150   // Synchronize on something convenient.  Right now we use the hash.
2151   JvSynchronize sync (global_ref_table);
2152
2153   // First see if we have an override in the hash table.
2154   strncpy (buf, name->chars (), name_length);
2155   buf[name_length] = '\0';
2156   strncpy (buf + name_length + 1, signature->chars (), sig_length);
2157   buf[name_length + sig_length + 1] = '\0';
2158   JNINativeMethod meth;
2159   meth.name = buf;
2160   meth.signature = buf + name_length + 1;
2161   function = nathash_find (&meth);
2162   if (function != NULL)
2163     return function;
2164
2165   // If there was no override, then look in the symbol table.
2166   buf[0] = '_';
2167   mangled_name (klass, name, signature, buf + 1, &long_start);
2168   char c = buf[long_start + 1];
2169   buf[long_start + 1] = '\0';
2170
2171   function = _Jv_FindSymbolInExecutable (buf + 1);
2172 #ifdef WIN32
2173   // On Win32, we use the "stdcall" calling convention (see JNICALL
2174   // in jni.h).
2175   // 
2176   // For a function named 'fooBar' that takes 'nn' bytes as arguments,
2177   // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports it
2178   // as '_fooBar@nn' and Borland C exports it as 'fooBar'. We try to
2179   // take care of all these variations here.
2180
2181   char asz_buf[12];    /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */
2182   char long_nm_sv[11]; /* Ditto, except for the '\0'. */
2183
2184   if (function == NULL)
2185     {
2186       // We have tried searching for the 'fooBar' form (BCC) - now
2187       // try the others.
2188
2189       // First, save the part of the long name that will be damaged
2190       // by appending '@nn'.
2191       memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv));
2192
2193       sprintf (asz_buf, "@%d", args_size);
2194       strcat (buf, asz_buf);
2195
2196       // Search for the '_fooBar@nn' form (MSVC).
2197       function = _Jv_FindSymbolInExecutable (buf);
2198
2199       if (function == NULL)
2200         {
2201           // Search for the 'fooBar@nn' form (MinGW GCC).
2202           function = _Jv_FindSymbolInExecutable (buf + 1);
2203         }
2204     }
2205 #endif /* WIN32 */
2206
2207   if (function == NULL)
2208     {
2209       buf[long_start + 1] = c;
2210 #ifdef WIN32
2211       // Restore the part of the long name that was damaged by 
2212       // appending the '@nn'.
2213       memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv));
2214 #endif /* WIN32 */
2215       function = _Jv_FindSymbolInExecutable (buf + 1);
2216       if (function == NULL)
2217         {
2218 #ifdef WIN32
2219           strcat (buf, asz_buf);
2220           function = _Jv_FindSymbolInExecutable (buf);
2221           if (function == NULL)
2222             function = _Jv_FindSymbolInExecutable (buf + 1);
2223
2224           if (function == NULL)
2225 #endif /* WIN32 */
2226             {
2227               jstring str = JvNewStringUTF (name->chars ());
2228               throw new java::lang::UnsatisfiedLinkError (str);
2229             }
2230         }
2231     }
2232
2233   return function;
2234 }
2235
2236 #ifdef INTERPRETER
2237
2238 // This function is the stub which is used to turn an ordinary (CNI)
2239 // method call into a JNI call.
2240 void
2241 _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this)
2242 {
2243   _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
2244
2245   JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class);
2246
2247   // FIXME: we should mark every reference parameter as a local.  For
2248   // now we assume a conservative GC, and we assume that the
2249   // references are on the stack somewhere.
2250
2251   // We cache the value that we find, of course, but if we don't find
2252   // a value we don't cache that fact -- we might subsequently load a
2253   // library which finds the function in question.
2254   {
2255     // Synchronize on a convenient object to ensure sanity in case two
2256     // threads reach this point for the same function at the same
2257     // time.
2258     JvSynchronize sync (global_ref_table);
2259     if (_this->function == NULL)
2260       {
2261         int args_size = sizeof (JNIEnv *) + _this->args_raw_size;
2262
2263         if (_this->self->accflags & java::lang::reflect::Modifier::STATIC)
2264           args_size += sizeof (_this->defining_class);
2265
2266         _this->function = _Jv_LookupJNIMethod (_this->defining_class,
2267                                                _this->self->name,
2268                                                _this->self->signature,
2269                                                args_size);
2270       }
2271   }
2272
2273   JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0);
2274   ffi_raw real_args[2 + _this->args_raw_size / sizeof (ffi_raw)];
2275   int offset = 0;
2276
2277   // First argument is always the environment pointer.
2278   real_args[offset++].ptr = env;
2279
2280   // For a static method, we pass in the Class.  For non-static
2281   // methods, the `this' argument is already handled.
2282   if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
2283     real_args[offset++].ptr = _this->defining_class;
2284
2285   // In libgcj, the callee synchronizes.
2286   jobject sync = NULL;
2287   if ((_this->self->accflags & java::lang::reflect::Modifier::SYNCHRONIZED))
2288     {
2289       if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
2290         sync = _this->defining_class;
2291       else
2292         sync = (jobject) args[0].ptr;
2293       _Jv_MonitorEnter (sync);
2294     }
2295
2296   // Copy over passed-in arguments.
2297   memcpy (&real_args[offset], args, _this->args_raw_size);
2298
2299   // The actual call to the JNI function.
2300 #if FFI_NATIVE_RAW_API
2301   ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function,
2302                 ret, real_args);
2303 #else
2304   ffi_java_raw_call (&_this->jni_cif, (void (*)()) _this->function,
2305                      ret, real_args);
2306 #endif
2307
2308   if (sync != NULL)
2309     _Jv_MonitorExit (sync);
2310
2311   _Jv_JNI_PopSystemFrame (env);
2312 }
2313
2314 #endif /* INTERPRETER */
2315
2316 \f
2317
2318 //
2319 // Invocation API.
2320 //
2321
2322 // An internal helper function.
2323 static jint
2324 _Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
2325                              void *args, jboolean is_daemon)
2326 {
2327   JavaVMAttachArgs *attach = reinterpret_cast<JavaVMAttachArgs *> (args);
2328   java::lang::ThreadGroup *group = NULL;
2329
2330   if (attach)
2331     {
2332       // FIXME: do we really want to support 1.1?
2333       if (attach->version != JNI_VERSION_1_4
2334           && attach->version != JNI_VERSION_1_2
2335           && attach->version != JNI_VERSION_1_1)
2336         return JNI_EVERSION;
2337
2338       JvAssert (java::lang::ThreadGroup::class$.isInstance (attach->group));
2339       group = reinterpret_cast<java::lang::ThreadGroup *> (attach->group);
2340     }
2341
2342   // Attaching an already-attached thread is a no-op.
2343   if (_Jv_GetCurrentJNIEnv () != NULL)
2344     return 0;
2345
2346   JNIEnv *env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
2347   if (env == NULL)
2348     return JNI_ERR;
2349   env->p = &_Jv_JNIFunctions;
2350   env->ex = NULL;
2351   env->klass = NULL;
2352   env->bottom_locals
2353     = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
2354                                                   + (FRAME_SIZE
2355                                                      * sizeof (jobject)));
2356   env->locals = env->bottom_locals;
2357   if (env->locals == NULL)
2358     {
2359       _Jv_Free (env);
2360       return JNI_ERR;
2361     }
2362
2363   env->locals->allocated_p = 0;
2364   env->locals->marker = MARK_SYSTEM;
2365   env->locals->size = FRAME_SIZE;
2366   env->locals->next = NULL;
2367
2368   for (int i = 0; i < env->locals->size; ++i)
2369     env->locals->vec[i] = NULL;
2370
2371   *penv = reinterpret_cast<void *> (env);
2372
2373   // This thread might already be a Java thread -- this function might
2374   // have been called simply to set the new JNIEnv.
2375   if (_Jv_ThreadCurrent () == NULL)
2376     {
2377       try
2378         {
2379           if (is_daemon)
2380             _Jv_AttachCurrentThreadAsDaemon (name, group);
2381           else
2382             _Jv_AttachCurrentThread (name, group);
2383         }
2384       catch (jthrowable t)
2385         {
2386           return JNI_ERR;
2387         }
2388     }
2389   _Jv_SetCurrentJNIEnv (env);
2390
2391   return 0;
2392 }
2393
2394 // This is the one actually used by JNI.
2395 static jint JNICALL
2396 _Jv_JNI_AttachCurrentThread (JavaVM *vm, void **penv, void *args)
2397 {
2398   return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, false);
2399 }
2400
2401 static jint JNICALL
2402 _Jv_JNI_AttachCurrentThreadAsDaemon (JavaVM *vm, void **penv, 
2403                                      void *args)
2404 {
2405   return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, true);
2406 }
2407
2408 static jint JNICALL
2409 _Jv_JNI_DestroyJavaVM (JavaVM *vm)
2410 {
2411   JvAssert (the_vm && vm == the_vm);
2412
2413   JNIEnv *env;
2414   if (_Jv_ThreadCurrent () != NULL)
2415     {
2416       jstring main_name;
2417       // This sucks.
2418       try
2419         {
2420           main_name = JvNewStringLatin1 ("main");
2421         }
2422       catch (jthrowable t)
2423         {
2424           return JNI_ERR;
2425         }
2426
2427       jint r = _Jv_JNI_AttachCurrentThread (vm, main_name,
2428                                             reinterpret_cast<void **> (&env),
2429                                             NULL, false);
2430       if (r < 0)
2431         return r;
2432     }
2433   else
2434     env = _Jv_GetCurrentJNIEnv ();
2435
2436   _Jv_ThreadWait ();
2437
2438   // Docs say that this always returns an error code.
2439   return JNI_ERR;
2440 }
2441
2442 jint JNICALL
2443 _Jv_JNI_DetachCurrentThread (JavaVM *)
2444 {
2445   jint code = _Jv_DetachCurrentThread ();
2446   return code  ? JNI_EDETACHED : 0;
2447 }
2448
2449 static jint JNICALL
2450 _Jv_JNI_GetEnv (JavaVM *, void **penv, jint version)
2451 {
2452   if (_Jv_ThreadCurrent () == NULL)
2453     {
2454       *penv = NULL;
2455       return JNI_EDETACHED;
2456     }
2457
2458 #ifdef ENABLE_JVMPI
2459   // Handle JVMPI requests.
2460   if (version == JVMPI_VERSION_1)
2461     {
2462       *penv = (void *) &_Jv_JVMPI_Interface;
2463       return 0;
2464     }
2465 #endif
2466
2467   // FIXME: do we really want to support 1.1?
2468   if (version != JNI_VERSION_1_4 && version != JNI_VERSION_1_2
2469       && version != JNI_VERSION_1_1)
2470     {
2471       *penv = NULL;
2472       return JNI_EVERSION;
2473     }
2474
2475   *penv = (void *) _Jv_GetCurrentJNIEnv ();
2476   return 0;
2477 }
2478
2479 jint JNICALL
2480 JNI_GetDefaultJavaVMInitArgs (void *args)
2481 {
2482   jint version = * (jint *) args;
2483   // Here we only support 1.2 and 1.4.
2484   if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4)
2485     return JNI_EVERSION;
2486
2487   JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
2488   ia->version = JNI_VERSION_1_4;
2489   ia->nOptions = 0;
2490   ia->options = NULL;
2491   ia->ignoreUnrecognized = true;
2492
2493   return 0;
2494 }
2495
2496 jint JNICALL
2497 JNI_CreateJavaVM (JavaVM **vm, void **penv, void *args)
2498 {
2499   JvAssert (! the_vm);
2500
2501   _Jv_CreateJavaVM (NULL);
2502
2503   // FIXME: synchronize
2504   JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
2505   if (nvm == NULL)
2506     return JNI_ERR;
2507   nvm->functions = &_Jv_JNI_InvokeFunctions;
2508
2509   // Parse the arguments.
2510   if (args != NULL)
2511     {
2512       jint version = * (jint *) args;
2513       // We only support 1.2 and 1.4.
2514       if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4)
2515         return JNI_EVERSION;
2516       JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
2517       for (int i = 0; i < ia->nOptions; ++i)
2518         {
2519           if (! strcmp (ia->options[i].optionString, "vfprintf")
2520               || ! strcmp (ia->options[i].optionString, "exit")
2521               || ! strcmp (ia->options[i].optionString, "abort"))
2522             {
2523               // We are required to recognize these, but for now we
2524               // don't handle them in any way.  FIXME.
2525               continue;
2526             }
2527           else if (! strncmp (ia->options[i].optionString,
2528                               "-verbose", sizeof ("-verbose") - 1))
2529             {
2530               // We don't do anything with this option either.  We
2531               // might want to make sure the argument is valid, but we
2532               // don't really care all that much for now.
2533               continue;
2534             }
2535           else if (! strncmp (ia->options[i].optionString, "-D", 2))
2536             {
2537               // FIXME.
2538               continue;
2539             }
2540           else if (ia->ignoreUnrecognized)
2541             {
2542               if (ia->options[i].optionString[0] == '_'
2543                   || ! strncmp (ia->options[i].optionString, "-X", 2))
2544                 continue;
2545             }
2546
2547           return JNI_ERR;
2548         }
2549     }
2550
2551   jint r =_Jv_JNI_AttachCurrentThread (nvm, penv, NULL);
2552   if (r < 0)
2553     return r;
2554
2555   the_vm = nvm;
2556   *vm = the_vm;
2557
2558   return 0;
2559 }
2560
2561 jint JNICALL
2562 JNI_GetCreatedJavaVMs (JavaVM **vm_buffer, jsize buf_len, jsize *n_vms)
2563 {
2564   if (buf_len <= 0)
2565     return JNI_ERR;
2566
2567   // We only support a single VM.
2568   if (the_vm != NULL)
2569     {
2570       vm_buffer[0] = the_vm;
2571       *n_vms = 1;
2572     }
2573   else
2574     *n_vms = 0;
2575   return 0;
2576 }
2577
2578 JavaVM *
2579 _Jv_GetJavaVM ()
2580 {
2581   // FIXME: synchronize
2582   if (! the_vm)
2583     {
2584       JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
2585       if (nvm != NULL)
2586         nvm->functions = &_Jv_JNI_InvokeFunctions;
2587       the_vm = nvm;
2588     }
2589
2590   // If this is a Java thread, we want to make sure it has an
2591   // associated JNIEnv.
2592   if (_Jv_ThreadCurrent () != NULL)
2593     {
2594       void *ignore;
2595       _Jv_JNI_AttachCurrentThread (the_vm, &ignore, NULL);
2596     }
2597
2598   return the_vm;
2599 }
2600
2601 static jint JNICALL
2602 _Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
2603 {
2604   *vm = _Jv_GetJavaVM ();
2605   return *vm == NULL ? JNI_ERR : JNI_OK;
2606 }
2607
2608 \f
2609
2610 #define RESERVED NULL
2611
2612 struct JNINativeInterface _Jv_JNIFunctions =
2613 {
2614   RESERVED,
2615   RESERVED,
2616   RESERVED,
2617   RESERVED,
2618   _Jv_JNI_GetVersion,           // GetVersion
2619   _Jv_JNI_DefineClass,          // DefineClass
2620   _Jv_JNI_FindClass,            // FindClass
2621   _Jv_JNI_FromReflectedMethod,  // FromReflectedMethod
2622   _Jv_JNI_FromReflectedField,   // FromReflectedField
2623   _Jv_JNI_ToReflectedMethod,    // ToReflectedMethod
2624   _Jv_JNI_GetSuperclass,        // GetSuperclass
2625   _Jv_JNI_IsAssignableFrom,     // IsAssignableFrom
2626   _Jv_JNI_ToReflectedField,     // ToReflectedField
2627   _Jv_JNI_Throw,                // Throw
2628   _Jv_JNI_ThrowNew,             // ThrowNew
2629   _Jv_JNI_ExceptionOccurred,    // ExceptionOccurred
2630   _Jv_JNI_ExceptionDescribe,    // ExceptionDescribe
2631   _Jv_JNI_ExceptionClear,       // ExceptionClear
2632   _Jv_JNI_FatalError,           // FatalError
2633
2634   _Jv_JNI_PushLocalFrame,       // PushLocalFrame
2635   _Jv_JNI_PopLocalFrame,        // PopLocalFrame
2636   _Jv_JNI_NewGlobalRef,         // NewGlobalRef
2637   _Jv_JNI_DeleteGlobalRef,      // DeleteGlobalRef
2638   _Jv_JNI_DeleteLocalRef,       // DeleteLocalRef
2639
2640   _Jv_JNI_IsSameObject,         // IsSameObject
2641
2642   _Jv_JNI_NewLocalRef,          // NewLocalRef
2643   _Jv_JNI_EnsureLocalCapacity,  // EnsureLocalCapacity
2644
2645   _Jv_JNI_AllocObject,              // AllocObject
2646   _Jv_JNI_NewObject,                // NewObject
2647   _Jv_JNI_NewObjectV,               // NewObjectV
2648   _Jv_JNI_NewObjectA,               // NewObjectA
2649   _Jv_JNI_GetObjectClass,           // GetObjectClass
2650   _Jv_JNI_IsInstanceOf,             // IsInstanceOf
2651   _Jv_JNI_GetAnyMethodID<false>,    // GetMethodID
2652
2653   _Jv_JNI_CallMethod<jobject>,          // CallObjectMethod
2654   _Jv_JNI_CallMethodV<jobject>,         // CallObjectMethodV
2655   _Jv_JNI_CallMethodA<jobject>,         // CallObjectMethodA
2656   _Jv_JNI_CallMethod<jboolean>,         // CallBooleanMethod
2657   _Jv_JNI_CallMethodV<jboolean>,        // CallBooleanMethodV
2658   _Jv_JNI_CallMethodA<jboolean>,        // CallBooleanMethodA
2659   _Jv_JNI_CallMethod<jbyte>,            // CallByteMethod
2660   _Jv_JNI_CallMethodV<jbyte>,           // CallByteMethodV
2661   _Jv_JNI_CallMethodA<jbyte>,           // CallByteMethodA
2662   _Jv_JNI_CallMethod<jchar>,            // CallCharMethod
2663   _Jv_JNI_CallMethodV<jchar>,           // CallCharMethodV
2664   _Jv_JNI_CallMethodA<jchar>,           // CallCharMethodA
2665   _Jv_JNI_CallMethod<jshort>,           // CallShortMethod
2666   _Jv_JNI_CallMethodV<jshort>,          // CallShortMethodV
2667   _Jv_JNI_CallMethodA<jshort>,          // CallShortMethodA
2668   _Jv_JNI_CallMethod<jint>,             // CallIntMethod
2669   _Jv_JNI_CallMethodV<jint>,            // CallIntMethodV
2670   _Jv_JNI_CallMethodA<jint>,            // CallIntMethodA
2671   _Jv_JNI_CallMethod<jlong>,            // CallLongMethod
2672   _Jv_JNI_CallMethodV<jlong>,           // CallLongMethodV
2673   _Jv_JNI_CallMethodA<jlong>,           // CallLongMethodA
2674   _Jv_JNI_CallMethod<jfloat>,           // CallFloatMethod
2675   _Jv_JNI_CallMethodV<jfloat>,          // CallFloatMethodV
2676   _Jv_JNI_CallMethodA<jfloat>,          // CallFloatMethodA
2677   _Jv_JNI_CallMethod<jdouble>,          // CallDoubleMethod
2678   _Jv_JNI_CallMethodV<jdouble>,         // CallDoubleMethodV
2679   _Jv_JNI_CallMethodA<jdouble>,         // CallDoubleMethodA
2680   _Jv_JNI_CallVoidMethod,               // CallVoidMethod
2681   _Jv_JNI_CallVoidMethodV,              // CallVoidMethodV
2682   _Jv_JNI_CallVoidMethodA,              // CallVoidMethodA
2683
2684   // Nonvirtual method invocation functions follow.
2685   _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,   // CallNonvirtualObjectMethod
2686   _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,  // CallNonvirtualObjectMethodV
2687   _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,  // CallNonvirtualObjectMethodA
2688   _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,  // CallNonvirtualBooleanMethod
2689   _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodV
2690   _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodA
2691   _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,     // CallNonvirtualByteMethod
2692   _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,    // CallNonvirtualByteMethodV
2693   _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,    // CallNonvirtualByteMethodA
2694   _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,     // CallNonvirtualCharMethod
2695   _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,    // CallNonvirtualCharMethodV
2696   _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,    // CallNonvirtualCharMethodA
2697   _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,    // CallNonvirtualShortMethod
2698   _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,   // CallNonvirtualShortMethodV
2699   _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,   // CallNonvirtualShortMethodA
2700   _Jv_JNI_CallAnyMethod<jint, nonvirtual>,      // CallNonvirtualIntMethod
2701   _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,     // CallNonvirtualIntMethodV
2702   _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,     // CallNonvirtualIntMethodA
2703   _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,     // CallNonvirtualLongMethod
2704   _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,    // CallNonvirtualLongMethodV
2705   _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,    // CallNonvirtualLongMethodA
2706   _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,    // CallNonvirtualFloatMethod
2707   _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodV
2708   _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodA
2709   _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,   // CallNonvirtualDoubleMethod
2710   _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodV
2711   _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodA
2712   _Jv_JNI_CallAnyVoidMethod<nonvirtual>,        // CallNonvirtualVoidMethod
2713   _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,       // CallNonvirtualVoidMethodV
2714   _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,       // CallNonvirtualVoidMethodA
2715
2716   _Jv_JNI_GetAnyFieldID<false>, // GetFieldID
2717   _Jv_JNI_GetField<jobject>,    // GetObjectField
2718   _Jv_JNI_GetField<jboolean>,   // GetBooleanField
2719   _Jv_JNI_GetField<jbyte>,      // GetByteField
2720   _Jv_JNI_GetField<jchar>,      // GetCharField
2721   _Jv_JNI_GetField<jshort>,     // GetShortField
2722   _Jv_JNI_GetField<jint>,       // GetIntField
2723   _Jv_JNI_GetField<jlong>,      // GetLongField
2724   _Jv_JNI_GetField<jfloat>,     // GetFloatField
2725   _Jv_JNI_GetField<jdouble>,    // GetDoubleField
2726   _Jv_JNI_SetField,             // SetObjectField
2727   _Jv_JNI_SetField,             // SetBooleanField
2728   _Jv_JNI_SetField,             // SetByteField
2729   _Jv_JNI_SetField,             // SetCharField
2730   _Jv_JNI_SetField,             // SetShortField
2731   _Jv_JNI_SetField,             // SetIntField
2732   _Jv_JNI_SetField,             // SetLongField
2733   _Jv_JNI_SetField,             // SetFloatField
2734   _Jv_JNI_SetField,             // SetDoubleField
2735   _Jv_JNI_GetAnyMethodID<true>, // GetStaticMethodID
2736
2737   _Jv_JNI_CallStaticMethod<jobject>,      // CallStaticObjectMethod
2738   _Jv_JNI_CallStaticMethodV<jobject>,     // CallStaticObjectMethodV
2739   _Jv_JNI_CallStaticMethodA<jobject>,     // CallStaticObjectMethodA
2740   _Jv_JNI_CallStaticMethod<jboolean>,     // CallStaticBooleanMethod
2741   _Jv_JNI_CallStaticMethodV<jboolean>,    // CallStaticBooleanMethodV
2742   _Jv_JNI_CallStaticMethodA<jboolean>,    // CallStaticBooleanMethodA
2743   _Jv_JNI_CallStaticMethod<jbyte>,        // CallStaticByteMethod
2744   _Jv_JNI_CallStaticMethodV<jbyte>,       // CallStaticByteMethodV
2745   _Jv_JNI_CallStaticMethodA<jbyte>,       // CallStaticByteMethodA
2746   _Jv_JNI_CallStaticMethod<jchar>,        // CallStaticCharMethod
2747   _Jv_JNI_CallStaticMethodV<jchar>,       // CallStaticCharMethodV
2748   _Jv_JNI_CallStaticMethodA<jchar>,       // CallStaticCharMethodA
2749   _Jv_JNI_CallStaticMethod<jshort>,       // CallStaticShortMethod
2750   _Jv_JNI_CallStaticMethodV<jshort>,      // CallStaticShortMethodV
2751   _Jv_JNI_CallStaticMethodA<jshort>,      // CallStaticShortMethodA
2752   _Jv_JNI_CallStaticMethod<jint>,         // CallStaticIntMethod
2753   _Jv_JNI_CallStaticMethodV<jint>,        // CallStaticIntMethodV
2754   _Jv_JNI_CallStaticMethodA<jint>,        // CallStaticIntMethodA
2755   _Jv_JNI_CallStaticMethod<jlong>,        // CallStaticLongMethod
2756   _Jv_JNI_CallStaticMethodV<jlong>,       // CallStaticLongMethodV
2757   _Jv_JNI_CallStaticMethodA<jlong>,       // CallStaticLongMethodA
2758   _Jv_JNI_CallStaticMethod<jfloat>,       // CallStaticFloatMethod
2759   _Jv_JNI_CallStaticMethodV<jfloat>,      // CallStaticFloatMethodV
2760   _Jv_JNI_CallStaticMethodA<jfloat>,      // CallStaticFloatMethodA
2761   _Jv_JNI_CallStaticMethod<jdouble>,      // CallStaticDoubleMethod
2762   _Jv_JNI_CallStaticMethodV<jdouble>,     // CallStaticDoubleMethodV
2763   _Jv_JNI_CallStaticMethodA<jdouble>,     // CallStaticDoubleMethodA
2764   _Jv_JNI_CallStaticVoidMethod,           // CallStaticVoidMethod
2765   _Jv_JNI_CallStaticVoidMethodV,          // CallStaticVoidMethodV
2766   _Jv_JNI_CallStaticVoidMethodA,          // CallStaticVoidMethodA
2767
2768   _Jv_JNI_GetAnyFieldID<true>,         // GetStaticFieldID
2769   _Jv_JNI_GetStaticField<jobject>,     // GetStaticObjectField
2770   _Jv_JNI_GetStaticField<jboolean>,    // GetStaticBooleanField
2771   _Jv_JNI_GetStaticField<jbyte>,       // GetStaticByteField
2772   _Jv_JNI_GetStaticField<jchar>,       // GetStaticCharField
2773   _Jv_JNI_GetStaticField<jshort>,      // GetStaticShortField
2774   _Jv_JNI_GetStaticField<jint>,        // GetStaticIntField
2775   _Jv_JNI_GetStaticField<jlong>,       // GetStaticLongField
2776   _Jv_JNI_GetStaticField<jfloat>,      // GetStaticFloatField
2777   _Jv_JNI_GetStaticField<jdouble>,     // GetStaticDoubleField
2778   _Jv_JNI_SetStaticField,              // SetStaticObjectField
2779   _Jv_JNI_SetStaticField,              // SetStaticBooleanField
2780   _Jv_JNI_SetStaticField,              // SetStaticByteField
2781   _Jv_JNI_SetStaticField,              // SetStaticCharField
2782   _Jv_JNI_SetStaticField,              // SetStaticShortField
2783   _Jv_JNI_SetStaticField,              // SetStaticIntField
2784   _Jv_JNI_SetStaticField,              // SetStaticLongField
2785   _Jv_JNI_SetStaticField,              // SetStaticFloatField
2786   _Jv_JNI_SetStaticField,              // SetStaticDoubleField
2787   _Jv_JNI_NewString,                   // NewString
2788   _Jv_JNI_GetStringLength,             // GetStringLength
2789   _Jv_JNI_GetStringChars,              // GetStringChars
2790   _Jv_JNI_ReleaseStringChars,          // ReleaseStringChars
2791   _Jv_JNI_NewStringUTF,                // NewStringUTF
2792   _Jv_JNI_GetStringUTFLength,          // GetStringUTFLength
2793   _Jv_JNI_GetStringUTFChars,           // GetStringUTFChars
2794   _Jv_JNI_ReleaseStringUTFChars,       // ReleaseStringUTFChars
2795   _Jv_JNI_GetArrayLength,              // GetArrayLength
2796   _Jv_JNI_NewObjectArray,              // NewObjectArray
2797   _Jv_JNI_GetObjectArrayElement,       // GetObjectArrayElement
2798   _Jv_JNI_SetObjectArrayElement,       // SetObjectArrayElement
2799   _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
2800                                                             // NewBooleanArray
2801   _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,     // NewByteArray
2802   _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,     // NewCharArray
2803   _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,   // NewShortArray
2804   _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,       // NewIntArray
2805   _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,     // NewLongArray
2806   _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,   // NewFloatArray
2807   _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>, // NewDoubleArray
2808   _Jv_JNI_GetPrimitiveArrayElements<jboolean, JvPrimClass (boolean)>,       
2809                                             // GetBooleanArrayElements
2810   _Jv_JNI_GetPrimitiveArrayElements<jbyte, JvPrimClass (byte)>,  
2811                                             // GetByteArrayElements
2812   _Jv_JNI_GetPrimitiveArrayElements<jchar, JvPrimClass (char)>,
2813                                             // GetCharArrayElements
2814   _Jv_JNI_GetPrimitiveArrayElements<jshort, JvPrimClass (short)>,           
2815                                             // GetShortArrayElements
2816   _Jv_JNI_GetPrimitiveArrayElements<jint, JvPrimClass (int)>,               
2817                                             // GetIntArrayElements
2818   _Jv_JNI_GetPrimitiveArrayElements<jlong, JvPrimClass (long)>,             
2819                                             // GetLongArrayElements
2820   _Jv_JNI_GetPrimitiveArrayElements<jfloat, JvPrimClass (float)>,           
2821                                             // GetFloatArrayElements
2822   _Jv_JNI_GetPrimitiveArrayElements<jdouble, JvPrimClass (double)>,         
2823                                             // GetDoubleArrayElements
2824   _Jv_JNI_ReleasePrimitiveArrayElements<jboolean, JvPrimClass (boolean)>,    
2825                                             // ReleaseBooleanArrayElements
2826   _Jv_JNI_ReleasePrimitiveArrayElements<jbyte, JvPrimClass (byte)>,    
2827                                             // ReleaseByteArrayElements
2828   _Jv_JNI_ReleasePrimitiveArrayElements<jchar, JvPrimClass (char)>,    
2829                                             // ReleaseCharArrayElements
2830   _Jv_JNI_ReleasePrimitiveArrayElements<jshort, JvPrimClass (short)>,    
2831                                             // ReleaseShortArrayElements
2832   _Jv_JNI_ReleasePrimitiveArrayElements<jint, JvPrimClass (int)>,    
2833                                             // ReleaseIntArrayElements
2834   _Jv_JNI_ReleasePrimitiveArrayElements<jlong, JvPrimClass (long)>,    
2835                                             // ReleaseLongArrayElements
2836   _Jv_JNI_ReleasePrimitiveArrayElements<jfloat, JvPrimClass (float)>,    
2837                                             // ReleaseFloatArrayElements
2838   _Jv_JNI_ReleasePrimitiveArrayElements<jdouble, JvPrimClass (double)>,    
2839                                             // ReleaseDoubleArrayElements
2840   _Jv_JNI_GetPrimitiveArrayRegion<jboolean, JvPrimClass (boolean)>,         
2841                                             // GetBooleanArrayRegion
2842   _Jv_JNI_GetPrimitiveArrayRegion<jbyte, JvPrimClass (byte)>,       
2843                                             // GetByteArrayRegion
2844   _Jv_JNI_GetPrimitiveArrayRegion<jchar, JvPrimClass (char)>,       
2845                                             // GetCharArrayRegion
2846   _Jv_JNI_GetPrimitiveArrayRegion<jshort, JvPrimClass (short)>,     
2847                                             // GetShortArrayRegion
2848   _Jv_JNI_GetPrimitiveArrayRegion<jint, JvPrimClass (int)>,         
2849                                             // GetIntArrayRegion
2850   _Jv_JNI_GetPrimitiveArrayRegion<jlong, JvPrimClass (long)>,       
2851                                             // GetLongArrayRegion
2852   _Jv_JNI_GetPrimitiveArrayRegion<jfloat, JvPrimClass (float)>,     
2853                                             // GetFloatArrayRegion
2854   _Jv_JNI_GetPrimitiveArrayRegion<jdouble, JvPrimClass (double)>,           
2855                                             // GetDoubleArrayRegion
2856   _Jv_JNI_SetPrimitiveArrayRegion<jboolean, JvPrimClass (boolean)>,         
2857                                             // SetBooleanArrayRegion
2858   _Jv_JNI_SetPrimitiveArrayRegion<jbyte, JvPrimClass (byte)>,       
2859                                             // SetByteArrayRegion
2860   _Jv_JNI_SetPrimitiveArrayRegion<jchar, JvPrimClass (char)>,       
2861                                             // SetCharArrayRegion
2862   _Jv_JNI_SetPrimitiveArrayRegion<jshort, JvPrimClass (short)>,     
2863                                             // SetShortArrayRegion
2864   _Jv_JNI_SetPrimitiveArrayRegion<jint, JvPrimClass (int)>,         
2865                                             // SetIntArrayRegion
2866   _Jv_JNI_SetPrimitiveArrayRegion<jlong, JvPrimClass (long)>,       
2867                                             // SetLongArrayRegion
2868   _Jv_JNI_SetPrimitiveArrayRegion<jfloat, JvPrimClass (float)>,     
2869                                             // SetFloatArrayRegion
2870   _Jv_JNI_SetPrimitiveArrayRegion<jdouble, JvPrimClass (double)>,           
2871                                             // SetDoubleArrayRegion
2872   _Jv_JNI_RegisterNatives,                  // RegisterNatives
2873   _Jv_JNI_UnregisterNatives,                // UnregisterNatives
2874   _Jv_JNI_MonitorEnter,                     // MonitorEnter
2875   _Jv_JNI_MonitorExit,                      // MonitorExit
2876   _Jv_JNI_GetJavaVM,                        // GetJavaVM
2877
2878   _Jv_JNI_GetStringRegion,                  // GetStringRegion
2879   _Jv_JNI_GetStringUTFRegion,               // GetStringUTFRegion
2880   _Jv_JNI_GetPrimitiveArrayCritical,        // GetPrimitiveArrayCritical
2881   _Jv_JNI_ReleasePrimitiveArrayCritical,    // ReleasePrimitiveArrayCritical
2882   _Jv_JNI_GetStringCritical,                // GetStringCritical
2883   _Jv_JNI_ReleaseStringCritical,            // ReleaseStringCritical
2884
2885   _Jv_JNI_NewWeakGlobalRef,                 // NewWeakGlobalRef
2886   _Jv_JNI_DeleteWeakGlobalRef,              // DeleteWeakGlobalRef
2887
2888   _Jv_JNI_ExceptionCheck,                   // ExceptionCheck
2889
2890   _Jv_JNI_NewDirectByteBuffer,              // NewDirectByteBuffer
2891   _Jv_JNI_GetDirectBufferAddress,           // GetDirectBufferAddress
2892   _Jv_JNI_GetDirectBufferCapacity           // GetDirectBufferCapacity
2893 };
2894
2895 struct JNIInvokeInterface _Jv_JNI_InvokeFunctions =
2896 {
2897   RESERVED,
2898   RESERVED,
2899   RESERVED,
2900
2901   _Jv_JNI_DestroyJavaVM,
2902   _Jv_JNI_AttachCurrentThread,
2903   _Jv_JNI_DetachCurrentThread,
2904   _Jv_JNI_GetEnv,
2905   _Jv_JNI_AttachCurrentThreadAsDaemon
2906 };