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