02739634b943e30f3d6e71c938987bc3906e9939
[cacao.git] / src / native / jni.c
1 /* src/native/jni.c - implementation of the Java Native Interface functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: jni.c 8362 2007-08-20 18:35:26Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <string.h>
35
36 #include "vm/types.h"
37
38 #include "mm/gc-common.h"
39 #include "mm/memory.h"
40
41 #include "native/jni.h"
42 #include "native/llni.h"
43 #include "native/localref.h"
44 #include "native/native.h"
45
46 #if defined(ENABLE_JAVASE)
47 # if defined(WITH_CLASSPATH_GNU)
48 #  include "native/include/gnu_classpath_Pointer.h"
49
50 #  if SIZEOF_VOID_P == 8
51 #   include "native/include/gnu_classpath_Pointer64.h"
52 #  else
53 #   include "native/include/gnu_classpath_Pointer32.h"
54 #  endif
55 # endif
56 #endif
57
58 #include "native/include/java_lang_Object.h"
59 #include "native/include/java_lang_Byte.h"
60 #include "native/include/java_lang_Character.h"
61 #include "native/include/java_lang_Short.h"
62 #include "native/include/java_lang_Integer.h"
63 #include "native/include/java_lang_Boolean.h"
64 #include "native/include/java_lang_Long.h"
65 #include "native/include/java_lang_Float.h"
66 #include "native/include/java_lang_Double.h"
67 #include "native/include/java_lang_String.h"
68 #include "native/include/java_lang_Throwable.h"
69
70 #if defined(ENABLE_JAVASE)
71 # if defined(WITH_CLASSPATH_SUN)
72 #  include "native/include/java_nio_ByteBuffer.h"       /* required by j.l.CL */
73 # endif
74
75 # include "native/include/java_lang_ClassLoader.h"
76
77 # include "native/include/java_lang_reflect_Constructor.h"
78 # include "native/include/java_lang_reflect_Field.h"
79 # include "native/include/java_lang_reflect_Method.h"
80
81 # include "native/include/java_nio_Buffer.h"
82
83 # if defined(WITH_CLASSPATH_GNU)
84 #  include "native/include/java_nio_DirectByteBufferImpl.h"
85 # endif
86 #endif
87
88 #if defined(ENABLE_JVMTI)
89 # include "native/jvmti/cacaodbg.h"
90 #endif
91
92 #include "native/vm/java_lang_Class.h"
93
94 #if defined(ENABLE_JAVASE)
95 # include "native/vm/java_lang_ClassLoader.h"
96 # include "native/vm/reflect.h"
97 #endif
98
99 #include "threads/lock-common.h"
100 #include "threads/threads-common.h"
101
102 #include "toolbox/logging.h"
103
104 #include "vm/builtin.h"
105 #include "vm/exceptions.h"
106 #include "vm/global.h"
107 #include "vm/initialize.h"
108 #include "vm/primitive.h"
109 #include "vm/resolve.h"
110 #include "vm/stringlocal.h"
111 #include "vm/vm.h"
112
113 #include "vm/jit/asmpart.h"
114 #include "vm/jit/jit.h"
115 #include "vm/jit/stacktrace.h"
116
117 #include "vmcore/loader.h"
118 #include "vmcore/options.h"
119 #include "vmcore/statistics.h"
120
121
122 /* debug **********************************************************************/
123
124 #if !defined(NDEBUG)
125 # define TRACEJNICALLS(format, ...) \
126     do { \
127         if (opt_TraceJNICalls) { \
128             log_println((format), __VA_ARGS__); \
129         } \
130     } while (0)
131 #else
132 # define TRACEJNICALLS(format, ...)
133 #endif
134
135
136 /* global variables ***********************************************************/
137
138 /* global reference table *****************************************************/
139
140 /* hashsize must be power of 2 */
141
142 #define HASHTABLE_GLOBAL_REF_SIZE    64 /* initial size of globalref-hash     */
143
144 static hashtable *hashtable_global_ref; /* hashtable for globalrefs           */
145
146
147 /* direct buffer stuff ********************************************************/
148
149 #if defined(ENABLE_JAVASE)
150 static classinfo *class_java_nio_Buffer;
151 static classinfo *class_java_nio_DirectByteBufferImpl;
152 static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
153
154 # if defined(WITH_CLASSPATH_GNU)
155 #  if SIZEOF_VOID_P == 8
156 static classinfo *class_gnu_classpath_Pointer64;
157 #  else
158 static classinfo *class_gnu_classpath_Pointer32;
159 #  endif
160 # endif
161
162 static methodinfo *dbbirw_init;
163 #endif
164
165
166 /* accessing instance fields macros *******************************************/
167
168 #define SET_FIELD(o,type,f,value) \
169     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
170
171 #define GET_FIELD(o,type,f) \
172     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
173
174
175 /* some forward declarations **************************************************/
176
177 jobject _Jv_JNI_NewLocalRef(JNIEnv *env, jobject ref);
178 jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity);
179
180
181 /* jni_init ********************************************************************
182
183    Initialize the JNI subsystem.
184
185 *******************************************************************************/
186
187 bool jni_init(void)
188 {
189         /* create global ref hashtable */
190
191         hashtable_global_ref = NEW(hashtable);
192
193         hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
194
195
196 #if defined(ENABLE_JAVASE)
197         /* direct buffer stuff */
198
199         if (!(class_java_nio_Buffer =
200                   load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
201                 !link_class(class_java_nio_Buffer))
202                 return false;
203
204 # if defined(WITH_CLASSPATH_GNU)
205         if (!(class_java_nio_DirectByteBufferImpl =
206                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
207                 !link_class(class_java_nio_DirectByteBufferImpl))
208                 return false;
209
210         if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
211                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
212                 !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
213                 return false;
214
215         if (!(dbbirw_init =
216                 class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
217                                                         utf_init,
218                                                         utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
219                 return false;
220
221 #  if SIZEOF_VOID_P == 8
222         if (!(class_gnu_classpath_Pointer64 =
223                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
224                 !link_class(class_gnu_classpath_Pointer64))
225                 return false;
226 #  else
227         if (!(class_gnu_classpath_Pointer32 =
228                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
229                 !link_class(class_gnu_classpath_Pointer32))
230                 return false;
231 #  endif
232 # endif
233 #endif /* defined(ENABLE_JAVASE) */
234
235         return true;
236 }
237
238
239 /* _Jv_jni_CallObjectMethod ****************************************************
240
241    Internal function to call Java Object methods.
242
243 *******************************************************************************/
244
245 static java_handle_t *_Jv_jni_CallObjectMethod(java_handle_t *o,
246                                                                                            vftbl_t *vftbl,
247                                                                                            methodinfo *m, va_list ap)
248 {
249         methodinfo    *resm;
250         java_handle_t *ro;
251
252         STATISTICS(jniinvokation());
253
254         if (m == NULL) {
255                 exceptions_throw_nullpointerexception();
256                 return NULL;
257         }
258
259         /* Class initialization is done by the JIT compiler.  This is ok
260            since a static method always belongs to the declaring class. */
261
262         if (m->flags & ACC_STATIC) {
263                 /* For static methods we reset the object. */
264
265                 if (o != NULL)
266                         o = NULL;
267
268                 /* for convenience */
269
270                 resm = m;
271
272         } else {
273                 /* For instance methods we make a virtual function table lookup. */
274
275                 resm = method_vftbl_lookup(vftbl, m);
276         }
277
278         STATISTICS(jnicallXmethodnvokation());
279
280         ro = vm_call_method_valist(resm, o, ap);
281
282         return ro;
283 }
284
285
286 /* _Jv_jni_CallObjectMethodA ***************************************************
287
288    Internal function to call Java Object methods.
289
290 *******************************************************************************/
291
292 static java_handle_t *_Jv_jni_CallObjectMethodA(java_handle_t *o,
293                                                                                                 vftbl_t *vftbl,
294                                                                                                 methodinfo *m,
295                                                                                                 const jvalue *args)
296 {
297         methodinfo    *resm;
298         java_handle_t *ro;
299
300         STATISTICS(jniinvokation());
301
302         if (m == NULL) {
303                 exceptions_throw_nullpointerexception();
304                 return NULL;
305         }
306
307         /* Class initialization is done by the JIT compiler.  This is ok
308            since a static method always belongs to the declaring class. */
309
310         if (m->flags & ACC_STATIC) {
311                 /* For static methods we reset the object. */
312
313                 if (o != NULL)
314                         o = NULL;
315
316                 /* for convenience */
317
318                 resm = m;
319
320         } else {
321                 /* For instance methods we make a virtual function table lookup. */
322
323                 resm = method_vftbl_lookup(vftbl, m);
324         }
325
326         STATISTICS(jnicallXmethodnvokation());
327
328         ro = vm_call_method_jvalue(resm, o, args);
329
330         return ro;
331 }
332
333
334 /* _Jv_jni_CallIntMethod *******************************************************
335
336    Internal function to call Java integer class methods (boolean,
337    byte, char, short, int).
338
339 *******************************************************************************/
340
341 static jint _Jv_jni_CallIntMethod(java_handle_t *o, vftbl_t *vftbl,
342                                                                   methodinfo *m, va_list ap)
343 {
344         methodinfo *resm;
345         jint        i;
346
347         STATISTICS(jniinvokation());
348
349         if (m == NULL) {
350                 exceptions_throw_nullpointerexception();
351                 return 0;
352         }
353         
354         /* Class initialization is done by the JIT compiler.  This is ok
355            since a static method always belongs to the declaring class. */
356
357         if (m->flags & ACC_STATIC) {
358                 /* For static methods we reset the object. */
359
360                 if (o != NULL)
361                         o = NULL;
362
363                 /* for convenience */
364
365                 resm = m;
366
367         } else {
368                 /* For instance methods we make a virtual function table lookup. */
369
370                 resm = method_vftbl_lookup(vftbl, m);
371         }
372
373         STATISTICS(jnicallXmethodnvokation());
374
375         i = vm_call_method_int_valist(resm, o, ap);
376
377         return i;
378 }
379
380
381 /* _Jv_jni_CallIntMethodA ******************************************************
382
383    Internal function to call Java integer class methods (boolean,
384    byte, char, short, int).
385
386 *******************************************************************************/
387
388 static jint _Jv_jni_CallIntMethodA(java_handle_t *o, vftbl_t *vftbl,
389                                                                    methodinfo *m, const jvalue *args)
390 {
391         methodinfo *resm;
392         jint        i;
393
394         STATISTICS(jniinvokation());
395
396         if (m == NULL) {
397                 exceptions_throw_nullpointerexception();
398                 return 0;
399         }
400         
401         /* Class initialization is done by the JIT compiler.  This is ok
402            since a static method always belongs to the declaring class. */
403
404         if (m->flags & ACC_STATIC) {
405                 /* For static methods we reset the object. */
406
407                 if (o != NULL)
408                         o = NULL;
409
410                 /* for convenience */
411
412                 resm = m;
413
414         } else {
415                 /* For instance methods we make a virtual function table lookup. */
416
417                 resm = method_vftbl_lookup(vftbl, m);
418         }
419
420         STATISTICS(jnicallXmethodnvokation());
421
422         i = vm_call_method_int_jvalue(resm, o, args);
423
424         return i;
425 }
426
427
428 /* _Jv_jni_CallLongMethod ******************************************************
429
430    Internal function to call Java long methods.
431
432 *******************************************************************************/
433
434 static jlong _Jv_jni_CallLongMethod(java_handle_t *o, vftbl_t *vftbl,
435                                                                         methodinfo *m, va_list ap)
436 {
437         methodinfo *resm;
438         jlong       l;
439
440         STATISTICS(jniinvokation());
441
442         if (m == NULL) {
443                 exceptions_throw_nullpointerexception();
444                 return 0;
445         }
446
447         /* Class initialization is done by the JIT compiler.  This is ok
448            since a static method always belongs to the declaring class. */
449
450         if (m->flags & ACC_STATIC) {
451                 /* For static methods we reset the object. */
452
453                 if (o != NULL)
454                         o = NULL;
455
456                 /* for convenience */
457
458                 resm = m;
459
460         } else {
461                 /* For instance methods we make a virtual function table lookup. */
462
463                 resm = method_vftbl_lookup(vftbl, m);
464         }
465
466         STATISTICS(jnicallXmethodnvokation());
467
468         l = vm_call_method_long_valist(resm, o, ap);
469
470         return l;
471 }
472
473
474 /* _Jv_jni_CallLongMethodA *****************************************************
475
476    Internal function to call Java long methods.
477
478 *******************************************************************************/
479
480 static jlong _Jv_jni_CallLongMethodA(java_handle_t *o, vftbl_t *vftbl,
481                                                                          methodinfo *m, const jvalue *args)
482 {
483         methodinfo *resm;
484         jlong       l;
485
486         STATISTICS(jniinvokation());
487
488         if (m == NULL) {
489                 exceptions_throw_nullpointerexception();
490                 return 0;
491         }
492
493         /* Class initialization is done by the JIT compiler.  This is ok
494            since a static method always belongs to the declaring class. */
495
496         if (m->flags & ACC_STATIC) {
497                 /* For static methods we reset the object. */
498
499                 if (o != NULL)
500                         o = NULL;
501
502                 /* for convenience */
503
504                 resm = m;
505         }
506         else {
507                 /* For instance methods we make a virtual function table lookup. */
508
509                 resm = method_vftbl_lookup(vftbl, m);
510         }
511
512         STATISTICS(jnicallXmethodnvokation());
513
514         l = vm_call_method_long_jvalue(resm, o, args);
515
516         return l;
517 }
518
519
520 /* _Jv_jni_CallFloatMethod *****************************************************
521
522    Internal function to call Java float methods.
523
524 *******************************************************************************/
525
526 static jfloat _Jv_jni_CallFloatMethod(java_handle_t *o, vftbl_t *vftbl,
527                                                                           methodinfo *m, va_list ap)
528 {
529         methodinfo *resm;
530         jfloat      f;
531
532         /* Class initialization is done by the JIT compiler.  This is ok
533            since a static method always belongs to the declaring class. */
534
535         if (m->flags & ACC_STATIC) {
536                 /* For static methods we reset the object. */
537
538                 if (o != NULL)
539                         o = NULL;
540
541                 /* for convenience */
542
543                 resm = m;
544
545         } else {
546                 /* For instance methods we make a virtual function table lookup. */
547
548                 resm = method_vftbl_lookup(vftbl, m);
549         }
550
551         STATISTICS(jnicallXmethodnvokation());
552
553         f = vm_call_method_float_valist(resm, o, ap);
554
555         return f;
556 }
557
558
559 /* _Jv_jni_CallFloatMethodA ****************************************************
560
561    Internal function to call Java float methods.
562
563 *******************************************************************************/
564
565 static jfloat _Jv_jni_CallFloatMethodA(java_handle_t *o, vftbl_t *vftbl,
566                                                                            methodinfo *m, const jvalue *args)
567 {
568         methodinfo *resm;
569         jfloat      f;
570
571         /* Class initialization is done by the JIT compiler.  This is ok
572            since a static method always belongs to the declaring class. */
573
574         if (m->flags & ACC_STATIC) {
575                 /* For static methods we reset the object. */
576
577                 if (o != NULL)
578                         o = NULL;
579
580                 /* for convenience */
581
582                 resm = m;
583         }
584         else {
585                 /* For instance methods we make a virtual function table lookup. */
586
587                 resm = method_vftbl_lookup(vftbl, m);
588         }
589
590         STATISTICS(jnicallXmethodnvokation());
591
592         f = vm_call_method_float_jvalue(resm, o, args);
593
594         return f;
595 }
596
597
598 /* _Jv_jni_CallDoubleMethod ****************************************************
599
600    Internal function to call Java double methods.
601
602 *******************************************************************************/
603
604 static jdouble _Jv_jni_CallDoubleMethod(java_handle_t *o, vftbl_t *vftbl,
605                                                                                 methodinfo *m, va_list ap)
606 {
607         methodinfo *resm;
608         jdouble     d;
609
610         /* Class initialization is done by the JIT compiler.  This is ok
611            since a static method always belongs to the declaring class. */
612
613         if (m->flags & ACC_STATIC) {
614                 /* For static methods we reset the object. */
615
616                 if (o != NULL)
617                         o = NULL;
618
619                 /* for convenience */
620
621                 resm = m;
622
623         } else {
624                 /* For instance methods we make a virtual function table lookup. */
625
626                 resm = method_vftbl_lookup(vftbl, m);
627         }
628
629         d = vm_call_method_double_valist(resm, o, ap);
630
631         return d;
632 }
633
634
635 /* _Jv_jni_CallDoubleMethodA ***************************************************
636
637    Internal function to call Java double methods.
638
639 *******************************************************************************/
640
641 static jdouble _Jv_jni_CallDoubleMethodA(java_handle_t *o, vftbl_t *vftbl,
642                                                                                  methodinfo *m, const jvalue *args)
643 {
644         methodinfo *resm;
645         jdouble     d;
646
647         /* Class initialization is done by the JIT compiler.  This is ok
648            since a static method always belongs to the declaring class. */
649
650         if (m->flags & ACC_STATIC) {
651                 /* For static methods we reset the object. */
652
653                 if (o != NULL)
654                         o = NULL;
655
656                 /* for convenience */
657
658                 resm = m;
659         }
660         else {
661                 /* For instance methods we make a virtual function table lookup. */
662
663                 resm = method_vftbl_lookup(vftbl, m);
664         }
665
666         d = vm_call_method_double_jvalue(resm, o, args);
667
668         return d;
669 }
670
671
672 /* _Jv_jni_CallVoidMethod ******************************************************
673
674    Internal function to call Java void methods.
675
676 *******************************************************************************/
677
678 static void _Jv_jni_CallVoidMethod(java_handle_t *o, vftbl_t *vftbl,
679                                                                    methodinfo *m, va_list ap)
680 {       
681         methodinfo *resm;
682
683         if (m == NULL) {
684                 exceptions_throw_nullpointerexception();
685                 return;
686         }
687
688         /* Class initialization is done by the JIT compiler.  This is ok
689            since a static method always belongs to the declaring class. */
690
691         if (m->flags & ACC_STATIC) {
692                 /* For static methods we reset the object. */
693
694                 if (o != NULL)
695                         o = NULL;
696
697                 /* for convenience */
698
699                 resm = m;
700
701         } else {
702                 /* For instance methods we make a virtual function table lookup. */
703
704                 resm = method_vftbl_lookup(vftbl, m);
705         }
706
707         STATISTICS(jnicallXmethodnvokation());
708
709         (void) vm_call_method_valist(resm, o, ap);
710 }
711
712
713 /* _Jv_jni_CallVoidMethodA *****************************************************
714
715    Internal function to call Java void methods.
716
717 *******************************************************************************/
718
719 static void _Jv_jni_CallVoidMethodA(java_handle_t *o, vftbl_t *vftbl,
720                                                                         methodinfo *m, const jvalue *args)
721 {       
722         methodinfo *resm;
723
724         if (m == NULL) {
725                 exceptions_throw_nullpointerexception();
726                 return;
727         }
728
729         /* Class initialization is done by the JIT compiler.  This is ok
730            since a static method always belongs to the declaring class. */
731
732         if (m->flags & ACC_STATIC) {
733                 /* For static methods we reset the object. */
734
735                 if (o != NULL)
736                         o = NULL;
737
738                 /* for convenience */
739
740                 resm = m;
741
742         } else {
743                 /* For instance methods we make a virtual function table lookup. */
744
745                 resm = method_vftbl_lookup(vftbl, m);
746         }
747
748         STATISTICS(jnicallXmethodnvokation());
749
750         (void) vm_call_method_jvalue(resm, o, args);
751 }
752
753
754 /* _Jv_jni_invokeNative ********************************************************
755
756    Invoke a method on the given object with the given arguments.
757
758    For instance methods OBJ must be != NULL and the method is looked up
759    in the vftbl of the object.
760
761    For static methods, OBJ is ignored.
762
763 *******************************************************************************/
764
765 java_handle_t *_Jv_jni_invokeNative(methodinfo *m, java_handle_t *o,
766                                                                         java_handle_objectarray_t *params)
767 {
768         methodinfo    *resm;
769         java_handle_t *ro;
770         s4             argcount;
771         s4             paramcount;
772         java_handle_t *xptr;
773         int32_t        dumpsize;
774         uint64_t      *array;
775         imm_union          value;
776
777         if (m == NULL) {
778                 exceptions_throw_nullpointerexception();
779                 return NULL;
780         }
781
782         argcount = m->parseddesc->paramcount;
783         paramcount = argcount;
784
785         /* if method is non-static, remove the `this' pointer */
786
787         if (!(m->flags & ACC_STATIC))
788                 paramcount--;
789
790         /* For instance methods the object has to be an instance of the
791            class the method belongs to. For static methods the obj
792            parameter is ignored. */
793
794         if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
795                 exceptions_throw_illegalargumentexception();
796                 return NULL;
797         }
798
799         /* check if we got the right number of arguments */
800
801         if (((params == NULL) && (paramcount != 0)) ||
802                 (params && (LLNI_array_size(params) != paramcount))) 
803         {
804                 exceptions_throw_illegalargumentexception();
805                 return NULL;
806         }
807
808         /* for instance methods we need an object */
809
810         if (!(m->flags & ACC_STATIC) && (o == NULL)) {
811                 /* XXX not sure if that is the correct exception */
812                 exceptions_throw_nullpointerexception();
813                 return NULL;
814         }
815
816         /* for static methods, zero object to make subsequent code simpler */
817         if (m->flags & ACC_STATIC)
818                 o = NULL;
819
820         if (o != NULL) {
821                 /* for instance methods we must do a vftbl lookup */
822                 resm = method_vftbl_lookup(o->vftbl, m);
823         }
824         else {
825                 /* for static methods, just for convenience */
826                 resm = m;
827         }
828
829         /* mark start of dump memory area */
830
831         dumpsize = dump_size();
832
833         /* Fill the argument array from a object-array. */
834
835         array = vm_array_from_objectarray(resm, o, params);
836
837         /* The array can be NULL if we don't have any arguments to pass
838            and the architecture does not have any argument registers
839            (e.g. i386).  In that case we additionally check for an
840            exception thrown. */
841
842         if ((array == NULL) && (exceptions_get_exception() != NULL)) {
843                 /* release dump area */
844
845                 dump_release(dumpsize);
846
847                 return NULL;
848         }
849
850         switch (resm->parseddesc->returntype.decltype) {
851         case TYPE_VOID:
852                 (void) vm_call_array(resm, array);
853                 ro = NULL;
854                 break;
855
856         case PRIMITIVETYPE_BOOLEAN:
857         case PRIMITIVETYPE_BYTE:
858         case PRIMITIVETYPE_CHAR:
859         case PRIMITIVETYPE_SHORT:
860         case PRIMITIVETYPE_INT:
861                 value.i = vm_call_int_array(resm, array);
862                 ro = primitive_box(resm->parseddesc->returntype.decltype, value);
863                 break;
864
865         case PRIMITIVETYPE_LONG:
866                 value.l = vm_call_long_array(resm, array);
867                 ro = primitive_box(resm->parseddesc->returntype.decltype, value);
868                 break;
869
870         case PRIMITIVETYPE_FLOAT:
871                 value.f = vm_call_float_array(resm, array);
872                 ro = primitive_box(resm->parseddesc->returntype.decltype, value);
873                 break;
874
875         case PRIMITIVETYPE_DOUBLE:
876                 value.d = vm_call_double_array(resm, array);
877                 ro = primitive_box(resm->parseddesc->returntype.decltype, value);
878                 break;
879
880         case TYPE_ADR:
881                 ro = vm_call_array(resm, array);
882                 break;
883
884         default:
885                 vm_abort("_Jv_jni_invokeNative: invalid return type %d", resm->parseddesc->returntype.decltype);
886         }
887
888         xptr = exceptions_get_exception();
889
890         if (xptr != NULL) {
891                 /* clear exception pointer, we are calling JIT code again */
892
893                 exceptions_clear_exception();
894
895                 exceptions_throw_invocationtargetexception(xptr);
896         }
897
898         /* release dump area */
899
900         dump_release(dumpsize);
901
902         return ro;
903 }
904
905
906 /* GetVersion ******************************************************************
907
908    Returns the major version number in the higher 16 bits and the
909    minor version number in the lower 16 bits.
910
911 *******************************************************************************/
912
913 jint _Jv_JNI_GetVersion(JNIEnv *env)
914 {
915         STATISTICS(jniinvokation());
916
917         /* we support JNI 1.4 */
918
919         return JNI_VERSION_1_4;
920 }
921
922
923 /* Class Operations ***********************************************************/
924
925 /* DefineClass *****************************************************************
926
927    Loads a class from a buffer of raw class data. The buffer
928    containing the raw class data is not referenced by the VM after the
929    DefineClass call returns, and it may be discarded if desired.
930
931 *******************************************************************************/
932
933 jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
934                                                    const jbyte *buf, jsize bufLen)
935 {
936 #if defined(ENABLE_JAVASE)
937         utf         *u;
938         classloader *cl;
939         classinfo   *c;
940
941         TRACEJNICALLS("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d", env, name, loader, buf, bufLen);
942
943         u  = utf_new_char(name);
944         cl = loader_hashtable_classloader_add((java_handle_t *) loader);
945
946         c = class_define(u, cl, bufLen, (const uint8_t *) buf);
947
948         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
949 #else
950         vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
951
952         /* keep compiler happy */
953
954         return 0;
955 #endif
956 }
957
958
959 /* FindClass *******************************************************************
960
961    This function loads a locally-defined class. It searches the
962    directories and zip files specified by the CLASSPATH environment
963    variable for the class with the specified name.
964
965 *******************************************************************************/
966
967 jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
968 {
969 #if defined(ENABLE_JAVASE)
970         utf       *u;
971         classinfo *cc;
972         classinfo *c;
973
974         STATISTICS(jniinvokation());
975
976         u = utf_new_char_classname((char *) name);
977
978         /* Check stacktrace for classloader, if one found use it,
979            otherwise use the system classloader. */
980
981         /* Quote from the JNI documentation:
982          
983            In the Java 2 Platform, FindClass locates the class loader
984            associated with the current native method.  If the native code
985            belongs to a system class, no class loader will be
986            involved. Otherwise, the proper class loader will be invoked to
987            load and link the named class. When FindClass is called through
988            the Invocation Interface, there is no current native method or
989            its associated class loader. In that case, the result of
990            ClassLoader.getBaseClassLoader is used." */
991
992         cc = stacktrace_getCurrentClass();
993
994         if (cc == NULL)
995                 c = load_class_from_sysloader(u);
996         else
997                 c = load_class_from_classloader(u, cc->classloader);
998
999         if (c == NULL)
1000                 return NULL;
1001
1002         if (!link_class(c))
1003                 return NULL;
1004
1005         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
1006 #else
1007         vm_abort("_Jv_JNI_FindClass: not implemented in this configuration");
1008
1009         /* keep compiler happy */
1010
1011         return NULL;
1012 #endif
1013 }
1014   
1015
1016 /* GetSuperclass ***************************************************************
1017
1018    If clazz represents any class other than the class Object, then
1019    this function returns the object that represents the superclass of
1020    the class specified by clazz.
1021
1022 *******************************************************************************/
1023  
1024 jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
1025 {
1026         classinfo *c;
1027         classinfo *super;
1028
1029         TRACEJNICALLS("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub);
1030
1031         c = LLNI_classinfo_unwrap(sub);
1032
1033         if (c == NULL)
1034                 return NULL;
1035
1036         super = class_get_superclass(c);
1037
1038         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) super);
1039 }
1040   
1041  
1042 /* IsAssignableFrom ************************************************************
1043
1044    Determines whether an object of sub can be safely cast to sup.
1045
1046 *******************************************************************************/
1047
1048 jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
1049 {
1050         java_lang_Class *csup;
1051         java_lang_Class *csub;
1052
1053         csup = (java_lang_Class *) sup;
1054         csub = (java_lang_Class *) sub;
1055
1056         STATISTICS(jniinvokation());
1057
1058         return _Jv_java_lang_Class_isAssignableFrom(csup, csub);
1059 }
1060
1061
1062 /* Throw ***********************************************************************
1063
1064    Causes a java.lang.Throwable object to be thrown.
1065
1066 *******************************************************************************/
1067
1068 jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
1069 {
1070         java_handle_t *o;
1071
1072         STATISTICS(jniinvokation());
1073
1074         o = (java_handle_t *) obj;
1075
1076         exceptions_set_exception(o);
1077
1078         return JNI_OK;
1079 }
1080
1081
1082 /* ThrowNew ********************************************************************
1083
1084    Constructs an exception object from the specified class with the
1085    message specified by message and causes that exception to be
1086    thrown.
1087
1088 *******************************************************************************/
1089
1090 jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
1091 {
1092         classinfo     *c;
1093         java_handle_t *o;
1094         java_handle_t *s;
1095
1096         STATISTICS(jniinvokation());
1097
1098         c = LLNI_classinfo_unwrap(clazz);
1099         if (msg == NULL)
1100                 msg = "";
1101         s = javastring_new_from_utf_string(msg);
1102
1103         /* instantiate exception object */
1104
1105         o = native_new_and_init_string(c, s);
1106
1107         if (o == NULL)
1108                 return -1;
1109
1110         exceptions_set_exception(o);
1111
1112         return 0;
1113 }
1114
1115
1116 /* ExceptionOccurred ***********************************************************
1117
1118    Determines if an exception is being thrown. The exception stays
1119    being thrown until either the native code calls ExceptionClear(),
1120    or the Java code handles the exception.
1121
1122 *******************************************************************************/
1123
1124 jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
1125 {
1126         java_handle_t *o;
1127
1128         STATISTICS(jniinvokation());
1129
1130         o = exceptions_get_exception();
1131
1132         return _Jv_JNI_NewLocalRef(env, (jthrowable) o);
1133 }
1134
1135
1136 /* ExceptionDescribe ***********************************************************
1137
1138    Prints an exception and a backtrace of the stack to a system
1139    error-reporting channel, such as stderr. This is a convenience
1140    routine provided for debugging.
1141
1142 *******************************************************************************/
1143
1144 void _Jv_JNI_ExceptionDescribe(JNIEnv *env)
1145 {
1146         java_handle_t *o;
1147         methodinfo    *m;
1148
1149         STATISTICS(jniinvokation());
1150
1151         o = exceptions_get_exception();
1152
1153         if (o == NULL) {
1154                 /* clear exception, because we are calling jit code again */
1155
1156                 exceptions_clear_exception();
1157
1158                 /* get printStackTrace method from exception class */
1159
1160                 m = class_resolveclassmethod(o->vftbl->class,
1161                                                                          utf_printStackTrace,
1162                                                                          utf_void__void,
1163                                                                          NULL,
1164                                                                          true);
1165
1166                 if (m == NULL)
1167                         /* XXX what should we do? */
1168                         return;
1169
1170                 /* print the stacktrace */
1171
1172                 (void) vm_call_method(m, o);
1173         }
1174 }
1175
1176
1177 /* ExceptionClear **************************************************************
1178
1179    Clears any exception that is currently being thrown. If no
1180    exception is currently being thrown, this routine has no effect.
1181
1182 *******************************************************************************/
1183
1184 void _Jv_JNI_ExceptionClear(JNIEnv *env)
1185 {
1186         STATISTICS(jniinvokation());
1187
1188         exceptions_clear_exception();
1189 }
1190
1191
1192 /* FatalError ******************************************************************
1193
1194    Raises a fatal error and does not expect the VM to recover. This
1195    function does not return.
1196
1197 *******************************************************************************/
1198
1199 void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
1200 {
1201         STATISTICS(jniinvokation());
1202
1203         /* this seems to be the best way */
1204
1205         vm_abort("JNI Fatal error: %s", msg);
1206 }
1207
1208
1209 /* PushLocalFrame **************************************************************
1210
1211    Creates a new local reference frame, in which at least a given
1212    number of local references can be created.
1213
1214 *******************************************************************************/
1215
1216 jint _Jv_JNI_PushLocalFrame(JNIEnv* env, jint capacity)
1217 {
1218         STATISTICS(jniinvokation());
1219
1220         if (capacity <= 0)
1221                 return -1;
1222
1223         /* add new local reference frame to current table */
1224
1225         if (!localref_frame_push(capacity))
1226                 return -1;
1227
1228         return 0;
1229 }
1230
1231
1232 /* PopLocalFrame ***************************************************************
1233
1234    Pops off the current local reference frame, frees all the local
1235    references, and returns a local reference in the previous local
1236    reference frame for the given result object.
1237
1238 *******************************************************************************/
1239
1240 jobject _Jv_JNI_PopLocalFrame(JNIEnv* env, jobject result)
1241 {
1242         STATISTICS(jniinvokation());
1243
1244         /* release all current local frames */
1245
1246         localref_frame_pop_all();
1247
1248         /* add local reference and return the value */
1249
1250         return _Jv_JNI_NewLocalRef(env, result);
1251 }
1252
1253
1254 /* DeleteLocalRef **************************************************************
1255
1256    Deletes the local reference pointed to by localRef.
1257
1258 *******************************************************************************/
1259
1260 void _Jv_JNI_DeleteLocalRef(JNIEnv *env, jobject localRef)
1261 {
1262         java_handle_t  *o;
1263         localref_table *lrt;
1264         s4              i;
1265
1266         STATISTICS(jniinvokation());
1267
1268         o = (java_handle_t *) localRef;
1269
1270         /* get local reference table (thread specific) */
1271
1272         lrt = LOCALREFTABLE;
1273
1274         /* go through all local frames */
1275
1276         for (; lrt != NULL; lrt = lrt->prev) {
1277
1278                 /* and try to remove the reference */
1279
1280                 for (i = 0; i < lrt->capacity; i++) {
1281                         if (lrt->refs[i] == o) {
1282                                 lrt->refs[i] = NULL;
1283                                 lrt->used--;
1284
1285                                 return;
1286                         }
1287                 }
1288         }
1289
1290         /* this should not happen */
1291
1292 /*      if (opt_checkjni) */
1293 /*      FatalError(env, "Bad global or local ref passed to JNI"); */
1294         log_text("JNI-DeleteLocalRef: Local ref passed to JNI not found");
1295 }
1296
1297
1298 /* IsSameObject ****************************************************************
1299
1300    Tests whether two references refer to the same Java object.
1301
1302 *******************************************************************************/
1303
1304 jboolean _Jv_JNI_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
1305 {
1306         STATISTICS(jniinvokation());
1307
1308         if (ref1 == ref2)
1309                 return JNI_TRUE;
1310         else
1311                 return JNI_FALSE;
1312 }
1313
1314
1315 /* NewLocalRef *****************************************************************
1316
1317    Creates a new local reference that refers to the same object as ref.
1318
1319 *******************************************************************************/
1320
1321 jobject _Jv_JNI_NewLocalRef(JNIEnv *env, jobject ref)
1322 {
1323         localref_table *lrt;
1324         s4              i;
1325
1326         STATISTICS(jniinvokation());
1327
1328         if (ref == NULL)
1329                 return NULL;
1330
1331         /* get local reference table (thread specific) */
1332
1333         lrt = LOCALREFTABLE;
1334
1335         /* Check if we have space for the requested reference?  No,
1336            allocate a new frame.  This is actually not what the spec says,
1337            but for compatibility reasons... */
1338
1339         if (lrt->used == lrt->capacity) {
1340                 if (_Jv_JNI_EnsureLocalCapacity(env, 16) != 0)
1341                         return NULL;
1342
1343                 /* get the new local reference table */
1344
1345                 lrt = LOCALREFTABLE;
1346         }
1347
1348         /* insert the reference */
1349
1350         for (i = 0; i < lrt->capacity; i++) {
1351                 if (lrt->refs[i] == NULL) {
1352                         lrt->refs[i] = (java_handle_t *) ref;
1353                         lrt->used++;
1354
1355                         return ref;
1356                 }
1357         }
1358
1359         /* should not happen, just to be sure */
1360
1361         assert(0);
1362
1363         /* keep compiler happy */
1364
1365         return NULL;
1366 }
1367
1368
1369 /* EnsureLocalCapacity *********************************************************
1370
1371    Ensures that at least a given number of local references can be
1372    created in the current thread
1373
1374 *******************************************************************************/
1375
1376 jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity)
1377 {
1378         localref_table *lrt;
1379
1380         STATISTICS(jniinvokation());
1381
1382         /* get local reference table (thread specific) */
1383
1384         lrt = LOCALREFTABLE;
1385
1386         /* check if capacity elements are available in the local references table */
1387
1388         if ((lrt->used + capacity) > lrt->capacity)
1389                 return _Jv_JNI_PushLocalFrame(env, capacity);
1390
1391         return 0;
1392 }
1393
1394
1395 /* AllocObject *****************************************************************
1396
1397    Allocates a new Java object without invoking any of the
1398    constructors for the object. Returns a reference to the object.
1399
1400 *******************************************************************************/
1401
1402 jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
1403 {
1404         classinfo     *c;
1405         java_handle_t *o;
1406
1407         STATISTICS(jniinvokation());
1408
1409         c = LLNI_classinfo_unwrap(clazz);
1410
1411         if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
1412                 exceptions_throw_instantiationexception(c);
1413                 return NULL;
1414         }
1415                 
1416         o = builtin_new(c);
1417
1418         return _Jv_JNI_NewLocalRef(env, (jobject) o);
1419 }
1420
1421
1422 /* NewObject *******************************************************************
1423
1424    Programmers place all arguments that are to be passed to the
1425    constructor immediately following the methodID
1426    argument. NewObject() accepts these arguments and passes them to
1427    the Java method that the programmer wishes to invoke.
1428
1429 *******************************************************************************/
1430
1431 jobject _Jv_JNI_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
1432 {
1433         java_handle_t *o;
1434         classinfo     *c;
1435         methodinfo    *m;
1436         va_list        ap;
1437
1438         STATISTICS(jniinvokation());
1439
1440         c = LLNI_classinfo_unwrap(clazz);
1441         m = (methodinfo *) methodID;
1442
1443         /* create object */
1444
1445         o = builtin_new(c);
1446         
1447         if (o == NULL)
1448                 return NULL;
1449
1450         /* call constructor */
1451
1452         va_start(ap, methodID);
1453         _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
1454         va_end(ap);
1455
1456         return _Jv_JNI_NewLocalRef(env, (jobject) o);
1457 }
1458
1459
1460 /* NewObjectV ******************************************************************
1461
1462    Programmers place all arguments that are to be passed to the
1463    constructor in an args argument of type va_list that immediately
1464    follows the methodID argument. NewObjectV() accepts these
1465    arguments, and, in turn, passes them to the Java method that the
1466    programmer wishes to invoke.
1467
1468 *******************************************************************************/
1469
1470 jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1471                                                    va_list args)
1472 {
1473         java_handle_t *o;
1474         classinfo     *c;
1475         methodinfo    *m;
1476
1477         STATISTICS(jniinvokation());
1478
1479         c = LLNI_classinfo_unwrap(clazz);
1480         m = (methodinfo *) methodID;
1481
1482         /* create object */
1483
1484         o = builtin_new(c);
1485         
1486         if (o == NULL)
1487                 return NULL;
1488
1489         /* call constructor */
1490
1491         _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
1492
1493         return _Jv_JNI_NewLocalRef(env, (jobject) o);
1494 }
1495
1496
1497 /* NewObjectA ***************************************************************** 
1498
1499    Programmers place all arguments that are to be passed to the
1500    constructor in an args array of jvalues that immediately follows
1501    the methodID argument. NewObjectA() accepts the arguments in this
1502    array, and, in turn, passes them to the Java method that the
1503    programmer wishes to invoke.
1504
1505 *******************************************************************************/
1506
1507 jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1508                                                    const jvalue *args)
1509 {
1510         java_handle_t *o;
1511         classinfo     *c;
1512         methodinfo    *m;
1513
1514         STATISTICS(jniinvokation());
1515
1516         c = LLNI_classinfo_unwrap(clazz);
1517         m = (methodinfo *) methodID;
1518
1519         /* create object */
1520
1521         o = builtin_new(c);
1522         
1523         if (o == NULL)
1524                 return NULL;
1525
1526         /* call constructor */
1527
1528         _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
1529
1530         return _Jv_JNI_NewLocalRef(env, (jobject) o);
1531 }
1532
1533
1534 /* GetObjectClass **************************************************************
1535
1536  Returns the class of an object.
1537
1538 *******************************************************************************/
1539
1540 jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
1541 {
1542         java_handle_t *o;
1543         classinfo     *c;
1544
1545         STATISTICS(jniinvokation());
1546
1547         o = (java_handle_t *) obj;
1548
1549         if ((o == NULL) || (o->vftbl == NULL))
1550                 return NULL;
1551
1552         c = o->vftbl->class;
1553
1554         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
1555 }
1556
1557
1558 /* IsInstanceOf ****************************************************************
1559
1560    Tests whether an object is an instance of a class.
1561
1562 *******************************************************************************/
1563
1564 jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
1565 {
1566         java_lang_Class  *c;
1567         java_lang_Object *o;
1568
1569         STATISTICS(jniinvokation());
1570
1571         c = (java_lang_Class *) clazz;
1572         o = (java_lang_Object *) obj;
1573
1574         return _Jv_java_lang_Class_isInstance(c, o);
1575 }
1576
1577
1578 /* Reflection Support *********************************************************/
1579
1580 /* FromReflectedMethod *********************************************************
1581
1582    Converts java.lang.reflect.Method or java.lang.reflect.Constructor
1583    object to a method ID.
1584   
1585 *******************************************************************************/
1586   
1587 jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
1588 {
1589 #if defined(ENABLE_JAVASE)
1590         java_handle_t *o;
1591         classinfo     *c;
1592         methodinfo    *m;
1593         s4             slot;
1594
1595         STATISTICS(jniinvokation());
1596
1597         o = (java_handle_t *) method;
1598
1599         if (o == NULL)
1600                 return NULL;
1601         
1602         if (builtin_instanceof(o, class_java_lang_reflect_Method)) {
1603                 java_lang_reflect_Method *rm;
1604
1605                 rm   = (java_lang_reflect_Method *) method;
1606                 LLNI_field_get_cls(rm, clazz, c);
1607                 LLNI_field_get_val(rm, slot , slot);
1608         }
1609         else if (builtin_instanceof(o, class_java_lang_reflect_Constructor)) {
1610                 java_lang_reflect_Constructor *rc;
1611
1612                 rc   = (java_lang_reflect_Constructor *) method;
1613                 LLNI_field_get_cls(rc, clazz, c);
1614                 LLNI_field_get_val(rc, slot , slot);
1615         }
1616         else
1617                 return NULL;
1618
1619         m = &(c->methods[slot]);
1620
1621         return (jmethodID) m;
1622 #else
1623         vm_abort("_Jv_JNI_FromReflectedMethod: not implemented in this configuration");
1624
1625         /* keep compiler happy */
1626
1627         return NULL;
1628 #endif
1629 }
1630
1631
1632 /* FromReflectedField **********************************************************
1633
1634    Converts a java.lang.reflect.Field to a field ID.
1635
1636 *******************************************************************************/
1637  
1638 jfieldID _Jv_JNI_FromReflectedField(JNIEnv* env, jobject field)
1639 {
1640 #if defined(ENABLE_JAVASE)
1641         java_lang_reflect_Field *rf;
1642         classinfo               *c;
1643         fieldinfo               *f;
1644         int32_t                  slot;
1645
1646         STATISTICS(jniinvokation());
1647
1648         rf = (java_lang_reflect_Field *) field;
1649
1650         if (rf == NULL)
1651                 return NULL;
1652
1653         LLNI_field_get_cls(rf, clazz, c);
1654         LLNI_field_get_val(rf, slot , slot);
1655         f = &(c->fields[slot]);
1656
1657         return (jfieldID) f;
1658 #else
1659         vm_abort("_Jv_JNI_FromReflectedField: not implemented in this configuration");
1660
1661         /* keep compiler happy */
1662
1663         return NULL;
1664 #endif
1665 }
1666
1667
1668 /* ToReflectedMethod ***********************************************************
1669
1670    Converts a method ID derived from cls to an instance of the
1671    java.lang.reflect.Method class or to an instance of the
1672    java.lang.reflect.Constructor class.
1673
1674 *******************************************************************************/
1675
1676 jobject _Jv_JNI_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
1677                                                                   jboolean isStatic)
1678 {
1679 #if defined(ENABLE_JAVASE)
1680         methodinfo                    *m;
1681         java_lang_reflect_Constructor *rc;
1682         java_lang_reflect_Method      *rm;
1683
1684         STATISTICS(jniinvokation());
1685
1686         m = (methodinfo *) methodID;
1687
1688         /* HotSpot does the same assert. */
1689
1690         assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
1691
1692         if (m->name == utf_init) {
1693                 rc = reflect_constructor_new(m);
1694
1695                 return (jobject) rc;
1696         }
1697         else {
1698                 rm = reflect_method_new(m);
1699
1700                 return (jobject) rm;
1701         }
1702 #else
1703         vm_abort("_Jv_JNI_ToReflectedMethod: not implemented in this configuration");
1704
1705         /* keep compiler happy */
1706
1707         return NULL;
1708 #endif
1709 }
1710
1711
1712 /* ToReflectedField ************************************************************
1713
1714    Converts a field ID derived from cls to an instance of the
1715    java.lang.reflect.Field class.
1716
1717 *******************************************************************************/
1718
1719 jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1720                                                                  jboolean isStatic)
1721 {
1722         STATISTICS(jniinvokation());
1723
1724         log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
1725
1726         return NULL;
1727 }
1728
1729
1730 /* Calling Instance Methods ***************************************************/
1731
1732 /* GetMethodID *****************************************************************
1733
1734    Returns the method ID for an instance (nonstatic) method of a class
1735    or interface. The method may be defined in one of the clazz's
1736    superclasses and inherited by clazz. The method is determined by
1737    its name and signature.
1738
1739    GetMethodID() causes an uninitialized class to be initialized.
1740
1741 *******************************************************************************/
1742
1743 jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
1744                                                           const char *sig)
1745 {
1746         classinfo  *c;
1747         utf        *uname;
1748         utf        *udesc;
1749         methodinfo *m;
1750
1751         STATISTICS(jniinvokation());
1752
1753         c = LLNI_classinfo_unwrap(clazz);
1754
1755         if (c == NULL)
1756                 return NULL;
1757
1758         if (!(c->state & CLASS_INITIALIZED))
1759                 if (!initialize_class(c))
1760                         return NULL;
1761
1762         /* try to get the method of the class or one of it's superclasses */
1763
1764         uname = utf_new_char((char *) name);
1765         udesc = utf_new_char((char *) sig);
1766
1767         m = class_resolvemethod(c, uname, udesc);
1768
1769         if ((m == NULL) || (m->flags & ACC_STATIC)) {
1770                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
1771
1772                 return NULL;
1773         }
1774
1775         return (jmethodID) m;
1776 }
1777
1778
1779 /* JNI-functions for calling instance methods *********************************/
1780
1781 #define JNI_CALL_VIRTUAL_METHOD(name, type, intern)         \
1782 type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj,   \
1783                                                                 jmethodID methodID, ...)    \
1784 {                                                           \
1785         java_handle_t *o;                                       \
1786         methodinfo    *m;                                       \
1787         va_list        ap;                                      \
1788         type           ret;                                     \
1789                                                             \
1790         o = (java_handle_t *) obj;                              \
1791         m = (methodinfo *) methodID;                            \
1792                                                             \
1793         va_start(ap, methodID);                                 \
1794         ret = _Jv_jni_Call##intern##Method(o, o->vftbl, m, ap); \
1795         va_end(ap);                                             \
1796                                                             \
1797         return ret;                                             \
1798 }
1799
1800 JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
1801 JNI_CALL_VIRTUAL_METHOD(Byte,    jbyte,    Int)
1802 JNI_CALL_VIRTUAL_METHOD(Char,    jchar,    Int)
1803 JNI_CALL_VIRTUAL_METHOD(Short,   jshort,   Int)
1804 JNI_CALL_VIRTUAL_METHOD(Int,     jint,     Int)
1805 JNI_CALL_VIRTUAL_METHOD(Long,    jlong,    Long)
1806 JNI_CALL_VIRTUAL_METHOD(Float,   jfloat,   Float)
1807 JNI_CALL_VIRTUAL_METHOD(Double,  jdouble,  Double)
1808
1809
1810 #define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern)              \
1811 type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj,         \
1812                                                                  jmethodID methodID, va_list args) \
1813 {                                                                  \
1814         java_handle_t *o;                                              \
1815         methodinfo    *m;                                              \
1816         type           ret;                                            \
1817                                                                    \
1818         o = (java_handle_t *) obj;                                     \
1819         m = (methodinfo *) methodID;                                   \
1820                                                                    \
1821         ret = _Jv_jni_Call##intern##Method(o, o->vftbl, m, args);      \
1822                                                                    \
1823         return ret;                                                    \
1824 }
1825
1826 JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
1827 JNI_CALL_VIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1828 JNI_CALL_VIRTUAL_METHOD_V(Char,    jchar,    Int)
1829 JNI_CALL_VIRTUAL_METHOD_V(Short,   jshort,   Int)
1830 JNI_CALL_VIRTUAL_METHOD_V(Int,     jint,     Int)
1831 JNI_CALL_VIRTUAL_METHOD_V(Long,    jlong,    Long)
1832 JNI_CALL_VIRTUAL_METHOD_V(Float,   jfloat,   Float)
1833 JNI_CALL_VIRTUAL_METHOD_V(Double,  jdouble,  Double)
1834
1835
1836 #define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern)          \
1837 type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj,     \
1838                                                                  jmethodID methodID,           \
1839                                                                  const jvalue *args)           \
1840 {                                                              \
1841         java_handle_t *o;                                          \
1842         methodinfo    *m;                                          \
1843         type           ret;                                        \
1844                                                                \
1845         o = (java_handle_t *) obj;                                 \
1846         m = (methodinfo *) methodID;                               \
1847                                                                \
1848         ret = _Jv_jni_Call##intern##MethodA(o, o->vftbl, m, args); \
1849                                                                \
1850         return ret;                                                \
1851 }
1852
1853 JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
1854 JNI_CALL_VIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1855 JNI_CALL_VIRTUAL_METHOD_A(Char,    jchar,    Int)
1856 JNI_CALL_VIRTUAL_METHOD_A(Short,   jshort,   Int)
1857 JNI_CALL_VIRTUAL_METHOD_A(Int,     jint,     Int)
1858 JNI_CALL_VIRTUAL_METHOD_A(Long,    jlong,    Long)
1859 JNI_CALL_VIRTUAL_METHOD_A(Float,   jfloat,   Float)
1860 JNI_CALL_VIRTUAL_METHOD_A(Double,  jdouble,  Double)
1861
1862
1863 jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
1864                                                                  ...)
1865 {
1866         java_handle_t *o;
1867         methodinfo    *m;
1868         java_handle_t *ret;
1869         va_list        ap;
1870
1871         o = (java_handle_t *) obj;
1872         m = (methodinfo *) methodID;
1873
1874         va_start(ap, methodID);
1875         ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, ap);
1876         va_end(ap);
1877
1878         return _Jv_JNI_NewLocalRef(env, (jobject) ret);
1879 }
1880
1881
1882 jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1883                                                                   va_list args)
1884 {
1885         java_handle_t *o;
1886         methodinfo    *m;
1887         java_handle_t *ret;
1888
1889         o = (java_handle_t *) obj;
1890         m = (methodinfo *) methodID;
1891
1892         ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args);
1893
1894         return _Jv_JNI_NewLocalRef(env, (jobject) ret);
1895 }
1896
1897
1898 jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1899                                                                   const jvalue *args)
1900 {
1901         java_handle_t *o;
1902         methodinfo    *m;
1903         java_handle_t *ret;
1904
1905         o = (java_handle_t *) obj;
1906         m = (methodinfo *) methodID;
1907
1908         ret = _Jv_jni_CallObjectMethodA(o, o->vftbl, m, args);
1909
1910         return _Jv_JNI_NewLocalRef(env, (jobject) ret);
1911 }
1912
1913
1914
1915 void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1916 {
1917         java_handle_t *o;
1918         methodinfo    *m;
1919         va_list        ap;
1920
1921         o = (java_handle_t *) obj;
1922         m = (methodinfo *) methodID;
1923
1924         va_start(ap, methodID);
1925         _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
1926         va_end(ap);
1927 }
1928
1929
1930 void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1931                                                          va_list args)
1932 {
1933         java_handle_t *o;
1934         methodinfo    *m;
1935
1936         o = (java_handle_t *) obj;
1937         m = (methodinfo *) methodID;
1938
1939         _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
1940 }
1941
1942
1943 void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1944                                                          const jvalue *args)
1945 {
1946         java_handle_t *o;
1947         methodinfo    *m;
1948
1949         o = (java_handle_t *) obj;
1950         m = (methodinfo *) methodID;
1951
1952         _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
1953 }
1954
1955
1956
1957 #define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern)                      \
1958 type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj,         \
1959                                                                                   jclass clazz, jmethodID methodID, \
1960                                                                                   ...)                              \
1961 {                                                                           \
1962         java_handle_t *o;                                                       \
1963         classinfo     *c;                                                       \
1964         methodinfo    *m;                                                       \
1965         va_list        ap;                                                      \
1966         type           ret;                                                     \
1967                                                                             \
1968         o = (java_handle_t *) obj;                                              \
1969         c = LLNI_classinfo_unwrap(clazz);                                       \
1970         m = (methodinfo *) methodID;                                            \
1971                                                                             \
1972         va_start(ap, methodID);                                                 \
1973         ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap);                 \
1974         va_end(ap);                                                             \
1975                                                                             \
1976         return ret;                                                             \
1977 }
1978
1979 JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
1980 JNI_CALL_NONVIRTUAL_METHOD(Byte,    jbyte,    Int)
1981 JNI_CALL_NONVIRTUAL_METHOD(Char,    jchar,    Int)
1982 JNI_CALL_NONVIRTUAL_METHOD(Short,   jshort,   Int)
1983 JNI_CALL_NONVIRTUAL_METHOD(Int,     jint,     Int)
1984 JNI_CALL_NONVIRTUAL_METHOD(Long,    jlong,    Long)
1985 JNI_CALL_NONVIRTUAL_METHOD(Float,   jfloat,   Float)
1986 JNI_CALL_NONVIRTUAL_METHOD(Double,  jdouble,  Double)
1987
1988
1989 #define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern)                     \
1990 type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj,         \
1991                                                                                    jclass clazz, jmethodID methodID, \
1992                                                                                    va_list args)                     \
1993 {                                                                            \
1994         java_handle_t *o;                                                        \
1995         classinfo     *c;                                                        \
1996         methodinfo    *m;                                                        \
1997         type           ret;                                                      \
1998                                                                              \
1999         o = (java_handle_t *) obj;                                               \
2000         c = LLNI_classinfo_unwrap(clazz);                                        \
2001         m = (methodinfo *) methodID;                                             \
2002                                                                              \
2003         ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);                       \
2004                                                                              \
2005         return ret;                                                              \
2006 }
2007
2008 JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
2009 JNI_CALL_NONVIRTUAL_METHOD_V(Byte,    jbyte,    Int)
2010 JNI_CALL_NONVIRTUAL_METHOD_V(Char,    jchar,    Int)
2011 JNI_CALL_NONVIRTUAL_METHOD_V(Short,   jshort,   Int)
2012 JNI_CALL_NONVIRTUAL_METHOD_V(Int,     jint,     Int)
2013 JNI_CALL_NONVIRTUAL_METHOD_V(Long,    jlong,    Long)
2014 JNI_CALL_NONVIRTUAL_METHOD_V(Float,   jfloat,   Float)
2015 JNI_CALL_NONVIRTUAL_METHOD_V(Double,  jdouble,  Double)
2016
2017
2018 #define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern)                     \
2019 type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj,         \
2020                                                                                    jclass clazz, jmethodID methodID, \
2021                                                                                    const jvalue *args)               \
2022 {                                                                            \
2023         log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!");      \
2024                                                                              \
2025         return 0;                                                                \
2026 }
2027
2028 JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
2029 JNI_CALL_NONVIRTUAL_METHOD_A(Byte,    jbyte,    Int)
2030 JNI_CALL_NONVIRTUAL_METHOD_A(Char,    jchar,    Int)
2031 JNI_CALL_NONVIRTUAL_METHOD_A(Short,   jshort,   Int)
2032 JNI_CALL_NONVIRTUAL_METHOD_A(Int,     jint,     Int)
2033 JNI_CALL_NONVIRTUAL_METHOD_A(Long,    jlong,    Long)
2034 JNI_CALL_NONVIRTUAL_METHOD_A(Float,   jfloat,   Float)
2035 JNI_CALL_NONVIRTUAL_METHOD_A(Double,  jdouble,  Double)
2036
2037 jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
2038                                                                                    jclass clazz, jmethodID methodID,
2039                                                                                    ...)
2040 {
2041         java_handle_t *o;
2042         classinfo     *c;
2043         methodinfo    *m;
2044         java_handle_t *r;
2045         va_list        ap;
2046
2047         o = (java_handle_t *) obj;
2048         c = LLNI_classinfo_unwrap(clazz);
2049         m = (methodinfo *) methodID;
2050
2051         va_start(ap, methodID);
2052         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
2053         va_end(ap);
2054
2055         return _Jv_JNI_NewLocalRef(env, (jobject) r);
2056 }
2057
2058
2059 jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
2060                                                                                         jclass clazz, jmethodID methodID,
2061                                                                                         va_list args)
2062 {
2063         java_handle_t *o;
2064         classinfo     *c;
2065         methodinfo    *m;
2066         java_handle_t *r;
2067
2068         o = (java_handle_t *) obj;
2069         c = LLNI_classinfo_unwrap(clazz);
2070         m = (methodinfo *) methodID;
2071
2072         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
2073
2074         return _Jv_JNI_NewLocalRef(env, (jobject) r);
2075 }
2076
2077
2078 jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
2079                                                                                         jclass clazz, jmethodID methodID,
2080                                                                                         const jvalue *args)
2081 {
2082         log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
2083
2084         return _Jv_JNI_NewLocalRef(env, NULL);
2085 }
2086
2087
2088 void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
2089                                                                           jmethodID methodID, ...)
2090 {
2091         java_handle_t *o;
2092         classinfo     *c;
2093         methodinfo    *m;
2094         va_list        ap;
2095
2096         o = (java_handle_t *) obj;
2097         c = LLNI_classinfo_unwrap(clazz);
2098         m = (methodinfo *) methodID;
2099
2100         va_start(ap, methodID);
2101         _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
2102         va_end(ap);
2103 }
2104
2105
2106 void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
2107                                                                            jmethodID methodID, va_list args)
2108 {
2109         java_handle_t *o;
2110         classinfo     *c;
2111         methodinfo    *m;
2112
2113         o = (java_handle_t *) obj;
2114         c = LLNI_classinfo_unwrap(clazz);
2115         m = (methodinfo *) methodID;
2116
2117         _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
2118 }
2119
2120
2121 void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
2122                                                                            jmethodID methodID, const jvalue * args)
2123 {       
2124         java_handle_t *o;
2125         classinfo     *c;
2126         methodinfo    *m;
2127
2128         o = (java_handle_t *) obj;
2129         c = LLNI_classinfo_unwrap(clazz);
2130         m = (methodinfo *) methodID;
2131
2132         _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
2133 }
2134
2135
2136 /* Accessing Fields of Objects ************************************************/
2137
2138 /* GetFieldID ******************************************************************
2139
2140    Returns the field ID for an instance (nonstatic) field of a
2141    class. The field is specified by its name and signature. The
2142    Get<type>Field and Set<type>Field families of accessor functions
2143    use field IDs to retrieve object fields.
2144
2145 *******************************************************************************/
2146
2147 jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
2148                                                         const char *sig)
2149 {
2150         classinfo *c;
2151         fieldinfo *f;
2152         utf       *uname;
2153         utf       *udesc;
2154
2155         STATISTICS(jniinvokation());
2156
2157         c = LLNI_classinfo_unwrap(clazz);
2158
2159         /* XXX NPE check? */
2160
2161         uname = utf_new_char((char *) name);
2162         udesc = utf_new_char((char *) sig);
2163
2164         f = class_findfield(c, uname, udesc); 
2165         
2166         if (f == NULL)
2167                 exceptions_throw_nosuchfielderror(c, uname);  
2168
2169         return (jfieldID) f;
2170 }
2171
2172
2173 /* Get<type>Field Routines *****************************************************
2174
2175    This family of accessor routines returns the value of an instance
2176    (nonstatic) field of an object. The field to access is specified by
2177    a field ID obtained by calling GetFieldID().
2178
2179 *******************************************************************************/
2180
2181 #define JNI_GET_FIELD(name, type, intern)                                 \
2182 type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
2183 {                                                                         \
2184         intern ret;                                                           \
2185                                                                           \
2186         STATISTICS(jniinvokation());                                          \
2187                                                                           \
2188         ret = GET_FIELD(obj, intern, fieldID);                                \
2189                                                                           \
2190         return (type) ret;                                                    \
2191 }
2192
2193 JNI_GET_FIELD(Boolean, jboolean, s4)
2194 JNI_GET_FIELD(Byte,    jbyte,    s4)
2195 JNI_GET_FIELD(Char,    jchar,    s4)
2196 JNI_GET_FIELD(Short,   jshort,   s4)
2197 JNI_GET_FIELD(Int,     jint,     s4)
2198 JNI_GET_FIELD(Long,    jlong,    s8)
2199 JNI_GET_FIELD(Float,   jfloat,   float)
2200 JNI_GET_FIELD(Double,  jdouble,  double)
2201
2202
2203 jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
2204 {
2205         java_handle_t *o;
2206
2207         STATISTICS(jniinvokation());
2208
2209 #warning this needs to be fixed
2210         o = GET_FIELD(obj, java_handle_t*, fieldID);
2211
2212         return _Jv_JNI_NewLocalRef(env, (jobject) o);
2213 }
2214
2215
2216 /* Set<type>Field Routines *****************************************************
2217
2218    This family of accessor routines sets the value of an instance
2219    (nonstatic) field of an object. The field to access is specified by
2220    a field ID obtained by calling GetFieldID().
2221
2222 *******************************************************************************/
2223
2224 #define JNI_SET_FIELD(name, type, intern)                                 \
2225 void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID, \
2226                                                           type value)                                 \
2227 {                                                                         \
2228         STATISTICS(jniinvokation());                                          \
2229                                                                           \
2230         SET_FIELD(obj, intern, fieldID, value);                               \
2231 }
2232
2233 JNI_SET_FIELD(Boolean, jboolean, s4)
2234 JNI_SET_FIELD(Byte,    jbyte,    s4)
2235 JNI_SET_FIELD(Char,    jchar,    s4)
2236 JNI_SET_FIELD(Short,   jshort,   s4)
2237 JNI_SET_FIELD(Int,     jint,     s4)
2238 JNI_SET_FIELD(Long,    jlong,    s8)
2239 JNI_SET_FIELD(Float,   jfloat,   float)
2240 JNI_SET_FIELD(Double,  jdouble,  double)
2241
2242
2243 void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
2244                                                         jobject value)
2245 {
2246         STATISTICS(jniinvokation());
2247
2248 #warning this needs to be fixed
2249         SET_FIELD(obj, java_handle_t*, fieldID, value);
2250 }
2251
2252
2253 /* Calling Static Methods *****************************************************/
2254
2255 /* GetStaticMethodID ***********************************************************
2256
2257    Returns the method ID for a static method of a class. The method is
2258    specified by its name and signature.
2259
2260    GetStaticMethodID() causes an uninitialized class to be
2261    initialized.
2262
2263 *******************************************************************************/
2264
2265 jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
2266                                                                         const char *sig)
2267 {
2268         classinfo  *c;
2269         utf        *uname;
2270         utf        *udesc;
2271         methodinfo *m;
2272
2273         STATISTICS(jniinvokation());
2274
2275         c = LLNI_classinfo_unwrap(clazz);
2276
2277         if (!c)
2278                 return NULL;
2279
2280         if (!(c->state & CLASS_INITIALIZED))
2281                 if (!initialize_class(c))
2282                         return NULL;
2283
2284         /* try to get the static method of the class */
2285
2286         uname = utf_new_char((char *) name);
2287         udesc = utf_new_char((char *) sig);
2288
2289         m = class_resolvemethod(c, uname, udesc);
2290
2291         if ((m == NULL) || !(m->flags & ACC_STATIC)) {
2292                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
2293
2294                 return NULL;
2295         }
2296
2297         return (jmethodID) m;
2298 }
2299
2300
2301 #define JNI_CALL_STATIC_METHOD(name, type, intern)               \
2302 type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
2303                                                                           jmethodID methodID, ...)   \
2304 {                                                                \
2305         methodinfo *m;                                               \
2306         va_list     ap;                                              \
2307         type        res;                                             \
2308                                                                  \
2309         m = (methodinfo *) methodID;                                 \
2310                                                                  \
2311         va_start(ap, methodID);                                      \
2312         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap);       \
2313         va_end(ap);                                                  \
2314                                                                  \
2315         return res;                                                  \
2316 }
2317
2318 JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
2319 JNI_CALL_STATIC_METHOD(Byte,    jbyte,    Int)
2320 JNI_CALL_STATIC_METHOD(Char,    jchar,    Int)
2321 JNI_CALL_STATIC_METHOD(Short,   jshort,   Int)
2322 JNI_CALL_STATIC_METHOD(Int,     jint,     Int)
2323 JNI_CALL_STATIC_METHOD(Long,    jlong,    Long)
2324 JNI_CALL_STATIC_METHOD(Float,   jfloat,   Float)
2325 JNI_CALL_STATIC_METHOD(Double,  jdouble,  Double)
2326
2327
2328 #define JNI_CALL_STATIC_METHOD_V(name, type, intern)                     \
2329 type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz,        \
2330                                                                            jmethodID methodID, va_list args) \
2331 {                                                                        \
2332         methodinfo *m;                                                       \
2333         type        res;                                                     \
2334                                                                          \
2335         m = (methodinfo *) methodID;                                         \
2336                                                                          \
2337         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args);             \
2338                                                                          \
2339         return res;                                                          \
2340 }
2341
2342 JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
2343 JNI_CALL_STATIC_METHOD_V(Byte,    jbyte,    Int)
2344 JNI_CALL_STATIC_METHOD_V(Char,    jchar,    Int)
2345 JNI_CALL_STATIC_METHOD_V(Short,   jshort,   Int)
2346 JNI_CALL_STATIC_METHOD_V(Int,     jint,     Int)
2347 JNI_CALL_STATIC_METHOD_V(Long,    jlong,    Long)
2348 JNI_CALL_STATIC_METHOD_V(Float,   jfloat,   Float)
2349 JNI_CALL_STATIC_METHOD_V(Double,  jdouble,  Double)
2350
2351
2352 #define JNI_CALL_STATIC_METHOD_A(name, type, intern)                           \
2353 type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz,              \
2354                                                                            jmethodID methodID, const jvalue *args) \
2355 {                                                                              \
2356         methodinfo *m;                                                             \
2357         type        res;                                                           \
2358                                                                                \
2359         m = (methodinfo *) methodID;                                               \
2360                                                                                \
2361         res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args);                  \
2362                                                                                \
2363         return res;                                                                \
2364 }
2365
2366 JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
2367 JNI_CALL_STATIC_METHOD_A(Byte,    jbyte,    Int)
2368 JNI_CALL_STATIC_METHOD_A(Char,    jchar,    Int)
2369 JNI_CALL_STATIC_METHOD_A(Short,   jshort,   Int)
2370 JNI_CALL_STATIC_METHOD_A(Int,     jint,     Int)
2371 JNI_CALL_STATIC_METHOD_A(Long,    jlong,    Long)
2372 JNI_CALL_STATIC_METHOD_A(Float,   jfloat,   Float)
2373 JNI_CALL_STATIC_METHOD_A(Double,  jdouble,  Double)
2374
2375
2376 jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
2377                                                                            jmethodID methodID, ...)
2378 {
2379         methodinfo    *m;
2380         java_handle_t *o;
2381         va_list        ap;
2382
2383         m = (methodinfo *) methodID;
2384
2385         va_start(ap, methodID);
2386         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
2387         va_end(ap);
2388
2389         return _Jv_JNI_NewLocalRef(env, (jobject) o);
2390 }
2391
2392
2393 jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
2394                                                                                 jmethodID methodID, va_list args)
2395 {
2396         methodinfo    *m;
2397         java_handle_t *o;
2398
2399         m = (methodinfo *) methodID;
2400
2401         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
2402
2403         return _Jv_JNI_NewLocalRef(env, (jobject) o);
2404 }
2405
2406
2407 jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
2408                                                                                 jmethodID methodID, const jvalue *args)
2409 {
2410         methodinfo    *m;
2411         java_handle_t *o;
2412
2413         m = (methodinfo *) methodID;
2414
2415         o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
2416
2417         return _Jv_JNI_NewLocalRef(env, (jobject) o);
2418 }
2419
2420
2421 void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
2422                                                                   jmethodID methodID, ...)
2423 {
2424         methodinfo *m;
2425         va_list     ap;
2426
2427         m = (methodinfo *) methodID;
2428
2429         va_start(ap, methodID);
2430         _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
2431         va_end(ap);
2432 }
2433
2434
2435 void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
2436                                                                    jmethodID methodID, va_list args)
2437 {
2438         methodinfo *m;
2439
2440         m = (methodinfo *) methodID;
2441
2442         _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
2443 }
2444
2445
2446 void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
2447                                                                    jmethodID methodID, const jvalue * args)
2448 {
2449         methodinfo *m;
2450
2451         m = (methodinfo *) methodID;
2452
2453         _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
2454 }
2455
2456
2457 /* Accessing Static Fields ****************************************************/
2458
2459 /* GetStaticFieldID ************************************************************
2460
2461    Returns the field ID for a static field of a class. The field is
2462    specified by its name and signature. The GetStatic<type>Field and
2463    SetStatic<type>Field families of accessor functions use field IDs
2464    to retrieve static fields.
2465
2466 *******************************************************************************/
2467
2468 jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
2469                                                                   const char *sig)
2470 {
2471         classinfo *c;
2472         fieldinfo *f;
2473         utf       *uname;
2474         utf       *usig;
2475
2476         STATISTICS(jniinvokation());
2477
2478         c = LLNI_classinfo_unwrap(clazz);
2479
2480         uname = utf_new_char((char *) name);
2481         usig  = utf_new_char((char *) sig);
2482
2483         f = class_findfield(c, uname, usig);
2484         
2485         if (f == NULL)
2486                 exceptions_throw_nosuchfielderror(c, uname);
2487
2488         return (jfieldID) f;
2489 }
2490
2491
2492 /* GetStatic<type>Field ********************************************************
2493
2494    This family of accessor routines returns the value of a static
2495    field of an object.
2496
2497 *******************************************************************************/
2498
2499 #define JNI_GET_STATIC_FIELD(name, type, field)                \
2500 type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
2501                                                                         jfieldID fieldID)          \
2502 {                                                              \
2503         classinfo *c;                                              \
2504         fieldinfo *f;                                              \
2505                                                                \
2506         STATISTICS(jniinvokation());                               \
2507                                                                \
2508         c = LLNI_classinfo_unwrap(clazz);                          \
2509         f = (fieldinfo *) fieldID;                                 \
2510                                                                \
2511         if (!(c->state & CLASS_INITIALIZED))                       \
2512                 if (!initialize_class(c))                              \
2513                         return 0;                                          \
2514                                                                \
2515         return f->value->field;                                    \
2516 }
2517
2518 JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
2519 JNI_GET_STATIC_FIELD(Byte,    jbyte,    i)
2520 JNI_GET_STATIC_FIELD(Char,    jchar,    i)
2521 JNI_GET_STATIC_FIELD(Short,   jshort,   i)
2522 JNI_GET_STATIC_FIELD(Int,     jint,     i)
2523 JNI_GET_STATIC_FIELD(Long,    jlong,    l)
2524 JNI_GET_STATIC_FIELD(Float,   jfloat,   f)
2525 JNI_GET_STATIC_FIELD(Double,  jdouble,  d)
2526
2527
2528 jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
2529                                                                          jfieldID fieldID)
2530 {
2531         classinfo *c;
2532         fieldinfo *f;
2533
2534         STATISTICS(jniinvokation());
2535
2536         c = LLNI_classinfo_unwrap(clazz);
2537         f = (fieldinfo *) fieldID;
2538
2539         if (!(c->state & CLASS_INITIALIZED))
2540                 if (!initialize_class(c))
2541                         return NULL;
2542
2543         return _Jv_JNI_NewLocalRef(env, f->value->a);
2544 }
2545
2546
2547 /*  SetStatic<type>Field *******************************************************
2548
2549         This family of accessor routines sets the value of a static field
2550         of an object.
2551
2552 *******************************************************************************/
2553
2554 #define JNI_SET_STATIC_FIELD(name, type, field)                \
2555 void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
2556                                                                         jfieldID fieldID,          \
2557                                                                         type value)                \
2558 {                                                              \
2559         classinfo *c;                                              \
2560         fieldinfo *f;                                              \
2561                                                                \
2562         STATISTICS(jniinvokation());                               \
2563                                                                \
2564         c = LLNI_classinfo_unwrap(clazz);                          \
2565         f = (fieldinfo *) fieldID;                                 \
2566                                                                \
2567         if (!(c->state & CLASS_INITIALIZED))                       \
2568                 if (!initialize_class(c))                              \
2569                         return;                                            \
2570                                                                \
2571         f->value->field = value;                                   \
2572 }
2573
2574 JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
2575 JNI_SET_STATIC_FIELD(Byte,    jbyte,    i)
2576 JNI_SET_STATIC_FIELD(Char,    jchar,    i)
2577 JNI_SET_STATIC_FIELD(Short,   jshort,   i)
2578 JNI_SET_STATIC_FIELD(Int,     jint,     i)
2579 JNI_SET_STATIC_FIELD(Long,    jlong,    l)
2580 JNI_SET_STATIC_FIELD(Float,   jfloat,   f)
2581 JNI_SET_STATIC_FIELD(Double,  jdouble,  d)
2582
2583
2584 void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
2585                                                                   jobject value)
2586 {
2587         classinfo *c;
2588         fieldinfo *f;
2589
2590         STATISTICS(jniinvokation());
2591
2592         c = LLNI_classinfo_unwrap(clazz);
2593         f = (fieldinfo *) fieldID;
2594
2595         if (!(c->state & CLASS_INITIALIZED))
2596                 if (!initialize_class(c))
2597                         return;
2598
2599         f->value->a = value;
2600 }
2601
2602
2603 /* String Operations **********************************************************/
2604
2605 /* NewString *******************************************************************
2606
2607    Create new java.lang.String object from an array of Unicode
2608    characters.
2609
2610 *******************************************************************************/
2611
2612 jstring _Jv_JNI_NewString(JNIEnv *env, const jchar *buf, jsize len)
2613 {
2614         java_lang_String        *s;
2615         java_handle_chararray_t *a;
2616         u4                       i;
2617
2618         STATISTICS(jniinvokation());
2619         
2620         s = (java_lang_String *) builtin_new(class_java_lang_String);
2621         a = builtin_newarray_char(len);
2622
2623         /* javastring or characterarray could not be created */
2624         if ((a == NULL) || (s == NULL))
2625                 return NULL;
2626
2627         /* copy text */
2628         for (i = 0; i < len; i++)
2629                 LLNI_array_direct(a, i) = buf[i];
2630
2631         LLNI_field_set_ref(s, value , a);
2632         LLNI_field_set_val(s, offset, 0);
2633         LLNI_field_set_val(s, count , len);
2634
2635         return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
2636 }
2637
2638
2639 static jchar emptyStringJ[]={0,0};
2640
2641 /* GetStringLength *************************************************************
2642
2643    Returns the length (the count of Unicode characters) of a Java
2644    string.
2645
2646 *******************************************************************************/
2647
2648 jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
2649 {
2650         java_lang_String *s;
2651         jsize             len;
2652
2653         TRACEJNICALLS("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str);
2654
2655         s = (java_lang_String *) str;
2656
2657         LLNI_field_get_val(s, count, len);
2658
2659         return len;
2660 }
2661
2662
2663 /********************  convertes javastring to u2-array ****************************/
2664         
2665 u2 *javastring_tou2(jstring so) 
2666 {
2667         java_lang_String        *s;
2668         java_handle_chararray_t *a;
2669         u2                      *stringbuffer;
2670         u4                       i;
2671         int32_t                  count;
2672         int32_t                  offset;
2673
2674         STATISTICS(jniinvokation());
2675         
2676         s = (java_lang_String *) so;
2677
2678         if (!s)
2679                 return NULL;
2680
2681         LLNI_field_get_ref(s, value, a);
2682
2683         if (!a)
2684                 return NULL;
2685
2686         LLNI_field_get_val(s, count, count);
2687         LLNI_field_get_val(s, offset, offset);
2688
2689         /* allocate memory */
2690
2691         stringbuffer = MNEW(u2, count + 1);
2692
2693         /* copy text */
2694
2695         for (i = 0; i < count; i++)
2696                 stringbuffer[i] = LLNI_array_direct(a, offset + i);
2697         
2698         /* terminate string */
2699
2700         stringbuffer[i] = '\0';
2701
2702         return stringbuffer;
2703 }
2704
2705
2706 /* GetStringChars **************************************************************
2707
2708    Returns a pointer to the array of Unicode characters of the
2709    string. This pointer is valid until ReleaseStringChars() is called.
2710
2711 *******************************************************************************/
2712
2713 const jchar *_Jv_JNI_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
2714 {       
2715         jchar *jc;
2716
2717         STATISTICS(jniinvokation());
2718
2719         jc = javastring_tou2(str);
2720
2721         if (jc) {
2722                 if (isCopy)
2723                         *isCopy = JNI_TRUE;
2724
2725                 return jc;
2726         }
2727
2728         if (isCopy)
2729                 *isCopy = JNI_TRUE;
2730
2731         return emptyStringJ;
2732 }
2733
2734
2735 /* ReleaseStringChars **********************************************************
2736
2737    Informs the VM that the native code no longer needs access to
2738    chars. The chars argument is a pointer obtained from string using
2739    GetStringChars().
2740
2741 *******************************************************************************/
2742
2743 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
2744 {
2745         java_lang_String *s;
2746
2747         STATISTICS(jniinvokation());
2748
2749         if (chars == emptyStringJ)
2750                 return;
2751
2752         s = (java_lang_String *) str;
2753
2754         MFREE(((jchar *) chars), jchar, LLNI_field_direct(s, count) + 1);
2755 }
2756
2757
2758 /* NewStringUTF ****************************************************************
2759
2760    Constructs a new java.lang.String object from an array of UTF-8
2761    characters.
2762
2763 *******************************************************************************/
2764
2765 jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
2766 {
2767         java_lang_String *s;
2768
2769         TRACEJNICALLS("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes);
2770
2771         s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
2772
2773     return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
2774 }
2775
2776
2777 /****************** returns the utf8 length in bytes of a string *******************/
2778
2779 jsize _Jv_JNI_GetStringUTFLength(JNIEnv *env, jstring string)
2780 {   
2781         java_lang_String *s;
2782         s4                length;
2783
2784         TRACEJNICALLS("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string);
2785
2786         s = (java_lang_String *) string;
2787
2788         length = u2_utflength(LLNI_field_direct(s, value)->data, LLNI_field_direct(s, count));
2789
2790         return length;
2791 }
2792
2793
2794 /* GetStringUTFChars ***********************************************************
2795
2796    Returns a pointer to an array of UTF-8 characters of the
2797    string. This array is valid until it is released by
2798    ReleaseStringUTFChars().
2799
2800 *******************************************************************************/
2801
2802 const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
2803                                                                           jboolean *isCopy)
2804 {
2805         utf *u;
2806
2807         STATISTICS(jniinvokation());
2808
2809         if (string == NULL)
2810                 return "";
2811
2812         if (isCopy)
2813                 *isCopy = JNI_TRUE;
2814         
2815         u = javastring_toutf((java_handle_t *) string, false);
2816
2817         if (u != NULL)
2818                 return u->text;
2819
2820         return "";
2821 }
2822
2823
2824 /* ReleaseStringUTFChars *******************************************************
2825
2826    Informs the VM that the native code no longer needs access to
2827    utf. The utf argument is a pointer derived from string using
2828    GetStringUTFChars().
2829
2830 *******************************************************************************/
2831
2832 void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
2833 {
2834         STATISTICS(jniinvokation());
2835
2836     /* XXX we don't release utf chars right now, perhaps that should be done 
2837            later. Since there is always one reference the garbage collector will
2838            never get them */
2839 }
2840
2841
2842 /* Array Operations ***********************************************************/
2843
2844 /* GetArrayLength **************************************************************
2845
2846    Returns the number of elements in the array.
2847
2848 *******************************************************************************/
2849
2850 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
2851 {
2852         java_handle_t *a;
2853         jsize          size;
2854
2855         STATISTICS(jniinvokation());
2856
2857         a = (java_handle_t *) array;
2858
2859         size = LLNI_array_size(a);
2860
2861         return size;
2862 }
2863
2864
2865 /* NewObjectArray **************************************************************
2866
2867    Constructs a new array holding objects in class elementClass. All
2868    elements are initially set to initialElement.
2869
2870 *******************************************************************************/
2871
2872 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
2873                                                                         jclass elementClass, jobject initialElement)
2874 {
2875         classinfo                 *c;
2876         java_handle_t             *o;
2877         java_handle_objectarray_t *oa;
2878         s4                         i;
2879
2880         STATISTICS(jniinvokation());
2881
2882         c = LLNI_classinfo_unwrap(elementClass);
2883         o = (java_handle_t *) initialElement;
2884
2885         if (length < 0) {
2886                 exceptions_throw_negativearraysizeexception();
2887                 return NULL;
2888         }
2889
2890     oa = builtin_anewarray(length, c);
2891
2892         if (oa == NULL)
2893                 return NULL;
2894
2895         /* set all elements to initialElement */
2896
2897         for (i = 0; i < length; i++)
2898                 LLNI_objectarray_element_set(oa, i, o);
2899
2900         return (jobjectArray) _Jv_JNI_NewLocalRef(env, (jobject) oa);
2901 }
2902
2903
2904 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
2905                                                                           jsize index)
2906 {
2907         java_handle_objectarray_t *oa;
2908         java_handle_t             *o;
2909
2910         STATISTICS(jniinvokation());
2911
2912         oa = (java_handle_objectarray_t *) array;
2913
2914         if (index >= LLNI_array_size(oa)) {
2915                 exceptions_throw_arrayindexoutofboundsexception();
2916                 return NULL;
2917         }
2918
2919         LLNI_objectarray_element_get(oa, index, o);
2920
2921         return _Jv_JNI_NewLocalRef(env, (jobject) o);
2922 }
2923
2924
2925 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
2926                                                                    jsize index, jobject val)
2927 {
2928         java_handle_objectarray_t *oa;
2929         java_handle_t             *o;
2930
2931         STATISTICS(jniinvokation());
2932
2933         oa = (java_handle_objectarray_t *) array;
2934         o  = (java_handle_t *) val;
2935
2936         if (index >= LLNI_array_size(oa)) {
2937                 exceptions_throw_arrayindexoutofboundsexception();
2938                 return;
2939         }
2940
2941         /* check if the class of value is a subclass of the element class
2942            of the array */
2943
2944         if (!builtin_canstore(oa, o))
2945                 return;
2946
2947         LLNI_objectarray_element_set(oa, index, o);
2948 }
2949
2950
2951 #define JNI_NEW_ARRAY(name, type, intern)                \
2952 type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
2953 {                                                        \
2954         java_handle_##intern##array_t *a;                    \
2955                                                          \
2956         STATISTICS(jniinvokation());                         \
2957                                                          \
2958         if (len < 0) {                                       \
2959                 exceptions_throw_negativearraysizeexception();   \
2960                 return NULL;                                     \
2961         }                                                    \
2962                                                          \
2963         a = builtin_newarray_##intern(len);                  \
2964                                                          \
2965         return (type) _Jv_JNI_NewLocalRef(env, (jobject) a); \
2966 }
2967
2968 JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
2969 JNI_NEW_ARRAY(Byte,    jbyteArray,    byte)
2970 JNI_NEW_ARRAY(Char,    jcharArray,    char)
2971 JNI_NEW_ARRAY(Short,   jshortArray,   byte)
2972 JNI_NEW_ARRAY(Int,     jintArray,     int)
2973 JNI_NEW_ARRAY(Long,    jlongArray,    long)
2974 JNI_NEW_ARRAY(Float,   jfloatArray,   float)
2975 JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
2976
2977
2978 /* Get<PrimitiveType>ArrayElements *********************************************
2979
2980    A family of functions that returns the body of the primitive array.
2981
2982 *******************************************************************************/
2983
2984 #define JNI_GET_ARRAY_ELEMENTS(name, type, intern)                     \
2985 type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
2986                                                                                  jboolean *isCopy)             \
2987 {                                                                      \
2988         java_handle_##intern##array_t *a;                                  \
2989                                                                        \
2990         STATISTICS(jniinvokation());                                       \
2991                                                                        \
2992         a = (java_handle_##intern##array_t *) array;                       \
2993                                                                        \
2994         if (isCopy)                                                        \
2995                 *isCopy = JNI_FALSE;                                           \
2996                                                                        \
2997         return LLNI_array_data(a);                                         \
2998 }
2999
3000 JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
3001 JNI_GET_ARRAY_ELEMENTS(Byte,    jbyte,    byte)
3002 JNI_GET_ARRAY_ELEMENTS(Char,    jchar,    char)
3003 JNI_GET_ARRAY_ELEMENTS(Short,   jshort,   short)
3004 JNI_GET_ARRAY_ELEMENTS(Int,     jint,     int)
3005 JNI_GET_ARRAY_ELEMENTS(Long,    jlong,    long)
3006 JNI_GET_ARRAY_ELEMENTS(Float,   jfloat,   float)
3007 JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
3008
3009
3010 /* Release<PrimitiveType>ArrayElements *****************************************
3011
3012    A family of functions that informs the VM that the native code no
3013    longer needs access to elems. The elems argument is a pointer
3014    derived from array using the corresponding
3015    Get<PrimitiveType>ArrayElements() function. If necessary, this
3016    function copies back all changes made to elems to the original
3017    array.
3018
3019 *******************************************************************************/
3020
3021 #define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2)            \
3022 void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
3023                                                                                   type *elems, jint mode)          \
3024 {                                                                          \
3025         java_handle_##intern##array_t *a;                                      \
3026                                                                            \
3027         STATISTICS(jniinvokation());                                           \
3028                                                                            \
3029         a = (java_handle_##intern##array_t *) array;                           \
3030                                                                            \
3031         if (elems != LLNI_array_data(a)) {                                     \
3032                 switch (mode) {                                                    \
3033                 case JNI_COMMIT:                                                   \
3034                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
3035                         break;                                                         \
3036                 case 0:                                                            \
3037                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
3038                         /* XXX TWISTI how should it be freed? */                       \
3039                         break;                                                         \
3040                 case JNI_ABORT:                                                    \
3041                         /* XXX TWISTI how should it be freed? */                       \
3042                         break;                                                         \
3043                 }                                                                  \
3044         }                                                                      \
3045 }
3046
3047 JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
3048 JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
3049 JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
3050 JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
3051 JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
3052 JNI_RELEASE_ARRAY_ELEMENTS(Long,    jlong,    long,    s8)
3053 JNI_RELEASE_ARRAY_ELEMENTS(Float,   jfloat,   float,   float)
3054 JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
3055
3056
3057 /*  Get<PrimitiveType>ArrayRegion **********************************************
3058
3059         A family of functions that copies a region of a primitive array
3060         into a buffer.
3061
3062 *******************************************************************************/
3063
3064 #define JNI_GET_ARRAY_REGION(name, type, intern, intern2)               \
3065 void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
3066                                                                         jsize start, jsize len, type *buf)  \
3067 {                                                                       \
3068         java_handle_##intern##array_t *a;                                   \
3069                                                                         \
3070         STATISTICS(jniinvokation());                                        \
3071                                                                         \
3072         a = (java_handle_##intern##array_t *) array;                        \
3073                                                                         \
3074         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
3075                 exceptions_throw_arrayindexoutofboundsexception();              \
3076         else                                                                \
3077                 MCOPY(buf, &LLNI_array_direct(a, start), intern2, len);         \
3078 }
3079
3080 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
3081 JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
3082 JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
3083 JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
3084 JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
3085 JNI_GET_ARRAY_REGION(Long,    jlong,    long,    s8)
3086 JNI_GET_ARRAY_REGION(Float,   jfloat,   float,   float)
3087 JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
3088
3089
3090 /*  Set<PrimitiveType>ArrayRegion **********************************************
3091
3092         A family of functions that copies back a region of a primitive
3093         array from a buffer.
3094
3095 *******************************************************************************/
3096
3097 #define JNI_SET_ARRAY_REGION(name, type, intern, intern2)                    \
3098 void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
3099                                                                         jsize start, jsize len, const type *buf) \
3100 {                                                                            \
3101         java_handle_##intern##array_t *a;                                        \
3102                                                                              \
3103         STATISTICS(jniinvokation());                                             \
3104                                                                              \
3105         a = (java_handle_##intern##array_t *) array;                             \
3106                                                                              \
3107         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a)))      \
3108                 exceptions_throw_arrayindexoutofboundsexception();                   \
3109         else                                                                     \
3110                 MCOPY(&LLNI_array_direct(a, start), buf, intern2, len);              \
3111 }
3112
3113 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
3114 JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
3115 JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
3116 JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
3117 JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
3118 JNI_SET_ARRAY_REGION(Long,    jlong,    long,    s8)
3119 JNI_SET_ARRAY_REGION(Float,   jfloat,   float,   float)
3120 JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
3121
3122
3123 /* Registering Native Methods *************************************************/
3124
3125 /* RegisterNatives *************************************************************
3126
3127    Registers native methods with the class specified by the clazz
3128    argument. The methods parameter specifies an array of
3129    JNINativeMethod structures that contain the names, signatures, and
3130    function pointers of the native methods. The nMethods parameter
3131    specifies the number of native methods in the array.
3132
3133 *******************************************************************************/
3134
3135 jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
3136                                                          const JNINativeMethod *methods, jint nMethods)
3137 {
3138         classinfo *c;
3139
3140         STATISTICS(jniinvokation());
3141
3142         c = LLNI_classinfo_unwrap(clazz);
3143
3144         /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
3145         if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
3146         */
3147
3148         native_method_register(c->name, methods, nMethods);
3149
3150     return 0;
3151 }
3152
3153
3154 /* UnregisterNatives ***********************************************************
3155
3156    Unregisters native methods of a class. The class goes back to the
3157    state before it was linked or registered with its native method
3158    functions.
3159
3160    This function should not be used in normal native code. Instead, it
3161    provides special programs a way to reload and relink native
3162    libraries.
3163
3164 *******************************************************************************/
3165
3166 jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
3167 {
3168         STATISTICS(jniinvokation());
3169
3170         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
3171
3172     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
3173
3174     return 0;
3175 }
3176
3177
3178 /* Monitor Operations *********************************************************/
3179
3180 /* MonitorEnter ****************************************************************
3181
3182    Enters the monitor associated with the underlying Java object
3183    referred to by obj.
3184
3185 *******************************************************************************/
3186
3187 jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
3188 {
3189         STATISTICS(jniinvokation());
3190
3191         if (obj == NULL) {
3192                 exceptions_throw_nullpointerexception();
3193                 return JNI_ERR;
3194         }
3195
3196         LOCK_MONITOR_ENTER(obj);
3197
3198         return JNI_OK;
3199 }
3200
3201
3202 /* MonitorExit *****************************************************************
3203
3204    The current thread must be the owner of the monitor associated with
3205    the underlying Java object referred to by obj. The thread
3206    decrements the counter indicating the number of times it has
3207    entered this monitor. If the value of the counter becomes zero, the
3208    current thread releases the monitor.
3209
3210 *******************************************************************************/
3211
3212 jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
3213 {
3214         STATISTICS(jniinvokation());
3215
3216         if (obj == NULL) {
3217                 exceptions_throw_nullpointerexception();
3218                 return JNI_ERR;
3219         }
3220
3221         LOCK_MONITOR_EXIT(obj);
3222
3223         return JNI_OK;
3224 }
3225
3226
3227 /* JavaVM Interface ***********************************************************/
3228
3229 /* GetJavaVM *******************************************************************
3230
3231    Returns the Java VM interface (used in the Invocation API)
3232    associated with the current thread. The result is placed at the
3233    location pointed to by the second argument, vm.
3234
3235 *******************************************************************************/
3236
3237 jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **vm)
3238 {
3239         STATISTICS(jniinvokation());
3240
3241     *vm = (JavaVM *) _Jv_jvm;
3242
3243         return 0;
3244 }
3245
3246
3247 /* GetStringRegion *************************************************************
3248
3249    Copies len number of Unicode characters beginning at offset start
3250    to the given buffer buf.
3251
3252    Throws StringIndexOutOfBoundsException on index overflow.
3253
3254 *******************************************************************************/
3255
3256 void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
3257                                                          jchar *buf)
3258 {
3259         java_lang_String        *s;
3260         java_handle_chararray_t *ca;
3261
3262         STATISTICS(jniinvokation());
3263
3264         s  = (java_lang_String *) str;
3265         LLNI_field_get_ref(s, value, ca);
3266
3267         if ((start < 0) || (len < 0) || (start > LLNI_field_direct(s, count)) ||
3268                 (start + len > LLNI_field_direct(s, count))) {
3269                 exceptions_throw_stringindexoutofboundsexception();
3270                 return;
3271         }
3272
3273         MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
3274 }
3275
3276
3277 /* GetStringUTFRegion **********************************************************
3278
3279     Translates len number of Unicode characters beginning at offset
3280     start into UTF-8 format and place the result in the given buffer
3281     buf.
3282
3283     Throws StringIndexOutOfBoundsException on index overflow. 
3284
3285 *******************************************************************************/
3286
3287 void _Jv_JNI_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
3288                                                                 jsize len, char *buf)
3289 {
3290         java_lang_String        *s;
3291         java_handle_chararray_t *ca;
3292         s4                       i;
3293         int32_t                  count;
3294         int32_t                  offset;
3295
3296         TRACEJNICALLS("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf);
3297
3298         s  = (java_lang_String *) str;
3299         LLNI_field_get_ref(s, value, ca);
3300         LLNI_field_get_val(s, count, count);
3301         LLNI_field_get_val(s, offset, offset);
3302
3303         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3304                 exceptions_throw_stringindexoutofboundsexception();
3305                 return;
3306         }
3307
3308         for (i = 0; i < len; i++)
3309                 buf[i] = LLNI_array_direct(ca, offset + start + i);
3310
3311         buf[i] = '\0';
3312 }
3313
3314
3315 /* GetPrimitiveArrayCritical ***************************************************
3316
3317    Obtain a direct pointer to array elements.
3318
3319 *******************************************************************************/
3320
3321 void *_Jv_JNI_GetPrimitiveArrayCritical(JNIEnv *env, jarray array,
3322                                                                                 jboolean *isCopy)
3323 {
3324         java_handle_bytearray_t *ba;
3325         jbyte                   *bp;
3326
3327         ba = (java_handle_bytearray_t *) array;
3328
3329         /* do the same as Kaffe does */
3330
3331         bp = _Jv_JNI_GetByteArrayElements(env, (jbyteArray) ba, isCopy);
3332
3333         return (void *) bp;
3334 }
3335
3336
3337 /* ReleasePrimitiveArrayCritical ***********************************************
3338
3339    No specific documentation.
3340
3341 *******************************************************************************/
3342
3343 void _Jv_JNI_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array,
3344                                                                                    void *carray, jint mode)
3345 {
3346         STATISTICS(jniinvokation());
3347
3348         /* do the same as Kaffe does */
3349
3350         _Jv_JNI_ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray,
3351                                                                          mode);
3352 }
3353
3354
3355 /* GetStringCritical ***********************************************************
3356
3357    The semantics of these two functions are similar to the existing
3358    Get/ReleaseStringChars functions.
3359
3360 *******************************************************************************/
3361
3362 const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
3363                                                                            jboolean *isCopy)
3364 {
3365         STATISTICS(jniinvokation());
3366
3367         return _Jv_JNI_GetStringChars(env, string, isCopy);
3368 }
3369
3370
3371 void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
3372                                                                    const jchar *cstring)
3373 {
3374         STATISTICS(jniinvokation());
3375
3376         _Jv_JNI_ReleaseStringChars(env, string, cstring);
3377 }
3378
3379
3380 jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
3381 {
3382         STATISTICS(jniinvokation());
3383
3384         log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!");
3385
3386         return obj;
3387 }
3388
3389
3390 void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
3391 {
3392         STATISTICS(jniinvokation());
3393
3394         log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME");
3395 }
3396
3397
3398 /* NewGlobalRef ****************************************************************
3399
3400    Creates a new global reference to the object referred to by the obj
3401    argument.
3402
3403 *******************************************************************************/
3404     
3405 jobject _Jv_JNI_NewGlobalRef(JNIEnv* env, jobject obj)
3406 {
3407         hashtable_global_ref_entry *gre;
3408         u4   key;                           /* hashkey                            */
3409         u4   slot;                          /* slot in hashtable                  */
3410         java_handle_t *o;
3411
3412         STATISTICS(jniinvokation());
3413
3414         o = (java_handle_t *) obj;
3415
3416         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
3417
3418         /* normally addresses are aligned to 4, 8 or 16 bytes */
3419
3420         key  = ((u4) (ptrint) obj) >> 4;           /* align to 16-byte boundaries */
3421         slot = key & (hashtable_global_ref->size - 1);
3422         gre  = hashtable_global_ref->ptr[slot];
3423         
3424         /* search external hash chain for the entry */
3425
3426         while (gre) {
3427                 if (gre->o == o) {
3428                         /* global object found, increment the reference */
3429
3430                         gre->refs++;
3431
3432                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3433
3434                         return obj;
3435                 }
3436
3437                 gre = gre->hashlink;                /* next element in external chain */
3438         }
3439
3440         /* global ref not found, create a new one */
3441
3442         gre = NEW(hashtable_global_ref_entry);
3443
3444 #if defined(ENABLE_GC_CACAO)
3445         /* register global ref with the GC */
3446
3447         gc_reference_register(&(gre->o));
3448 #endif
3449
3450         gre->o    = o;
3451         gre->refs = 1;
3452
3453         /* insert entry into hashtable */
3454
3455         gre->hashlink = hashtable_global_ref->ptr[slot];
3456
3457         hashtable_global_ref->ptr[slot] = gre;
3458
3459         /* update number of hashtable-entries */
3460
3461         hashtable_global_ref->entries++;
3462
3463         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3464
3465         return obj;
3466 }
3467
3468
3469 /* DeleteGlobalRef *************************************************************
3470
3471    Deletes the global reference pointed to by globalRef.
3472
3473 *******************************************************************************/
3474
3475 void _Jv_JNI_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
3476 {
3477         hashtable_global_ref_entry *gre;
3478         hashtable_global_ref_entry *prevgre;
3479         u4   key;                           /* hashkey                            */
3480         u4   slot;                          /* slot in hashtable                  */
3481         java_handle_t              *o;
3482
3483         STATISTICS(jniinvokation());
3484
3485         o = (java_handle_t *) globalRef;
3486
3487         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
3488
3489         /* normally addresses are aligned to 4, 8 or 16 bytes */
3490
3491         key  = ((u4) (ptrint) globalRef) >> 4;     /* align to 16-byte boundaries */
3492         slot = key & (hashtable_global_ref->size - 1);
3493         gre  = hashtable_global_ref->ptr[slot];
3494
3495         /* initialize prevgre */
3496
3497         prevgre = NULL;
3498
3499         /* search external hash chain for the entry */
3500
3501         while (gre) {
3502                 if (gre->o == o) {
3503                         /* global object found, decrement the reference count */
3504
3505                         gre->refs--;
3506
3507                         /* if reference count is 0, remove the entry */
3508
3509                         if (gre->refs == 0) {
3510                                 /* special handling if it's the first in the chain */
3511
3512                                 if (prevgre == NULL)
3513                                         hashtable_global_ref->ptr[slot] = gre->hashlink;
3514                                 else
3515                                         prevgre->hashlink = gre->hashlink;
3516
3517 #if defined(ENABLE_GC_CACAO)
3518                                 /* unregister global ref with the GC */
3519
3520                                 gc_reference_unregister(&(gre->o));
3521 #endif
3522
3523                                 FREE(gre, hashtable_global_ref_entry);
3524                         }
3525
3526                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3527
3528                         return;
3529                 }
3530
3531                 prevgre = gre;                    /* save current pointer for removal */
3532                 gre     = gre->hashlink;            /* next element in external chain */
3533         }
3534
3535         log_println("JNI-DeleteGlobalRef: global reference not found");
3536
3537         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3538 }
3539
3540
3541 /* ExceptionCheck **************************************************************
3542
3543    Returns JNI_TRUE when there is a pending exception; otherwise,
3544    returns JNI_FALSE.
3545
3546 *******************************************************************************/
3547
3548 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
3549 {
3550         java_handle_t *o;
3551
3552         STATISTICS(jniinvokation());
3553
3554         o = exceptions_get_exception();
3555
3556         return (o != NULL) ? JNI_TRUE : JNI_FALSE;
3557 }
3558
3559
3560 /* New JNI 1.4 functions ******************************************************/
3561
3562 /* NewDirectByteBuffer *********************************************************
3563
3564    Allocates and returns a direct java.nio.ByteBuffer referring to the
3565    block of memory starting at the memory address address and
3566    extending capacity bytes.
3567
3568 *******************************************************************************/
3569
3570 jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
3571 {
3572 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
3573         java_handle_t           *nbuf;
3574
3575 # if SIZEOF_VOID_P == 8
3576         gnu_classpath_Pointer64 *paddress;
3577 # else
3578         gnu_classpath_Pointer32 *paddress;
3579 # endif
3580
3581         STATISTICS(jniinvokation());
3582
3583         /* alocate a gnu.classpath.Pointer{32,64} object */
3584
3585 # if SIZEOF_VOID_P == 8
3586         if (!(paddress = (gnu_classpath_Pointer64 *)
3587                   builtin_new(class_gnu_classpath_Pointer64)))
3588 # else
3589         if (!(paddress = (gnu_classpath_Pointer32 *)
3590                   builtin_new(class_gnu_classpath_Pointer32)))
3591 # endif
3592                 return NULL;
3593
3594         /* fill gnu.classpath.Pointer{32,64} with address */
3595
3596         LLNI_field_set_val(paddress, data, (ptrint) address);
3597
3598         /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
3599
3600         nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
3601                                                          (jmethodID) dbbirw_init, NULL, paddress,
3602                                                          (jint) capacity, (jint) capacity, (jint) 0);
3603
3604         /* add local reference and return the value */
3605
3606         return _Jv_JNI_NewLocalRef(env, nbuf);
3607 #else
3608         vm_abort("_Jv_JNI_NewDirectByteBuffer: not implemented in this configuration");
3609
3610         /* keep compiler happy */
3611
3612         return NULL;
3613 #endif
3614 }
3615
3616
3617 /* GetDirectBufferAddress ******************************************************
3618
3619    Fetches and returns the starting address of the memory region
3620    referenced by the given direct java.nio.Buffer.
3621
3622 *******************************************************************************/
3623
3624 void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
3625 {
3626 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
3627         java_nio_DirectByteBufferImpl *nbuf;
3628 # if SIZEOF_VOID_P == 8
3629         gnu_classpath_Pointer64       *paddress;
3630 # else
3631         gnu_classpath_Pointer32       *paddress;
3632 # endif
3633         void                          *address;
3634
3635         STATISTICS(jniinvokation());
3636
3637         if (!builtin_instanceof(buf, class_java_nio_Buffer))
3638                 return NULL;
3639
3640         nbuf = (java_nio_DirectByteBufferImpl *) buf;
3641
3642 # if SIZEOF_VOID_P == 8
3643         LLNI_field_get_ref(nbuf, address, paddress);
3644         /* this was the cast to avaoid warning: (gnu_classpath_Pointer64 *) nbuf->address; */
3645 # else
3646         LLNI_field_get_ref(nbuf, address, paddress); 
3647         /* this was the cast to avaoid warning: (gnu_classpath_Pointer32 *) nbuf->address; */
3648 # endif
3649
3650         if (paddress == NULL)
3651                 return NULL;
3652
3653         LLNI_field_get_val(paddress, data, address);
3654         /* this was the cast to avaoid warning: (void *) paddress->data */
3655
3656         return address;
3657 #else
3658         vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
3659
3660         /* keep compiler happy */
3661
3662         return NULL;
3663 #endif
3664 }
3665
3666
3667 /* GetDirectBufferCapacity *****************************************************
3668
3669    Fetches and returns the capacity in bytes of the memory region
3670    referenced by the given direct java.nio.Buffer.
3671
3672 *******************************************************************************/
3673
3674 jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
3675 {
3676 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
3677         java_handle_t   *o;
3678         java_nio_Buffer *nbuf;
3679         jlong            capacity;
3680
3681         STATISTICS(jniinvokation());
3682
3683         o = (java_handle_t *) buf;
3684
3685         if (!builtin_instanceof(o, class_java_nio_DirectByteBufferImpl))
3686                 return -1;
3687
3688         nbuf = (java_nio_Buffer *) o;
3689
3690         LLNI_field_get_val(nbuf, cap, capacity);
3691
3692         return capacity;
3693 #else
3694         vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
3695
3696         /* keep compiler happy */
3697
3698         return 0;
3699 #endif
3700 }
3701
3702
3703 /* DestroyJavaVM ***************************************************************
3704
3705    Unloads a Java VM and reclaims its resources. Only the main thread
3706    can unload the VM. The system waits until the main thread is only
3707    remaining user thread before it destroys the VM.
3708
3709 *******************************************************************************/
3710
3711 jint _Jv_JNI_DestroyJavaVM(JavaVM *vm)
3712 {
3713         s4 status;
3714
3715         STATISTICS(jniinvokation());
3716
3717     status = vm_destroy(vm);
3718
3719         return status;
3720 }
3721
3722
3723 /* AttachCurrentThread *********************************************************
3724
3725    Attaches the current thread to a Java VM. Returns a JNI interface
3726    pointer in the JNIEnv argument.
3727
3728    Trying to attach a thread that is already attached is a no-op.
3729
3730    A native thread cannot be attached simultaneously to two Java VMs.
3731
3732    When a thread is attached to the VM, the context class loader is
3733    the bootstrap loader.
3734
3735 *******************************************************************************/
3736
3737 static s4 jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
3738 {
3739         JavaVMAttachArgs *vm_aargs;
3740
3741 #if defined(ENABLE_THREADS)
3742         if (threads_get_current_threadobject() == NULL) {
3743                 vm_aargs = (JavaVMAttachArgs *) thr_args;
3744
3745                 if (vm_aargs != NULL) {
3746                         if ((vm_aargs->version != JNI_VERSION_1_2) &&
3747                                 (vm_aargs->version != JNI_VERSION_1_4))
3748                                 return JNI_EVERSION;
3749                 }
3750
3751                 if (!threads_attach_current_thread(vm_aargs, false))
3752                         return JNI_ERR;
3753
3754                 if (!localref_table_init())
3755                         return JNI_ERR;
3756         }
3757 #endif
3758
3759         *p_env = _Jv_env;
3760
3761         return JNI_OK;
3762 }
3763
3764
3765 jint _Jv_JNI_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
3766 {
3767         STATISTICS(jniinvokation());
3768
3769         return jni_attach_current_thread(p_env, thr_args, false);
3770 }
3771
3772
3773 /* DetachCurrentThread *********************************************************
3774
3775    Detaches the current thread from a Java VM. All Java monitors held
3776    by this thread are released. All Java threads waiting for this
3777    thread to die are notified.
3778
3779    In JDK 1.1, the main thread cannot be detached from the VM. It must
3780    call DestroyJavaVM to unload the entire VM.
3781
3782    In the JDK, the main thread can be detached from the VM.
3783
3784    The main thread, which is the thread that created the Java VM,
3785    cannot be detached from the VM. Instead, the main thread must call
3786    JNI_DestroyJavaVM() to unload the entire VM.
3787
3788 *******************************************************************************/
3789
3790 jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
3791 {
3792 #if defined(ENABLE_THREADS)
3793         threadobject *thread;
3794
3795         STATISTICS(jniinvokation());
3796
3797         thread = threads_get_current_threadobject();
3798
3799         if (thread == NULL)
3800                 return JNI_ERR;
3801
3802         if (!localref_table_destroy())
3803                 return JNI_ERR;
3804
3805         if (!threads_detach_thread(thread))
3806                 return JNI_ERR;
3807 #endif
3808
3809         return JNI_OK;
3810 }
3811
3812
3813 /* GetEnv **********************************************************************
3814
3815    If the current thread is not attached to the VM, sets *env to NULL,
3816    and returns JNI_EDETACHED. If the specified version is not
3817    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
3818    sets *env to the appropriate interface, and returns JNI_OK.
3819
3820 *******************************************************************************/
3821
3822 jint _Jv_JNI_GetEnv(JavaVM *vm, void **env, jint version)
3823 {
3824         STATISTICS(jniinvokation());
3825
3826 #if defined(ENABLE_THREADS)
3827         if (threads_get_current_threadobject() == NULL) {
3828                 *env = NULL;
3829
3830                 return JNI_EDETACHED;
3831         }
3832 #endif
3833
3834         /* check the JNI version */
3835
3836         switch (version) {
3837         case JNI_VERSION_1_1:
3838         case JNI_VERSION_1_2:
3839         case JNI_VERSION_1_4:
3840                 *env = _Jv_env;
3841                 return JNI_OK;
3842
3843         default:
3844                 ;
3845         }
3846
3847 #if defined(ENABLE_JVMTI)
3848         if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
3849                 == JVMTI_VERSION_INTERFACE_JVMTI) {
3850
3851                 *env = (void *) jvmti_new_environment();
3852
3853                 if (env != NULL)
3854                         return JNI_OK;
3855         }
3856 #endif
3857         
3858         *env = NULL;
3859
3860         return JNI_EVERSION;
3861 }
3862
3863
3864 /* AttachCurrentThreadAsDaemon *************************************************
3865
3866    Same semantics as AttachCurrentThread, but the newly-created
3867    java.lang.Thread instance is a daemon.
3868
3869    If the thread has already been attached via either
3870    AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
3871    simply sets the value pointed to by penv to the JNIEnv of the
3872    current thread. In this case neither AttachCurrentThread nor this
3873    routine have any effect on the daemon status of the thread.
3874
3875 *******************************************************************************/
3876
3877 jint _Jv_JNI_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
3878 {
3879         STATISTICS(jniinvokation());
3880
3881         return jni_attach_current_thread(penv, args, true);
3882 }
3883
3884
3885 /* JNI invocation table *******************************************************/
3886
3887 const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
3888         NULL,
3889         NULL,
3890         NULL,
3891
3892         _Jv_JNI_DestroyJavaVM,
3893         _Jv_JNI_AttachCurrentThread,
3894         _Jv_JNI_DetachCurrentThread,
3895         _Jv_JNI_GetEnv,
3896         _Jv_JNI_AttachCurrentThreadAsDaemon
3897 };
3898
3899
3900 /* JNI function table *********************************************************/
3901
3902 struct JNINativeInterface_ _Jv_JNINativeInterface = {
3903         NULL,
3904         NULL,
3905         NULL,
3906         NULL,    
3907         _Jv_JNI_GetVersion,
3908
3909         _Jv_JNI_DefineClass,
3910         _Jv_JNI_FindClass,
3911         _Jv_JNI_FromReflectedMethod,
3912         _Jv_JNI_FromReflectedField,
3913         _Jv_JNI_ToReflectedMethod,
3914         _Jv_JNI_GetSuperclass,
3915         _Jv_JNI_IsAssignableFrom,
3916         _Jv_JNI_ToReflectedField,
3917
3918         _Jv_JNI_Throw,
3919         _Jv_JNI_ThrowNew,
3920         _Jv_JNI_ExceptionOccurred,
3921         _Jv_JNI_ExceptionDescribe,
3922         _Jv_JNI_ExceptionClear,
3923         _Jv_JNI_FatalError,
3924         _Jv_JNI_PushLocalFrame,
3925         _Jv_JNI_PopLocalFrame,
3926
3927         _Jv_JNI_NewGlobalRef,
3928         _Jv_JNI_DeleteGlobalRef,
3929         _Jv_JNI_DeleteLocalRef,
3930         _Jv_JNI_IsSameObject,
3931         _Jv_JNI_NewLocalRef,
3932         _Jv_JNI_EnsureLocalCapacity,
3933
3934         _Jv_JNI_AllocObject,
3935         _Jv_JNI_NewObject,
3936         _Jv_JNI_NewObjectV,
3937         _Jv_JNI_NewObjectA,
3938
3939         _Jv_JNI_GetObjectClass,
3940         _Jv_JNI_IsInstanceOf,
3941
3942         _Jv_JNI_GetMethodID,
3943
3944         _Jv_JNI_CallObjectMethod,
3945         _Jv_JNI_CallObjectMethodV,
3946         _Jv_JNI_CallObjectMethodA,
3947         _Jv_JNI_CallBooleanMethod,
3948         _Jv_JNI_CallBooleanMethodV,
3949         _Jv_JNI_CallBooleanMethodA,
3950         _Jv_JNI_CallByteMethod,
3951         _Jv_JNI_CallByteMethodV,
3952         _Jv_JNI_CallByteMethodA,
3953         _Jv_JNI_CallCharMethod,
3954         _Jv_JNI_CallCharMethodV,
3955         _Jv_JNI_CallCharMethodA,
3956         _Jv_JNI_CallShortMethod,
3957         _Jv_JNI_CallShortMethodV,
3958         _Jv_JNI_CallShortMethodA,
3959         _Jv_JNI_CallIntMethod,
3960         _Jv_JNI_CallIntMethodV,
3961         _Jv_JNI_CallIntMethodA,
3962         _Jv_JNI_CallLongMethod,
3963         _Jv_JNI_CallLongMethodV,
3964         _Jv_JNI_CallLongMethodA,
3965         _Jv_JNI_CallFloatMethod,
3966         _Jv_JNI_CallFloatMethodV,
3967         _Jv_JNI_CallFloatMethodA,
3968         _Jv_JNI_CallDoubleMethod,
3969         _Jv_JNI_CallDoubleMethodV,
3970         _Jv_JNI_CallDoubleMethodA,
3971         _Jv_JNI_CallVoidMethod,
3972         _Jv_JNI_CallVoidMethodV,
3973         _Jv_JNI_CallVoidMethodA,
3974
3975         _Jv_JNI_CallNonvirtualObjectMethod,
3976         _Jv_JNI_CallNonvirtualObjectMethodV,
3977         _Jv_JNI_CallNonvirtualObjectMethodA,
3978         _Jv_JNI_CallNonvirtualBooleanMethod,
3979         _Jv_JNI_CallNonvirtualBooleanMethodV,
3980         _Jv_JNI_CallNonvirtualBooleanMethodA,
3981         _Jv_JNI_CallNonvirtualByteMethod,
3982         _Jv_JNI_CallNonvirtualByteMethodV,
3983         _Jv_JNI_CallNonvirtualByteMethodA,
3984         _Jv_JNI_CallNonvirtualCharMethod,
3985         _Jv_JNI_CallNonvirtualCharMethodV,
3986         _Jv_JNI_CallNonvirtualCharMethodA,
3987         _Jv_JNI_CallNonvirtualShortMethod,
3988         _Jv_JNI_CallNonvirtualShortMethodV,
3989         _Jv_JNI_CallNonvirtualShortMethodA,
3990         _Jv_JNI_CallNonvirtualIntMethod,
3991         _Jv_JNI_CallNonvirtualIntMethodV,
3992         _Jv_JNI_CallNonvirtualIntMethodA,
3993         _Jv_JNI_CallNonvirtualLongMethod,
3994         _Jv_JNI_CallNonvirtualLongMethodV,
3995         _Jv_JNI_CallNonvirtualLongMethodA,
3996         _Jv_JNI_CallNonvirtualFloatMethod,
3997         _Jv_JNI_CallNonvirtualFloatMethodV,
3998         _Jv_JNI_CallNonvirtualFloatMethodA,
3999         _Jv_JNI_CallNonvirtualDoubleMethod,
4000         _Jv_JNI_CallNonvirtualDoubleMethodV,
4001         _Jv_JNI_CallNonvirtualDoubleMethodA,
4002         _Jv_JNI_CallNonvirtualVoidMethod,
4003         _Jv_JNI_CallNonvirtualVoidMethodV,
4004         _Jv_JNI_CallNonvirtualVoidMethodA,
4005
4006         _Jv_JNI_GetFieldID,
4007
4008         _Jv_JNI_GetObjectField,
4009         _Jv_JNI_GetBooleanField,
4010         _Jv_JNI_GetByteField,
4011         _Jv_JNI_GetCharField,
4012         _Jv_JNI_GetShortField,
4013         _Jv_JNI_GetIntField,
4014         _Jv_JNI_GetLongField,
4015         _Jv_JNI_GetFloatField,
4016         _Jv_JNI_GetDoubleField,
4017         _Jv_JNI_SetObjectField,
4018         _Jv_JNI_SetBooleanField,
4019         _Jv_JNI_SetByteField,
4020         _Jv_JNI_SetCharField,
4021         _Jv_JNI_SetShortField,
4022         _Jv_JNI_SetIntField,
4023         _Jv_JNI_SetLongField,
4024         _Jv_JNI_SetFloatField,
4025         _Jv_JNI_SetDoubleField,
4026
4027         _Jv_JNI_GetStaticMethodID,
4028
4029         _Jv_JNI_CallStaticObjectMethod,
4030         _Jv_JNI_CallStaticObjectMethodV,
4031         _Jv_JNI_CallStaticObjectMethodA,
4032         _Jv_JNI_CallStaticBooleanMethod,
4033         _Jv_JNI_CallStaticBooleanMethodV,
4034         _Jv_JNI_CallStaticBooleanMethodA,
4035         _Jv_JNI_CallStaticByteMethod,
4036         _Jv_JNI_CallStaticByteMethodV,
4037         _Jv_JNI_CallStaticByteMethodA,
4038         _Jv_JNI_CallStaticCharMethod,
4039         _Jv_JNI_CallStaticCharMethodV,
4040         _Jv_JNI_CallStaticCharMethodA,
4041         _Jv_JNI_CallStaticShortMethod,
4042         _Jv_JNI_CallStaticShortMethodV,
4043         _Jv_JNI_CallStaticShortMethodA,
4044         _Jv_JNI_CallStaticIntMethod,
4045         _Jv_JNI_CallStaticIntMethodV,
4046         _Jv_JNI_CallStaticIntMethodA,
4047         _Jv_JNI_CallStaticLongMethod,
4048         _Jv_JNI_CallStaticLongMethodV,
4049         _Jv_JNI_CallStaticLongMethodA,
4050         _Jv_JNI_CallStaticFloatMethod,
4051         _Jv_JNI_CallStaticFloatMethodV,
4052         _Jv_JNI_CallStaticFloatMethodA,
4053         _Jv_JNI_CallStaticDoubleMethod,
4054         _Jv_JNI_CallStaticDoubleMethodV,
4055         _Jv_JNI_CallStaticDoubleMethodA,
4056         _Jv_JNI_CallStaticVoidMethod,
4057         _Jv_JNI_CallStaticVoidMethodV,
4058         _Jv_JNI_CallStaticVoidMethodA,
4059
4060         _Jv_JNI_GetStaticFieldID,
4061
4062         _Jv_JNI_GetStaticObjectField,
4063         _Jv_JNI_GetStaticBooleanField,
4064         _Jv_JNI_GetStaticByteField,
4065         _Jv_JNI_GetStaticCharField,
4066         _Jv_JNI_GetStaticShortField,
4067         _Jv_JNI_GetStaticIntField,
4068         _Jv_JNI_GetStaticLongField,
4069         _Jv_JNI_GetStaticFloatField,
4070         _Jv_JNI_GetStaticDoubleField,
4071         _Jv_JNI_SetStaticObjectField,
4072         _Jv_JNI_SetStaticBooleanField,
4073         _Jv_JNI_SetStaticByteField,
4074         _Jv_JNI_SetStaticCharField,
4075         _Jv_JNI_SetStaticShortField,
4076         _Jv_JNI_SetStaticIntField,
4077         _Jv_JNI_SetStaticLongField,
4078         _Jv_JNI_SetStaticFloatField,
4079         _Jv_JNI_SetStaticDoubleField,
4080
4081         _Jv_JNI_NewString,
4082         _Jv_JNI_GetStringLength,
4083         _Jv_JNI_GetStringChars,
4084         _Jv_JNI_ReleaseStringChars,
4085
4086         _Jv_JNI_NewStringUTF,
4087         _Jv_JNI_GetStringUTFLength,
4088         _Jv_JNI_GetStringUTFChars,
4089         _Jv_JNI_ReleaseStringUTFChars,
4090
4091         _Jv_JNI_GetArrayLength,
4092
4093         _Jv_JNI_NewObjectArray,
4094         _Jv_JNI_GetObjectArrayElement,
4095         _Jv_JNI_SetObjectArrayElement,
4096
4097         _Jv_JNI_NewBooleanArray,
4098         _Jv_JNI_NewByteArray,
4099         _Jv_JNI_NewCharArray,
4100         _Jv_JNI_NewShortArray,
4101         _Jv_JNI_NewIntArray,
4102         _Jv_JNI_NewLongArray,
4103         _Jv_JNI_NewFloatArray,
4104         _Jv_JNI_NewDoubleArray,
4105
4106         _Jv_JNI_GetBooleanArrayElements,
4107         _Jv_JNI_GetByteArrayElements,
4108         _Jv_JNI_GetCharArrayElements,
4109         _Jv_JNI_GetShortArrayElements,
4110         _Jv_JNI_GetIntArrayElements,
4111         _Jv_JNI_GetLongArrayElements,
4112         _Jv_JNI_GetFloatArrayElements,
4113         _Jv_JNI_GetDoubleArrayElements,
4114
4115         _Jv_JNI_ReleaseBooleanArrayElements,
4116         _Jv_JNI_ReleaseByteArrayElements,
4117         _Jv_JNI_ReleaseCharArrayElements,
4118         _Jv_JNI_ReleaseShortArrayElements,
4119         _Jv_JNI_ReleaseIntArrayElements,
4120         _Jv_JNI_ReleaseLongArrayElements,
4121         _Jv_JNI_ReleaseFloatArrayElements,
4122         _Jv_JNI_ReleaseDoubleArrayElements,
4123
4124         _Jv_JNI_GetBooleanArrayRegion,
4125         _Jv_JNI_GetByteArrayRegion,
4126         _Jv_JNI_GetCharArrayRegion,
4127         _Jv_JNI_GetShortArrayRegion,
4128         _Jv_JNI_GetIntArrayRegion,
4129         _Jv_JNI_GetLongArrayRegion,
4130         _Jv_JNI_GetFloatArrayRegion,
4131         _Jv_JNI_GetDoubleArrayRegion,
4132         _Jv_JNI_SetBooleanArrayRegion,
4133         _Jv_JNI_SetByteArrayRegion,
4134         _Jv_JNI_SetCharArrayRegion,
4135         _Jv_JNI_SetShortArrayRegion,
4136         _Jv_JNI_SetIntArrayRegion,
4137         _Jv_JNI_SetLongArrayRegion,
4138         _Jv_JNI_SetFloatArrayRegion,
4139         _Jv_JNI_SetDoubleArrayRegion,
4140
4141         _Jv_JNI_RegisterNatives,
4142         _Jv_JNI_UnregisterNatives,
4143
4144         _Jv_JNI_MonitorEnter,
4145         _Jv_JNI_MonitorExit,
4146
4147         _Jv_JNI_GetJavaVM,
4148
4149         /* new JNI 1.2 functions */
4150
4151         _Jv_JNI_GetStringRegion,
4152         _Jv_JNI_GetStringUTFRegion,
4153
4154         _Jv_JNI_GetPrimitiveArrayCritical,
4155         _Jv_JNI_ReleasePrimitiveArrayCritical,
4156
4157         _Jv_JNI_GetStringCritical,
4158         _Jv_JNI_ReleaseStringCritical,
4159
4160         _Jv_JNI_NewWeakGlobalRef,
4161         _Jv_JNI_DeleteWeakGlobalRef,
4162
4163         _Jv_JNI_ExceptionCheck,
4164
4165         /* new JNI 1.4 functions */
4166
4167         _Jv_JNI_NewDirectByteBuffer,
4168         _Jv_JNI_GetDirectBufferAddress,
4169         _Jv_JNI_GetDirectBufferCapacity
4170 };
4171
4172
4173 /* Invocation API Functions ***************************************************/
4174
4175 /* JNI_GetDefaultJavaVMInitArgs ************************************************
4176
4177    Returns a default configuration for the Java VM.
4178
4179 *******************************************************************************/
4180
4181 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
4182 {
4183         JavaVMInitArgs *_vm_args;
4184
4185         _vm_args = (JavaVMInitArgs *) vm_args;
4186
4187         /* GNU classpath currently supports JNI 1.2 */
4188
4189         switch (_vm_args->version) {
4190     case JNI_VERSION_1_1:
4191                 _vm_args->version = JNI_VERSION_1_1;
4192                 break;
4193
4194     case JNI_VERSION_1_2:
4195     case JNI_VERSION_1_4:
4196                 _vm_args->ignoreUnrecognized = JNI_FALSE;
4197                 _vm_args->options = NULL;
4198                 _vm_args->nOptions = 0;
4199                 break;
4200
4201     default:
4202                 return -1;
4203         }
4204   
4205         return 0;
4206 }
4207
4208
4209 /* JNI_GetCreatedJavaVMs *******************************************************
4210
4211    Returns all Java VMs that have been created. Pointers to VMs are written in
4212    the buffer vmBuf in the order they are created. At most bufLen number of
4213    entries will be written. The total number of created VMs is returned in
4214    *nVMs.
4215
4216 *******************************************************************************/
4217
4218 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
4219 {
4220         TRACEJNICALLS("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs);
4221
4222         if (bufLen <= 0)
4223                 return JNI_ERR;
4224
4225         /* We currently only support 1 VM running. */
4226
4227         vmBuf[0] = (JavaVM *) _Jv_jvm;
4228         *nVMs    = 1;
4229
4230     return JNI_OK;
4231 }
4232
4233
4234 /* JNI_CreateJavaVM ************************************************************
4235
4236    Loads and initializes a Java VM. The current thread becomes the main thread.
4237    Sets the env argument to the JNI interface pointer of the main thread.
4238
4239 *******************************************************************************/
4240
4241 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
4242 {
4243         TRACEJNICALLS("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args);
4244
4245         /* actually create the JVM */
4246
4247         if (!vm_createjvm(p_vm, p_env, vm_args))
4248                 return JNI_ERR;
4249
4250         return JNI_OK;
4251 }
4252
4253
4254 /*
4255  * These are local overrides for various environment variables in Emacs.
4256  * Please do not remove this and leave it at the end of the file, where
4257  * Emacs will automagically detect them.
4258  * ---------------------------------------------------------------------
4259  * Local variables:
4260  * mode: c
4261  * indent-tabs-mode: t
4262  * c-basic-offset: 4
4263  * tab-width: 4
4264  * End:
4265  * vim:noexpandtab:sw=4:ts=4:
4266  */