* This commit adds C++ wrapper classes for OpenJDK. Actually I'm done
[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.h"
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/thread.hpp"
48
49 #include "toolbox/logging.h"
50
51 #include "vm/array.h"
52 #include "vm/builtin.h"
53 #include "vm/exceptions.hpp"
54 #include "vm/global.h"
55 #include "vm/initialize.h"
56 #include "vm/primitive.hpp"
57 #include "vm/resolve.h"
58 #include "vm/string.hpp"
59 #include "vm/vm.hpp"
60
61 #include "vm/jit/argument.h"
62 #include "vm/jit/asmpart.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/stacktrace.hpp"
65
66 #include "vmcore/globals.hpp"
67 #include "vmcore/javaobjects.hpp"
68 #include "vmcore/loader.h"
69 #include "vmcore/options.h"
70 #include "vmcore/statistics.h"
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         java_handle_t* o;
1453         methodinfo*    m;
1454
1455         TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
1456
1457         o = (java_handle_t *) method;
1458
1459         if (o == NULL)
1460                 return NULL;
1461
1462         // FIXME We can't access the object here directly.
1463         if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
1464                 java_lang_reflect_Constructor rc(method);
1465                 m = rc.get_method();
1466         }
1467         else {
1468                 // FIXME We can't access the object here directly.
1469                 assert(o->vftbl->clazz == class_java_lang_reflect_Method);
1470
1471                 java_lang_reflect_Method rm(method);
1472                 m = rm.get_method();
1473         }
1474
1475         return (jmethodID) m;
1476 #else
1477         vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
1478
1479         // Keep compiler happy.
1480         return NULL;
1481 #endif
1482 }
1483
1484
1485 /* FromReflectedField **********************************************************
1486
1487    Converts a java.lang.reflect.Field to a field ID.
1488
1489 *******************************************************************************/
1490  
1491 jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
1492 {
1493 #if defined(ENABLE_JAVASE)
1494
1495         TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
1496
1497         java_lang_reflect_Field rf(field);
1498
1499         if (rf.is_null())
1500                 return NULL;
1501
1502         fieldinfo* f = rf.get_field();
1503
1504         return (jfieldID) f;
1505 #else
1506         vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
1507
1508         // Keep compiler happy.
1509         return NULL;
1510 #endif
1511 }
1512
1513
1514 /* ToReflectedMethod ***********************************************************
1515
1516    Converts a method ID derived from cls to an instance of the
1517    java.lang.reflect.Method class or to an instance of the
1518    java.lang.reflect.Constructor class.
1519
1520 *******************************************************************************/
1521
1522 jobject jni_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
1523 {
1524 #if defined(ENABLE_JAVASE)
1525         TRACEJNICALLS(("jni_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
1526
1527         methodinfo* m = (methodinfo *) methodID;
1528
1529         /* HotSpot does the same assert. */
1530
1531         assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
1532
1533         java_handle_t* h;
1534
1535         if (m->name == utf_init) {
1536                 h = java_lang_reflect_Constructor(m).get_handle();
1537         }
1538         else {
1539                 h = java_lang_reflect_Method(m).get_handle();
1540         }
1541
1542         return (jobject) h;
1543 #else
1544         vm_abort("jni_ToReflectedMethod: Not implemented in this configuration.");
1545
1546         /* keep compiler happy */
1547
1548         return NULL;
1549 #endif
1550 }
1551
1552
1553 /* ToReflectedField ************************************************************
1554
1555    Converts a field ID derived from cls to an instance of the
1556    java.lang.reflect.Field class.
1557
1558 *******************************************************************************/
1559
1560 jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1561                                                                  jboolean isStatic)
1562 {
1563         STATISTICS(jniinvokation());
1564
1565         log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
1566
1567         return NULL;
1568 }
1569
1570
1571 /* Calling Instance Methods ***************************************************/
1572
1573 /* GetMethodID *****************************************************************
1574
1575    Returns the method ID for an instance (nonstatic) method of a class
1576    or interface. The method may be defined in one of the clazz's
1577    superclasses and inherited by clazz. The method is determined by
1578    its name and signature.
1579
1580    GetMethodID() causes an uninitialized class to be initialized.
1581
1582 *******************************************************************************/
1583
1584 jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
1585                                                           const char *sig)
1586 {
1587         classinfo  *c;
1588         utf        *uname;
1589         utf        *udesc;
1590         methodinfo *m;
1591
1592         STATISTICS(jniinvokation());
1593
1594         c = LLNI_classinfo_unwrap(clazz);
1595
1596         if (c == NULL)
1597                 return NULL;
1598
1599         if (!(c->state & CLASS_INITIALIZED))
1600                 if (!initialize_class(c))
1601                         return NULL;
1602
1603         /* try to get the method of the class or one of it's superclasses */
1604
1605         uname = utf_new_char((char *) name);
1606         udesc = utf_new_char((char *) sig);
1607
1608         m = class_resolvemethod(c, uname, udesc);
1609
1610         if ((m == NULL) || (m->flags & ACC_STATIC)) {
1611                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
1612
1613                 return NULL;
1614         }
1615
1616         return (jmethodID) m;
1617 }
1618
1619
1620 /* JNI-functions for calling instance methods *********************************/
1621
1622 #define JNI_CALL_VIRTUAL_METHOD(name, type, intern)         \
1623 type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj,   \
1624                                                                 jmethodID methodID, ...)    \
1625 {                                                           \
1626         java_handle_t *o;                                       \
1627         methodinfo    *m;                                       \
1628         va_list        ap;                                      \
1629         type           ret;                                     \
1630                                                             \
1631         o = (java_handle_t *) obj;                              \
1632         m = (methodinfo *) methodID;                            \
1633                                                             \
1634         va_start(ap, methodID);                                 \
1635         ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, ap); \
1636         va_end(ap);                                             \
1637                                                             \
1638         return ret;                                             \
1639 }
1640
1641 JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
1642 JNI_CALL_VIRTUAL_METHOD(Byte,    jbyte,    Int)
1643 JNI_CALL_VIRTUAL_METHOD(Char,    jchar,    Int)
1644 JNI_CALL_VIRTUAL_METHOD(Short,   jshort,   Int)
1645 JNI_CALL_VIRTUAL_METHOD(Int,     jint,     Int)
1646 JNI_CALL_VIRTUAL_METHOD(Long,    jlong,    Long)
1647 JNI_CALL_VIRTUAL_METHOD(Float,   jfloat,   Float)
1648 JNI_CALL_VIRTUAL_METHOD(Double,  jdouble,  Double)
1649
1650
1651 #define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern)              \
1652 type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj,         \
1653                                                                  jmethodID methodID, va_list args) \
1654 {                                                                  \
1655         java_handle_t *o;                                              \
1656         methodinfo    *m;                                              \
1657         type           ret;                                            \
1658                                                                    \
1659         o = (java_handle_t *) obj;                                     \
1660         m = (methodinfo *) methodID;                                   \
1661                                                                    \
1662         ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, args);      \
1663                                                                    \
1664         return ret;                                                    \
1665 }
1666
1667 JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
1668 JNI_CALL_VIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1669 JNI_CALL_VIRTUAL_METHOD_V(Char,    jchar,    Int)
1670 JNI_CALL_VIRTUAL_METHOD_V(Short,   jshort,   Int)
1671 JNI_CALL_VIRTUAL_METHOD_V(Int,     jint,     Int)
1672 JNI_CALL_VIRTUAL_METHOD_V(Long,    jlong,    Long)
1673 JNI_CALL_VIRTUAL_METHOD_V(Float,   jfloat,   Float)
1674 JNI_CALL_VIRTUAL_METHOD_V(Double,  jdouble,  Double)
1675
1676
1677 #define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern)          \
1678 type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj,     \
1679                                                                  jmethodID methodID,           \
1680                                                                  const jvalue *args)           \
1681 {                                                              \
1682         java_handle_t *o;                                          \
1683         methodinfo    *m;                                          \
1684         type           ret;                                        \
1685                                                                \
1686         o = (java_handle_t *) obj;                                 \
1687         m = (methodinfo *) methodID;                               \
1688                                                                \
1689         ret = _Jv_jni_Call##intern##MethodA(o, LLNI_vftbl_direct(o), m, args); \
1690                                                                \
1691         return ret;                                                \
1692 }
1693
1694 JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
1695 JNI_CALL_VIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1696 JNI_CALL_VIRTUAL_METHOD_A(Char,    jchar,    Int)
1697 JNI_CALL_VIRTUAL_METHOD_A(Short,   jshort,   Int)
1698 JNI_CALL_VIRTUAL_METHOD_A(Int,     jint,     Int)
1699 JNI_CALL_VIRTUAL_METHOD_A(Long,    jlong,    Long)
1700 JNI_CALL_VIRTUAL_METHOD_A(Float,   jfloat,   Float)
1701 JNI_CALL_VIRTUAL_METHOD_A(Double,  jdouble,  Double)
1702
1703
1704 jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
1705                                                                  ...)
1706 {
1707         java_handle_t *o;
1708         methodinfo    *m;
1709         java_handle_t *ret;
1710         va_list        ap;
1711
1712         o = (java_handle_t *) obj;
1713         m = (methodinfo *) methodID;
1714
1715         va_start(ap, methodID);
1716         ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, ap);
1717         va_end(ap);
1718
1719         return jni_NewLocalRef(env, (jobject) ret);
1720 }
1721
1722
1723 jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1724                                                                   va_list args)
1725 {
1726         java_handle_t *o;
1727         methodinfo    *m;
1728         java_handle_t *ret;
1729
1730         o = (java_handle_t *) obj;
1731         m = (methodinfo *) methodID;
1732
1733         ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, args);
1734
1735         return jni_NewLocalRef(env, (jobject) ret);
1736 }
1737
1738
1739 jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1740                                                                   const jvalue *args)
1741 {
1742         java_handle_t *o;
1743         methodinfo    *m;
1744         java_handle_t *ret;
1745
1746         o = (java_handle_t *) obj;
1747         m = (methodinfo *) methodID;
1748
1749         ret = _Jv_jni_CallObjectMethodA(o, LLNI_vftbl_direct(o), m, args);
1750
1751         return jni_NewLocalRef(env, (jobject) ret);
1752 }
1753
1754
1755
1756 void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1757 {
1758         java_handle_t *o;
1759         methodinfo    *m;
1760         va_list        ap;
1761
1762         o = (java_handle_t *) obj;
1763         m = (methodinfo *) methodID;
1764
1765         va_start(ap, methodID);
1766         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
1767         va_end(ap);
1768 }
1769
1770
1771 void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1772                                                          va_list args)
1773 {
1774         java_handle_t *o;
1775         methodinfo    *m;
1776
1777         o = (java_handle_t *) obj;
1778         m = (methodinfo *) methodID;
1779
1780         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
1781 }
1782
1783
1784 void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1785                                                          const jvalue *args)
1786 {
1787         java_handle_t *o;
1788         methodinfo    *m;
1789
1790         o = (java_handle_t *) obj;
1791         m = (methodinfo *) methodID;
1792
1793         _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
1794 }
1795
1796
1797
1798 #define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern)                      \
1799 type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj,         \
1800                                                                                   jclass clazz, jmethodID methodID, \
1801                                                                                   ...)                              \
1802 {                                                                           \
1803         java_handle_t *o;                                                       \
1804         classinfo     *c;                                                       \
1805         methodinfo    *m;                                                       \
1806         va_list        ap;                                                      \
1807         type           ret;                                                     \
1808                                                                             \
1809         o = (java_handle_t *) obj;                                              \
1810         c = LLNI_classinfo_unwrap(clazz);                                       \
1811         m = (methodinfo *) methodID;                                            \
1812                                                                             \
1813         va_start(ap, methodID);                                                 \
1814         ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap);                 \
1815         va_end(ap);                                                             \
1816                                                                             \
1817         return ret;                                                             \
1818 }
1819
1820 JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
1821 JNI_CALL_NONVIRTUAL_METHOD(Byte,    jbyte,    Int)
1822 JNI_CALL_NONVIRTUAL_METHOD(Char,    jchar,    Int)
1823 JNI_CALL_NONVIRTUAL_METHOD(Short,   jshort,   Int)
1824 JNI_CALL_NONVIRTUAL_METHOD(Int,     jint,     Int)
1825 JNI_CALL_NONVIRTUAL_METHOD(Long,    jlong,    Long)
1826 JNI_CALL_NONVIRTUAL_METHOD(Float,   jfloat,   Float)
1827 JNI_CALL_NONVIRTUAL_METHOD(Double,  jdouble,  Double)
1828
1829
1830 #define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern)                     \
1831 type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj,         \
1832                                                                                    jclass clazz, jmethodID methodID, \
1833                                                                                    va_list args)                     \
1834 {                                                                            \
1835         java_handle_t *o;                                                        \
1836         classinfo     *c;                                                        \
1837         methodinfo    *m;                                                        \
1838         type           ret;                                                      \
1839                                                                              \
1840         o = (java_handle_t *) obj;                                               \
1841         c = LLNI_classinfo_unwrap(clazz);                                        \
1842         m = (methodinfo *) methodID;                                             \
1843                                                                              \
1844         ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);                       \
1845                                                                              \
1846         return ret;                                                              \
1847 }
1848
1849 JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
1850 JNI_CALL_NONVIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1851 JNI_CALL_NONVIRTUAL_METHOD_V(Char,    jchar,    Int)
1852 JNI_CALL_NONVIRTUAL_METHOD_V(Short,   jshort,   Int)
1853 JNI_CALL_NONVIRTUAL_METHOD_V(Int,     jint,     Int)
1854 JNI_CALL_NONVIRTUAL_METHOD_V(Long,    jlong,    Long)
1855 JNI_CALL_NONVIRTUAL_METHOD_V(Float,   jfloat,   Float)
1856 JNI_CALL_NONVIRTUAL_METHOD_V(Double,  jdouble,  Double)
1857
1858
1859 #define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern)                     \
1860 type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj,         \
1861                                                                                    jclass clazz, jmethodID methodID, \
1862                                                                                    const jvalue *args)               \
1863 {                                                                            \
1864         log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!");      \
1865                                                                              \
1866         return 0;                                                                \
1867 }
1868
1869 JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
1870 JNI_CALL_NONVIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1871 JNI_CALL_NONVIRTUAL_METHOD_A(Char,    jchar,    Int)
1872 JNI_CALL_NONVIRTUAL_METHOD_A(Short,   jshort,   Int)
1873 JNI_CALL_NONVIRTUAL_METHOD_A(Int,     jint,     Int)
1874 JNI_CALL_NONVIRTUAL_METHOD_A(Long,    jlong,    Long)
1875 JNI_CALL_NONVIRTUAL_METHOD_A(Float,   jfloat,   Float)
1876 JNI_CALL_NONVIRTUAL_METHOD_A(Double,  jdouble,  Double)
1877
1878 jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
1879                                                                                    jclass clazz, jmethodID methodID,
1880                                                                                    ...)
1881 {
1882         java_handle_t *o;
1883         classinfo     *c;
1884         methodinfo    *m;
1885         java_handle_t *r;
1886         va_list        ap;
1887
1888         o = (java_handle_t *) obj;
1889         c = LLNI_classinfo_unwrap(clazz);
1890         m = (methodinfo *) methodID;
1891
1892         va_start(ap, methodID);
1893         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
1894         va_end(ap);
1895
1896         return jni_NewLocalRef(env, (jobject) r);
1897 }
1898
1899
1900 jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
1901                                                                                         jclass clazz, jmethodID methodID,
1902                                                                                         va_list args)
1903 {
1904         java_handle_t *o;
1905         classinfo     *c;
1906         methodinfo    *m;
1907         java_handle_t *r;
1908
1909         o = (java_handle_t *) obj;
1910         c = LLNI_classinfo_unwrap(clazz);
1911         m = (methodinfo *) methodID;
1912
1913         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
1914
1915         return jni_NewLocalRef(env, (jobject) r);
1916 }
1917
1918
1919 jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
1920                                                                                         jclass clazz, jmethodID methodID,
1921                                                                                         const jvalue *args)
1922 {
1923         log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
1924
1925         return jni_NewLocalRef(env, NULL);
1926 }
1927
1928
1929 void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
1930                                                                           jmethodID methodID, ...)
1931 {
1932         java_handle_t *o;
1933         classinfo     *c;
1934         methodinfo    *m;
1935         va_list        ap;
1936
1937         o = (java_handle_t *) obj;
1938         c = LLNI_classinfo_unwrap(clazz);
1939         m = (methodinfo *) methodID;
1940
1941         va_start(ap, methodID);
1942         _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
1943         va_end(ap);
1944 }
1945
1946
1947 void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
1948                                                                            jmethodID methodID, va_list args)
1949 {
1950         java_handle_t *o;
1951         classinfo     *c;
1952         methodinfo    *m;
1953
1954         o = (java_handle_t *) obj;
1955         c = LLNI_classinfo_unwrap(clazz);
1956         m = (methodinfo *) methodID;
1957
1958         _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
1959 }
1960
1961
1962 void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
1963                                                                            jmethodID methodID, const jvalue * args)
1964 {       
1965         java_handle_t *o;
1966         classinfo     *c;
1967         methodinfo    *m;
1968
1969         o = (java_handle_t *) obj;
1970         c = LLNI_classinfo_unwrap(clazz);
1971         m = (methodinfo *) methodID;
1972
1973         _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
1974 }
1975
1976
1977 /* Accessing Fields of Objects ************************************************/
1978
1979 /* GetFieldID ******************************************************************
1980
1981    Returns the field ID for an instance (nonstatic) field of a
1982    class. The field is specified by its name and signature. The
1983    Get<type>Field and Set<type>Field families of accessor functions
1984    use field IDs to retrieve object fields.
1985
1986 *******************************************************************************/
1987
1988 jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
1989                                                         const char *sig)
1990 {
1991         classinfo *c;
1992         fieldinfo *f;
1993         utf       *uname;
1994         utf       *udesc;
1995
1996         STATISTICS(jniinvokation());
1997
1998         c = LLNI_classinfo_unwrap(clazz);
1999
2000         /* XXX NPE check? */
2001
2002         uname = utf_new_char((char *) name);
2003         udesc = utf_new_char((char *) sig);
2004
2005         f = class_findfield(c, uname, udesc); 
2006         
2007         if (f == NULL)
2008                 exceptions_throw_nosuchfielderror(c, uname);  
2009
2010         return (jfieldID) f;
2011 }
2012
2013
2014 /* Get<type>Field Routines *****************************************************
2015
2016    This family of accessor routines returns the value of an instance
2017    (nonstatic) field of an object. The field to access is specified by
2018    a field ID obtained by calling GetFieldID().
2019
2020 *******************************************************************************/
2021
2022 #define GET_FIELD(o,type,f) \
2023     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
2024
2025 #define JNI_GET_FIELD(name, type, intern)                                 \
2026 type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
2027 {                                                                         \
2028         intern ret;                                                           \
2029                                                                           \
2030         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "Field(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID)); \
2031                                                                           \
2032         LLNI_CRITICAL_START;                                                  \
2033                                                                           \
2034         ret = GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID); \
2035                                                                           \
2036         LLNI_CRITICAL_END;                                                    \
2037                                                                           \
2038         return (type) ret;                                                    \
2039 }
2040
2041 JNI_GET_FIELD(Boolean, jboolean, s4)
2042 JNI_GET_FIELD(Byte,    jbyte,    s4)
2043 JNI_GET_FIELD(Char,    jchar,    s4)
2044 JNI_GET_FIELD(Short,   jshort,   s4)
2045 JNI_GET_FIELD(Int,     jint,     s4)
2046 JNI_GET_FIELD(Long,    jlong,    s8)
2047 JNI_GET_FIELD(Float,   jfloat,   float)
2048 JNI_GET_FIELD(Double,  jdouble,  double)
2049
2050
2051 jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
2052 {
2053         java_handle_t *o;
2054
2055         TRACEJNICALLS(("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID));
2056
2057         LLNI_CRITICAL_START;
2058
2059         o = LLNI_WRAP(GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), java_object_t*, fieldID));
2060
2061         LLNI_CRITICAL_END;
2062
2063         return jni_NewLocalRef(env, (jobject) o);
2064 }
2065
2066
2067 /* Set<type>Field Routines *****************************************************
2068
2069    This family of accessor routines sets the value of an instance
2070    (nonstatic) field of an object. The field to access is specified by
2071    a field ID obtained by calling GetFieldID().
2072
2073 *******************************************************************************/
2074
2075 #define SET_FIELD(o,type,f,value) \
2076     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
2077
2078 #define JNI_SET_FIELD(name, type, intern)                                  \
2079 void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
2080                                                           type value)                                  \
2081 {                                                                          \
2082         TRACEJNICALLS(("_Jv_JNI_Set" STR(name) "Field(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value)); \
2083                                                                            \
2084         LLNI_CRITICAL_START;                                                   \
2085                                                                            \
2086         SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
2087                                                                                \
2088         LLNI_CRITICAL_START;                                                   \
2089 }
2090
2091 JNI_SET_FIELD(Boolean, jboolean, s4)
2092 JNI_SET_FIELD(Byte,    jbyte,    s4)
2093 JNI_SET_FIELD(Char,    jchar,    s4)
2094 JNI_SET_FIELD(Short,   jshort,   s4)
2095 JNI_SET_FIELD(Int,     jint,     s4)
2096 JNI_SET_FIELD(Long,    jlong,    s8)
2097 JNI_SET_FIELD(Float,   jfloat,   float)
2098 JNI_SET_FIELD(Double,  jdouble,  double)
2099
2100
2101 void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
2102                                                         jobject value)
2103 {
2104         TRACEJNICALLS(("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value));
2105
2106         LLNI_CRITICAL_START;
2107
2108         SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
2109
2110         LLNI_CRITICAL_END;
2111 }
2112
2113
2114 /* Calling Static Methods *****************************************************/
2115
2116 /* GetStaticMethodID ***********************************************************
2117
2118    Returns the method ID for a static method of a class. The method is
2119    specified by its name and signature.
2120
2121    GetStaticMethodID() causes an uninitialized class to be
2122    initialized.
2123
2124 *******************************************************************************/
2125
2126 jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
2127                                                                         const char *sig)
2128 {
2129         classinfo  *c;
2130         utf        *uname;
2131         utf        *udesc;
2132         methodinfo *m;
2133
2134         TRACEJNICALLS(("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig));
2135
2136         c = LLNI_classinfo_unwrap(clazz);
2137
2138         if (c == NULL)
2139                 return NULL;
2140
2141         if (!(c->state & CLASS_INITIALIZED))
2142                 if (!initialize_class(c))
2143                         return NULL;
2144
2145         /* try to get the static method of the class */
2146
2147         uname = utf_new_char((char *) name);
2148         udesc = utf_new_char((char *) sig);
2149
2150         m = class_resolvemethod(c, uname, udesc);
2151
2152         if ((m == NULL) || !(m->flags & ACC_STATIC)) {
2153                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
2154
2155                 return NULL;
2156         }
2157
2158         return (jmethodID) m;
2159 }
2160
2161
2162 #define JNI_CALL_STATIC_METHOD(name, type, intern)               \
2163 type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
2164                                                                           jmethodID methodID, ...)   \
2165 {                                                                \
2166         methodinfo *m;                                               \
2167         va_list     ap;                                              \
2168         type        res;                                             \
2169                                                                  \
2170         m = (methodinfo *) methodID;                                 \
2171                                                                  \
2172         va_start(ap, methodID);                                      \
2173         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap);       \
2174         va_end(ap);                                                  \
2175                                                                  \
2176         return res;                                                  \
2177 }
2178
2179 JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
2180 JNI_CALL_STATIC_METHOD(Byte,    jbyte,    Int)
2181 JNI_CALL_STATIC_METHOD(Char,    jchar,    Int)
2182 JNI_CALL_STATIC_METHOD(Short,   jshort,   Int)
2183 JNI_CALL_STATIC_METHOD(Int,     jint,     Int)
2184 JNI_CALL_STATIC_METHOD(Long,    jlong,    Long)
2185 JNI_CALL_STATIC_METHOD(Float,   jfloat,   Float)
2186 JNI_CALL_STATIC_METHOD(Double,  jdouble,  Double)
2187
2188
2189 #define JNI_CALL_STATIC_METHOD_V(name, type, intern)                     \
2190 type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz,        \
2191                                                                            jmethodID methodID, va_list args) \
2192 {                                                                        \
2193         methodinfo *m;                                                       \
2194         type        res;                                                     \
2195                                                                          \
2196         m = (methodinfo *) methodID;                                         \
2197                                                                          \
2198         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args);             \
2199                                                                          \
2200         return res;                                                          \
2201 }
2202
2203 JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
2204 JNI_CALL_STATIC_METHOD_V(Byte,    jbyte,    Int)
2205 JNI_CALL_STATIC_METHOD_V(Char,    jchar,    Int)
2206 JNI_CALL_STATIC_METHOD_V(Short,   jshort,   Int)
2207 JNI_CALL_STATIC_METHOD_V(Int,     jint,     Int)
2208 JNI_CALL_STATIC_METHOD_V(Long,    jlong,    Long)
2209 JNI_CALL_STATIC_METHOD_V(Float,   jfloat,   Float)
2210 JNI_CALL_STATIC_METHOD_V(Double,  jdouble,  Double)
2211
2212
2213 #define JNI_CALL_STATIC_METHOD_A(name, type, intern)                           \
2214 type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz,              \
2215                                                                            jmethodID methodID, const jvalue *args) \
2216 {                                                                              \
2217         methodinfo *m;                                                             \
2218         type        res;                                                           \
2219                                                                                \
2220         m = (methodinfo *) methodID;                                               \
2221                                                                                \
2222         res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args);                  \
2223                                                                                \
2224         return res;                                                                \
2225 }
2226
2227 JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
2228 JNI_CALL_STATIC_METHOD_A(Byte,    jbyte,    Int)
2229 JNI_CALL_STATIC_METHOD_A(Char,    jchar,    Int)
2230 JNI_CALL_STATIC_METHOD_A(Short,   jshort,   Int)
2231 JNI_CALL_STATIC_METHOD_A(Int,     jint,     Int)
2232 JNI_CALL_STATIC_METHOD_A(Long,    jlong,    Long)
2233 JNI_CALL_STATIC_METHOD_A(Float,   jfloat,   Float)
2234 JNI_CALL_STATIC_METHOD_A(Double,  jdouble,  Double)
2235
2236
2237 jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
2238                                                                            jmethodID methodID, ...)
2239 {
2240         methodinfo    *m;
2241         java_handle_t *o;
2242         va_list        ap;
2243
2244         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
2245
2246         m = (methodinfo *) methodID;
2247
2248         va_start(ap, methodID);
2249         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
2250         va_end(ap);
2251
2252         return jni_NewLocalRef(env, (jobject) o);
2253 }
2254
2255
2256 jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
2257                                                                                 jmethodID methodID, va_list args)
2258 {
2259         methodinfo    *m;
2260         java_handle_t *o;
2261
2262         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2263
2264         m = (methodinfo *) methodID;
2265
2266         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
2267
2268         return jni_NewLocalRef(env, (jobject) o);
2269 }
2270
2271
2272 jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
2273                                                                                 jmethodID methodID, const jvalue *args)
2274 {
2275         methodinfo    *m;
2276         java_handle_t *o;
2277
2278         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2279
2280         m = (methodinfo *) methodID;
2281
2282         o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
2283
2284         return jni_NewLocalRef(env, (jobject) o);
2285 }
2286
2287
2288 void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
2289                                                                   jmethodID methodID, ...)
2290 {
2291         methodinfo *m;
2292         va_list     ap;
2293
2294         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
2295
2296         m = (methodinfo *) methodID;
2297
2298         va_start(ap, methodID);
2299         _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
2300         va_end(ap);
2301 }
2302
2303
2304 void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
2305                                                                    jmethodID methodID, va_list args)
2306 {
2307         methodinfo *m;
2308
2309         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2310
2311         m = (methodinfo *) methodID;
2312
2313         _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
2314 }
2315
2316
2317 void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
2318                                                                    jmethodID methodID, const jvalue * args)
2319 {
2320         methodinfo *m;
2321
2322         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2323
2324         m = (methodinfo *) methodID;
2325
2326         _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
2327 }
2328
2329
2330 /* Accessing Static Fields ****************************************************/
2331
2332 /* GetStaticFieldID ************************************************************
2333
2334    Returns the field ID for a static field of a class. The field is
2335    specified by its name and signature. The GetStatic<type>Field and
2336    SetStatic<type>Field families of accessor functions use field IDs
2337    to retrieve static fields.
2338
2339 *******************************************************************************/
2340
2341 jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
2342                                                                   const char *sig)
2343 {
2344         classinfo *c;
2345         fieldinfo *f;
2346         utf       *uname;
2347         utf       *usig;
2348
2349         STATISTICS(jniinvokation());
2350
2351         c = LLNI_classinfo_unwrap(clazz);
2352
2353         uname = utf_new_char((char *) name);
2354         usig  = utf_new_char((char *) sig);
2355
2356         f = class_findfield(c, uname, usig);
2357         
2358         if (f == NULL)
2359                 exceptions_throw_nosuchfielderror(c, uname);
2360
2361         return (jfieldID) f;
2362 }
2363
2364
2365 /* GetStatic<type>Field ********************************************************
2366
2367    This family of accessor routines returns the value of a static
2368    field of an object.
2369
2370 *******************************************************************************/
2371
2372 #define JNI_GET_STATIC_FIELD(name, type, field)                \
2373 type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
2374                                                                         jfieldID fieldID)          \
2375 {                                                              \
2376         classinfo *c;                                              \
2377         fieldinfo *f;                                              \
2378                                                                \
2379         STATISTICS(jniinvokation());                               \
2380                                                                \
2381         c = LLNI_classinfo_unwrap(clazz);                          \
2382         f = (fieldinfo *) fieldID;                                 \
2383                                                                \
2384         if (!(c->state & CLASS_INITIALIZED))                       \
2385                 if (!initialize_class(c))                              \
2386                         return 0;                                          \
2387                                                                \
2388         return f->value->field;                                    \
2389 }
2390
2391 JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
2392 JNI_GET_STATIC_FIELD(Byte,    jbyte,    i)
2393 JNI_GET_STATIC_FIELD(Char,    jchar,    i)
2394 JNI_GET_STATIC_FIELD(Short,   jshort,   i)
2395 JNI_GET_STATIC_FIELD(Int,     jint,     i)
2396 JNI_GET_STATIC_FIELD(Long,    jlong,    l)
2397 JNI_GET_STATIC_FIELD(Float,   jfloat,   f)
2398 JNI_GET_STATIC_FIELD(Double,  jdouble,  d)
2399
2400
2401 jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
2402                                                                          jfieldID fieldID)
2403 {
2404         classinfo     *c;
2405         fieldinfo     *f;
2406         java_handle_t *h;
2407
2408         STATISTICS(jniinvokation());
2409
2410         c = LLNI_classinfo_unwrap(clazz);
2411         f = (fieldinfo *) fieldID;
2412
2413         if (!(c->state & CLASS_INITIALIZED))
2414                 if (!initialize_class(c))
2415                         return NULL;
2416
2417         h = (java_handle_t*) LLNI_WRAP(f->value->a);
2418
2419         return jni_NewLocalRef(env, (jobject) h);
2420 }
2421
2422
2423 /*  SetStatic<type>Field *******************************************************
2424
2425         This family of accessor routines sets the value of a static field
2426         of an object.
2427
2428 *******************************************************************************/
2429
2430 #define JNI_SET_STATIC_FIELD(name, type, field)                \
2431 void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
2432                                                                         jfieldID fieldID,          \
2433                                                                         type value)                \
2434 {                                                              \
2435         classinfo *c;                                              \
2436         fieldinfo *f;                                              \
2437                                                                \
2438         STATISTICS(jniinvokation());                               \
2439                                                                \
2440         c = LLNI_classinfo_unwrap(clazz);                          \
2441         f = (fieldinfo *) fieldID;                                 \
2442                                                                \
2443         if (!(c->state & CLASS_INITIALIZED))                       \
2444                 if (!initialize_class(c))                              \
2445                         return;                                            \
2446                                                                \
2447         f->value->field = value;                                   \
2448 }
2449
2450 JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
2451 JNI_SET_STATIC_FIELD(Byte,    jbyte,    i)
2452 JNI_SET_STATIC_FIELD(Char,    jchar,    i)
2453 JNI_SET_STATIC_FIELD(Short,   jshort,   i)
2454 JNI_SET_STATIC_FIELD(Int,     jint,     i)
2455 JNI_SET_STATIC_FIELD(Long,    jlong,    l)
2456 JNI_SET_STATIC_FIELD(Float,   jfloat,   f)
2457 JNI_SET_STATIC_FIELD(Double,  jdouble,  d)
2458
2459
2460 void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
2461                                                                   jobject value)
2462 {
2463         classinfo *c;
2464         fieldinfo *f;
2465
2466         STATISTICS(jniinvokation());
2467
2468         c = LLNI_classinfo_unwrap(clazz);
2469         f = (fieldinfo *) fieldID;
2470
2471         if (!(c->state & CLASS_INITIALIZED))
2472                 if (!initialize_class(c))
2473                         return;
2474
2475         f->value->a = LLNI_UNWRAP((java_handle_t *) value);
2476 }
2477
2478
2479 /* String Operations **********************************************************/
2480
2481 /* NewString *******************************************************************
2482
2483    Create new java.lang.String object from an array of Unicode
2484    characters.
2485
2486 *******************************************************************************/
2487
2488 jstring jni_NewString(JNIEnv *env, const jchar *buf, jsize len)
2489 {
2490         TRACEJNICALLS(("jni_NewString(env=%p, buf=%p, len=%d)", env, buf, len));
2491         
2492         java_handle_chararray_t* a = builtin_newarray_char(len);
2493
2494         if (a == NULL)
2495                 return NULL;
2496
2497         /* copy text */
2498         for (jsize i = 0; i < len; i++)
2499                 LLNI_array_direct(a, i) = buf[i];
2500
2501         java_handle_t* h = builtin_new(class_java_lang_String);
2502
2503         if (h == NULL)
2504                 return NULL;
2505
2506         java_lang_String s(h, a, len, 0);
2507
2508         return (jstring) jni_NewLocalRef(env, (jobject) s.get_handle());
2509 }
2510
2511
2512 static jchar emptyStringJ[]={0,0};
2513
2514 /* GetStringLength *************************************************************
2515
2516    Returns the length (the count of Unicode characters) of a Java
2517    string.
2518
2519 *******************************************************************************/
2520
2521 jsize jni_GetStringLength(JNIEnv *env, jstring str)
2522 {
2523         TRACEJNICALLSENTER(("jni_GetStringLength(env=%p, str=%p)", env, str));
2524
2525         java_lang_String s(str);
2526         jsize count = s.get_count();
2527
2528         TRACEJNICALLSEXIT(("->%d)", count));
2529
2530         return count;
2531 }
2532
2533
2534 /* GetStringChars **************************************************************
2535
2536    Returns a pointer to the array of Unicode characters of the
2537    string. This pointer is valid until ReleaseStringChars() is called.
2538
2539 *******************************************************************************/
2540
2541 const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
2542 {       
2543         u2      *stringbuffer;
2544         int32_t  i;
2545
2546         TRACEJNICALLS(("jni_GetStringChars(env=%p, str=%p, isCopy=%p)", env, str, isCopy));
2547
2548         if (str == NULL)
2549                 // FIXME This is really ugly.
2550                 return emptyStringJ;
2551
2552         java_lang_String s(str);
2553
2554         java_handle_chararray_t* ca     = s.get_value();
2555         int32_t                  count  = s.get_count();
2556         int32_t                  offset = s.get_offset();
2557         
2558         if (ca == NULL)
2559                 return NULL;
2560
2561         /* allocate memory */
2562
2563         stringbuffer = MNEW(u2, count + 1);
2564
2565         /* copy text */
2566
2567         for (i = 0; i < count; i++)
2568                 stringbuffer[i] = LLNI_array_direct(ca, offset + i);
2569         
2570         /* terminate string */
2571
2572         stringbuffer[i] = '\0';
2573
2574         if (isCopy)
2575                 *isCopy = JNI_TRUE;
2576
2577         return (jchar*) stringbuffer;
2578 }
2579
2580
2581 /* ReleaseStringChars **********************************************************
2582
2583    Informs the VM that the native code no longer needs access to
2584    chars. The chars argument is a pointer obtained from string using
2585    GetStringChars().
2586
2587 *******************************************************************************/
2588
2589 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
2590 {
2591         TRACEJNICALLS(("jni_ReleaseStringChars(env=%p, str=%p, chars=%p)", env, str, chars));
2592
2593         // FIXME
2594         if (chars == emptyStringJ)
2595                 return;
2596
2597         java_lang_String s(str);
2598         int32_t count = s.get_count();
2599
2600         MFREE(((jchar*) chars), jchar, count + 1);
2601 }
2602
2603
2604 /* NewStringUTF ****************************************************************
2605
2606    Constructs a new java.lang.String object from an array of UTF-8
2607    characters.
2608
2609 *******************************************************************************/
2610
2611 jstring jni_NewStringUTF(JNIEnv *env, const char *bytes)
2612 {
2613         TRACEJNICALLS(("jni_NewStringUTF(env=%p, bytes=%s)", env, bytes));
2614
2615         java_handle_t *h = javastring_safe_new_from_utf8(bytes);
2616
2617     return (jstring) jni_NewLocalRef(env, (jobject) h);
2618 }
2619
2620
2621 /****************** returns the utf8 length in bytes of a string *******************/
2622
2623 jsize jni_GetStringUTFLength(JNIEnv *env, jstring string)
2624 {   
2625         TRACEJNICALLS(("jni_GetStringUTFLength(env=%p, string=%p)", env, string));
2626
2627         java_lang_String s(string);
2628         java_handle_chararray_t* ca     = s.get_value();
2629         int32_t                  count  = s.get_count();
2630
2631         // FIXME GC critical section!
2632         int32_t length = u2_utflength(ca->data, count);
2633
2634         return length;
2635 }
2636
2637
2638 /* GetStringUTFChars ***********************************************************
2639
2640    Returns a pointer to an array of UTF-8 characters of the
2641    string. This array is valid until it is released by
2642    ReleaseStringUTFChars().
2643
2644 *******************************************************************************/
2645
2646 const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
2647                                                                           jboolean *isCopy)
2648 {
2649         utf *u;
2650
2651         STATISTICS(jniinvokation());
2652
2653         if (string == NULL)
2654                 return "";
2655
2656         if (isCopy)
2657                 *isCopy = JNI_TRUE;
2658         
2659         u = javastring_toutf((java_handle_t *) string, false);
2660
2661         if (u != NULL)
2662                 return u->text;
2663
2664         return "";
2665 }
2666
2667
2668 /* ReleaseStringUTFChars *******************************************************
2669
2670    Informs the VM that the native code no longer needs access to
2671    utf. The utf argument is a pointer derived from string using
2672    GetStringUTFChars().
2673
2674 *******************************************************************************/
2675
2676 void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
2677 {
2678         STATISTICS(jniinvokation());
2679
2680     /* XXX we don't release utf chars right now, perhaps that should be done 
2681            later. Since there is always one reference the garbage collector will
2682            never get them */
2683 }
2684
2685
2686 /* Array Operations ***********************************************************/
2687
2688 /* GetArrayLength **************************************************************
2689
2690    Returns the number of elements in the array.
2691
2692 *******************************************************************************/
2693
2694 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
2695 {
2696         java_handle_t *a;
2697         jsize          size;
2698
2699         TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
2700
2701         a = (java_handle_t *) array;
2702
2703         size = LLNI_array_size(a);
2704
2705         return size;
2706 }
2707
2708
2709 /* NewObjectArray **************************************************************
2710
2711    Constructs a new array holding objects in class elementClass. All
2712    elements are initially set to initialElement.
2713
2714 *******************************************************************************/
2715
2716 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
2717                                                                         jclass elementClass, jobject initialElement)
2718 {
2719         classinfo                 *c;
2720         java_handle_t             *o;
2721         java_handle_objectarray_t *oa;
2722         s4                         i;
2723
2724         STATISTICS(jniinvokation());
2725
2726         c = LLNI_classinfo_unwrap(elementClass);
2727         o = (java_handle_t *) initialElement;
2728
2729         if (length < 0) {
2730                 exceptions_throw_negativearraysizeexception();
2731                 return NULL;
2732         }
2733
2734     oa = builtin_anewarray(length, c);
2735
2736         if (oa == NULL)
2737                 return NULL;
2738
2739         /* set all elements to initialElement */
2740
2741         for (i = 0; i < length; i++)
2742                 array_objectarray_element_set(oa, i, o);
2743
2744         return (jobjectArray) jni_NewLocalRef(env, (jobject) oa);
2745 }
2746
2747
2748 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
2749                                                                           jsize index)
2750 {
2751         java_handle_objectarray_t *oa;
2752         java_handle_t             *o;
2753
2754         STATISTICS(jniinvokation());
2755
2756         oa = (java_handle_objectarray_t *) array;
2757
2758         if (index >= LLNI_array_size(oa)) {
2759                 exceptions_throw_arrayindexoutofboundsexception();
2760                 return NULL;
2761         }
2762
2763         o = array_objectarray_element_get(oa, index);
2764
2765         return jni_NewLocalRef(env, (jobject) o);
2766 }
2767
2768
2769 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
2770                                                                    jsize index, jobject val)
2771 {
2772         java_handle_objectarray_t *oa;
2773         java_handle_t             *o;
2774
2775         STATISTICS(jniinvokation());
2776
2777         oa = (java_handle_objectarray_t *) array;
2778         o  = (java_handle_t *) val;
2779
2780         if (index >= LLNI_array_size(oa)) {
2781                 exceptions_throw_arrayindexoutofboundsexception();
2782                 return;
2783         }
2784
2785         /* check if the class of value is a subclass of the element class
2786            of the array */
2787
2788         if (!builtin_canstore(oa, o))
2789                 return;
2790
2791         array_objectarray_element_set(oa, index, o);
2792 }
2793
2794
2795 #define JNI_NEW_ARRAY(name, type, intern)                \
2796 type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
2797 {                                                        \
2798         java_handle_##intern##array_t *a;                    \
2799                                                          \
2800         STATISTICS(jniinvokation());                         \
2801                                                          \
2802         if (len < 0) {                                       \
2803                 exceptions_throw_negativearraysizeexception();   \
2804                 return NULL;                                     \
2805         }                                                    \
2806                                                          \
2807         a = builtin_newarray_##intern(len);                  \
2808                                                          \
2809         return (type) jni_NewLocalRef(env, (jobject) a); \
2810 }
2811
2812 JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
2813 JNI_NEW_ARRAY(Byte,    jbyteArray,    byte)
2814 JNI_NEW_ARRAY(Char,    jcharArray,    char)
2815 JNI_NEW_ARRAY(Short,   jshortArray,   short)
2816 JNI_NEW_ARRAY(Int,     jintArray,     int)
2817 JNI_NEW_ARRAY(Long,    jlongArray,    long)
2818 JNI_NEW_ARRAY(Float,   jfloatArray,   float)
2819 JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
2820
2821
2822 /* Get<PrimitiveType>ArrayElements *********************************************
2823
2824    A family of functions that returns the body of the primitive array.
2825
2826 *******************************************************************************/
2827
2828 #define JNI_GET_ARRAY_ELEMENTS(name, type, intern)                     \
2829 type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
2830                                                                                  jboolean *isCopy)             \
2831 {                                                                      \
2832         java_handle_##intern##array_t *a;                                  \
2833                                                                        \
2834         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
2835                                                                        \
2836         a = (java_handle_##intern##array_t *) array;                       \
2837                                                                        \
2838         if (isCopy)                                                        \
2839                 *isCopy = JNI_FALSE;                                           \
2840                                                                        \
2841         return (type *) LLNI_array_data(a);                                \
2842 }
2843
2844 JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
2845 JNI_GET_ARRAY_ELEMENTS(Byte,    jbyte,    byte)
2846 JNI_GET_ARRAY_ELEMENTS(Char,    jchar,    char)
2847 JNI_GET_ARRAY_ELEMENTS(Short,   jshort,   short)
2848 JNI_GET_ARRAY_ELEMENTS(Int,     jint,     int)
2849 JNI_GET_ARRAY_ELEMENTS(Long,    jlong,    long)
2850 JNI_GET_ARRAY_ELEMENTS(Float,   jfloat,   float)
2851 JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
2852
2853
2854 /* Release<PrimitiveType>ArrayElements *****************************************
2855
2856    A family of functions that informs the VM that the native code no
2857    longer needs access to elems. The elems argument is a pointer
2858    derived from array using the corresponding
2859    Get<PrimitiveType>ArrayElements() function. If necessary, this
2860    function copies back all changes made to elems to the original
2861    array.
2862
2863 *******************************************************************************/
2864
2865 #define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2)            \
2866 void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
2867                                                                                   type *elems, jint mode)          \
2868 {                                                                          \
2869         java_handle_##intern##array_t *a;                                      \
2870                                                                            \
2871         STATISTICS(jniinvokation());                                           \
2872                                                                            \
2873         a = (java_handle_##intern##array_t *) array;                           \
2874                                                                            \
2875         if (elems != (type *) LLNI_array_data(a)) {                            \
2876                 switch (mode) {                                                    \
2877                 case JNI_COMMIT:                                                   \
2878                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
2879                         break;                                                         \
2880                 case 0:                                                            \
2881                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
2882                         /* XXX TWISTI how should it be freed? */                       \
2883                         break;                                                         \
2884                 case JNI_ABORT:                                                    \
2885                         /* XXX TWISTI how should it be freed? */                       \
2886                         break;                                                         \
2887                 }                                                                  \
2888         }                                                                      \
2889 }
2890
2891 JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
2892 JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
2893 JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
2894 JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
2895 JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
2896 JNI_RELEASE_ARRAY_ELEMENTS(Long,    jlong,    long,    s8)
2897 JNI_RELEASE_ARRAY_ELEMENTS(Float,   jfloat,   float,   float)
2898 JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
2899
2900
2901 /*  Get<PrimitiveType>ArrayRegion **********************************************
2902
2903         A family of functions that copies a region of a primitive array
2904         into a buffer.
2905
2906 *******************************************************************************/
2907
2908 #define JNI_GET_ARRAY_REGION(name, type, intern, intern2)               \
2909 void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
2910                                                                         jsize start, jsize len, type *buf)  \
2911 {                                                                       \
2912         java_handle_##intern##array_t *a;                                   \
2913                                                                         \
2914         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
2915                                                                         \
2916         a = (java_handle_##intern##array_t *) array;                        \
2917                                                                         \
2918         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
2919                 exceptions_throw_arrayindexoutofboundsexception();              \
2920         else                                                                \
2921                 MCOPY(buf, &LLNI_array_direct(a, start), intern2, len);         \
2922 }
2923
2924 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
2925 JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
2926 JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
2927 JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
2928 JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
2929 JNI_GET_ARRAY_REGION(Long,    jlong,    long,    s8)
2930 JNI_GET_ARRAY_REGION(Float,   jfloat,   float,   float)
2931 JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
2932
2933
2934 /*  Set<PrimitiveType>ArrayRegion **********************************************
2935
2936         A family of functions that copies back a region of a primitive
2937         array from a buffer.
2938
2939 *******************************************************************************/
2940
2941 #define JNI_SET_ARRAY_REGION(name, type, intern, intern2)                    \
2942 void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
2943                                                                         jsize start, jsize len, const type *buf) \
2944 {                                                                            \
2945         java_handle_##intern##array_t *a;                                        \
2946                                                                              \
2947         STATISTICS(jniinvokation());                                             \
2948                                                                              \
2949         a = (java_handle_##intern##array_t *) array;                             \
2950                                                                              \
2951         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a)))      \
2952                 exceptions_throw_arrayindexoutofboundsexception();                   \
2953         else                                                                     \
2954                 MCOPY(&LLNI_array_direct(a, start), buf, intern2, len);              \
2955 }
2956
2957 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
2958 JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
2959 JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
2960 JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
2961 JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
2962 JNI_SET_ARRAY_REGION(Long,    jlong,    long,    s8)
2963 JNI_SET_ARRAY_REGION(Float,   jfloat,   float,   float)
2964 JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
2965
2966
2967 /* Registering Native Methods *************************************************/
2968
2969 /* RegisterNatives *************************************************************
2970
2971    Registers native methods with the class specified by the clazz
2972    argument. The methods parameter specifies an array of
2973    JNINativeMethod structures that contain the names, signatures, and
2974    function pointers of the native methods. The nMethods parameter
2975    specifies the number of native methods in the array.
2976
2977 *******************************************************************************/
2978
2979 jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
2980                                                          const JNINativeMethod *methods, jint nMethods)
2981 {
2982         classinfo *c;
2983
2984         STATISTICS(jniinvokation());
2985
2986         c = LLNI_classinfo_unwrap(clazz);
2987
2988         /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
2989         if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
2990         */
2991
2992         native_method_register(c->name, methods, nMethods);
2993
2994     return 0;
2995 }
2996
2997
2998 /* UnregisterNatives ***********************************************************
2999
3000    Unregisters native methods of a class. The class goes back to the
3001    state before it was linked or registered with its native method
3002    functions.
3003
3004    This function should not be used in normal native code. Instead, it
3005    provides special programs a way to reload and relink native
3006    libraries.
3007
3008 *******************************************************************************/
3009
3010 jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
3011 {
3012         STATISTICS(jniinvokation());
3013
3014         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
3015
3016     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
3017
3018     return 0;
3019 }
3020
3021
3022 /* Monitor Operations *********************************************************/
3023
3024 /* MonitorEnter ****************************************************************
3025
3026    Enters the monitor associated with the underlying Java object
3027    referred to by obj.
3028
3029 *******************************************************************************/
3030
3031 jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
3032 {
3033         STATISTICS(jniinvokation());
3034
3035         if (obj == NULL) {
3036                 exceptions_throw_nullpointerexception();
3037                 return JNI_ERR;
3038         }
3039
3040         LOCK_MONITOR_ENTER(obj);
3041
3042         return JNI_OK;
3043 }
3044
3045
3046 /* MonitorExit *****************************************************************
3047
3048    The current thread must be the owner of the monitor associated with
3049    the underlying Java object referred to by obj. The thread
3050    decrements the counter indicating the number of times it has
3051    entered this monitor. If the value of the counter becomes zero, the
3052    current thread releases the monitor.
3053
3054 *******************************************************************************/
3055
3056 jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
3057 {
3058         STATISTICS(jniinvokation());
3059
3060         if (obj == NULL) {
3061                 exceptions_throw_nullpointerexception();
3062                 return JNI_ERR;
3063         }
3064
3065         LOCK_MONITOR_EXIT(obj);
3066
3067         return JNI_OK;
3068 }
3069
3070
3071 /* JavaVM Interface ***********************************************************/
3072
3073 /* GetJavaVM *******************************************************************
3074
3075    Returns the Java VM interface (used in the Invocation API)
3076    associated with the current thread. The result is placed at the
3077    location pointed to by the second argument, vm.
3078
3079 *******************************************************************************/
3080
3081 jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
3082 {
3083         STATISTICS(jniinvokation());
3084
3085     *javavm = vm->get_javavm();
3086
3087         return 0;
3088 }
3089
3090
3091 /* GetStringRegion *************************************************************
3092
3093    Copies len number of Unicode characters beginning at offset start
3094    to the given buffer buf.
3095
3096    Throws StringIndexOutOfBoundsException on index overflow.
3097
3098 *******************************************************************************/
3099
3100 void jni_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
3101 {
3102         java_lang_String s(str);
3103         java_handle_chararray_t* ca    = s.get_value();
3104         int32_t                  count = s.get_count();
3105
3106         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3107                 exceptions_throw_stringindexoutofboundsexception();
3108                 return;
3109         }
3110
3111         MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
3112 }
3113
3114
3115 /* GetStringUTFRegion **********************************************************
3116
3117     Translates len number of Unicode characters beginning at offset
3118     start into UTF-8 format and place the result in the given buffer
3119     buf.
3120
3121     Throws StringIndexOutOfBoundsException on index overflow. 
3122
3123 *******************************************************************************/
3124
3125 void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
3126 {
3127         TRACEJNICALLS(("jni_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
3128
3129         java_lang_String s(str);
3130         java_handle_chararray_t* ca     = s.get_value();
3131         int32_t                  count  = s.get_count();
3132         int32_t                  offset = s.get_offset();
3133
3134         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3135                 exceptions_throw_stringindexoutofboundsexception();
3136                 return;
3137         }
3138
3139         int32_t i;
3140
3141         for (i = 0; i < len; i++)
3142                 buf[i] = LLNI_array_direct(ca, offset + start + i);
3143
3144         buf[i] = '\0';
3145 }
3146
3147
3148 /* GetPrimitiveArrayCritical ***************************************************
3149
3150    Obtain a direct pointer to array elements.
3151
3152    ATTENTION: Critical section keeps open when this function returns!
3153    See ReleasePrimitiveArrayCritical.
3154
3155 *******************************************************************************/
3156
3157 void* jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
3158 {
3159         java_handle_t*   h;
3160         java_array_t*    a;
3161         arraydescriptor* ad;
3162         void*            data;
3163
3164         TRACEJNICALLS(("jni_GetPrimitiveArrayCritical(env=%p, array=%p, isCopy=%d)", env, array, isCopy));
3165
3166         if (isCopy != NULL) {
3167                 *isCopy = JNI_FALSE;
3168         }
3169
3170         LLNI_CRITICAL_START;
3171
3172         h  = (java_handle_t*) array;
3173         a  = (java_array_t*) LLNI_UNWRAP(h);
3174         ad = a->objheader.vftbl->arraydesc;
3175
3176         /* Sanity check. */
3177
3178         assert(ad != NULL);
3179
3180         data = (void*) (((intptr_t) a) + ad->dataoffset);
3181
3182         return data;
3183 }
3184
3185
3186 /* ReleasePrimitiveArrayCritical ***********************************************
3187
3188    No specific documentation.
3189
3190    ATTENTION: This function closes the critical section opened in
3191    GetPrimitiveArrayCritical!
3192
3193 *******************************************************************************/
3194
3195 void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
3196 {
3197         TRACEJNICALLS(("jni_ReleasePrimitiveArrayCritical(env=%p, array=%p, carray=%p, mode=%d)", env, array, carray, mode));
3198
3199         LLNI_CRITICAL_END;
3200 }
3201
3202
3203 /* GetStringCritical ***********************************************************
3204
3205    The semantics of these two functions are similar to the existing
3206    Get/ReleaseStringChars functions.
3207
3208 *******************************************************************************/
3209
3210 const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
3211                                                                            jboolean *isCopy)
3212 {
3213         STATISTICS(jniinvokation());
3214
3215         return jni_GetStringChars(env, string, isCopy);
3216 }
3217
3218
3219 void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
3220                                                                    const jchar *cstring)
3221 {
3222         STATISTICS(jniinvokation());
3223
3224         _Jv_JNI_ReleaseStringChars(env, string, cstring);
3225 }
3226
3227
3228 jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
3229 {
3230         TRACEJNICALLS(("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj));
3231
3232         return (jweak) obj;
3233 }
3234
3235
3236 void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
3237 {
3238         TRACEJNICALLS(("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref));
3239 }
3240
3241
3242 /* NewGlobalRef ****************************************************************
3243
3244    Creates a new global reference to the object referred to by the obj
3245    argument.
3246
3247 *******************************************************************************/
3248     
3249 jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
3250 {
3251         hashtable_global_ref_entry *gre;
3252         u4   key;                           /* hashkey                            */
3253         u4   slot;                          /* slot in hashtable                  */
3254         java_handle_t *o;
3255
3256         TRACEJNICALLS(("jni_NewGlobalRef(env=%p, obj=%p)", env, obj));
3257
3258         o = (java_handle_t *) obj;
3259
3260         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
3261
3262         LLNI_CRITICAL_START;
3263
3264         /* normally addresses are aligned to 4, 8 or 16 bytes */
3265
3266         key  = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
3267         slot = key & (hashtable_global_ref->size - 1);
3268         gre  = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3269         
3270         /* search external hash chain for the entry */
3271
3272         while (gre) {
3273                 if (gre->o == LLNI_DIRECT(o)) {
3274                         /* global object found, increment the reference */
3275
3276                         gre->refs++;
3277
3278                         break;
3279                 }
3280
3281                 gre = gre->hashlink;                /* next element in external chain */
3282         }
3283
3284         LLNI_CRITICAL_END;
3285
3286         /* global ref not found, create a new one */
3287
3288         if (gre == NULL) {
3289                 gre = (hashtable_global_ref_entry*) heap_alloc_uncollectable(sizeof(hashtable_global_ref_entry));
3290
3291 #if defined(ENABLE_GC_CACAO)
3292                 /* register global ref with the GC */
3293
3294                 gc_reference_register(&(gre->o), GC_REFTYPE_JNI_GLOBALREF);
3295 #endif
3296
3297                 LLNI_CRITICAL_START;
3298
3299                 gre->o    = LLNI_DIRECT(o);
3300                 gre->refs = 1;
3301
3302                 LLNI_CRITICAL_END;
3303
3304                 /* insert entry into hashtable */
3305
3306                 gre->hashlink = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3307
3308                 hashtable_global_ref->ptr[slot] = gre;
3309
3310                 /* update number of hashtable-entries */
3311
3312                 hashtable_global_ref->entries++;
3313         }
3314
3315         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3316
3317 #if defined(ENABLE_HANDLES)
3318         return gre;
3319 #else
3320         return obj;
3321 #endif
3322 }
3323
3324
3325 /* DeleteGlobalRef *************************************************************
3326
3327    Deletes the global reference pointed to by globalRef.
3328
3329 *******************************************************************************/
3330
3331 void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
3332 {
3333         hashtable_global_ref_entry *gre;
3334         hashtable_global_ref_entry *prevgre;
3335         u4   key;                           /* hashkey                            */
3336         u4   slot;                          /* slot in hashtable                  */
3337         java_handle_t              *o;
3338
3339         TRACEJNICALLS(("jni_DeleteGlobalRef(env=%p, globalRef=%p)", env, globalRef));
3340
3341         o = (java_handle_t *) globalRef;
3342
3343         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
3344
3345         LLNI_CRITICAL_START;
3346
3347         /* normally addresses are aligned to 4, 8 or 16 bytes */
3348
3349         key  = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
3350         slot = key & (hashtable_global_ref->size - 1);
3351         gre  = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3352
3353         /* initialize prevgre */
3354
3355         prevgre = NULL;
3356
3357         /* search external hash chain for the entry */
3358
3359         while (gre) {
3360                 if (gre->o == LLNI_DIRECT(o)) {
3361                         /* global object found, decrement the reference count */
3362
3363                         gre->refs--;
3364
3365                         /* if reference count is 0, remove the entry */
3366
3367                         if (gre->refs == 0) {
3368                                 /* special handling if it's the first in the chain */
3369
3370                                 if (prevgre == NULL)
3371                                         hashtable_global_ref->ptr[slot] = gre->hashlink;
3372                                 else
3373                                         prevgre->hashlink = gre->hashlink;
3374
3375 #if defined(ENABLE_GC_CACAO)
3376                                 /* unregister global ref with the GC */
3377
3378                                 gc_reference_unregister(&(gre->o));
3379 #endif
3380
3381                                 heap_free(gre);
3382                         }
3383
3384                         LLNI_CRITICAL_END;
3385
3386                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3387
3388                         return;
3389                 }
3390
3391                 prevgre = gre;                    /* save current pointer for removal */
3392                 gre     = gre->hashlink;            /* next element in external chain */
3393         }
3394
3395         log_println("jni_DeleteGlobalRef: Global reference not found.");
3396
3397         LLNI_CRITICAL_END;
3398
3399         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
3400 }
3401
3402
3403 /* ExceptionCheck **************************************************************
3404
3405    Returns JNI_TRUE when there is a pending exception; otherwise,
3406    returns JNI_FALSE.
3407
3408 *******************************************************************************/
3409
3410 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
3411 {
3412         java_handle_t *o;
3413
3414         STATISTICS(jniinvokation());
3415
3416         o = exceptions_get_exception();
3417
3418         return (o != NULL) ? JNI_TRUE : JNI_FALSE;
3419 }
3420
3421
3422 /* New JNI 1.4 functions ******************************************************/
3423
3424 /* NewDirectByteBuffer *********************************************************
3425
3426    Allocates and returns a direct java.nio.ByteBuffer referring to the
3427    block of memory starting at the memory address address and
3428    extending capacity bytes.
3429
3430 *******************************************************************************/
3431
3432 jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
3433 {
3434 #if defined(ENABLE_JAVASE)
3435 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3436         TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
3437
3438         // Allocate a gnu.classpath.Pointer{32,64} object.
3439
3440 # if SIZEOF_VOID_P == 8
3441         java_handle_t* h = builtin_new(class_gnu_classpath_Pointer64);
3442 # else
3443         java_handle_t* h = builtin_new(class_gnu_classpath_Pointer32);
3444 # endif
3445
3446         if (h == NULL)
3447                 return NULL;
3448
3449         gnu_classpath_Pointer p(h, address);
3450
3451         // Create a java.nio.DirectByteBufferImpl$ReadWrite object.
3452
3453         java_handle_t* nbuf =
3454                 (java_handle_t*) jni_NewObject(env, (jclass) class_java_nio_DirectByteBufferImpl_ReadWrite,
3455                                                                            (jmethodID) dbbirw_init, NULL, p.get_handle(),
3456                                                                            (jint) capacity, (jint) capacity, (jint) 0);
3457
3458         // Add a local reference and return the value.
3459
3460         TRACEJNICALLSEXIT(("->%p", nbuf));
3461
3462         return jni_NewLocalRef(env, (jobject) nbuf);
3463
3464 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3465
3466         jobject o;
3467         int64_t addr;
3468         int32_t cap;
3469
3470         TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
3471
3472         /* Be paranoid about address sign-extension. */
3473
3474         addr = (int64_t) ((uintptr_t) address);
3475         cap  = (int32_t) capacity;
3476
3477         o = jni_NewObject(env, (jclass) class_java_nio_DirectByteBuffer,
3478                                           (jmethodID) dbb_init, addr, cap);
3479
3480         /* Add local reference and return the value. */
3481
3482         TRACEJNICALLSEXIT(("->%p", o));
3483
3484         return jni_NewLocalRef(env, o);
3485
3486 # else
3487 #  error unknown classpath configuration
3488 # endif
3489
3490 #else
3491         vm_abort("jni_NewDirectByteBuffer: Not implemented in this configuration.");
3492
3493         /* keep compiler happy */
3494
3495         return NULL;
3496 #endif
3497 }
3498
3499
3500 /* GetDirectBufferAddress ******************************************************
3501
3502    Fetches and returns the starting address of the memory region
3503    referenced by the given direct java.nio.Buffer.
3504
3505 *******************************************************************************/
3506
3507 void* jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
3508 {
3509 #if defined(ENABLE_JAVASE)
3510 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3511
3512         TRACEJNICALLSENTER(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
3513
3514         /* Prevent compiler warning. */
3515
3516         java_handle_t* h = (java_handle_t *) buf;
3517
3518         if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
3519                 return NULL;
3520
3521         java_nio_DirectByteBufferImpl dbb(buf);
3522         java_handle_t* address = dbb.get_address();
3523
3524         if (address == NULL) {
3525                 TRACEJNICALLSEXIT(("->%p", NULL));
3526                 return NULL;
3527         }
3528
3529         gnu_classpath_Pointer p(address);
3530         void* data = p.get_data();
3531
3532         TRACEJNICALLSEXIT(("->%p", data));
3533
3534         return data;
3535
3536 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3537
3538         TRACEJNICALLS(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
3539
3540         java_nio_Buffer jnb(buf);
3541
3542         if (jnb.is_non_null() && !builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
3543                 return NULL;
3544
3545         void* address = jnb.get_address();
3546
3547         return address;
3548
3549 # else
3550 #  error unknown classpath configuration
3551 # endif
3552
3553 #else
3554
3555         vm_abort("jni_GetDirectBufferAddress: Not implemented in this configuration.");
3556
3557         // Keep compiler happy.
3558         return NULL;
3559
3560 #endif
3561 }
3562
3563
3564 /* GetDirectBufferCapacity *****************************************************
3565
3566    Fetches and returns the capacity in bytes of the memory region
3567    referenced by the given direct java.nio.Buffer.
3568
3569 *******************************************************************************/
3570
3571 jlong jni_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
3572 {
3573 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3574         TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
3575
3576         java_handle_t* h = (java_handle_t *) buf;
3577
3578         if (!builtin_instanceof(h, class_java_nio_DirectByteBufferImpl))
3579                 return -1;
3580
3581         java_nio_Buffer b(h);
3582         jlong capacity = b.get_cap();
3583
3584         return capacity;
3585 #else
3586         vm_abort("jni_GetDirectBufferCapacity: not implemented in this configuration");
3587
3588         // Keep compiler happy.
3589
3590         return 0;
3591 #endif
3592 }
3593
3594
3595 /* GetObjectRefType ************************************************************
3596
3597    Returns the type of the object referred to by the obj argument. The
3598    argument obj can either be a local, global or weak global
3599    reference.
3600
3601 *******************************************************************************/
3602
3603 jobjectRefType jni_GetObjectRefType(JNIEnv *env, jobject obj)
3604 {
3605         log_println("jni_GetObjectRefType: IMPLEMENT ME!");
3606
3607         return (jobjectRefType) NULL;
3608 }
3609
3610
3611 /* DestroyJavaVM ***************************************************************
3612
3613    Unloads a Java VM and reclaims its resources. Only the main thread
3614    can unload the VM. The system waits until the main thread is only
3615    remaining user thread before it destroys the VM.
3616
3617 *******************************************************************************/
3618
3619 jint _Jv_JNI_DestroyJavaVM(JavaVM *javavm)
3620 {
3621         int status;
3622
3623         TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
3624
3625         if (vm->is_created() == false)
3626                 return JNI_ERR;
3627
3628     status = vm_destroy(javavm);
3629
3630         return status;
3631 }
3632
3633
3634 /* AttachCurrentThread *********************************************************
3635
3636    Attaches the current thread to a Java VM. Returns a JNI interface
3637    pointer in the JNIEnv argument.
3638
3639    Trying to attach a thread that is already attached is a no-op.
3640
3641    A native thread cannot be attached simultaneously to two Java VMs.
3642
3643    When a thread is attached to the VM, the context class loader is
3644    the bootstrap loader.
3645
3646 *******************************************************************************/
3647
3648 static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
3649 {
3650 #if defined(ENABLE_THREADS)
3651         JavaVMAttachArgs *vm_aargs;
3652         bool              result;
3653
3654     /* If the current thread has already been attached, this operation
3655            is a no-op. */
3656
3657         result = thread_current_is_attached();
3658
3659         if (result == true) {
3660                 *p_env = vm->get_jnienv();
3661                 return JNI_OK;
3662         }
3663
3664         vm_aargs = (JavaVMAttachArgs *) thr_args;
3665
3666         if (vm_aargs != NULL) {
3667                 if ((vm_aargs->version != JNI_VERSION_1_2) &&
3668                         (vm_aargs->version != JNI_VERSION_1_4))
3669                         return JNI_EVERSION;
3670         }
3671
3672         if (!thread_attach_current_external_thread(vm_aargs, false))
3673                 return JNI_ERR;
3674
3675         if (!localref_table_init())
3676                 return JNI_ERR;
3677 #endif
3678
3679         *p_env = vm->get_jnienv();
3680
3681         return JNI_OK;
3682 }
3683
3684
3685 jint jni_AttachCurrentThread(JavaVM *javavm, void **p_env, void *thr_args)
3686 {
3687         int result;
3688
3689         TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
3690
3691         if (vm->is_created() == false)
3692                 return JNI_ERR;
3693
3694         result = jni_attach_current_thread(p_env, thr_args, false);
3695
3696         return result;
3697 }
3698
3699
3700 /* DetachCurrentThread *********************************************************
3701
3702    Detaches the current thread from a Java VM. All Java monitors held
3703    by this thread are released. All Java threads waiting for this
3704    thread to die are notified.
3705
3706    In JDK 1.1, the main thread cannot be detached from the VM. It must
3707    call DestroyJavaVM to unload the entire VM.
3708
3709    In the JDK, the main thread can be detached from the VM.
3710
3711    The main thread, which is the thread that created the Java VM,
3712    cannot be detached from the VM. Instead, the main thread must call
3713    JNI_DestroyJavaVM() to unload the entire VM.
3714
3715 *******************************************************************************/
3716
3717 jint jni_DetachCurrentThread(JavaVM *vm)
3718 {
3719 #if defined(ENABLE_THREADS)
3720         bool result;
3721
3722         TRACEJNICALLS(("jni_DetachCurrentThread(vm=%p)", vm));
3723
3724     /* If the current thread has already been detached, this operation
3725            is a no-op. */
3726
3727         result = thread_current_is_attached();
3728
3729         if (result == false)
3730                 return true;
3731
3732         /* We need to pop all frames before we can destroy the table. */
3733
3734         localref_frame_pop_all();
3735
3736         if (!localref_table_destroy())
3737                 return JNI_ERR;
3738
3739         if (!thread_detach_current_external_thread())
3740                 return JNI_ERR;
3741 #endif
3742
3743         return JNI_OK;
3744 }
3745
3746
3747 /* GetEnv **********************************************************************
3748
3749    If the current thread is not attached to the VM, sets *env to NULL,
3750    and returns JNI_EDETACHED. If the specified version is not
3751    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
3752    sets *env to the appropriate interface, and returns JNI_OK.
3753
3754 *******************************************************************************/
3755
3756 jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
3757 {
3758         TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
3759
3760         if (vm->is_created() == false) {
3761                 *env = NULL;
3762                 return JNI_EDETACHED;
3763         }
3764
3765 #if defined(ENABLE_THREADS)
3766         if (thread_get_current() == NULL) {
3767                 *env = NULL;
3768
3769                 return JNI_EDETACHED;
3770         }
3771 #endif
3772
3773         /* Check the JNI version. */
3774
3775         if (jni_version_check(version) == true) {
3776                 *env = vm->get_jnienv();
3777                 return JNI_OK;
3778         }
3779
3780 #if defined(ENABLE_JVMTI)
3781         if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
3782                 == JVMTI_VERSION_INTERFACE_JVMTI) {
3783
3784                 *env = (void *) jvmti_new_environment();
3785
3786                 if (env != NULL)
3787                         return JNI_OK;
3788         }
3789 #endif
3790         
3791         *env = NULL;
3792
3793         return JNI_EVERSION;
3794 }
3795
3796
3797 /* AttachCurrentThreadAsDaemon *************************************************
3798
3799    Same semantics as AttachCurrentThread, but the newly-created
3800    java.lang.Thread instance is a daemon.
3801
3802    If the thread has already been attached via either
3803    AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
3804    simply sets the value pointed to by penv to the JNIEnv of the
3805    current thread. In this case neither AttachCurrentThread nor this
3806    routine have any effect on the daemon status of the thread.
3807
3808 *******************************************************************************/
3809
3810 jint jni_AttachCurrentThreadAsDaemon(JavaVM *javavm, void **penv, void *args)
3811 {
3812         int result;
3813
3814         TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
3815
3816         if (vm->is_created() == false)
3817                 return JNI_ERR;
3818
3819         result = jni_attach_current_thread(penv, args, true);
3820
3821         return result;
3822 }
3823
3824
3825 /* JNI invocation table *******************************************************/
3826
3827 const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
3828         NULL,
3829         NULL,
3830         NULL,
3831
3832         _Jv_JNI_DestroyJavaVM,
3833         jni_AttachCurrentThread,
3834         jni_DetachCurrentThread,
3835         jni_GetEnv,
3836         jni_AttachCurrentThreadAsDaemon
3837 };
3838
3839
3840 /* JNI function table *********************************************************/
3841
3842 struct JNINativeInterface_ _Jv_JNINativeInterface = {
3843         NULL,
3844         NULL,
3845         NULL,
3846         NULL,    
3847         _Jv_JNI_GetVersion,
3848
3849         jni_DefineClass,
3850         jni_FindClass,
3851         jni_FromReflectedMethod,
3852         jni_FromReflectedField,
3853         jni_ToReflectedMethod,
3854         jni_GetSuperclass,
3855         _Jv_JNI_IsAssignableFrom,
3856         _Jv_JNI_ToReflectedField,
3857
3858         _Jv_JNI_Throw,
3859         _Jv_JNI_ThrowNew,
3860         _Jv_JNI_ExceptionOccurred,
3861         jni_ExceptionDescribe,
3862         jni_ExceptionClear,
3863         _Jv_JNI_FatalError,
3864         jni_PushLocalFrame,
3865         jni_PopLocalFrame,
3866
3867         jni_NewGlobalRef,
3868         jni_DeleteGlobalRef,
3869         jni_DeleteLocalRef,
3870         _Jv_JNI_IsSameObject,
3871         jni_NewLocalRef,
3872         jni_EnsureLocalCapacity,
3873
3874         _Jv_JNI_AllocObject,
3875         jni_NewObject,
3876         _Jv_JNI_NewObjectV,
3877         _Jv_JNI_NewObjectA,
3878
3879         jni_GetObjectClass,
3880         _Jv_JNI_IsInstanceOf,
3881
3882         _Jv_JNI_GetMethodID,
3883
3884         _Jv_JNI_CallObjectMethod,
3885         _Jv_JNI_CallObjectMethodV,
3886         _Jv_JNI_CallObjectMethodA,
3887         _Jv_JNI_CallBooleanMethod,
3888         _Jv_JNI_CallBooleanMethodV,
3889         _Jv_JNI_CallBooleanMethodA,
3890         _Jv_JNI_CallByteMethod,
3891         _Jv_JNI_CallByteMethodV,
3892         _Jv_JNI_CallByteMethodA,
3893         _Jv_JNI_CallCharMethod,
3894         _Jv_JNI_CallCharMethodV,
3895         _Jv_JNI_CallCharMethodA,
3896         _Jv_JNI_CallShortMethod,
3897         _Jv_JNI_CallShortMethodV,
3898         _Jv_JNI_CallShortMethodA,
3899         _Jv_JNI_CallIntMethod,
3900         _Jv_JNI_CallIntMethodV,
3901         _Jv_JNI_CallIntMethodA,
3902         _Jv_JNI_CallLongMethod,
3903         _Jv_JNI_CallLongMethodV,
3904         _Jv_JNI_CallLongMethodA,
3905         _Jv_JNI_CallFloatMethod,
3906         _Jv_JNI_CallFloatMethodV,
3907         _Jv_JNI_CallFloatMethodA,
3908         _Jv_JNI_CallDoubleMethod,
3909         _Jv_JNI_CallDoubleMethodV,
3910         _Jv_JNI_CallDoubleMethodA,
3911         _Jv_JNI_CallVoidMethod,
3912         _Jv_JNI_CallVoidMethodV,
3913         _Jv_JNI_CallVoidMethodA,
3914
3915         _Jv_JNI_CallNonvirtualObjectMethod,
3916         _Jv_JNI_CallNonvirtualObjectMethodV,
3917         _Jv_JNI_CallNonvirtualObjectMethodA,
3918         _Jv_JNI_CallNonvirtualBooleanMethod,
3919         _Jv_JNI_CallNonvirtualBooleanMethodV,
3920         _Jv_JNI_CallNonvirtualBooleanMethodA,
3921         _Jv_JNI_CallNonvirtualByteMethod,
3922         _Jv_JNI_CallNonvirtualByteMethodV,
3923         _Jv_JNI_CallNonvirtualByteMethodA,
3924         _Jv_JNI_CallNonvirtualCharMethod,
3925         _Jv_JNI_CallNonvirtualCharMethodV,
3926         _Jv_JNI_CallNonvirtualCharMethodA,
3927         _Jv_JNI_CallNonvirtualShortMethod,
3928         _Jv_JNI_CallNonvirtualShortMethodV,
3929         _Jv_JNI_CallNonvirtualShortMethodA,
3930         _Jv_JNI_CallNonvirtualIntMethod,
3931         _Jv_JNI_CallNonvirtualIntMethodV,
3932         _Jv_JNI_CallNonvirtualIntMethodA,
3933         _Jv_JNI_CallNonvirtualLongMethod,
3934         _Jv_JNI_CallNonvirtualLongMethodV,
3935         _Jv_JNI_CallNonvirtualLongMethodA,
3936         _Jv_JNI_CallNonvirtualFloatMethod,
3937         _Jv_JNI_CallNonvirtualFloatMethodV,
3938         _Jv_JNI_CallNonvirtualFloatMethodA,
3939         _Jv_JNI_CallNonvirtualDoubleMethod,
3940         _Jv_JNI_CallNonvirtualDoubleMethodV,
3941         _Jv_JNI_CallNonvirtualDoubleMethodA,
3942         _Jv_JNI_CallNonvirtualVoidMethod,
3943         _Jv_JNI_CallNonvirtualVoidMethodV,
3944         _Jv_JNI_CallNonvirtualVoidMethodA,
3945
3946         _Jv_JNI_GetFieldID,
3947
3948         _Jv_JNI_GetObjectField,
3949         _Jv_JNI_GetBooleanField,
3950         _Jv_JNI_GetByteField,
3951         _Jv_JNI_GetCharField,
3952         _Jv_JNI_GetShortField,
3953         _Jv_JNI_GetIntField,
3954         _Jv_JNI_GetLongField,
3955         _Jv_JNI_GetFloatField,
3956         _Jv_JNI_GetDoubleField,
3957         _Jv_JNI_SetObjectField,
3958         _Jv_JNI_SetBooleanField,
3959         _Jv_JNI_SetByteField,
3960         _Jv_JNI_SetCharField,
3961         _Jv_JNI_SetShortField,
3962         _Jv_JNI_SetIntField,
3963         _Jv_JNI_SetLongField,
3964         _Jv_JNI_SetFloatField,
3965         _Jv_JNI_SetDoubleField,
3966
3967         _Jv_JNI_GetStaticMethodID,
3968
3969         _Jv_JNI_CallStaticObjectMethod,
3970         _Jv_JNI_CallStaticObjectMethodV,
3971         _Jv_JNI_CallStaticObjectMethodA,
3972         _Jv_JNI_CallStaticBooleanMethod,
3973         _Jv_JNI_CallStaticBooleanMethodV,
3974         _Jv_JNI_CallStaticBooleanMethodA,
3975         _Jv_JNI_CallStaticByteMethod,
3976         _Jv_JNI_CallStaticByteMethodV,
3977         _Jv_JNI_CallStaticByteMethodA,
3978         _Jv_JNI_CallStaticCharMethod,
3979         _Jv_JNI_CallStaticCharMethodV,
3980         _Jv_JNI_CallStaticCharMethodA,
3981         _Jv_JNI_CallStaticShortMethod,
3982         _Jv_JNI_CallStaticShortMethodV,
3983         _Jv_JNI_CallStaticShortMethodA,
3984         _Jv_JNI_CallStaticIntMethod,
3985         _Jv_JNI_CallStaticIntMethodV,
3986         _Jv_JNI_CallStaticIntMethodA,
3987         _Jv_JNI_CallStaticLongMethod,
3988         _Jv_JNI_CallStaticLongMethodV,
3989         _Jv_JNI_CallStaticLongMethodA,
3990         _Jv_JNI_CallStaticFloatMethod,
3991         _Jv_JNI_CallStaticFloatMethodV,
3992         _Jv_JNI_CallStaticFloatMethodA,
3993         _Jv_JNI_CallStaticDoubleMethod,
3994         _Jv_JNI_CallStaticDoubleMethodV,
3995         _Jv_JNI_CallStaticDoubleMethodA,
3996         _Jv_JNI_CallStaticVoidMethod,
3997         _Jv_JNI_CallStaticVoidMethodV,
3998         _Jv_JNI_CallStaticVoidMethodA,
3999
4000         _Jv_JNI_GetStaticFieldID,
4001
4002         _Jv_JNI_GetStaticObjectField,
4003         _Jv_JNI_GetStaticBooleanField,
4004         _Jv_JNI_GetStaticByteField,
4005         _Jv_JNI_GetStaticCharField,
4006         _Jv_JNI_GetStaticShortField,
4007         _Jv_JNI_GetStaticIntField,
4008         _Jv_JNI_GetStaticLongField,
4009         _Jv_JNI_GetStaticFloatField,
4010         _Jv_JNI_GetStaticDoubleField,
4011         _Jv_JNI_SetStaticObjectField,
4012         _Jv_JNI_SetStaticBooleanField,
4013         _Jv_JNI_SetStaticByteField,
4014         _Jv_JNI_SetStaticCharField,
4015         _Jv_JNI_SetStaticShortField,
4016         _Jv_JNI_SetStaticIntField,
4017         _Jv_JNI_SetStaticLongField,
4018         _Jv_JNI_SetStaticFloatField,
4019         _Jv_JNI_SetStaticDoubleField,
4020
4021         jni_NewString,
4022         jni_GetStringLength,
4023         jni_GetStringChars,
4024         _Jv_JNI_ReleaseStringChars,
4025
4026         jni_NewStringUTF,
4027         jni_GetStringUTFLength,
4028         _Jv_JNI_GetStringUTFChars,
4029         _Jv_JNI_ReleaseStringUTFChars,
4030
4031         _Jv_JNI_GetArrayLength,
4032
4033         _Jv_JNI_NewObjectArray,
4034         _Jv_JNI_GetObjectArrayElement,
4035         _Jv_JNI_SetObjectArrayElement,
4036
4037         _Jv_JNI_NewBooleanArray,
4038         _Jv_JNI_NewByteArray,
4039         _Jv_JNI_NewCharArray,
4040         _Jv_JNI_NewShortArray,
4041         _Jv_JNI_NewIntArray,
4042         _Jv_JNI_NewLongArray,
4043         _Jv_JNI_NewFloatArray,
4044         _Jv_JNI_NewDoubleArray,
4045
4046         _Jv_JNI_GetBooleanArrayElements,
4047         _Jv_JNI_GetByteArrayElements,
4048         _Jv_JNI_GetCharArrayElements,
4049         _Jv_JNI_GetShortArrayElements,
4050         _Jv_JNI_GetIntArrayElements,
4051         _Jv_JNI_GetLongArrayElements,
4052         _Jv_JNI_GetFloatArrayElements,
4053         _Jv_JNI_GetDoubleArrayElements,
4054
4055         _Jv_JNI_ReleaseBooleanArrayElements,
4056         _Jv_JNI_ReleaseByteArrayElements,
4057         _Jv_JNI_ReleaseCharArrayElements,
4058         _Jv_JNI_ReleaseShortArrayElements,
4059         _Jv_JNI_ReleaseIntArrayElements,
4060         _Jv_JNI_ReleaseLongArrayElements,
4061         _Jv_JNI_ReleaseFloatArrayElements,
4062         _Jv_JNI_ReleaseDoubleArrayElements,
4063
4064         _Jv_JNI_GetBooleanArrayRegion,
4065         _Jv_JNI_GetByteArrayRegion,
4066         _Jv_JNI_GetCharArrayRegion,
4067         _Jv_JNI_GetShortArrayRegion,
4068         _Jv_JNI_GetIntArrayRegion,
4069         _Jv_JNI_GetLongArrayRegion,
4070         _Jv_JNI_GetFloatArrayRegion,
4071         _Jv_JNI_GetDoubleArrayRegion,
4072         _Jv_JNI_SetBooleanArrayRegion,
4073         _Jv_JNI_SetByteArrayRegion,
4074         _Jv_JNI_SetCharArrayRegion,
4075         _Jv_JNI_SetShortArrayRegion,
4076         _Jv_JNI_SetIntArrayRegion,
4077         _Jv_JNI_SetLongArrayRegion,
4078         _Jv_JNI_SetFloatArrayRegion,
4079         _Jv_JNI_SetDoubleArrayRegion,
4080
4081         _Jv_JNI_RegisterNatives,
4082         _Jv_JNI_UnregisterNatives,
4083
4084         _Jv_JNI_MonitorEnter,
4085         _Jv_JNI_MonitorExit,
4086
4087         _Jv_JNI_GetJavaVM,
4088
4089         /* New JNI 1.2 functions. */
4090
4091         jni_GetStringRegion,
4092         jni_GetStringUTFRegion,
4093
4094         jni_GetPrimitiveArrayCritical,
4095         jni_ReleasePrimitiveArrayCritical,
4096
4097         _Jv_JNI_GetStringCritical,
4098         _Jv_JNI_ReleaseStringCritical,
4099
4100         _Jv_JNI_NewWeakGlobalRef,
4101         _Jv_JNI_DeleteWeakGlobalRef,
4102
4103         _Jv_JNI_ExceptionCheck,
4104
4105         /* New JNI 1.4 functions. */
4106
4107         jni_NewDirectByteBuffer,
4108         jni_GetDirectBufferAddress,
4109         jni_GetDirectBufferCapacity,
4110
4111         /* New JNI 1.6 functions. */
4112
4113         jni_GetObjectRefType
4114 };
4115
4116
4117 /* Invocation API Functions ***************************************************/
4118
4119 /* JNI_GetDefaultJavaVMInitArgs ************************************************
4120
4121    Returns a default configuration for the Java VM.
4122
4123 *******************************************************************************/
4124
4125 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
4126 {
4127         JavaVMInitArgs *_vm_args;
4128
4129         _vm_args = (JavaVMInitArgs *) vm_args;
4130
4131         /* GNU classpath currently supports JNI 1.2 */
4132
4133         switch (_vm_args->version) {
4134     case JNI_VERSION_1_1:
4135                 _vm_args->version = JNI_VERSION_1_1;
4136                 break;
4137
4138     case JNI_VERSION_1_2:
4139     case JNI_VERSION_1_4:
4140                 _vm_args->ignoreUnrecognized = JNI_FALSE;
4141                 _vm_args->options = NULL;
4142                 _vm_args->nOptions = 0;
4143                 break;
4144
4145     default:
4146                 return -1;
4147         }
4148   
4149         return 0;
4150 }
4151
4152
4153 /* JNI_GetCreatedJavaVMs *******************************************************
4154
4155    Returns all Java VMs that have been created. Pointers to VMs are written in
4156    the buffer vmBuf in the order they are created. At most bufLen number of
4157    entries will be written. The total number of created VMs is returned in
4158    *nVMs.
4159
4160 *******************************************************************************/
4161
4162 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
4163 {
4164         TRACEJNICALLS(("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs));
4165
4166         if (bufLen <= 0)
4167                 return JNI_ERR;
4168
4169         // We currently only support 1 VM running.
4170
4171         vmBuf[0] = vm->get_javavm();
4172         *nVMs    = 1;
4173
4174     return JNI_OK;
4175 }
4176
4177
4178 /* JNI_CreateJavaVM ************************************************************
4179
4180    Loads and initializes a Java VM. The current thread becomes the main thread.
4181    Sets the env argument to the JNI interface pointer of the main thread.
4182
4183 *******************************************************************************/
4184
4185 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
4186 {
4187         TRACEJNICALLS(("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args));
4188
4189         /* actually create the JVM */
4190
4191         if (!VM_create(p_vm, p_env, vm_args))
4192                 return JNI_ERR;
4193
4194         return JNI_OK;
4195 }
4196
4197 } // extern "C"
4198
4199
4200 /*
4201  * These are local overrides for various environment variables in Emacs.
4202  * Please do not remove this and leave it at the end of the file, where
4203  * Emacs will automagically detect them.
4204  * ---------------------------------------------------------------------
4205  * Local variables:
4206  * mode: c++
4207  * indent-tabs-mode: t
4208  * c-basic-offset: 4
4209  * tab-width: 4
4210  * End:
4211  * vim:noexpandtab:sw=4:ts=4:
4212  */