OSDN Git Service

* gcj/method.h (JvNumMethods): Moved from Class.h.
[pf3gnuchains/gcc-fork.git] / libjava / jni.cc
1 // jni.cc - JNI implementation, including the jump table.
2
3 /* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 // Note: currently we take the approach of not checking most
12 // arguments.  Instead we could do more checking conditionally (e.g.,
13 // if DEBUG is defined).  That might be beneficial in some cases,
14 // though to me it seems that one could just as easily use the
15 // debugger.
16
17 #include <config.h>
18
19 #include <stddef.h>
20
21 // Define this before including jni.h.
22 #define __GCJ_JNI_IMPL__
23
24 #include <gcj/cni.h>
25 #include <jvm.h>
26 #include <java-assert.h>
27 #include <jni.h>
28
29 #include <java/lang/Class.h>
30 #include <java/lang/ClassLoader.h>
31 #include <java/lang/Throwable.h>
32 #include <java/lang/ArrayIndexOutOfBoundsException.h>
33 #include <java/lang/StringIndexOutOfBoundsException.h>
34 #include <java/lang/InstantiationException.h>
35 #include <java/lang/NoSuchFieldError.h>
36 #include <java/lang/NoSuchMethodError.h>
37 #include <java/lang/reflect/Constructor.h>
38 #include <java/lang/reflect/Method.h>
39 #include <java/lang/reflect/Modifier.h>
40
41 #include <gcj/method.h>
42 #include <gcj/field.h>
43
44 #define ClassClass _CL_Q34java4lang5Class
45 extern java::lang::Class ClassClass;
46 #define ObjectClass _CL_Q34java4lang6Object
47 extern java::lang::Class ObjectClass;
48
49 #define MethodClass _CL_Q44java4lang7reflect6Method
50 extern java::lang::Class MethodClass;
51
52 // This enum is used to select different template instantiations in
53 // the invocation code.
54 enum invocation_type
55 {
56   normal,
57   nonvirtual,
58   static_type,
59   constructor
60 };
61
62 // Forward declaration.
63 extern struct JNINativeInterface _Jv_JNIFunctions;
64
65 \f
66
67 // Tell the GC that a certain pointer is live.
68 static void
69 mark_for_gc (void *)
70 {
71   // FIXME.
72 }
73
74 // Unmark a pointer.
75 static void
76 unmark_for_gc (void *)
77 {
78   // FIXME.
79 }
80
81 \f
82
83 static jint
84 _Jv_JNI_GetVersion (JNIEnv *)
85 {
86   return JNI_VERSION_1_2;
87 }
88
89 static jclass
90 _Jv_JNI_DefineClass (JNIEnv *, jobject loader, 
91                      const jbyte *buf, jsize bufLen)
92 {
93   jbyteArray bytes = JvNewByteArray (bufLen);
94   jbyte *elts = elements (bytes);
95   memcpy (elts, buf, bufLen * sizeof (jbyte));
96
97   java::lang::ClassLoader *l
98     = reinterpret_cast<java::lang::ClassLoader *> (loader);
99
100   // FIXME: exception processing.
101   jclass result = l->defineClass (bytes, 0, bufLen);
102   return result;
103 }
104
105 static jclass
106 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
107 {
108   // FIXME: assume that NAME isn't too long.
109   int len = strlen (name);
110   char s[len + 1];
111   for (int i = 0; i <= len; ++i)
112     s[i] = (name[i] == '/') ? '.' : name[i];
113   jstring n = JvNewStringUTF (s);
114
115   java::lang::ClassLoader *loader;
116   if (env->klass == NULL)
117     {
118       // FIXME: should use getBaseClassLoader, but we don't have that
119       // yet.
120       loader = java::lang::ClassLoader::getSystemClassLoader ();
121     }
122   else
123     loader = env->klass->getClassLoader ();
124
125   // FIXME: exception processing.
126   jclass r = loader->findClass (n);
127
128   return r;
129 }
130
131 static jclass
132 _Jv_JNI_GetSuperclass (JNIEnv *, jclass clazz)
133 {
134   return clazz->getSuperclass ();
135 }
136
137 static jboolean
138 _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
139 {
140   return clazz1->isAssignableFrom (clazz2);
141 }
142
143 static jint
144 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
145 {
146   env->ex = obj;
147   return 0;
148 }
149
150 static jint
151 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
152 {
153   using namespace java::lang::reflect;
154
155   JArray<jclass> *argtypes
156     = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
157
158   jclass *elts = elements (argtypes);
159   elts[0] = &StringClass;
160
161   // FIXME: exception processing.
162   Constructor *cons = clazz->getConstructor (argtypes);
163
164   jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
165   jobject *velts = elements (values);
166   velts[0] = JvNewStringUTF (message);
167
168   // FIXME: exception processing.
169   jobject obj = cons->newInstance (values);
170
171   env->ex = reinterpret_cast<jthrowable> (obj);
172   return 0;
173 }
174
175 static jthrowable
176 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
177 {
178   // FIXME: create local reference.
179   return env->ex;
180 }
181
182 static void
183 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
184 {
185   if (env->ex != NULL)
186     env->ex->printStackTrace();
187 }
188
189 static void
190 _Jv_JNI_ExceptionClear (JNIEnv *env)
191 {
192   env->ex = NULL;
193 }
194
195 static jboolean
196 _Jv_JNI_ExceptionCheck (JNIEnv *env)
197 {
198   return env->ex != NULL;
199 }
200
201 static void
202 _Jv_JNI_FatalError (JNIEnv *, const char *message)
203 {
204   JvFail (message);
205 }
206
207 static jboolean
208 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
209 {
210   return obj1 == obj2;
211 }
212
213 static jobject
214 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
215 {
216   jobject obj = NULL;
217   using namespace java::lang::reflect;
218   if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
219     env->ex = new java::lang::InstantiationException ();
220   else
221     {
222       // FIXME: exception processing.
223       // FIXME: will this work for String?
224       obj = JvAllocObject (clazz);
225     }
226
227   return obj;
228 }
229
230 static jclass
231 _Jv_JNI_GetObjectClass (JNIEnv *, jobject obj)
232 {
233   return obj->getClass();
234 }
235
236 static jboolean
237 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
238 {
239   return clazz->isInstance(obj);
240 }
241
242 \f
243
244 //
245 // This section concerns method invocation.
246 //
247
248 template<jboolean is_static>
249 static jmethodID
250 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
251                         const char *name, const char *sig)
252 {
253   // FIXME: exception processing.
254   _Jv_InitClass (clazz);
255
256   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
257   _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
258
259   JvAssert (! clazz->isPrimitive());
260
261   using namespace java::lang::reflect;
262
263   while (clazz != NULL)
264     {
265       jint count = JvNumMethods (clazz);
266       jmethodID meth = JvGetFirstMethod (clazz);
267
268       for (jint i = 0; i < count; ++i)
269         {
270           if (((is_static && Modifier::isStatic (meth->accflags))
271                || (! is_static && ! Modifier::isStatic (meth->accflags)))
272               && _Jv_equalUtf8Consts (meth->name, name_u)
273               && _Jv_equalUtf8Consts (meth->signature, sig_u))
274             return meth;
275
276           meth = meth->getNextMethod();
277         }
278
279       clazz = clazz->getSuperclass ();
280     }
281
282   env->ex = new java::lang::NoSuchMethodError ();
283   return NULL;
284 }
285
286 // This is a helper function which turns a va_list into an array of
287 // `jvalue's.  It needs signature information in order to do its work.
288 // The array of values must already be allocated.
289 static void
290 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
291 {
292   jclass *arg_elts = elements (arg_types);
293   for (int i = 0; i < arg_types->length; ++i)
294     {
295       if (arg_elts[i] == JvPrimClass (byte))
296         values[i].b = va_arg (vargs, jbyte);
297       else if (arg_elts[i] == JvPrimClass (short))
298         values[i].s = va_arg (vargs, jshort);
299       else if (arg_elts[i] == JvPrimClass (int))
300         values[i].i = va_arg (vargs, jint);
301       else if (arg_elts[i] == JvPrimClass (long))
302         values[i].j = va_arg (vargs, jlong);
303       else if (arg_elts[i] == JvPrimClass (float))
304         values[i].f = va_arg (vargs, jfloat);
305       else if (arg_elts[i] == JvPrimClass (double))
306         values[i].d = va_arg (vargs, jdouble);
307       else if (arg_elts[i] == JvPrimClass (boolean))
308         values[i].z = va_arg (vargs, jboolean);
309       else if (arg_elts[i] == JvPrimClass (char))
310         values[i].c = va_arg (vargs, jchar);
311       else
312         {
313           // An object.
314           values[i].l = va_arg (vargs, jobject);
315         }
316     }
317 }
318
319 // This can call any sort of method: virtual, "nonvirtual", static, or
320 // constructor.
321 template<typename T, invocation_type style>
322 static T
323 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
324                         jmethodID id, va_list vargs)
325 {
326   if (style == normal)
327     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
328
329   jclass decl_class = klass ? klass : obj->getClass ();
330   JvAssert (decl_class != NULL);
331
332   jclass return_type;
333   JArray<jclass> *arg_types;
334   // FIXME: exception processing.
335   _Jv_GetTypesFromSignature (id, decl_class,
336                              &arg_types, &return_type);
337
338   jvalue args[arg_types->length];
339   array_from_valist (args, arg_types, vargs);
340
341   jvalue result;
342   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
343                                       style == constructor,
344                                       arg_types, args, &result);
345
346   if (ex != NULL)
347     env->ex = ex;
348
349   // We cheat a little here.  FIXME.
350   return * (T *) &result;
351 }
352
353 template<typename T, invocation_type style>
354 static T
355 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
356                        jmethodID method, ...)
357 {
358   va_list args;
359   T result;
360
361   va_start (args, method);
362   result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
363   va_end (args);
364
365   return result;
366 }
367
368 template<typename T, invocation_type style>
369 static T
370 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
371                         jmethodID id, jvalue *args)
372 {
373   if (style == normal)
374     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
375
376   jclass decl_class = klass ? klass : obj->getClass ();
377   JvAssert (decl_class != NULL);
378
379   jclass return_type;
380   JArray<jclass> *arg_types;
381   // FIXME: exception processing.
382   _Jv_GetTypesFromSignature (id, decl_class,
383                              &arg_types, &return_type);
384
385   jvalue result;
386   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
387                                       style == constructor,
388                                       arg_types, args, &result);
389
390   if (ex != NULL)
391     env->ex = ex;
392
393   // We cheat a little here.  FIXME.
394   return * (T *) &result;
395 }
396
397 template<invocation_type style>
398 static void
399 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
400                             jmethodID id, va_list vargs)
401 {
402   if (style == normal)
403     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
404
405   jclass decl_class = klass ? klass : obj->getClass ();
406   JvAssert (decl_class != NULL);
407
408   jclass return_type;
409   JArray<jclass> *arg_types;
410   // FIXME: exception processing.
411   _Jv_GetTypesFromSignature (id, decl_class,
412                              &arg_types, &return_type);
413
414   jvalue args[arg_types->length];
415   array_from_valist (args, arg_types, vargs);
416
417   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
418                                       style == constructor,
419                                       arg_types, args, NULL);
420
421   if (ex != NULL)
422     env->ex = ex;
423 }
424
425 template<invocation_type style>
426 static void
427 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
428                            jmethodID method, ...)
429 {
430   va_list args;
431
432   va_start (args, method);
433   _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
434   va_end (args);
435 }
436
437 template<invocation_type style>
438 static void
439 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
440                             jmethodID id, jvalue *args)
441 {
442   if (style == normal)
443     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
444
445   jclass decl_class = klass ? klass : obj->getClass ();
446   JvAssert (decl_class != NULL);
447
448   jclass return_type;
449   JArray<jclass> *arg_types;
450   // FIXME: exception processing.
451   _Jv_GetTypesFromSignature (id, decl_class,
452                              &arg_types, &return_type);
453
454   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
455                                       style == constructor,
456                                       arg_types, args, NULL);
457
458   if (ex != NULL)
459     env->ex = ex;
460 }
461
462 // Functions with this signature are used to implement functions in
463 // the CallMethod family.
464 template<typename T>
465 static T
466 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
467 {
468   return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
469 }
470
471 // Functions with this signature are used to implement functions in
472 // the CallMethod family.
473 template<typename T>
474 static T
475 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
476 {
477   va_list args;
478   T result;
479
480   va_start (args, id);
481   result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
482   va_end (args);
483
484   return result;
485 }
486
487 // Functions with this signature are used to implement functions in
488 // the CallMethod family.
489 template<typename T>
490 static T
491 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
492 {
493   return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
494 }
495
496 static void
497 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
498 {
499   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
500 }
501
502 static void
503 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
504 {
505   va_list args;
506
507   va_start (args, id);
508   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
509   va_end (args);
510 }
511
512 static void
513 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
514 {
515   _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
516 }
517
518 // Functions with this signature are used to implement functions in
519 // the CallStaticMethod family.
520 template<typename T>
521 static T
522 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
523                            jmethodID id, va_list args)
524 {
525   return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
526 }
527
528 // Functions with this signature are used to implement functions in
529 // the CallStaticMethod family.
530 template<typename T>
531 static T
532 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
533 {
534   va_list args;
535   T result;
536
537   va_start (args, id);
538   result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
539                                                    id, args);
540   va_end (args);
541
542   return result;
543 }
544
545 // Functions with this signature are used to implement functions in
546 // the CallStaticMethod family.
547 template<typename T>
548 static T
549 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
550                            jvalue *args)
551 {
552   return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
553 }
554
555 static void
556 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
557                                va_list args)
558 {
559   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
560 }
561
562 static void
563 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
564 {
565   va_list args;
566
567   va_start (args, id);
568   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
569   va_end (args);
570 }
571
572 static void
573 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
574                                jvalue *args)
575 {
576   _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
577 }
578
579 static jobject
580 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
581                     jmethodID id, va_list args)
582 {
583   return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
584                                                        id, args);
585 }
586
587 static jobject
588 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
589 {
590   va_list args;
591   jobject result;
592
593   va_start (args, id);
594   result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
595                                                          id, args);
596   va_end (args);
597
598   return result;
599 }
600
601 static jobject
602 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
603                     jvalue *args)
604 {
605   return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
606                                                        id, args);
607 }
608
609 \f
610
611 template<typename T>
612 static T
613 _Jv_JNI_GetField (JNIEnv *, jobject obj, jfieldID field) 
614 {
615   T *ptr = (T *) ((char *) obj + field->getOffset ());
616   return *ptr;
617 }
618
619 template<typename T>
620 static void
621 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
622 {
623   T *ptr = (T *) ((char *) obj + field->getOffset ());
624   *ptr = value;
625 }
626
627 template<jboolean is_static>
628 static jfieldID
629 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
630                        const char *name, const char *sig)
631 {
632   // FIXME: exception processing.
633   _Jv_InitClass (clazz);
634
635   _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
636
637   jclass field_class = NULL;
638   if (sig[0] == '[')
639     field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
640   else
641     {
642       _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
643       field_class = _Jv_FindClass (sig_u, NULL);
644     }
645
646   // FIXME: what if field_class == NULL?
647
648   while (clazz != NULL)
649     {
650       jint count = (is_static
651                     ? JvNumStaticFields (clazz)
652                     : JvNumInstanceFields (clazz));
653       jfieldID field = (is_static
654                         ? JvGetFirstStaticField (clazz)
655                         : JvGetFirstInstanceField (clazz));
656       for (jint i = 0; i < count; ++i)
657         {
658           // The field is resolved as a side effect of class
659           // initialization.
660           JvAssert (field->isResolved ());
661
662           _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
663
664           if (_Jv_equalUtf8Consts (f_name, a_name)
665               && field->getClass() == field_class)
666             return field;
667
668           field = field->getNextField ();
669         }
670
671       clazz = clazz->getSuperclass ();
672     }
673
674   env->ex = new java::lang::NoSuchFieldError ();
675   return NULL;
676 }
677
678 template<typename T>
679 static T
680 _Jv_JNI_GetStaticField (JNIEnv *, jclass, jfieldID field)
681 {
682   T *ptr = (T *) field->u.addr;
683   return *ptr;
684 }
685
686 template<typename T>
687 static void
688 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
689 {
690   T *ptr = (T *) field->u.addr;
691   *ptr = value;
692 }
693
694 static jstring
695 _Jv_JNI_NewString (JNIEnv *, const jchar *unichars, jsize len)
696 {
697   // FIXME: exception processing.
698   jstring r = _Jv_NewString (unichars, len);
699   return r;
700 }
701
702 static jsize
703 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
704 {
705   return string->length();
706 }
707
708 static const jchar *
709 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
710 {
711   jchar *result = _Jv_GetStringChars (string);
712   mark_for_gc (result);
713   if (isCopy)
714     *isCopy = false;
715   return (const jchar *) result;
716 }
717
718 static void
719 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring, const jchar *chars)
720 {
721   unmark_for_gc ((void *) chars);
722 }
723
724 static jstring
725 _Jv_JNI_NewStringUTF (JNIEnv *, const char *bytes)
726 {
727   // FIXME: exception processing.
728   jstring r = JvNewStringUTF (bytes);
729   return r;
730 }
731
732 static jsize
733 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
734 {
735   return JvGetStringUTFLength (string);
736 }
737
738 static const char *
739 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
740 {
741   jsize len = JvGetStringUTFLength (string);
742   // FIXME: exception processing.
743   char *r = (char *) _Jv_Malloc (len + 1);
744   JvGetStringUTFRegion (string, 0, len, r);
745   r[len] = '\0';
746
747   if (isCopy)
748     *isCopy = true;
749
750   return (const char *) r;
751 }
752
753 static void
754 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
755 {
756   _Jv_Free ((void *) utf);
757 }
758
759 static void
760 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
761                          jchar *buf)
762 {
763   jchar *result = _Jv_GetStringChars (string);
764   if (start < 0 || start > string->length ()
765       || len < 0 || start + len > string->length ())
766     env->ex = new java::lang::StringIndexOutOfBoundsException ();
767   else
768     memcpy (buf, &result[start], len * sizeof (jchar));
769 }
770
771 static void
772 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
773                             jsize len, char *buf)
774 {
775   if (start < 0 || start > str->length ()
776       || len < 0 || start + len > str->length ())
777     env->ex = new java::lang::StringIndexOutOfBoundsException ();
778   else
779     _Jv_GetStringUTFRegion (str, start, len, buf);
780 }
781
782 static const jchar *
783 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
784 {
785   jchar *result = _Jv_GetStringChars (str);
786   if (isCopy)
787     *isCopy = false;
788   return result;
789 }
790
791 static void
792 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
793 {
794   // Nothing.
795 }
796
797 static jsize
798 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
799 {
800   return array->length;
801 }
802
803 static jarray
804 _Jv_JNI_NewObjectArray (JNIEnv *, jsize length, jclass elementClass,
805                         jobject init)
806 {
807   // FIXME: exception processing.
808   jarray result = JvNewObjectArray (length, elementClass, init);
809   return result;
810 }
811
812 static jobject
813 _Jv_JNI_GetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index)
814 {
815   jobject *elts = elements (array);
816   return elts[index];
817 }
818
819 static void
820 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
821                                jobject value)
822 {
823   // FIXME: exception processing.
824   _Jv_CheckArrayStore (array, value);
825   jobject *elts = elements (array);
826   elts[index] = value;
827 }
828
829 template<typename T, jclass K>
830 static JArray<T> *
831 _Jv_JNI_NewPrimitiveArray (JNIEnv *, jsize length)
832 {
833   return (JArray<T> *) _Jv_NewPrimArray (K, length);
834 }
835
836 template<typename T>
837 static T *
838 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
839                                    jboolean *isCopy)
840 {
841   T *elts = elements (array);
842   if (isCopy)
843     {
844       // We elect never to copy.
845       *isCopy = false;
846     }
847   mark_for_gc (elts);
848   return elts;
849 }
850
851 template<typename T>
852 static void
853 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *,
854                                        T *elems, jint /* mode */)
855 {
856   // Note that we ignore MODE.  We can do this because we never copy
857   // the array elements.  My reading of the JNI documentation is that
858   // this is an option for the implementor.
859   unmark_for_gc (elems);
860 }
861
862 template<typename T>
863 static void
864 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
865                                  jsize start, jsize len,
866                                  T *buf)
867 {
868   if (start < 0 || len >= array->length || start + len >= array->length)
869     {
870       // FIXME: index.
871       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
872     }
873   else
874     {
875       T *elts = elements (array) + start;
876       memcpy (buf, elts, len * sizeof (T));
877     }
878 }
879
880 template<typename T>
881 static void
882 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array, 
883                                  jsize start, jsize len, T *buf)
884 {
885   if (start < 0 || len >= array->length || start + len >= array->length)
886     {
887       // FIXME: index.
888       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
889     }
890   else
891     {
892       T *elts = elements (array) + start;
893       memcpy (elts, buf, len * sizeof (T));
894     }
895 }
896
897 static void *
898 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
899                                    jboolean *isCopy)
900 {
901   // FIXME: does this work?
902   jclass klass = array->getClass()->getComponentType();
903   JvAssert (klass->isPrimitive ());
904   char *r = _Jv_GetArrayElementFromElementType (array, klass);
905   if (isCopy)
906     *isCopy = false;
907   return r;
908 }
909
910 static void
911 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
912 {
913   // Nothing.
914 }
915
916 static jint
917 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
918 {
919   // FIXME: exception processing.
920   jint r = _Jv_MonitorEnter (obj);
921   return r;
922 }
923
924 static jint
925 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
926 {
927   // FIXME: exception processing.
928   jint r = _Jv_MonitorExit (obj);
929   return r;
930 }
931
932 // JDK 1.2
933 jobject
934 _Jv_JNI_ToReflectedField (JNIEnv *, jclass cls, jfieldID fieldID,
935                           jboolean)
936 {
937   // FIXME: exception processing.
938   java::lang::reflect::Field *field = new java::lang::reflect::Field();
939   field->declaringClass = cls;
940   field->offset = (char*) fieldID - (char *) cls->fields;
941   field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
942   // FIXME: make a local reference.
943   return field;
944 }
945
946 // JDK 1.2
947 static jfieldID
948 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
949 {
950   using namespace java::lang::reflect;
951
952   Field *field = reinterpret_cast<Field *> (f);
953   return _Jv_FromReflectedField (field);
954 }
955
956 jobject
957 _Jv_JNI_ToReflectedMethod (JNIEnv *, jclass klass, jmethodID id,
958                            jboolean)
959 {
960   using namespace java::lang::reflect;
961
962   // FIXME.
963   static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
964
965   jobject result;
966   if (_Jv_equalUtf8Consts (id->name, init_name))
967     {
968       // A constructor.
969       Constructor *cons = new Constructor ();
970       cons->offset = (char *) id - (char *) &klass->methods;
971       cons->declaringClass = klass;
972       result = cons;
973     }
974   else
975     {
976       Method *meth = new Method ();
977       meth->offset = (char *) id - (char *) &klass->methods;
978       meth->declaringClass = klass;
979       result = meth;
980     }
981
982   // FIXME: make a local reference.
983   return result;
984 }
985
986 static jmethodID
987 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
988 {
989   using namespace java::lang::reflect;
990   if ((&MethodClass)->isInstance (method))
991     return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
992   return
993     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
994 }
995
996 \f
997
998 // This function is the stub which is used to turn an ordinary (CNI)
999 // method call into a JNI call.
1000 #if 0
1001 template<typename T>
1002 static T
1003 _Jv_JNI_conversion_call (fixme)
1004 {
1005   JNIEnv env;
1006
1007   env.p = &_Jv_JNIFunctions;
1008   env.ex = NULL;
1009   env.klass = FIXME;
1010
1011   T result = FIXME_ffi_call (args);
1012
1013   if (env.ex)
1014     JvThrow (env.ex);
1015
1016   return T;
1017 }
1018 #endif
1019
1020 \f
1021
1022 #define NOT_IMPL NULL
1023 #define RESERVED NULL
1024
1025 struct JNINativeInterface _Jv_JNIFunctions =
1026 {
1027   RESERVED,
1028   RESERVED,
1029   RESERVED,
1030   RESERVED,
1031   _Jv_JNI_GetVersion,
1032   _Jv_JNI_DefineClass,
1033   _Jv_JNI_FindClass,
1034   _Jv_JNI_FromReflectedMethod,
1035   _Jv_JNI_FromReflectedField,
1036   _Jv_JNI_ToReflectedMethod,
1037   _Jv_JNI_GetSuperclass,
1038   _Jv_JNI_IsAssignableFrom,
1039   _Jv_JNI_ToReflectedField,
1040   _Jv_JNI_Throw,
1041   _Jv_JNI_ThrowNew,
1042   _Jv_JNI_ExceptionOccurred,
1043   _Jv_JNI_ExceptionDescribe,
1044   _Jv_JNI_ExceptionClear,
1045   _Jv_JNI_FatalError,
1046   NOT_IMPL,
1047   NOT_IMPL,
1048   NOT_IMPL /* NewGlobalRef */,
1049   NOT_IMPL /* DeleteGlobalRef */,
1050   NOT_IMPL /* DeleteLocalRef */,
1051   _Jv_JNI_IsSameObject,
1052   NOT_IMPL,
1053   NOT_IMPL,
1054   _Jv_JNI_AllocObject,
1055   _Jv_JNI_NewObject,
1056   _Jv_JNI_NewObjectV,
1057   _Jv_JNI_NewObjectA,
1058   _Jv_JNI_GetObjectClass,
1059   _Jv_JNI_IsInstanceOf,
1060   _Jv_JNI_GetAnyMethodID<false>,
1061
1062   _Jv_JNI_CallMethod<jobject>,
1063   _Jv_JNI_CallMethodV<jobject>,
1064   _Jv_JNI_CallMethodA<jobject>,
1065   _Jv_JNI_CallMethod<jboolean>,
1066   _Jv_JNI_CallMethodV<jboolean>,
1067   _Jv_JNI_CallMethodA<jboolean>,
1068   _Jv_JNI_CallMethod<jbyte>,
1069   _Jv_JNI_CallMethodV<jbyte>,
1070   _Jv_JNI_CallMethodA<jbyte>,
1071   _Jv_JNI_CallMethod<jchar>,
1072   _Jv_JNI_CallMethodV<jchar>,
1073   _Jv_JNI_CallMethodA<jchar>,
1074   _Jv_JNI_CallMethod<jshort>,
1075   _Jv_JNI_CallMethodV<jshort>,
1076   _Jv_JNI_CallMethodA<jshort>,
1077   _Jv_JNI_CallMethod<jint>,
1078   _Jv_JNI_CallMethodV<jint>,
1079   _Jv_JNI_CallMethodA<jint>,
1080   _Jv_JNI_CallMethod<jlong>,
1081   _Jv_JNI_CallMethodV<jlong>,
1082   _Jv_JNI_CallMethodA<jlong>,
1083   _Jv_JNI_CallMethod<jfloat>,
1084   _Jv_JNI_CallMethodV<jfloat>,
1085   _Jv_JNI_CallMethodA<jfloat>,
1086   _Jv_JNI_CallMethod<jdouble>,
1087   _Jv_JNI_CallMethodV<jdouble>,
1088   _Jv_JNI_CallMethodA<jdouble>,
1089   _Jv_JNI_CallVoidMethod,
1090   _Jv_JNI_CallVoidMethodV,
1091   _Jv_JNI_CallVoidMethodA,
1092
1093   // Nonvirtual method invocation functions follow.
1094   _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1095   _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1096   _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1097   _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1098   _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1099   _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1100   _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1101   _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1102   _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1103   _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1104   _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1105   _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1106   _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1107   _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1108   _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1109   _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1110   _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1111   _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1112   _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1113   _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1114   _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1115   _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1116   _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1117   _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1118   _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1119   _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1120   _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1121   _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1122   _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1123   _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1124
1125   _Jv_JNI_GetAnyFieldID<false>,
1126   _Jv_JNI_GetField<jobject>,
1127   _Jv_JNI_GetField<jboolean>,
1128   _Jv_JNI_GetField<jbyte>,
1129   _Jv_JNI_GetField<jchar>,
1130   _Jv_JNI_GetField<jshort>,
1131   _Jv_JNI_GetField<jint>,
1132   _Jv_JNI_GetField<jlong>,
1133   _Jv_JNI_GetField<jfloat>,
1134   _Jv_JNI_GetField<jdouble>,
1135   _Jv_JNI_SetField,
1136   _Jv_JNI_SetField,
1137   _Jv_JNI_SetField,
1138   _Jv_JNI_SetField,
1139   _Jv_JNI_SetField,
1140   _Jv_JNI_SetField,
1141   _Jv_JNI_SetField,
1142   _Jv_JNI_SetField,
1143   _Jv_JNI_SetField,
1144   _Jv_JNI_GetAnyMethodID<true>,
1145
1146   _Jv_JNI_CallStaticMethod<jobject>,
1147   _Jv_JNI_CallStaticMethodV<jobject>,
1148   _Jv_JNI_CallStaticMethodA<jobject>,
1149   _Jv_JNI_CallStaticMethod<jboolean>,
1150   _Jv_JNI_CallStaticMethodV<jboolean>,
1151   _Jv_JNI_CallStaticMethodA<jboolean>,
1152   _Jv_JNI_CallStaticMethod<jbyte>,
1153   _Jv_JNI_CallStaticMethodV<jbyte>,
1154   _Jv_JNI_CallStaticMethodA<jbyte>,
1155   _Jv_JNI_CallStaticMethod<jchar>,
1156   _Jv_JNI_CallStaticMethodV<jchar>,
1157   _Jv_JNI_CallStaticMethodA<jchar>,
1158   _Jv_JNI_CallStaticMethod<jshort>,
1159   _Jv_JNI_CallStaticMethodV<jshort>,
1160   _Jv_JNI_CallStaticMethodA<jshort>,
1161   _Jv_JNI_CallStaticMethod<jint>,
1162   _Jv_JNI_CallStaticMethodV<jint>,
1163   _Jv_JNI_CallStaticMethodA<jint>,
1164   _Jv_JNI_CallStaticMethod<jlong>,
1165   _Jv_JNI_CallStaticMethodV<jlong>,
1166   _Jv_JNI_CallStaticMethodA<jlong>,
1167   _Jv_JNI_CallStaticMethod<jfloat>,
1168   _Jv_JNI_CallStaticMethodV<jfloat>,
1169   _Jv_JNI_CallStaticMethodA<jfloat>,
1170   _Jv_JNI_CallStaticMethod<jdouble>,
1171   _Jv_JNI_CallStaticMethodV<jdouble>,
1172   _Jv_JNI_CallStaticMethodA<jdouble>,
1173   _Jv_JNI_CallStaticVoidMethod,
1174   _Jv_JNI_CallStaticVoidMethodV,
1175   _Jv_JNI_CallStaticVoidMethodA,
1176
1177   _Jv_JNI_GetAnyFieldID<true>,
1178   _Jv_JNI_GetStaticField<jobject>,
1179   _Jv_JNI_GetStaticField<jboolean>,
1180   _Jv_JNI_GetStaticField<jbyte>,
1181   _Jv_JNI_GetStaticField<jchar>,
1182   _Jv_JNI_GetStaticField<jshort>,
1183   _Jv_JNI_GetStaticField<jint>,
1184   _Jv_JNI_GetStaticField<jlong>,
1185   _Jv_JNI_GetStaticField<jfloat>,
1186   _Jv_JNI_GetStaticField<jdouble>,
1187   _Jv_JNI_SetStaticField,
1188   _Jv_JNI_SetStaticField,
1189   _Jv_JNI_SetStaticField,
1190   _Jv_JNI_SetStaticField,
1191   _Jv_JNI_SetStaticField,
1192   _Jv_JNI_SetStaticField,
1193   _Jv_JNI_SetStaticField,
1194   _Jv_JNI_SetStaticField,
1195   _Jv_JNI_SetStaticField,
1196   _Jv_JNI_NewString,
1197   _Jv_JNI_GetStringLength,
1198   _Jv_JNI_GetStringChars,
1199   _Jv_JNI_ReleaseStringChars,
1200   _Jv_JNI_NewStringUTF,
1201   _Jv_JNI_GetStringUTFLength,
1202   _Jv_JNI_GetStringUTFChars,
1203   _Jv_JNI_ReleaseStringUTFChars,
1204   _Jv_JNI_GetArrayLength,
1205   _Jv_JNI_NewObjectArray,
1206   _Jv_JNI_GetObjectArrayElement,
1207   _Jv_JNI_SetObjectArrayElement,
1208   _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1209   _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1210   _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1211   _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1212   _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1213   _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1214   _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1215   _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
1216   _Jv_JNI_GetPrimitiveArrayElements,
1217   _Jv_JNI_GetPrimitiveArrayElements,
1218   _Jv_JNI_GetPrimitiveArrayElements,
1219   _Jv_JNI_GetPrimitiveArrayElements,
1220   _Jv_JNI_GetPrimitiveArrayElements,
1221   _Jv_JNI_GetPrimitiveArrayElements,
1222   _Jv_JNI_GetPrimitiveArrayElements,
1223   _Jv_JNI_GetPrimitiveArrayElements,
1224   _Jv_JNI_ReleasePrimitiveArrayElements,
1225   _Jv_JNI_ReleasePrimitiveArrayElements,
1226   _Jv_JNI_ReleasePrimitiveArrayElements,
1227   _Jv_JNI_ReleasePrimitiveArrayElements,
1228   _Jv_JNI_ReleasePrimitiveArrayElements,
1229   _Jv_JNI_ReleasePrimitiveArrayElements,
1230   _Jv_JNI_ReleasePrimitiveArrayElements,
1231   _Jv_JNI_ReleasePrimitiveArrayElements,
1232   _Jv_JNI_GetPrimitiveArrayRegion,
1233   _Jv_JNI_GetPrimitiveArrayRegion,
1234   _Jv_JNI_GetPrimitiveArrayRegion,
1235   _Jv_JNI_GetPrimitiveArrayRegion,
1236   _Jv_JNI_GetPrimitiveArrayRegion,
1237   _Jv_JNI_GetPrimitiveArrayRegion,
1238   _Jv_JNI_GetPrimitiveArrayRegion,
1239   _Jv_JNI_GetPrimitiveArrayRegion,
1240   _Jv_JNI_SetPrimitiveArrayRegion,
1241   _Jv_JNI_SetPrimitiveArrayRegion,
1242   _Jv_JNI_SetPrimitiveArrayRegion,
1243   _Jv_JNI_SetPrimitiveArrayRegion,
1244   _Jv_JNI_SetPrimitiveArrayRegion,
1245   _Jv_JNI_SetPrimitiveArrayRegion,
1246   _Jv_JNI_SetPrimitiveArrayRegion,
1247   _Jv_JNI_SetPrimitiveArrayRegion,
1248   NOT_IMPL /* RegisterNatives */,
1249   NOT_IMPL /* UnregisterNatives */,
1250   _Jv_JNI_MonitorEnter,
1251   _Jv_JNI_MonitorExit,
1252   NOT_IMPL /* GetJavaVM */,
1253
1254   _Jv_JNI_GetStringRegion,
1255   _Jv_JNI_GetStringUTFRegion,
1256   _Jv_JNI_GetPrimitiveArrayCritical,
1257   _Jv_JNI_ReleasePrimitiveArrayCritical,
1258   _Jv_JNI_GetStringCritical,
1259   _Jv_JNI_ReleaseStringCritical,
1260
1261   NOT_IMPL /* newweakglobalref */,
1262   NOT_IMPL /* deleteweakglobalref */,
1263
1264   _Jv_JNI_ExceptionCheck
1265 };