* Removed all Id tags.
[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 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32 #include <string.h>
33
34 #include "vm/types.h"
35
36 #include "mm/gc-common.h"
37 #include "mm/memory.h"
38
39 #include "native/jni.h"
40 #include "native/llni.h"
41 #include "native/localref.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_handle_objectarray_t *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 && (LLNI_array_size(params) != 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, NULL);
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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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_handle_chararray_t *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                 LLNI_array_direct(a, 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_handle_chararray_t *a;
2667         u2                      *stringbuffer;
2668         u4                       i;
2669         int32_t                  count;
2670         int32_t                  offset;
2671
2672         STATISTICS(jniinvokation());
2673         
2674         s = (java_lang_String *) so;
2675
2676         if (!s)
2677                 return NULL;
2678
2679         LLNI_field_get_ref(s, value, a);
2680
2681         if (!a)
2682                 return NULL;
2683
2684         LLNI_field_get_val(s, count, count);
2685         LLNI_field_get_val(s, offset, offset);
2686
2687         /* allocate memory */
2688
2689         stringbuffer = MNEW(u2, count + 1);
2690
2691         /* copy text */
2692
2693         for (i = 0; i < count; i++)
2694                 stringbuffer[i] = LLNI_array_direct(a, offset + i);
2695         
2696         /* terminate string */
2697
2698         stringbuffer[i] = '\0';
2699
2700         return stringbuffer;
2701 }
2702
2703
2704 /* GetStringChars **************************************************************
2705
2706    Returns a pointer to the array of Unicode characters of the
2707    string. This pointer is valid until ReleaseStringChars() is called.
2708
2709 *******************************************************************************/
2710
2711 const jchar *_Jv_JNI_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
2712 {       
2713         jchar *jc;
2714
2715         STATISTICS(jniinvokation());
2716
2717         jc = javastring_tou2(str);
2718
2719         if (jc) {
2720                 if (isCopy)
2721                         *isCopy = JNI_TRUE;
2722
2723                 return jc;
2724         }
2725
2726         if (isCopy)
2727                 *isCopy = JNI_TRUE;
2728
2729         return emptyStringJ;
2730 }
2731
2732
2733 /* ReleaseStringChars **********************************************************
2734
2735    Informs the VM that the native code no longer needs access to
2736    chars. The chars argument is a pointer obtained from string using
2737    GetStringChars().
2738
2739 *******************************************************************************/
2740
2741 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
2742 {
2743         java_lang_String *s;
2744
2745         STATISTICS(jniinvokation());
2746
2747         if (chars == emptyStringJ)
2748                 return;
2749
2750         s = (java_lang_String *) str;
2751
2752         MFREE(((jchar *) chars), jchar, LLNI_field_direct(s, count) + 1);
2753 }
2754
2755
2756 /* NewStringUTF ****************************************************************
2757
2758    Constructs a new java.lang.String object from an array of UTF-8
2759    characters.
2760
2761 *******************************************************************************/
2762
2763 jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
2764 {
2765         java_lang_String *s;
2766
2767         TRACEJNICALLS("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes);
2768
2769         s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
2770
2771     return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
2772 }
2773
2774
2775 /****************** returns the utf8 length in bytes of a string *******************/
2776
2777 jsize _Jv_JNI_GetStringUTFLength(JNIEnv *env, jstring string)
2778 {   
2779         java_lang_String *s;
2780         s4                length;
2781
2782         TRACEJNICALLS("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string);
2783
2784         s = (java_lang_String *) string;
2785
2786         length = u2_utflength(LLNI_field_direct(s, value)->data, LLNI_field_direct(s, count));
2787
2788         return length;
2789 }
2790
2791
2792 /* GetStringUTFChars ***********************************************************
2793
2794    Returns a pointer to an array of UTF-8 characters of the
2795    string. This array is valid until it is released by
2796    ReleaseStringUTFChars().
2797
2798 *******************************************************************************/
2799
2800 const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
2801                                                                           jboolean *isCopy)
2802 {
2803         utf *u;
2804
2805         STATISTICS(jniinvokation());
2806
2807         if (string == NULL)
2808                 return "";
2809
2810         if (isCopy)
2811                 *isCopy = JNI_TRUE;
2812         
2813         u = javastring_toutf((java_handle_t *) string, false);
2814
2815         if (u != NULL)
2816                 return u->text;
2817
2818         return "";
2819 }
2820
2821
2822 /* ReleaseStringUTFChars *******************************************************
2823
2824    Informs the VM that the native code no longer needs access to
2825    utf. The utf argument is a pointer derived from string using
2826    GetStringUTFChars().
2827
2828 *******************************************************************************/
2829
2830 void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
2831 {
2832         STATISTICS(jniinvokation());
2833
2834     /* XXX we don't release utf chars right now, perhaps that should be done 
2835            later. Since there is always one reference the garbage collector will
2836            never get them */
2837 }
2838
2839
2840 /* Array Operations ***********************************************************/
2841
2842 /* GetArrayLength **************************************************************
2843
2844    Returns the number of elements in the array.
2845
2846 *******************************************************************************/
2847
2848 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
2849 {
2850         java_handle_t *a;
2851         jsize          size;
2852
2853         STATISTICS(jniinvokation());
2854
2855         a = (java_handle_t *) array;
2856
2857         size = LLNI_array_size(a);
2858
2859         return size;
2860 }
2861
2862
2863 /* NewObjectArray **************************************************************
2864
2865    Constructs a new array holding objects in class elementClass. All
2866    elements are initially set to initialElement.
2867
2868 *******************************************************************************/
2869
2870 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
2871                                                                         jclass elementClass, jobject initialElement)
2872 {
2873         classinfo                 *c;
2874         java_handle_t             *o;
2875         java_handle_objectarray_t *oa;
2876         s4                         i;
2877
2878         STATISTICS(jniinvokation());
2879
2880         c = LLNI_classinfo_unwrap(elementClass);
2881         o = (java_handle_t *) initialElement;
2882
2883         if (length < 0) {
2884                 exceptions_throw_negativearraysizeexception();
2885                 return NULL;
2886         }
2887
2888     oa = builtin_anewarray(length, c);
2889
2890         if (oa == NULL)
2891                 return NULL;
2892
2893         /* set all elements to initialElement */
2894
2895         for (i = 0; i < length; i++)
2896                 LLNI_objectarray_element_set(oa, i, o);
2897
2898         return (jobjectArray) _Jv_JNI_NewLocalRef(env, (jobject) oa);
2899 }
2900
2901
2902 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
2903                                                                           jsize index)
2904 {
2905         java_handle_objectarray_t *oa;
2906         java_handle_t             *o;
2907
2908         STATISTICS(jniinvokation());
2909
2910         oa = (java_handle_objectarray_t *) array;
2911
2912         if (index >= LLNI_array_size(oa)) {
2913                 exceptions_throw_arrayindexoutofboundsexception();
2914                 return NULL;
2915         }
2916
2917         LLNI_objectarray_element_get(oa, index, o);
2918
2919         return _Jv_JNI_NewLocalRef(env, (jobject) o);
2920 }
2921
2922
2923 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
2924                                                                    jsize index, jobject val)
2925 {
2926         java_handle_objectarray_t *oa;
2927         java_handle_t             *o;
2928
2929         STATISTICS(jniinvokation());
2930
2931         oa = (java_handle_objectarray_t *) array;
2932         o  = (java_handle_t *) val;
2933
2934         if (index >= LLNI_array_size(oa)) {
2935                 exceptions_throw_arrayindexoutofboundsexception();
2936                 return;
2937         }
2938
2939         /* check if the class of value is a subclass of the element class
2940            of the array */
2941
2942         if (!builtin_canstore(oa, o))
2943                 return;
2944
2945         LLNI_objectarray_element_set(oa, index, o);
2946 }
2947
2948
2949 #define JNI_NEW_ARRAY(name, type, intern)                \
2950 type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
2951 {                                                        \
2952         java_handle_##intern##array_t *a;                    \
2953                                                          \
2954         STATISTICS(jniinvokation());                         \
2955                                                          \
2956         if (len < 0) {                                       \
2957                 exceptions_throw_negativearraysizeexception();   \
2958                 return NULL;                                     \
2959         }                                                    \
2960                                                          \
2961         a = builtin_newarray_##intern(len);                  \
2962                                                          \
2963         return (type) _Jv_JNI_NewLocalRef(env, (jobject) a); \
2964 }
2965
2966 JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
2967 JNI_NEW_ARRAY(Byte,    jbyteArray,    byte)
2968 JNI_NEW_ARRAY(Char,    jcharArray,    char)
2969 JNI_NEW_ARRAY(Short,   jshortArray,   byte)
2970 JNI_NEW_ARRAY(Int,     jintArray,     int)
2971 JNI_NEW_ARRAY(Long,    jlongArray,    long)
2972 JNI_NEW_ARRAY(Float,   jfloatArray,   float)
2973 JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
2974
2975
2976 /* Get<PrimitiveType>ArrayElements *********************************************
2977
2978    A family of functions that returns the body of the primitive array.
2979
2980 *******************************************************************************/
2981
2982 #define JNI_GET_ARRAY_ELEMENTS(name, type, intern)                     \
2983 type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
2984                                                                                  jboolean *isCopy)             \
2985 {                                                                      \
2986         java_handle_##intern##array_t *a;                                  \
2987                                                                        \
2988         STATISTICS(jniinvokation());                                       \
2989                                                                        \
2990         a = (java_handle_##intern##array_t *) array;                       \
2991                                                                        \
2992         if (isCopy)                                                        \
2993                 *isCopy = JNI_FALSE;                                           \
2994                                                                        \
2995         return LLNI_array_data(a);                                         \
2996 }
2997
2998 JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
2999 JNI_GET_ARRAY_ELEMENTS(Byte,    jbyte,    byte)
3000 JNI_GET_ARRAY_ELEMENTS(Char,    jchar,    char)
3001 JNI_GET_ARRAY_ELEMENTS(Short,   jshort,   short)
3002 JNI_GET_ARRAY_ELEMENTS(Int,     jint,     int)
3003 JNI_GET_ARRAY_ELEMENTS(Long,    jlong,    long)
3004 JNI_GET_ARRAY_ELEMENTS(Float,   jfloat,   float)
3005 JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
3006
3007
3008 /* Release<PrimitiveType>ArrayElements *****************************************
3009
3010    A family of functions that informs the VM that the native code no
3011    longer needs access to elems. The elems argument is a pointer
3012    derived from array using the corresponding
3013    Get<PrimitiveType>ArrayElements() function. If necessary, this
3014    function copies back all changes made to elems to the original
3015    array.
3016
3017 *******************************************************************************/
3018
3019 #define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2)            \
3020 void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
3021                                                                                   type *elems, jint mode)          \
3022 {                                                                          \
3023         java_handle_##intern##array_t *a;                                      \
3024                                                                            \
3025         STATISTICS(jniinvokation());                                           \
3026                                                                            \
3027         a = (java_handle_##intern##array_t *) array;                           \
3028                                                                            \
3029         if (elems != LLNI_array_data(a)) {                                     \
3030                 switch (mode) {                                                    \
3031                 case JNI_COMMIT:                                                   \
3032                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
3033                         break;                                                         \
3034                 case 0:                                                            \
3035                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
3036                         /* XXX TWISTI how should it be freed? */                       \
3037                         break;                                                         \
3038                 case JNI_ABORT:                                                    \
3039                         /* XXX TWISTI how should it be freed? */                       \
3040                         break;                                                         \
3041                 }                                                                  \
3042         }                                                                      \
3043 }
3044
3045 JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
3046 JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
3047 JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
3048 JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
3049 JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
3050 JNI_RELEASE_ARRAY_ELEMENTS(Long,    jlong,    long,    s8)
3051 JNI_RELEASE_ARRAY_ELEMENTS(Float,   jfloat,   float,   float)
3052 JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
3053
3054
3055 /*  Get<PrimitiveType>ArrayRegion **********************************************
3056
3057         A family of functions that copies a region of a primitive array
3058         into a buffer.
3059
3060 *******************************************************************************/
3061
3062 #define JNI_GET_ARRAY_REGION(name, type, intern, intern2)               \
3063 void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
3064                                                                         jsize start, jsize len, type *buf)  \
3065 {                                                                       \
3066         java_handle_##intern##array_t *a;                                   \
3067                                                                         \
3068         STATISTICS(jniinvokation());                                        \
3069                                                                         \
3070         a = (java_handle_##intern##array_t *) array;                        \
3071                                                                         \
3072         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
3073                 exceptions_throw_arrayindexoutofboundsexception();              \
3074         else                                                                \
3075                 MCOPY(buf, &LLNI_array_direct(a, start), intern2, len);         \
3076 }
3077
3078 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
3079 JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
3080 JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
3081 JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
3082 JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
3083 JNI_GET_ARRAY_REGION(Long,    jlong,    long,    s8)
3084 JNI_GET_ARRAY_REGION(Float,   jfloat,   float,   float)
3085 JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
3086
3087
3088 /*  Set<PrimitiveType>ArrayRegion **********************************************
3089
3090         A family of functions that copies back a region of a primitive
3091         array from a buffer.
3092
3093 *******************************************************************************/
3094
3095 #define JNI_SET_ARRAY_REGION(name, type, intern, intern2)                    \
3096 void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
3097                                                                         jsize start, jsize len, const type *buf) \
3098 {                                                                            \
3099         java_handle_##intern##array_t *a;                                        \
3100                                                                              \
3101         STATISTICS(jniinvokation());                                             \
3102                                                                              \
3103         a = (java_handle_##intern##array_t *) array;                             \
3104                                                                              \
3105         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a)))      \
3106                 exceptions_throw_arrayindexoutofboundsexception();                   \
3107         else                                                                     \
3108                 MCOPY(&LLNI_array_direct(a, start), buf, intern2, len);              \
3109 }
3110
3111 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
3112 JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
3113 JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
3114 JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
3115 JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
3116 JNI_SET_ARRAY_REGION(Long,    jlong,    long,    s8)
3117 JNI_SET_ARRAY_REGION(Float,   jfloat,   float,   float)
3118 JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
3119
3120
3121 /* Registering Native Methods *************************************************/
3122
3123 /* RegisterNatives *************************************************************
3124
3125    Registers native methods with the class specified by the clazz
3126    argument. The methods parameter specifies an array of
3127    JNINativeMethod structures that contain the names, signatures, and
3128    function pointers of the native methods. The nMethods parameter
3129    specifies the number of native methods in the array.
3130
3131 *******************************************************************************/
3132
3133 jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
3134                                                          const JNINativeMethod *methods, jint nMethods)
3135 {
3136         classinfo *c;
3137
3138         STATISTICS(jniinvokation());
3139
3140         c = LLNI_classinfo_unwrap(clazz);
3141
3142         /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
3143         if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
3144         */
3145
3146         native_method_register(c->name, methods, nMethods);
3147
3148     return 0;
3149 }
3150
3151
3152 /* UnregisterNatives ***********************************************************
3153
3154    Unregisters native methods of a class. The class goes back to the
3155    state before it was linked or registered with its native method
3156    functions.
3157
3158    This function should not be used in normal native code. Instead, it
3159    provides special programs a way to reload and relink native
3160    libraries.
3161
3162 *******************************************************************************/
3163
3164 jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
3165 {
3166         STATISTICS(jniinvokation());
3167
3168         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
3169
3170     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
3171
3172     return 0;
3173 }
3174
3175
3176 /* Monitor Operations *********************************************************/
3177
3178 /* MonitorEnter ****************************************************************
3179
3180    Enters the monitor associated with the underlying Java object
3181    referred to by obj.
3182
3183 *******************************************************************************/
3184
3185 jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
3186 {
3187         STATISTICS(jniinvokation());
3188
3189         if (obj == NULL) {
3190                 exceptions_throw_nullpointerexception();
3191                 return JNI_ERR;
3192         }
3193
3194         LOCK_MONITOR_ENTER(obj);
3195
3196         return JNI_OK;
3197 }
3198
3199
3200 /* MonitorExit *****************************************************************
3201
3202    The current thread must be the owner of the monitor associated with
3203    the underlying Java object referred to by obj. The thread
3204    decrements the counter indicating the number of times it has
3205    entered this monitor. If the value of the counter becomes zero, the
3206    current thread releases the monitor.
3207
3208 *******************************************************************************/
3209
3210 jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
3211 {
3212         STATISTICS(jniinvokation());
3213
3214         if (obj == NULL) {
3215                 exceptions_throw_nullpointerexception();
3216                 return JNI_ERR;
3217         }
3218
3219         LOCK_MONITOR_EXIT(obj);
3220
3221         return JNI_OK;
3222 }
3223
3224
3225 /* JavaVM Interface ***********************************************************/
3226
3227 /* GetJavaVM *******************************************************************
3228
3229    Returns the Java VM interface (used in the Invocation API)
3230    associated with the current thread. The result is placed at the
3231    location pointed to by the second argument, vm.
3232
3233 *******************************************************************************/
3234
3235 jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **vm)
3236 {
3237         STATISTICS(jniinvokation());
3238
3239     *vm = (JavaVM *) _Jv_jvm;
3240
3241         return 0;
3242 }
3243
3244
3245 /* GetStringRegion *************************************************************
3246
3247    Copies len number of Unicode characters beginning at offset start
3248    to the given buffer buf.
3249
3250    Throws StringIndexOutOfBoundsException on index overflow.
3251
3252 *******************************************************************************/
3253
3254 void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
3255                                                          jchar *buf)
3256 {
3257         java_lang_String        *s;
3258         java_handle_chararray_t *ca;
3259
3260         STATISTICS(jniinvokation());
3261
3262         s  = (java_lang_String *) str;
3263         LLNI_field_get_ref(s, value, ca);
3264
3265         if ((start < 0) || (len < 0) || (start > LLNI_field_direct(s, count)) ||
3266                 (start + len > LLNI_field_direct(s, count))) {
3267                 exceptions_throw_stringindexoutofboundsexception();
3268                 return;
3269         }
3270
3271         MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
3272 }
3273
3274
3275 /* GetStringUTFRegion **********************************************************
3276
3277     Translates len number of Unicode characters beginning at offset
3278     start into UTF-8 format and place the result in the given buffer
3279     buf.
3280
3281     Throws StringIndexOutOfBoundsException on index overflow. 
3282
3283 *******************************************************************************/
3284
3285 void _Jv_JNI_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
3286                                                                 jsize len, char *buf)
3287 {
3288         java_lang_String        *s;
3289         java_handle_chararray_t *ca;
3290         s4                       i;
3291         int32_t                  count;
3292         int32_t                  offset;
3293
3294         TRACEJNICALLS("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf);
3295
3296         s  = (java_lang_String *) str;
3297         LLNI_field_get_ref(s, value, ca);
3298         LLNI_field_get_val(s, count, count);
3299         LLNI_field_get_val(s, offset, offset);
3300
3301         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3302                 exceptions_throw_stringindexoutofboundsexception();
3303                 return;
3304         }
3305
3306         for (i = 0; i < len; i++)
3307                 buf[i] = LLNI_array_direct(ca, offset + start + i);
3308
3309         buf[i] = '\0';
3310 }
3311
3312
3313 /* GetPrimitiveArrayCritical ***************************************************
3314
3315    Obtain a direct pointer to array elements.
3316
3317 *******************************************************************************/
3318
3319 void *_Jv_JNI_GetPrimitiveArrayCritical(JNIEnv *env, jarray array,
3320                                                                                 jboolean *isCopy)
3321 {
3322         java_handle_bytearray_t *ba;
3323         jbyte                   *bp;
3324
3325         ba = (java_handle_bytearray_t *) array;
3326
3327         /* do the same as Kaffe does */
3328
3329         bp = _Jv_JNI_GetByteArrayElements(env, (jbyteArray) ba, isCopy);
3330
3331         return (void *) bp;
3332 }
3333
3334
3335 /* ReleasePrimitiveArrayCritical ***********************************************
3336
3337    No specific documentation.
3338
3339 *******************************************************************************/
3340
3341 void _Jv_JNI_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array,
3342                                                                                    void *carray, jint mode)
3343 {
3344         STATISTICS(jniinvokation());
3345
3346         /* do the same as Kaffe does */
3347
3348         _Jv_JNI_ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray,
3349                                                                          mode);
3350 }
3351
3352
3353 /* GetStringCritical ***********************************************************
3354
3355    The semantics of these two functions are similar to the existing
3356    Get/ReleaseStringChars functions.
3357
3358 *******************************************************************************/
3359
3360 const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
3361                                                                            jboolean *isCopy)
3362 {
3363         STATISTICS(jniinvokation());
3364
3365         return _Jv_JNI_GetStringChars(env, string, isCopy);
3366 }
3367
3368
3369 void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
3370                                                                    const jchar *cstring)
3371 {
3372         STATISTICS(jniinvokation());
3373
3374         _Jv_JNI_ReleaseStringChars(env, string, cstring);
3375 }
3376
3377
3378 jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
3379 {
3380         STATISTICS(jniinvokation());
3381
3382         log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!");
3383
3384         return obj;
3385 }
3386
3387
3388 void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
3389 {
3390         STATISTICS(jniinvokation());
3391
3392         log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME");
3393 }
3394
3395
3396 /* NewGlobalRef ****************************************************************
3397
3398    Creates a new global reference to the object referred to by the obj
3399    argument.
3400
3401 *******************************************************************************/
3402     
3403 jobject _Jv_JNI_NewGlobalRef(JNIEnv* env, jobject obj)
3404 {
3405         hashtable_global_ref_entry *gre;
3406         u4   key;                           /* hashkey                            */
3407         u4   slot;                          /* slot in hashtable                  */
3408         java_handle_t *o;
3409
3410         STATISTICS(jniinvokation());
3411
3412         o = (java_handle_t *) obj;
3413
3414         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
3415
3416         /* normally addresses are aligned to 4, 8 or 16 bytes */
3417
3418         key  = ((u4) (ptrint) obj) >> 4;           /* align to 16-byte boundaries */
3419         slot = key & (hashtable_global_ref->size - 1);
3420         gre  = hashtable_global_ref->ptr[slot];
3421         
3422         /* search external hash chain for the entry */
3423
3424         while (gre) {
3425                 if (gre->o == o) {
3426                         /* global object found, increment the reference */
3427
3428                         gre->refs++;
3429
3430                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3431
3432                         return obj;
3433                 }
3434
3435                 gre = gre->hashlink;                /* next element in external chain */
3436         }
3437
3438         /* global ref not found, create a new one */
3439
3440         gre = NEW(hashtable_global_ref_entry);
3441
3442         gre->o    = o;
3443         gre->refs = 1;
3444
3445         /* insert entry into hashtable */
3446
3447         gre->hashlink = hashtable_global_ref->ptr[slot];
3448
3449         hashtable_global_ref->ptr[slot] = gre;
3450
3451         /* update number of hashtable-entries */
3452
3453         hashtable_global_ref->entries++;
3454
3455         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3456
3457         return obj;
3458 }
3459
3460
3461 /* DeleteGlobalRef *************************************************************
3462
3463    Deletes the global reference pointed to by globalRef.
3464
3465 *******************************************************************************/
3466
3467 void _Jv_JNI_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
3468 {
3469         hashtable_global_ref_entry *gre;
3470         hashtable_global_ref_entry *prevgre;
3471         u4   key;                           /* hashkey                            */
3472         u4   slot;                          /* slot in hashtable                  */
3473         java_handle_t              *o;
3474
3475         STATISTICS(jniinvokation());
3476
3477         o = (java_handle_t *) globalRef;
3478
3479         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
3480
3481         /* normally addresses are aligned to 4, 8 or 16 bytes */
3482
3483         key  = ((u4) (ptrint) globalRef) >> 4;     /* align to 16-byte boundaries */
3484         slot = key & (hashtable_global_ref->size - 1);
3485         gre  = hashtable_global_ref->ptr[slot];
3486
3487         /* initialize prevgre */
3488
3489         prevgre = NULL;
3490
3491         /* search external hash chain for the entry */
3492
3493         while (gre) {
3494                 if (gre->o == o) {
3495                         /* global object found, decrement the reference count */
3496
3497                         gre->refs--;
3498
3499                         /* if reference count is 0, remove the entry */
3500
3501                         if (gre->refs == 0) {
3502                                 /* special handling if it's the first in the chain */
3503
3504                                 if (prevgre == NULL)
3505                                         hashtable_global_ref->ptr[slot] = gre->hashlink;
3506                                 else
3507                                         prevgre->hashlink = gre->hashlink;
3508
3509                                 FREE(gre, hashtable_global_ref_entry);
3510                         }
3511
3512                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3513
3514                         return;
3515                 }
3516
3517                 prevgre = gre;                    /* save current pointer for removal */
3518                 gre     = gre->hashlink;            /* next element in external chain */
3519         }
3520
3521         log_println("JNI-DeleteGlobalRef: global reference not found");
3522
3523         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3524 }
3525
3526
3527 /* ExceptionCheck **************************************************************
3528
3529    Returns JNI_TRUE when there is a pending exception; otherwise,
3530    returns JNI_FALSE.
3531
3532 *******************************************************************************/
3533
3534 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
3535 {
3536         java_handle_t *o;
3537
3538         STATISTICS(jniinvokation());
3539
3540         o = exceptions_get_exception();
3541
3542         return (o != NULL) ? JNI_TRUE : JNI_FALSE;
3543 }
3544
3545
3546 /* New JNI 1.4 functions ******************************************************/
3547
3548 /* NewDirectByteBuffer *********************************************************
3549
3550    Allocates and returns a direct java.nio.ByteBuffer referring to the
3551    block of memory starting at the memory address address and
3552    extending capacity bytes.
3553
3554 *******************************************************************************/
3555
3556 jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
3557 {
3558 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
3559         java_handle_t           *nbuf;
3560
3561 # if SIZEOF_VOID_P == 8
3562         gnu_classpath_Pointer64 *paddress;
3563 # else
3564         gnu_classpath_Pointer32 *paddress;
3565 # endif
3566
3567         STATISTICS(jniinvokation());
3568
3569         /* alocate a gnu.classpath.Pointer{32,64} object */
3570
3571 # if SIZEOF_VOID_P == 8
3572         if (!(paddress = (gnu_classpath_Pointer64 *)
3573                   builtin_new(class_gnu_classpath_Pointer64)))
3574 # else
3575         if (!(paddress = (gnu_classpath_Pointer32 *)
3576                   builtin_new(class_gnu_classpath_Pointer32)))
3577 # endif
3578                 return NULL;
3579
3580         /* fill gnu.classpath.Pointer{32,64} with address */
3581
3582         LLNI_field_set_val(paddress, data, (ptrint) address);
3583
3584         /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
3585
3586         nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
3587                                                          (jmethodID) dbbirw_init, NULL, paddress,
3588                                                          (jint) capacity, (jint) capacity, (jint) 0);
3589
3590         /* add local reference and return the value */
3591
3592         return _Jv_JNI_NewLocalRef(env, nbuf);
3593 #else
3594         vm_abort("_Jv_JNI_NewDirectByteBuffer: not implemented in this configuration");
3595
3596         /* keep compiler happy */
3597
3598         return NULL;
3599 #endif
3600 }
3601
3602
3603 /* GetDirectBufferAddress ******************************************************
3604
3605    Fetches and returns the starting address of the memory region
3606    referenced by the given direct java.nio.Buffer.
3607
3608 *******************************************************************************/
3609
3610 void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
3611 {
3612 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
3613         java_nio_DirectByteBufferImpl *nbuf;
3614 # if SIZEOF_VOID_P == 8
3615         gnu_classpath_Pointer64       *paddress;
3616 # else
3617         gnu_classpath_Pointer32       *paddress;
3618 # endif
3619         void                          *address;
3620
3621         STATISTICS(jniinvokation());
3622
3623         if (!builtin_instanceof(buf, class_java_nio_Buffer))
3624                 return NULL;
3625
3626         nbuf = (java_nio_DirectByteBufferImpl *) buf;
3627
3628 # if SIZEOF_VOID_P == 8
3629         LLNI_field_get_ref(nbuf, address, paddress);
3630         /* this was the cast to avaoid warning: (gnu_classpath_Pointer64 *) nbuf->address; */
3631 # else
3632         LLNI_field_get_ref(nbuf, address, paddress); 
3633         /* this was the cast to avaoid warning: (gnu_classpath_Pointer32 *) nbuf->address; */
3634 # endif
3635
3636         if (paddress == NULL)
3637                 return NULL;
3638
3639         LLNI_field_get_val(paddress, data, address);
3640         /* this was the cast to avaoid warning: (void *) paddress->data */
3641
3642         return address;
3643 #else
3644         vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
3645
3646         /* keep compiler happy */
3647
3648         return NULL;
3649 #endif
3650 }
3651
3652
3653 /* GetDirectBufferCapacity *****************************************************
3654
3655    Fetches and returns the capacity in bytes of the memory region
3656    referenced by the given direct java.nio.Buffer.
3657
3658 *******************************************************************************/
3659
3660 jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
3661 {
3662 #if defined(ENABLE_JAVASE) && defined(WITH_CLASSPATH_GNU)
3663         java_handle_t   *o;
3664         java_nio_Buffer *nbuf;
3665         jlong            capacity;
3666
3667         STATISTICS(jniinvokation());
3668
3669         o = (java_handle_t *) buf;
3670
3671         if (!builtin_instanceof(o, class_java_nio_DirectByteBufferImpl))
3672                 return -1;
3673
3674         nbuf = (java_nio_Buffer *) o;
3675
3676         LLNI_field_get_val(nbuf, cap, capacity);
3677
3678         return capacity;
3679 #else
3680         vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
3681
3682         /* keep compiler happy */
3683
3684         return 0;
3685 #endif
3686 }
3687
3688
3689 /* DestroyJavaVM ***************************************************************
3690
3691    Unloads a Java VM and reclaims its resources. Only the main thread
3692    can unload the VM. The system waits until the main thread is only
3693    remaining user thread before it destroys the VM.
3694
3695 *******************************************************************************/
3696
3697 jint _Jv_JNI_DestroyJavaVM(JavaVM *vm)
3698 {
3699         s4 status;
3700
3701         STATISTICS(jniinvokation());
3702
3703     status = vm_destroy(vm);
3704
3705         return status;
3706 }
3707
3708
3709 /* AttachCurrentThread *********************************************************
3710
3711    Attaches the current thread to a Java VM. Returns a JNI interface
3712    pointer in the JNIEnv argument.
3713
3714    Trying to attach a thread that is already attached is a no-op.
3715
3716    A native thread cannot be attached simultaneously to two Java VMs.
3717
3718    When a thread is attached to the VM, the context class loader is
3719    the bootstrap loader.
3720
3721 *******************************************************************************/
3722
3723 static s4 jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
3724 {
3725         JavaVMAttachArgs *vm_aargs;
3726
3727 #if defined(ENABLE_THREADS)
3728         if (threads_get_current_threadobject() == NULL) {
3729                 vm_aargs = (JavaVMAttachArgs *) thr_args;
3730
3731                 if (vm_aargs != NULL) {
3732                         if ((vm_aargs->version != JNI_VERSION_1_2) &&
3733                                 (vm_aargs->version != JNI_VERSION_1_4))
3734                                 return JNI_EVERSION;
3735                 }
3736
3737                 if (!threads_attach_current_thread(vm_aargs, false))
3738                         return JNI_ERR;
3739
3740                 if (!localref_table_init())
3741                         return JNI_ERR;
3742         }
3743 #endif
3744
3745         *p_env = _Jv_env;
3746
3747         return JNI_OK;
3748 }
3749
3750
3751 jint _Jv_JNI_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
3752 {
3753         STATISTICS(jniinvokation());
3754
3755         return jni_attach_current_thread(p_env, thr_args, false);
3756 }
3757
3758
3759 /* DetachCurrentThread *********************************************************
3760
3761    Detaches the current thread from a Java VM. All Java monitors held
3762    by this thread are released. All Java threads waiting for this
3763    thread to die are notified.
3764
3765    In JDK 1.1, the main thread cannot be detached from the VM. It must
3766    call DestroyJavaVM to unload the entire VM.
3767
3768    In the JDK, the main thread can be detached from the VM.
3769
3770    The main thread, which is the thread that created the Java VM,
3771    cannot be detached from the VM. Instead, the main thread must call
3772    JNI_DestroyJavaVM() to unload the entire VM.
3773
3774 *******************************************************************************/
3775
3776 jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
3777 {
3778 #if defined(ENABLE_THREADS)
3779         threadobject *thread;
3780
3781         STATISTICS(jniinvokation());
3782
3783         thread = threads_get_current_threadobject();
3784
3785         if (thread == NULL)
3786                 return JNI_ERR;
3787
3788         if (!threads_detach_thread(thread))
3789                 return JNI_ERR;
3790 #endif
3791
3792         return JNI_OK;
3793 }
3794
3795
3796 /* GetEnv **********************************************************************
3797
3798    If the current thread is not attached to the VM, sets *env to NULL,
3799    and returns JNI_EDETACHED. If the specified version is not
3800    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
3801    sets *env to the appropriate interface, and returns JNI_OK.
3802
3803 *******************************************************************************/
3804
3805 jint _Jv_JNI_GetEnv(JavaVM *vm, void **env, jint version)
3806 {
3807         STATISTICS(jniinvokation());
3808
3809 #if defined(ENABLE_THREADS)
3810         if (threads_get_current_threadobject() == NULL) {
3811                 *env = NULL;
3812
3813                 return JNI_EDETACHED;
3814         }
3815 #endif
3816
3817         /* check the JNI version */
3818
3819         switch (version) {
3820         case JNI_VERSION_1_1:
3821         case JNI_VERSION_1_2:
3822         case JNI_VERSION_1_4:
3823                 *env = _Jv_env;
3824                 return JNI_OK;
3825
3826         default:
3827                 ;
3828         }
3829
3830 #if defined(ENABLE_JVMTI)
3831         if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
3832                 == JVMTI_VERSION_INTERFACE_JVMTI) {
3833
3834                 *env = (void *) jvmti_new_environment();
3835
3836                 if (env != NULL)
3837                         return JNI_OK;
3838         }
3839 #endif
3840         
3841         *env = NULL;
3842
3843         return JNI_EVERSION;
3844 }
3845
3846
3847 /* AttachCurrentThreadAsDaemon *************************************************
3848
3849    Same semantics as AttachCurrentThread, but the newly-created
3850    java.lang.Thread instance is a daemon.
3851
3852    If the thread has already been attached via either
3853    AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
3854    simply sets the value pointed to by penv to the JNIEnv of the
3855    current thread. In this case neither AttachCurrentThread nor this
3856    routine have any effect on the daemon status of the thread.
3857
3858 *******************************************************************************/
3859
3860 jint _Jv_JNI_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
3861 {
3862         STATISTICS(jniinvokation());
3863
3864         return jni_attach_current_thread(penv, args, true);
3865 }
3866
3867
3868 /* JNI invocation table *******************************************************/
3869
3870 const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
3871         NULL,
3872         NULL,
3873         NULL,
3874
3875         _Jv_JNI_DestroyJavaVM,
3876         _Jv_JNI_AttachCurrentThread,
3877         _Jv_JNI_DetachCurrentThread,
3878         _Jv_JNI_GetEnv,
3879         _Jv_JNI_AttachCurrentThreadAsDaemon
3880 };
3881
3882
3883 /* JNI function table *********************************************************/
3884
3885 struct JNINativeInterface_ _Jv_JNINativeInterface = {
3886         NULL,
3887         NULL,
3888         NULL,
3889         NULL,    
3890         _Jv_JNI_GetVersion,
3891
3892         _Jv_JNI_DefineClass,
3893         _Jv_JNI_FindClass,
3894         _Jv_JNI_FromReflectedMethod,
3895         _Jv_JNI_FromReflectedField,
3896         _Jv_JNI_ToReflectedMethod,
3897         _Jv_JNI_GetSuperclass,
3898         _Jv_JNI_IsAssignableFrom,
3899         _Jv_JNI_ToReflectedField,
3900
3901         _Jv_JNI_Throw,
3902         _Jv_JNI_ThrowNew,
3903         _Jv_JNI_ExceptionOccurred,
3904         _Jv_JNI_ExceptionDescribe,
3905         _Jv_JNI_ExceptionClear,
3906         _Jv_JNI_FatalError,
3907         _Jv_JNI_PushLocalFrame,
3908         _Jv_JNI_PopLocalFrame,
3909
3910         _Jv_JNI_NewGlobalRef,
3911         _Jv_JNI_DeleteGlobalRef,
3912         _Jv_JNI_DeleteLocalRef,
3913         _Jv_JNI_IsSameObject,
3914         _Jv_JNI_NewLocalRef,
3915         _Jv_JNI_EnsureLocalCapacity,
3916
3917         _Jv_JNI_AllocObject,
3918         _Jv_JNI_NewObject,
3919         _Jv_JNI_NewObjectV,
3920         _Jv_JNI_NewObjectA,
3921
3922         _Jv_JNI_GetObjectClass,
3923         _Jv_JNI_IsInstanceOf,
3924
3925         _Jv_JNI_GetMethodID,
3926
3927         _Jv_JNI_CallObjectMethod,
3928         _Jv_JNI_CallObjectMethodV,
3929         _Jv_JNI_CallObjectMethodA,
3930         _Jv_JNI_CallBooleanMethod,
3931         _Jv_JNI_CallBooleanMethodV,
3932         _Jv_JNI_CallBooleanMethodA,
3933         _Jv_JNI_CallByteMethod,
3934         _Jv_JNI_CallByteMethodV,
3935         _Jv_JNI_CallByteMethodA,
3936         _Jv_JNI_CallCharMethod,
3937         _Jv_JNI_CallCharMethodV,
3938         _Jv_JNI_CallCharMethodA,
3939         _Jv_JNI_CallShortMethod,
3940         _Jv_JNI_CallShortMethodV,
3941         _Jv_JNI_CallShortMethodA,
3942         _Jv_JNI_CallIntMethod,
3943         _Jv_JNI_CallIntMethodV,
3944         _Jv_JNI_CallIntMethodA,
3945         _Jv_JNI_CallLongMethod,
3946         _Jv_JNI_CallLongMethodV,
3947         _Jv_JNI_CallLongMethodA,
3948         _Jv_JNI_CallFloatMethod,
3949         _Jv_JNI_CallFloatMethodV,
3950         _Jv_JNI_CallFloatMethodA,
3951         _Jv_JNI_CallDoubleMethod,
3952         _Jv_JNI_CallDoubleMethodV,
3953         _Jv_JNI_CallDoubleMethodA,
3954         _Jv_JNI_CallVoidMethod,
3955         _Jv_JNI_CallVoidMethodV,
3956         _Jv_JNI_CallVoidMethodA,
3957
3958         _Jv_JNI_CallNonvirtualObjectMethod,
3959         _Jv_JNI_CallNonvirtualObjectMethodV,
3960         _Jv_JNI_CallNonvirtualObjectMethodA,
3961         _Jv_JNI_CallNonvirtualBooleanMethod,
3962         _Jv_JNI_CallNonvirtualBooleanMethodV,
3963         _Jv_JNI_CallNonvirtualBooleanMethodA,
3964         _Jv_JNI_CallNonvirtualByteMethod,
3965         _Jv_JNI_CallNonvirtualByteMethodV,
3966         _Jv_JNI_CallNonvirtualByteMethodA,
3967         _Jv_JNI_CallNonvirtualCharMethod,
3968         _Jv_JNI_CallNonvirtualCharMethodV,
3969         _Jv_JNI_CallNonvirtualCharMethodA,
3970         _Jv_JNI_CallNonvirtualShortMethod,
3971         _Jv_JNI_CallNonvirtualShortMethodV,
3972         _Jv_JNI_CallNonvirtualShortMethodA,
3973         _Jv_JNI_CallNonvirtualIntMethod,
3974         _Jv_JNI_CallNonvirtualIntMethodV,
3975         _Jv_JNI_CallNonvirtualIntMethodA,
3976         _Jv_JNI_CallNonvirtualLongMethod,
3977         _Jv_JNI_CallNonvirtualLongMethodV,
3978         _Jv_JNI_CallNonvirtualLongMethodA,
3979         _Jv_JNI_CallNonvirtualFloatMethod,
3980         _Jv_JNI_CallNonvirtualFloatMethodV,
3981         _Jv_JNI_CallNonvirtualFloatMethodA,
3982         _Jv_JNI_CallNonvirtualDoubleMethod,
3983         _Jv_JNI_CallNonvirtualDoubleMethodV,
3984         _Jv_JNI_CallNonvirtualDoubleMethodA,
3985         _Jv_JNI_CallNonvirtualVoidMethod,
3986         _Jv_JNI_CallNonvirtualVoidMethodV,
3987         _Jv_JNI_CallNonvirtualVoidMethodA,
3988
3989         _Jv_JNI_GetFieldID,
3990
3991         _Jv_JNI_GetObjectField,
3992         _Jv_JNI_GetBooleanField,
3993         _Jv_JNI_GetByteField,
3994         _Jv_JNI_GetCharField,
3995         _Jv_JNI_GetShortField,
3996         _Jv_JNI_GetIntField,
3997         _Jv_JNI_GetLongField,
3998         _Jv_JNI_GetFloatField,
3999         _Jv_JNI_GetDoubleField,
4000         _Jv_JNI_SetObjectField,
4001         _Jv_JNI_SetBooleanField,
4002         _Jv_JNI_SetByteField,
4003         _Jv_JNI_SetCharField,
4004         _Jv_JNI_SetShortField,
4005         _Jv_JNI_SetIntField,
4006         _Jv_JNI_SetLongField,
4007         _Jv_JNI_SetFloatField,
4008         _Jv_JNI_SetDoubleField,
4009
4010         _Jv_JNI_GetStaticMethodID,
4011
4012         _Jv_JNI_CallStaticObjectMethod,
4013         _Jv_JNI_CallStaticObjectMethodV,
4014         _Jv_JNI_CallStaticObjectMethodA,
4015         _Jv_JNI_CallStaticBooleanMethod,
4016         _Jv_JNI_CallStaticBooleanMethodV,
4017         _Jv_JNI_CallStaticBooleanMethodA,
4018         _Jv_JNI_CallStaticByteMethod,
4019         _Jv_JNI_CallStaticByteMethodV,
4020         _Jv_JNI_CallStaticByteMethodA,
4021         _Jv_JNI_CallStaticCharMethod,
4022         _Jv_JNI_CallStaticCharMethodV,
4023         _Jv_JNI_CallStaticCharMethodA,
4024         _Jv_JNI_CallStaticShortMethod,
4025         _Jv_JNI_CallStaticShortMethodV,
4026         _Jv_JNI_CallStaticShortMethodA,
4027         _Jv_JNI_CallStaticIntMethod,
4028         _Jv_JNI_CallStaticIntMethodV,
4029         _Jv_JNI_CallStaticIntMethodA,
4030         _Jv_JNI_CallStaticLongMethod,
4031         _Jv_JNI_CallStaticLongMethodV,
4032         _Jv_JNI_CallStaticLongMethodA,
4033         _Jv_JNI_CallStaticFloatMethod,
4034         _Jv_JNI_CallStaticFloatMethodV,
4035         _Jv_JNI_CallStaticFloatMethodA,
4036         _Jv_JNI_CallStaticDoubleMethod,
4037         _Jv_JNI_CallStaticDoubleMethodV,
4038         _Jv_JNI_CallStaticDoubleMethodA,
4039         _Jv_JNI_CallStaticVoidMethod,
4040         _Jv_JNI_CallStaticVoidMethodV,
4041         _Jv_JNI_CallStaticVoidMethodA,
4042
4043         _Jv_JNI_GetStaticFieldID,
4044
4045         _Jv_JNI_GetStaticObjectField,
4046         _Jv_JNI_GetStaticBooleanField,
4047         _Jv_JNI_GetStaticByteField,
4048         _Jv_JNI_GetStaticCharField,
4049         _Jv_JNI_GetStaticShortField,
4050         _Jv_JNI_GetStaticIntField,
4051         _Jv_JNI_GetStaticLongField,
4052         _Jv_JNI_GetStaticFloatField,
4053         _Jv_JNI_GetStaticDoubleField,
4054         _Jv_JNI_SetStaticObjectField,
4055         _Jv_JNI_SetStaticBooleanField,
4056         _Jv_JNI_SetStaticByteField,
4057         _Jv_JNI_SetStaticCharField,
4058         _Jv_JNI_SetStaticShortField,
4059         _Jv_JNI_SetStaticIntField,
4060         _Jv_JNI_SetStaticLongField,
4061         _Jv_JNI_SetStaticFloatField,
4062         _Jv_JNI_SetStaticDoubleField,
4063
4064         _Jv_JNI_NewString,
4065         _Jv_JNI_GetStringLength,
4066         _Jv_JNI_GetStringChars,
4067         _Jv_JNI_ReleaseStringChars,
4068
4069         _Jv_JNI_NewStringUTF,
4070         _Jv_JNI_GetStringUTFLength,
4071         _Jv_JNI_GetStringUTFChars,
4072         _Jv_JNI_ReleaseStringUTFChars,
4073
4074         _Jv_JNI_GetArrayLength,
4075
4076         _Jv_JNI_NewObjectArray,
4077         _Jv_JNI_GetObjectArrayElement,
4078         _Jv_JNI_SetObjectArrayElement,
4079
4080         _Jv_JNI_NewBooleanArray,
4081         _Jv_JNI_NewByteArray,
4082         _Jv_JNI_NewCharArray,
4083         _Jv_JNI_NewShortArray,
4084         _Jv_JNI_NewIntArray,
4085         _Jv_JNI_NewLongArray,
4086         _Jv_JNI_NewFloatArray,
4087         _Jv_JNI_NewDoubleArray,
4088
4089         _Jv_JNI_GetBooleanArrayElements,
4090         _Jv_JNI_GetByteArrayElements,
4091         _Jv_JNI_GetCharArrayElements,
4092         _Jv_JNI_GetShortArrayElements,
4093         _Jv_JNI_GetIntArrayElements,
4094         _Jv_JNI_GetLongArrayElements,
4095         _Jv_JNI_GetFloatArrayElements,
4096         _Jv_JNI_GetDoubleArrayElements,
4097
4098         _Jv_JNI_ReleaseBooleanArrayElements,
4099         _Jv_JNI_ReleaseByteArrayElements,
4100         _Jv_JNI_ReleaseCharArrayElements,
4101         _Jv_JNI_ReleaseShortArrayElements,
4102         _Jv_JNI_ReleaseIntArrayElements,
4103         _Jv_JNI_ReleaseLongArrayElements,
4104         _Jv_JNI_ReleaseFloatArrayElements,
4105         _Jv_JNI_ReleaseDoubleArrayElements,
4106
4107         _Jv_JNI_GetBooleanArrayRegion,
4108         _Jv_JNI_GetByteArrayRegion,
4109         _Jv_JNI_GetCharArrayRegion,
4110         _Jv_JNI_GetShortArrayRegion,
4111         _Jv_JNI_GetIntArrayRegion,
4112         _Jv_JNI_GetLongArrayRegion,
4113         _Jv_JNI_GetFloatArrayRegion,
4114         _Jv_JNI_GetDoubleArrayRegion,
4115         _Jv_JNI_SetBooleanArrayRegion,
4116         _Jv_JNI_SetByteArrayRegion,
4117         _Jv_JNI_SetCharArrayRegion,
4118         _Jv_JNI_SetShortArrayRegion,
4119         _Jv_JNI_SetIntArrayRegion,
4120         _Jv_JNI_SetLongArrayRegion,
4121         _Jv_JNI_SetFloatArrayRegion,
4122         _Jv_JNI_SetDoubleArrayRegion,
4123
4124         _Jv_JNI_RegisterNatives,
4125         _Jv_JNI_UnregisterNatives,
4126
4127         _Jv_JNI_MonitorEnter,
4128         _Jv_JNI_MonitorExit,
4129
4130         _Jv_JNI_GetJavaVM,
4131
4132         /* new JNI 1.2 functions */
4133
4134         _Jv_JNI_GetStringRegion,
4135         _Jv_JNI_GetStringUTFRegion,
4136
4137         _Jv_JNI_GetPrimitiveArrayCritical,
4138         _Jv_JNI_ReleasePrimitiveArrayCritical,
4139
4140         _Jv_JNI_GetStringCritical,
4141         _Jv_JNI_ReleaseStringCritical,
4142
4143         _Jv_JNI_NewWeakGlobalRef,
4144         _Jv_JNI_DeleteWeakGlobalRef,
4145
4146         _Jv_JNI_ExceptionCheck,
4147
4148         /* new JNI 1.4 functions */
4149
4150         _Jv_JNI_NewDirectByteBuffer,
4151         _Jv_JNI_GetDirectBufferAddress,
4152         _Jv_JNI_GetDirectBufferCapacity
4153 };
4154
4155
4156 /* Invocation API Functions ***************************************************/
4157
4158 /* JNI_GetDefaultJavaVMInitArgs ************************************************
4159
4160    Returns a default configuration for the Java VM.
4161
4162 *******************************************************************************/
4163
4164 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
4165 {
4166         JavaVMInitArgs *_vm_args;
4167
4168         _vm_args = (JavaVMInitArgs *) vm_args;
4169
4170         /* GNU classpath currently supports JNI 1.2 */
4171
4172         switch (_vm_args->version) {
4173     case JNI_VERSION_1_1:
4174                 _vm_args->version = JNI_VERSION_1_1;
4175                 break;
4176
4177     case JNI_VERSION_1_2:
4178     case JNI_VERSION_1_4:
4179                 _vm_args->ignoreUnrecognized = JNI_FALSE;
4180                 _vm_args->options = NULL;
4181                 _vm_args->nOptions = 0;
4182                 break;
4183
4184     default:
4185                 return -1;
4186         }
4187   
4188         return 0;
4189 }
4190
4191
4192 /* JNI_GetCreatedJavaVMs *******************************************************
4193
4194    Returns all Java VMs that have been created. Pointers to VMs are written in
4195    the buffer vmBuf in the order they are created. At most bufLen number of
4196    entries will be written. The total number of created VMs is returned in
4197    *nVMs.
4198
4199 *******************************************************************************/
4200
4201 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
4202 {
4203         TRACEJNICALLS("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs);
4204
4205         if (bufLen <= 0)
4206                 return JNI_ERR;
4207
4208         /* We currently only support 1 VM running. */
4209
4210         vmBuf[0] = (JavaVM *) _Jv_jvm;
4211         *nVMs    = 1;
4212
4213     return JNI_OK;
4214 }
4215
4216
4217 /* JNI_CreateJavaVM ************************************************************
4218
4219    Loads and initializes a Java VM. The current thread becomes the main thread.
4220    Sets the env argument to the JNI interface pointer of the main thread.
4221
4222 *******************************************************************************/
4223
4224 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
4225 {
4226         TRACEJNICALLS("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args);
4227
4228         /* actually create the JVM */
4229
4230         if (!vm_createjvm(p_vm, p_env, vm_args))
4231                 return JNI_ERR;
4232
4233         return JNI_OK;
4234 }
4235
4236
4237 /*
4238  * These are local overrides for various environment variables in Emacs.
4239  * Please do not remove this and leave it at the end of the file, where
4240  * Emacs will automagically detect them.
4241  * ---------------------------------------------------------------------
4242  * Local variables:
4243  * mode: c
4244  * indent-tabs-mode: t
4245  * c-basic-offset: 4
4246  * tab-width: 4
4247  * End:
4248  * vim:noexpandtab:sw=4:ts=4:
4249  */