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