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