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