OSDN Git Service

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