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