OSDN Git Service

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