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