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