* src/vm/method.c (assert.h): Added.
[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 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    Contact: cacao@cacaojvm.org
26
27    Authors: Rainhard Grafl
28             Roman Obermaisser
29
30    Changes: Joseph Wenninger
31             Martin Platter
32             Christian Thalinger
33
34    $Id: jni.c 4501 2006-02-13 18:55:55Z twisti $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42 #include <string.h>
43
44 #include "vm/types.h"
45
46 #include "mm/boehm.h"
47 #include "mm/memory.h"
48 #include "native/jni.h"
49 #include "native/native.h"
50
51 #include "native/include/gnu_classpath_Pointer.h"
52
53 #if SIZEOF_VOID_P == 8
54 # include "native/include/gnu_classpath_Pointer64.h"
55 #else
56 # include "native/include/gnu_classpath_Pointer32.h"
57 #endif
58
59 #include "native/include/java_lang_Object.h"
60 #include "native/include/java_lang_Byte.h"
61 #include "native/include/java_lang_Character.h"
62 #include "native/include/java_lang_Short.h"
63 #include "native/include/java_lang_Integer.h"
64 #include "native/include/java_lang_Boolean.h"
65 #include "native/include/java_lang_Long.h"
66 #include "native/include/java_lang_Float.h"
67 #include "native/include/java_lang_Double.h"
68 #include "native/include/java_lang_Throwable.h"
69 #include "native/include/java_lang_reflect_Method.h"
70 #include "native/include/java_lang_reflect_Constructor.h"
71 #include "native/include/java_lang_reflect_Field.h"
72
73 #include "native/include/java_lang_Class.h" /* for java_lang_VMClass.h */
74 #include "native/include/java_lang_VMClass.h"
75 #include "native/include/java_lang_VMClassLoader.h"
76 #include "native/include/java_nio_Buffer.h"
77 #include "native/include/java_nio_DirectByteBufferImpl.h"
78
79 #if defined(ENABLE_JVMTI)
80 # include "native/jvmti/jvmti.h"
81 #endif
82
83 #if defined(USE_THREADS)
84 # if defined(NATIVE_THREADS)
85 #  include "threads/native/threads.h"
86 # else
87 #  include "threads/green/threads.h"
88 # endif
89 #endif
90
91 #include "toolbox/logging.h"
92 #include "vm/builtin.h"
93 #include "vm/exceptions.h"
94 #include "vm/global.h"
95 #include "vm/initialize.h"
96 #include "vm/loader.h"
97 #include "vm/options.h"
98 #include "vm/resolve.h"
99 #include "vm/statistics.h"
100 #include "vm/stringlocal.h"
101 #include "vm/jit/asmpart.h"
102 #include "vm/jit/jit.h"
103 #include "vm/statistics.h"
104
105
106 /* XXX TWISTI hack: define it extern so they can be found in this file */
107
108 extern const struct JNIInvokeInterface JNI_JavaVMTable;
109 extern struct JNINativeInterface JNI_JNIEnvTable;
110
111 /* pointers to VM and the environment needed by GetJavaVM and GetEnv */
112
113 static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable;
114 void *ptr_env = (void*) &JNI_JNIEnvTable;
115
116
117 #define PTR_TO_ITEM(ptr)   ((u8)(size_t)(ptr))
118
119 /* global variables ***********************************************************/
120
121 /* global reference table *****************************************************/
122
123 static java_objectheader **global_ref_table;
124
125 /* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/
126 static classinfo *ihmclass = NULL;
127 static methodinfo *putmid = NULL;
128 static methodinfo *getmid = NULL;
129 static methodinfo *removemid = NULL;
130
131
132 /* direct buffer stuff ********************************************************/
133
134 static classinfo *class_java_nio_Buffer;
135 static classinfo *class_java_nio_DirectByteBufferImpl;
136 static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
137 #if SIZEOF_VOID_P == 8
138 static classinfo *class_gnu_classpath_Pointer64;
139 #else
140 static classinfo *class_gnu_classpath_Pointer32;
141 #endif
142
143 static methodinfo *dbbirw_init;
144
145
146 /* local reference table ******************************************************/
147
148 #if !defined(USE_THREADS)
149 localref_table *_no_threads_localref_table;
150 #endif
151
152
153 /* accessing instance fields macros *******************************************/
154
155 #define SET_FIELD(obj,type,var,value) \
156     *((type *) ((ptrint) (obj) + (ptrint) (var)->offset)) = (type) (value)
157
158 #define GET_FIELD(obj,type,var) \
159     *((type *) ((ptrint) (obj) + (ptrint) (var)->offset))
160
161
162 /* some forward declarations **************************************************/
163
164 jobject NewLocalRef(JNIEnv *env, jobject ref);
165
166
167 /* jni_init ********************************************************************
168
169    Initialize the JNI subsystem.
170
171 *******************************************************************************/
172
173 bool jni_init(void)
174 {
175         /* initalize global reference table */
176
177         if (!(ihmclass =
178                   load_class_bootstrap(utf_new_char("java/util/IdentityHashMap"))))
179                 return false;
180
181         global_ref_table = GCNEW(jobject);
182
183         if (!(*global_ref_table = native_new_and_init(ihmclass)))
184                 return false;
185
186         if (!(getmid = class_resolvemethod(ihmclass, utf_get,
187                                                                            utf_java_lang_Object__java_lang_Object)))
188                 return false;
189
190         if (!(putmid = class_resolvemethod(ihmclass, utf_put,
191                                                                            utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"))))
192                 return false;
193
194         if (!(removemid =
195                   class_resolvemethod(ihmclass, utf_remove,
196                                                           utf_java_lang_Object__java_lang_Object)))
197                 return false;
198
199
200         /* direct buffer stuff */
201
202         if (!(class_java_nio_Buffer =
203                   load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
204                 !link_class(class_java_nio_Buffer))
205                 return false;
206
207         if (!(class_java_nio_DirectByteBufferImpl =
208                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
209                 !link_class(class_java_nio_DirectByteBufferImpl))
210                 return false;
211
212         if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
213                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
214                 !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
215                 return false;
216
217         if (!(dbbirw_init =
218                 class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
219                                                         utf_init,
220                                                         utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
221                 return false;
222
223 #if SIZEOF_VOID_P == 8
224         if (!(class_gnu_classpath_Pointer64 =
225                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
226                 !link_class(class_gnu_classpath_Pointer64))
227                 return false;
228 #else
229         if (!(class_gnu_classpath_Pointer32 =
230                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
231                 !link_class(class_gnu_classpath_Pointer32))
232                 return false;
233 #endif
234
235         return true;
236 }
237
238
239 static void fill_callblock_from_vargs(void *obj, methoddesc *descr,
240                                                                           jni_callblock blk[], va_list data,
241                                                                           s4 rettype)
242 {
243         typedesc *paramtypes;
244         s4        i;
245
246         paramtypes = descr->paramtypes;
247
248         /* if method is non-static fill first block and skip `this' pointer */
249
250         i = 0;
251
252         if (obj != NULL) {
253                 /* the `this' pointer */
254                 blk[0].itemtype = TYPE_ADR;
255                 blk[0].item = PTR_TO_ITEM(obj);
256
257                 paramtypes++;
258                 i++;
259         } 
260
261         for (; i < descr->paramcount; i++, paramtypes++) {
262                 switch (paramtypes->decltype) {
263                 /* primitive types */
264                 case PRIMITIVETYPE_BYTE:
265                 case PRIMITIVETYPE_CHAR:
266                 case PRIMITIVETYPE_SHORT: 
267                 case PRIMITIVETYPE_BOOLEAN: 
268                         blk[i].itemtype = TYPE_INT;
269                         blk[i].item = (s8) va_arg(data, s4);
270                         break;
271
272                 case PRIMITIVETYPE_INT:
273                         blk[i].itemtype = TYPE_INT;
274                         blk[i].item = (s8) va_arg(data, s4);
275                         break;
276
277                 case PRIMITIVETYPE_LONG:
278                         blk[i].itemtype = TYPE_LNG;
279                         blk[i].item = (s8) va_arg(data, s8);
280                         break;
281
282                 case PRIMITIVETYPE_FLOAT:
283                         blk[i].itemtype = TYPE_FLT;
284 #if defined(__ALPHA__)
285                         /* this keeps the assembler function much simpler */
286
287                         *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
288 #else
289                         *((jfloat *) (&blk[i].item)) = (jfloat) va_arg(data, jdouble);
290 #endif
291                         break;
292
293                 case PRIMITIVETYPE_DOUBLE:
294                         blk[i].itemtype = TYPE_DBL;
295                         *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble);
296                         break;
297
298                 case TYPE_ADR: 
299                         blk[i].itemtype = TYPE_ADR;
300                         blk[i].item = PTR_TO_ITEM(va_arg(data, void*));
301                         break;
302                 }
303         }
304
305         /* The standard doesn't say anything about return value checking,
306            but it appears to be useful. */
307
308         if (rettype != descr->returntype.decltype)
309                 log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
310 }
311
312
313 /* XXX it could be considered if we should do typechecking here in the future */
314
315 static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr,
316                                                                                         jni_callblock blk[],
317                                                                                         java_objectarray *params)
318 {
319     jobject    param;
320         s4         paramcount;
321         typedesc  *paramtypes;
322         classinfo *c;
323     s4         i;
324         s4         j;
325
326         paramcount = descr->paramcount;
327         paramtypes = descr->paramtypes;
328
329         /* if method is non-static fill first block and skip `this' pointer */
330
331         i = 0;
332
333         if (obj) {
334                 /* this pointer */
335                 blk[0].itemtype = TYPE_ADR;
336                 blk[0].item = PTR_TO_ITEM(obj);
337
338                 paramtypes++;
339                 paramcount--;
340                 i++;
341         }
342
343         for (j = 0; j < paramcount; i++, j++, paramtypes++) {
344                 switch (paramtypes->type) {
345                 /* primitive types */
346                 case TYPE_INT:
347                 case TYPE_LONG:
348                 case TYPE_FLOAT:
349                 case TYPE_DOUBLE:
350                         param = params->data[j];
351                         if (!param)
352                                 goto illegal_arg;
353
354                         /* internally used data type */
355                         blk[i].itemtype = paramtypes->type;
356
357                         /* convert the value according to its declared type */
358
359                         c = param->vftbl->class;
360
361                         switch (paramtypes->decltype) {
362                         case PRIMITIVETYPE_BOOLEAN:
363                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
364                                         blk[i].item = (s8) ((java_lang_Boolean *) param)->value;
365                                 else
366                                         goto illegal_arg;
367                                 break;
368
369                         case PRIMITIVETYPE_BYTE:
370                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
371                                         blk[i].item = (s8) ((java_lang_Byte *) param)->value;
372                                 else
373                                         goto illegal_arg;
374                                 break;
375
376                         case PRIMITIVETYPE_CHAR:
377                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
378                                         blk[i].item = (s8) ((java_lang_Character *) param)->value;
379                                 else
380                                         goto illegal_arg;
381                                 break;
382
383                         case PRIMITIVETYPE_SHORT:
384                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
385                                         blk[i].item = (s8) ((java_lang_Short *) param)->value;
386                                 else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
387                                         blk[i].item = (s8) ((java_lang_Byte *) param)->value;
388                                 else
389                                         goto illegal_arg;
390                                 break;
391
392                         case PRIMITIVETYPE_INT:
393                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
394                                         blk[i].item = (s8) ((java_lang_Integer *) param)->value;
395                                 else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
396                                         blk[i].item = (s8) ((java_lang_Short *) param)->value;
397                                 else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
398                                         blk[i].item = (s8) ((java_lang_Byte *) param)->value;
399                                 else
400                                         goto illegal_arg;
401                                 break;
402
403                         case PRIMITIVETYPE_LONG:
404                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
405                                         blk[i].item = (s8) ((java_lang_Long *) param)->value;
406                                 else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
407                                         blk[i].item = (s8) ((java_lang_Integer *) param)->value;
408                                 else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
409                                         blk[i].item = (s8) ((java_lang_Short *) param)->value;
410                                 else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
411                                         blk[i].item = (s8) ((java_lang_Byte *) param)->value;
412                                 else
413                                         goto illegal_arg;
414                                 break;
415
416                         case PRIMITIVETYPE_FLOAT:
417                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
418                                         *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
419                                 else
420                                         goto illegal_arg;
421                                 break;
422
423                         case PRIMITIVETYPE_DOUBLE:
424                                 if (c == primitivetype_table[paramtypes->decltype].class_wrap)
425                                         *((jdouble *) (&blk[i].item)) = (jdouble) ((java_lang_Double *) param)->value;
426                                 else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
427                                         *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value;
428                                 else
429                                         goto illegal_arg;
430                                 break;
431
432                         default:
433                                 goto illegal_arg;
434                         } /* end declared type switch */
435                         break;
436                 
437                         case TYPE_ADDRESS:
438                                 if (!resolve_class_from_typedesc(paramtypes, true, true, &c))
439                                         return false;
440
441                                 if (params->data[j] != 0) {
442                                         if (paramtypes->arraydim > 0) {
443                                                 if (!builtin_arrayinstanceof(params->data[j], c))
444                                                         goto illegal_arg;
445
446                                         } else {
447                                                 if (!builtin_instanceof(params->data[j], c))
448                                                         goto illegal_arg;
449                                         }
450                                 }
451                                 blk[i].itemtype = TYPE_ADR;
452                                 blk[i].item = PTR_TO_ITEM(params->data[j]);
453                                 break;                  
454
455                         default:
456                                 goto illegal_arg;
457                 } /* end param type switch */
458
459         } /* end param loop */
460
461 /*      if (rettype) */
462 /*              *rettype = descr->returntype.decltype; */
463
464         return true;
465
466 illegal_arg:
467         exceptions_throw_illegalargumentexception();
468         return false;
469 }
470
471
472 /* _Jv_jni_CallObjectMethod ****************************************************
473
474    Internal function to call Java Object methods.
475
476 *******************************************************************************/
477
478 static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
479                                                                                                    vftbl_t *vftbl,
480                                                                                                    methodinfo *m, va_list ap)
481 {
482         methodinfo        *resm;
483         s4                 paramcount;
484         jni_callblock     *blk;
485         java_objectheader *ret;
486         s4                 dumpsize;
487
488         STATISTICS(jniinvokation());
489
490         if (m == NULL) {
491                 exceptions_throw_nullpointerexception();
492                 return NULL;
493         }
494
495         /* Class initialization is done by the JIT compiler.  This is ok
496            since a static method always belongs to the declaring class. */
497
498         if (m->flags & ACC_STATIC) {
499                 /* For static methods we reset the object. */
500
501                 if (o != NULL)
502                         o = NULL;
503
504                 /* for convenience */
505
506                 resm = m;
507
508         } else {
509                 /* For instance methods we make a virtual function table lookup. */
510
511                 resm = method_vftbl_lookup(vftbl, m);
512         }
513
514         /* mark start of dump memory area */
515
516         dumpsize = dump_size();
517
518         paramcount = resm->parseddesc->paramcount;
519
520         blk = DMNEW(jni_callblock, paramcount);
521
522         fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, TYPE_ADR);
523
524         STATISTICS(jnicallXmethodnvokation());
525
526         ASM_CALLJAVAFUNCTION2_ADR(ret, resm, paramcount,
527                                                           paramcount * sizeof(jni_callblock),
528                                                           blk);
529
530         /* release dump area */
531
532         dump_release(dumpsize);
533
534         return ret;
535 }
536
537
538 /* _Jv_jni_CallIntMethod *******************************************************
539
540    Internal function to call Java integer class methods (boolean,
541    byte, char, short, int).
542
543 *******************************************************************************/
544
545 static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
546                                                                   methodinfo *m, va_list ap, s4 type)
547 {
548         methodinfo    *resm;
549         s4             paramcount;
550         jni_callblock *blk;
551         jint           ret;
552         s4             dumpsize;
553
554         STATISTICS(jniinvokation());
555
556         if (m == NULL) {
557                 exceptions_throw_nullpointerexception();
558                 return 0;
559         }
560         
561         /* Class initialization is done by the JIT compiler.  This is ok
562            since a static method always belongs to the declaring class. */
563
564         if (m->flags & ACC_STATIC) {
565                 /* For static methods we reset the object. */
566
567                 if (o != NULL)
568                         o = NULL;
569
570                 /* for convenience */
571
572                 resm = m;
573
574         } else {
575                 /* For instance methods we make a virtual function table lookup. */
576
577                 resm = method_vftbl_lookup(vftbl, m);
578         }
579
580         /* mark start of dump memory area */
581
582         dumpsize = dump_size();
583
584         paramcount = resm->parseddesc->paramcount;
585
586         blk = DMNEW(jni_callblock, paramcount);
587
588         fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, type);
589
590         STATISTICS(jnicallXmethodnvokation());
591
592         ASM_CALLJAVAFUNCTION2_INT(ret, resm, paramcount,
593                                                           paramcount * sizeof(jni_callblock),
594                                                           blk);
595
596         /* release dump area */
597
598         dump_release(dumpsize);
599
600         return ret;
601 }
602
603
604 /* _Jv_jni_CallLongMethod ******************************************************
605
606    Internal function to call Java long methods.
607
608 *******************************************************************************/
609
610 static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
611                                                                         methodinfo *m, va_list ap)
612 {
613         methodinfo    *resm;
614         s4             paramcount;
615         jni_callblock *blk;
616         jlong          ret;
617         s4             dumpsize;
618
619         STATISTICS(jniinvokation());
620
621         if (m == NULL) {
622                 exceptions_throw_nullpointerexception();
623                 return 0;
624         }
625
626         /* Class initialization is done by the JIT compiler.  This is ok
627            since a static method always belongs to the declaring class. */
628
629         if (m->flags & ACC_STATIC) {
630                 /* For static methods we reset the object. */
631
632                 if (o != NULL)
633                         o = NULL;
634
635                 /* for convenience */
636
637                 resm = m;
638
639         } else {
640                 /* For instance methods we make a virtual function table lookup. */
641
642                 resm = method_vftbl_lookup(vftbl, m);
643         }
644
645         /* mark start of dump memory area */
646
647         dumpsize = dump_size();
648
649         paramcount = resm->parseddesc->paramcount;
650
651         blk = DMNEW(jni_callblock, paramcount);
652
653         fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, PRIMITIVETYPE_LONG);
654
655         STATISTICS(jnicallXmethodnvokation());
656
657         ASM_CALLJAVAFUNCTION2_LONG(ret, resm, paramcount,
658                                                            paramcount * sizeof(jni_callblock),
659                                                            blk);
660
661         /* release dump area */
662
663         dump_release(dumpsize);
664
665         return ret;
666 }
667
668
669 /* _Jv_jni_CallFloatMethod *****************************************************
670
671    Internal function to call Java float methods.
672
673 *******************************************************************************/
674
675 static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
676                                                                           methodinfo *m, va_list ap)
677 {
678         methodinfo    *resm;
679         s4             paramcount;
680         jni_callblock *blk;
681         jdouble        ret;
682         s4             dumpsize;
683
684         /* Class initialization is done by the JIT compiler.  This is ok
685            since a static method always belongs to the declaring class. */
686
687         if (m->flags & ACC_STATIC) {
688                 /* For static methods we reset the object. */
689
690                 if (o != NULL)
691                         o = NULL;
692
693                 /* for convenience */
694
695                 resm = m;
696
697         } else {
698                 /* For instance methods we make a virtual function table lookup. */
699
700                 resm = method_vftbl_lookup(vftbl, m);
701         }
702
703         /* mark start of dump memory area */
704
705         dumpsize = dump_size();
706
707         paramcount = resm->parseddesc->paramcount;
708
709         blk = DMNEW(jni_callblock, paramcount);
710
711         fill_callblock_from_vargs(o, resm->parseddesc, blk, ap,
712                                                           PRIMITIVETYPE_FLOAT);
713
714         STATISTICS(jnicallXmethodnvokation());
715
716         ASM_CALLJAVAFUNCTION2_FLOAT(ret, resm, paramcount,
717                                                                 paramcount * sizeof(jni_callblock),
718                                                                 blk);
719
720         /* release dump area */
721
722         dump_release(dumpsize);
723
724         return ret;
725 }
726
727
728 /* _Jv_jni_CallDoubleMethod ****************************************************
729
730    Internal function to call Java double methods.
731
732 *******************************************************************************/
733
734 static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
735                                                                                 methodinfo *m, va_list ap)
736 {
737         methodinfo    *resm;
738         s4             paramcount;
739         jni_callblock *blk;
740         jfloat         ret;
741         s4             dumpsize;
742
743         /* Class initialization is done by the JIT compiler.  This is ok
744            since a static method always belongs to the declaring class. */
745
746         if (m->flags & ACC_STATIC) {
747                 /* For static methods we reset the object. */
748
749                 if (o != NULL)
750                         o = NULL;
751
752                 /* for convenience */
753
754                 resm = m;
755
756         } else {
757                 /* For instance methods we make a virtual function table lookup. */
758
759                 resm = method_vftbl_lookup(vftbl, m);
760         }
761
762         /* mark start of dump memory area */
763
764         dumpsize = dump_size();
765
766         paramcount = resm->parseddesc->paramcount;
767
768         blk = DMNEW(jni_callblock, paramcount);
769
770         fill_callblock_from_vargs(o, resm->parseddesc, blk, ap,
771                                                           PRIMITIVETYPE_DOUBLE);
772
773         STATISTICS(jnicallXmethodnvokation());
774
775         ASM_CALLJAVAFUNCTION2_DOUBLE(ret, resm, paramcount,
776                                                                  paramcount * sizeof(jni_callblock),
777                                                                  blk);
778
779         /* release dump area */
780
781         dump_release(dumpsize);
782
783         return ret;
784 }
785
786
787 /* _Jv_jni_CallVoidMethod ******************************************************
788
789    Internal function to call Java void methods.
790
791 *******************************************************************************/
792
793 static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl,
794                                                                    methodinfo *m, va_list ap)
795 {       
796         methodinfo    *resm;
797         s4             paramcount;
798         jni_callblock *blk;
799         s4             dumpsize;
800
801         if (m == NULL) {
802                 exceptions_throw_nullpointerexception();
803                 return;
804         }
805
806         /* Class initialization is done by the JIT compiler.  This is ok
807            since a static method always belongs to the declaring class. */
808
809         if (m->flags & ACC_STATIC) {
810                 /* For static methods we reset the object. */
811
812                 if (o != NULL)
813                         o = NULL;
814
815                 /* for convenience */
816
817                 resm = m;
818
819         } else {
820                 /* For instance methods we make a virtual function table lookup. */
821
822                 resm = method_vftbl_lookup(vftbl, m);
823         }
824
825         /* mark start of dump memory area */
826
827         dumpsize = dump_size();
828
829         paramcount = resm->parseddesc->paramcount;
830
831         blk = DMNEW(jni_callblock, paramcount);
832
833         fill_callblock_from_vargs(o, resm->parseddesc, blk, ap, TYPE_VOID);
834
835         STATISTICS(jnicallXmethodnvokation());
836
837         ASM_CALLJAVAFUNCTION2(resm, paramcount,
838                                                   paramcount * sizeof(jni_callblock),
839                                                   blk);
840
841         /* release dump area */
842
843         dump_release(dumpsize);
844 }
845
846
847 /* _Jv_jni_invokeNative ********************************************************
848
849    XXX
850
851 *******************************************************************************/
852
853 jobject *_Jv_jni_invokeNative(methodinfo *m, jobject obj,
854                                                           java_objectarray *params)
855 {
856         methodinfo        *resm;
857         jni_callblock     *blk;
858         java_objectheader *o;
859         s4                 argcount;
860         s4                 paramcount;
861
862         if (m == NULL) {
863                 exceptions_throw_nullpointerexception();
864                 return NULL;
865         }
866
867         argcount = m->parseddesc->paramcount;
868         paramcount = argcount;
869
870         /* if method is non-static, remove the `this' pointer */
871
872         if (!(m->flags & ACC_STATIC))
873                 paramcount--;
874
875         /* the method is an instance method the obj has to be an instance of the 
876            class the method belongs to. For static methods the obj parameter
877            is ignored. */
878
879         if (!(m->flags & ACC_STATIC) && obj &&
880                 (!builtin_instanceof((java_objectheader *) obj, m->class))) {
881                 *exceptionptr =
882                         new_exception_message(string_java_lang_IllegalArgumentException,
883                                                                   "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
884                 return NULL;
885         }
886
887         if (((params == NULL) && (paramcount != 0)) ||
888                 (params && (params->header.size != paramcount))) {
889                 *exceptionptr =
890                         new_exception(string_java_lang_IllegalArgumentException);
891                 return NULL;
892         }
893
894         if (!(m->flags & ACC_STATIC) && (obj == NULL))  {
895                 *exceptionptr =
896                         new_exception_message(string_java_lang_NullPointerException,
897                                                                   "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
898                 return NULL;
899         }
900
901         if ((m->flags & ACC_STATIC) && (obj != NULL))
902                 obj = NULL;
903
904         /* For virtual calls with abstract method of interface classes we
905            have to do a virtual function table lookup (XXX TWISTI: not
906            sure if this is correct, took it from the old
907            implementation). */
908
909         if ((obj != NULL) &&
910                 ((m->flags & ACC_ABSTRACT) || (m->class->flags & ACC_INTERFACE))) {
911                 resm = method_vftbl_lookup(obj->vftbl, m);
912
913         } else {
914                 /* just for convenience */
915
916                 resm = m;
917         }
918
919         blk = MNEW(jni_callblock, argcount);
920
921         if (!fill_callblock_from_objectarray(obj, resm->parseddesc, blk,
922                                                                                  params))
923                 return NULL;
924
925         switch (resm->parseddesc->returntype.decltype) {
926         case TYPE_VOID:
927                 ASM_CALLJAVAFUNCTION2(resm, argcount,
928                                                           argcount * sizeof(jni_callblock),
929                                                           blk);
930
931                 o = NULL;
932                 break;
933
934         case PRIMITIVETYPE_BOOLEAN: {
935                 s4 i;
936                 java_lang_Boolean *bo;
937
938                 ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
939                                                                   argcount * sizeof(jni_callblock),
940                                                                   blk);
941
942                 o = builtin_new(class_java_lang_Boolean);
943
944                 /* setting the value of the object direct */
945
946                 bo = (java_lang_Boolean *) o;
947                 bo->value = i;
948         }
949         break;
950
951         case PRIMITIVETYPE_BYTE: {
952                 s4 i;
953                 java_lang_Byte *bo;
954
955                 ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
956                                                                   argcount * sizeof(jni_callblock),
957                                                                   blk);
958
959                 o = builtin_new(class_java_lang_Byte);
960
961                 /* setting the value of the object direct */
962
963                 bo = (java_lang_Byte *) o;
964                 bo->value = i;
965         }
966         break;
967
968         case PRIMITIVETYPE_CHAR: {
969                 s4 i;
970                 java_lang_Character *co;
971
972                 ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
973                                                                   argcount * sizeof(jni_callblock),
974                                                                   blk);
975
976                 o = builtin_new(class_java_lang_Character);
977
978                 /* setting the value of the object direct */
979
980                 co = (java_lang_Character *) o;
981                 co->value = i;
982         }
983         break;
984
985         case PRIMITIVETYPE_SHORT: {
986                 s4 i;
987                 java_lang_Short *so;
988
989                 ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
990                                                                   argcount * sizeof(jni_callblock),
991                                                                   blk);
992
993                 o = builtin_new(class_java_lang_Short);
994
995                 /* setting the value of the object direct */
996
997                 so = (java_lang_Short *) o;
998                 so->value = i;
999         }
1000         break;
1001
1002         case PRIMITIVETYPE_INT: {
1003                 s4 i;
1004                 java_lang_Integer *io;
1005
1006                 ASM_CALLJAVAFUNCTION2_INT(i, resm, argcount,
1007                                                                   argcount * sizeof(jni_callblock),
1008                                                                   blk);
1009
1010                 o = builtin_new(class_java_lang_Integer);
1011
1012                 /* setting the value of the object direct */
1013
1014                 io = (java_lang_Integer *) o;
1015                 io->value = i;
1016         }
1017         break;
1018
1019         case PRIMITIVETYPE_LONG: {
1020                 s8 l;
1021                 java_lang_Long *lo;
1022
1023                 ASM_CALLJAVAFUNCTION2_LONG(l, resm, argcount,
1024                                                                    argcount * sizeof(jni_callblock),
1025                                                                    blk);
1026
1027                 o = builtin_new(class_java_lang_Long);
1028
1029                 /* setting the value of the object direct */
1030
1031                 lo = (java_lang_Long *) o;
1032                 lo->value = l;
1033         }
1034         break;
1035
1036         case PRIMITIVETYPE_FLOAT: {
1037                 float f;
1038                 java_lang_Float *fo;
1039
1040                 ASM_CALLJAVAFUNCTION2_FLOAT(f, resm, argcount,
1041                                                                         argcount * sizeof(jni_callblock),
1042                                                                         blk);
1043
1044                 o = builtin_new(class_java_lang_Float);
1045
1046                 /* setting the value of the object direct */
1047
1048                 fo = (java_lang_Float *) o;
1049                 fo->value = f;
1050         }
1051         break;
1052
1053         case PRIMITIVETYPE_DOUBLE: {
1054                 double d;
1055                 java_lang_Double *_do;
1056
1057                 ASM_CALLJAVAFUNCTION2_DOUBLE(d, resm, argcount,
1058                                                                          argcount * sizeof(jni_callblock),
1059                                                                          blk);
1060
1061                 o = builtin_new(class_java_lang_Double);
1062
1063                 /* setting the value of the object direct */
1064
1065                 _do = (java_lang_Double *) o;
1066                 _do->value = d;
1067         }
1068         break;
1069
1070         case TYPE_ADR:
1071                 ASM_CALLJAVAFUNCTION2_ADR(o, resm, argcount,
1072                                                                   argcount * sizeof(jni_callblock),
1073                                                                   blk);
1074                 break;
1075
1076         default:
1077                 /* if this happens the exception has already been set by
1078                    fill_callblock_from_objectarray */
1079
1080                 MFREE(blk, jni_callblock, argcount);
1081
1082                 return (jobject *) 0;
1083         }
1084
1085         MFREE(blk, jni_callblock, argcount);
1086
1087         if (*exceptionptr) {
1088                 java_objectheader *cause;
1089
1090                 cause = *exceptionptr;
1091
1092                 /* clear exception pointer, we are calling JIT code again */
1093
1094                 *exceptionptr = NULL;
1095
1096                 *exceptionptr =
1097                         new_exception_throwable(string_java_lang_reflect_InvocationTargetException,
1098                                                                         (java_lang_Throwable *) cause);
1099         }
1100
1101         return (jobject *) o;
1102 }
1103
1104
1105 /* GetVersion ******************************************************************
1106
1107    Returns the major version number in the higher 16 bits and the
1108    minor version number in the lower 16 bits.
1109
1110 *******************************************************************************/
1111
1112 jint GetVersion(JNIEnv *env)
1113 {
1114         STATISTICS(jniinvokation());
1115
1116         /* we support JNI 1.4 */
1117
1118         return JNI_VERSION_1_4;
1119 }
1120
1121
1122 /* Class Operations ***********************************************************/
1123
1124 /* DefineClass *****************************************************************
1125
1126    Loads a class from a buffer of raw class data. The buffer
1127    containing the raw class data is not referenced by the VM after the
1128    DefineClass call returns, and it may be discarded if desired.
1129
1130 *******************************************************************************/
1131
1132 jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
1133                                    const jbyte *buf, jsize bufLen)
1134 {
1135         java_lang_ClassLoader *cl;
1136         java_lang_String      *s;
1137         java_bytearray        *ba;
1138         jclass                 c;
1139
1140         STATISTICS(jniinvokation());
1141
1142         cl = (java_lang_ClassLoader *) loader;
1143         s = javastring_new_char(name);
1144         ba = (java_bytearray *) buf;
1145
1146         c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
1147                                                                                                                   0, bufLen, NULL);
1148
1149         return (jclass) NewLocalRef(env, (jobject) c);
1150 }
1151
1152
1153 /* FindClass *******************************************************************
1154
1155    This function loads a locally-defined class. It searches the
1156    directories and zip files specified by the CLASSPATH environment
1157    variable for the class with the specified name.
1158
1159 *******************************************************************************/
1160
1161 jclass FindClass(JNIEnv *env, const char *name)
1162 {
1163         utf               *u;
1164         classinfo         *c;
1165         java_objectheader *cl;
1166
1167         STATISTICS(jniinvokation());
1168
1169         u = utf_new_char_classname((char *) name);
1170
1171         /* Check stacktrace for classloader, if one found use it,
1172             otherwise use the system classloader. */
1173
1174 #if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__)
1175         /* these JITs support stacktraces, and so does the interpreter */
1176
1177         cl = stacktrace_getCurrentClassLoader();
1178 #else
1179 # if defined(ENABLE_INTRP)
1180         /* the interpreter supports stacktraces, even if the JIT does not */
1181
1182         if (opt_intrp)
1183                 cl = stacktrace_getCurrentClassLoader();
1184         else
1185 # endif
1186                 cl = NULL;
1187 #endif
1188
1189         if (!(c = load_class_from_classloader(u, cl)))
1190                 return NULL;
1191
1192         if (!link_class(c))
1193                 return NULL;
1194
1195         return (jclass) NewLocalRef(env, (jobject) c);
1196 }
1197   
1198
1199 /* FromReflectedMethod *********************************************************
1200
1201    Converts java.lang.reflect.Method or java.lang.reflect.Constructor
1202    object to a method ID.
1203   
1204 *******************************************************************************/
1205   
1206 jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
1207 {
1208         methodinfo *mi;
1209         classinfo  *c;
1210         s4          slot;
1211
1212         STATISTICS(jniinvokation());
1213
1214         if (method == NULL)
1215                 return NULL;
1216         
1217         if (builtin_instanceof(method, class_java_lang_reflect_Method)) {
1218                 java_lang_reflect_Method *rm;
1219
1220                 rm = (java_lang_reflect_Method *) method;
1221                 c = (classinfo *) (rm->declaringClass);
1222                 slot = rm->slot;
1223
1224         } else if (builtin_instanceof(method, class_java_lang_reflect_Constructor)) {
1225                 java_lang_reflect_Constructor *rc;
1226
1227                 rc = (java_lang_reflect_Constructor *) method;
1228                 c = (classinfo *) (rc->clazz);
1229                 slot = rc->slot;
1230
1231         } else
1232                 return NULL;
1233
1234         if ((slot < 0) || (slot >= c->methodscount)) {
1235                 /* this usually means a severe internal cacao error or somebody
1236                    tempered around with the reflected method */
1237                 log_text("error illegal slot for method in class(FromReflectedMethod)");
1238                 assert(0);
1239         }
1240
1241         mi = &(c->methods[slot]);
1242
1243         return mi;
1244 }
1245
1246
1247 /* GetSuperclass ***************************************************************
1248
1249    If clazz represents any class other than the class Object, then
1250    this function returns the object that represents the superclass of
1251    the class specified by clazz.
1252
1253 *******************************************************************************/
1254  
1255 jclass GetSuperclass(JNIEnv *env, jclass sub)
1256 {
1257         classinfo *c;
1258
1259         STATISTICS(jniinvokation());
1260
1261         c = ((classinfo *) sub)->super.cls;
1262
1263         if (!c)
1264                 return NULL;
1265
1266         return (jclass) NewLocalRef(env, (jobject) c);
1267 }
1268   
1269  
1270 /* IsAssignableFrom ************************************************************
1271
1272    Determines whether an object of sub can be safely cast to sup.
1273
1274 *******************************************************************************/
1275
1276 jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
1277 {
1278         STATISTICS(jniinvokation());
1279
1280         return Java_java_lang_VMClass_isAssignableFrom(env,
1281                                                                                                    NULL,
1282                                                                                                    (java_lang_Class *) sup,
1283                                                                                                    (java_lang_Class *) sub);
1284 }
1285
1286
1287 /* Throw ***********************************************************************
1288
1289    Causes a java.lang.Throwable object to be thrown.
1290
1291 *******************************************************************************/
1292
1293 jint Throw(JNIEnv *env, jthrowable obj)
1294 {
1295         STATISTICS(jniinvokation());
1296
1297         *exceptionptr = (java_objectheader *) obj;
1298
1299         return JNI_OK;
1300 }
1301
1302
1303 /* ThrowNew ********************************************************************
1304
1305    Constructs an exception object from the specified class with the
1306    message specified by message and causes that exception to be
1307    thrown.
1308
1309 *******************************************************************************/
1310
1311 jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
1312 {
1313         java_lang_Throwable *o;
1314         java_lang_String    *s;
1315
1316         STATISTICS(jniinvokation());
1317
1318         s = (java_lang_String *) javastring_new_char(msg);
1319
1320         /* instantiate exception object */
1321
1322         o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz,
1323                                                                                                                    s);
1324
1325         if (!o)
1326                 return -1;
1327
1328         *exceptionptr = (java_objectheader *) o;
1329
1330         return 0;
1331 }
1332
1333
1334 /* ExceptionOccurred ***********************************************************
1335
1336    Determines if an exception is being thrown. The exception stays
1337    being thrown until either the native code calls ExceptionClear(),
1338    or the Java code handles the exception.
1339
1340 *******************************************************************************/
1341
1342 jthrowable ExceptionOccurred(JNIEnv *env)
1343 {
1344         java_objectheader *e;
1345
1346         STATISTICS(jniinvokation());
1347
1348         e = *exceptionptr;
1349
1350         return NewLocalRef(env, (jthrowable) e);
1351 }
1352
1353
1354 /* ExceptionDescribe ***********************************************************
1355
1356    Prints an exception and a backtrace of the stack to a system
1357    error-reporting channel, such as stderr. This is a convenience
1358    routine provided for debugging.
1359
1360 *******************************************************************************/
1361
1362 void ExceptionDescribe(JNIEnv *env)
1363 {
1364         java_objectheader *e;
1365         methodinfo        *m;
1366
1367         STATISTICS(jniinvokation());
1368
1369         e = *exceptionptr;
1370
1371         if (e) {
1372                 /* clear exception, because we are calling jit code again */
1373
1374                 *exceptionptr = NULL;
1375
1376                 /* get printStackTrace method from exception class */
1377
1378                 m = class_resolveclassmethod(e->vftbl->class,
1379                                                                          utf_printStackTrace,
1380                                                                          utf_void__void,
1381                                                                          NULL,
1382                                                                          true);
1383
1384                 if (!m)
1385                         /* XXX what should we do? */
1386                         return;
1387
1388                 /* print the stacktrace */
1389
1390                 ASM_CALLJAVAFUNCTION(m, e, NULL, NULL, NULL);
1391         }
1392 }
1393
1394
1395 /* ExceptionClear **************************************************************
1396
1397    Clears any exception that is currently being thrown. If no
1398    exception is currently being thrown, this routine has no effect.
1399
1400 *******************************************************************************/
1401
1402 void ExceptionClear(JNIEnv *env)
1403 {
1404         STATISTICS(jniinvokation());
1405
1406         *exceptionptr = NULL;
1407 }
1408
1409
1410 /* FatalError ******************************************************************
1411
1412    Raises a fatal error and does not expect the VM to recover. This
1413    function does not return.
1414
1415 *******************************************************************************/
1416
1417 void FatalError(JNIEnv *env, const char *msg)
1418 {
1419         STATISTICS(jniinvokation());
1420
1421         throw_cacao_exception_exit(string_java_lang_InternalError, msg);
1422 }
1423
1424
1425 /* PushLocalFrame **************************************************************
1426
1427    Creates a new local reference frame, in which at least a given
1428    number of local references can be created.
1429
1430 *******************************************************************************/
1431
1432 jint PushLocalFrame(JNIEnv* env, jint capacity)
1433 {
1434         STATISTICS(jniinvokation());
1435
1436         log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!");
1437
1438         assert(0);
1439
1440         return 0;
1441 }
1442
1443 /* PopLocalFrame ***************************************************************
1444
1445    Pops off the current local reference frame, frees all the local
1446    references, and returns a local reference in the previous local
1447    reference frame for the given result object.
1448
1449 *******************************************************************************/
1450
1451 jobject PopLocalFrame(JNIEnv* env, jobject result)
1452 {
1453         STATISTICS(jniinvokation());
1454
1455         log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!");
1456
1457         assert(0);
1458
1459         /* add local reference and return the value */
1460
1461         return NewLocalRef(env, NULL);
1462 }
1463
1464
1465 /* DeleteLocalRef **************************************************************
1466
1467    Deletes the local reference pointed to by localRef.
1468
1469 *******************************************************************************/
1470
1471 void DeleteLocalRef(JNIEnv *env, jobject localRef)
1472 {
1473         java_objectheader *o;
1474         localref_table    *lrt;
1475         s4                 i;
1476
1477         STATISTICS(jniinvokation());
1478
1479         o = (java_objectheader *) localRef;
1480
1481         /* get local reference table (thread specific) */
1482
1483         lrt = LOCALREFTABLE;
1484
1485         /* remove the reference */
1486
1487         for (i = 0; i < lrt->capacity; i++) {
1488                 if (lrt->refs[i] == o) {
1489                         lrt->refs[i] = NULL;
1490                         lrt->used--;
1491
1492                         return;
1493                 }
1494         }
1495
1496         /* this should not happen */
1497
1498 /*      if (opt_checkjni) */
1499 /*      FatalError(env, "Bad global or local ref passed to JNI"); */
1500         log_text("JNI-DeleteLocalRef: Bad global or local ref passed to JNI");
1501 }
1502
1503
1504 /* IsSameObject ****************************************************************
1505
1506    Tests whether two references refer to the same Java object.
1507
1508 *******************************************************************************/
1509
1510 jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
1511 {
1512         STATISTICS(jniinvokation());
1513
1514         if (ref1 == ref2)
1515                 return JNI_TRUE;
1516         else
1517                 return JNI_FALSE;
1518 }
1519
1520
1521 /* NewLocalRef *****************************************************************
1522
1523    Creates a new local reference that refers to the same object as ref.
1524
1525 *******************************************************************************/
1526
1527 jobject NewLocalRef(JNIEnv *env, jobject ref)
1528 {
1529         localref_table *lrt;
1530         s4              i;
1531
1532         STATISTICS(jniinvokation());
1533
1534         if (ref == NULL)
1535                 return NULL;
1536
1537         /* get local reference table (thread specific) */
1538
1539         lrt = LOCALREFTABLE;
1540
1541         /* check if we have space for the requested reference */
1542
1543         if (lrt->used == lrt->capacity) {
1544 /*              throw_cacao_exception_exit(string_java_lang_InternalError, */
1545 /*                                                                 "Too many local references"); */
1546                 fprintf(stderr, "Too many local references");
1547                 assert(0);
1548         }
1549
1550         /* insert the reference */
1551
1552         for (i = 0; i < lrt->capacity; i++) {
1553                 if (lrt->refs[i] == NULL) {
1554                         lrt->refs[i] = (java_objectheader *) ref;
1555                         lrt->used++;
1556
1557                         return ref;
1558                 }
1559         }
1560
1561         /* should not happen, just to be sure */
1562
1563         assert(0);
1564
1565         /* keep compiler happy */
1566
1567         return NULL;
1568 }
1569
1570
1571 /* EnsureLocalCapacity *********************************************************
1572
1573    Ensures that at least a given number of local references can be
1574    created in the current thread
1575
1576 *******************************************************************************/
1577
1578 jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
1579 {
1580         localref_table *lrt;
1581
1582         STATISTICS(jniinvokation());
1583
1584         /* get local reference table (thread specific) */
1585
1586         lrt = LOCALREFTABLE;
1587
1588         /* check if capacity elements are available in the local references table */
1589
1590         if ((lrt->used + capacity) > lrt->capacity) {
1591                 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
1592                 return -1;
1593         }
1594
1595         return 0;
1596 }
1597
1598
1599 /* AllocObject *****************************************************************
1600
1601    Allocates a new Java object without invoking any of the
1602    constructors for the object. Returns a reference to the object.
1603
1604 *******************************************************************************/
1605
1606 jobject AllocObject(JNIEnv *env, jclass clazz)
1607 {
1608         java_objectheader *o;
1609
1610         STATISTICS(jniinvokation());
1611
1612         if ((clazz->flags & ACC_INTERFACE) || (clazz->flags & ACC_ABSTRACT)) {
1613                 *exceptionptr =
1614                         new_exception_utfmessage(string_java_lang_InstantiationException,
1615                                                                          clazz->name);
1616                 return NULL;
1617         }
1618                 
1619         o = builtin_new(clazz);
1620
1621         return NewLocalRef(env, o);
1622 }
1623
1624
1625 /* NewObject *******************************************************************
1626
1627    Programmers place all arguments that are to be passed to the
1628    constructor immediately following the methodID
1629    argument. NewObject() accepts these arguments and passes them to
1630    the Java method that the programmer wishes to invoke.
1631
1632 *******************************************************************************/
1633
1634 jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
1635 {
1636         java_objectheader *o;
1637         va_list            ap;
1638
1639         STATISTICS(jniinvokation());
1640
1641         /* create object */
1642
1643         o = builtin_new(clazz);
1644         
1645         if (!o)
1646                 return NULL;
1647
1648         /* call constructor */
1649
1650         va_start(ap, methodID);
1651         _Jv_jni_CallVoidMethod(o, o->vftbl, methodID, ap);
1652         va_end(ap);
1653
1654         return NewLocalRef(env, o);
1655 }
1656
1657
1658 /* NewObjectV ******************************************************************
1659
1660    Programmers place all arguments that are to be passed to the
1661    constructor in an args argument of type va_list that immediately
1662    follows the methodID argument. NewObjectV() accepts these
1663    arguments, and, in turn, passes them to the Java method that the
1664    programmer wishes to invoke.
1665
1666 *******************************************************************************/
1667
1668 jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args)
1669 {
1670         java_objectheader *o;
1671
1672         STATISTICS(jniinvokation());
1673
1674         /* create object */
1675
1676         o = builtin_new(clazz);
1677         
1678         if (!o)
1679                 return NULL;
1680
1681         /* call constructor */
1682
1683         _Jv_jni_CallVoidMethod(o, o->vftbl, methodID, args);
1684
1685         return NewLocalRef(env, o);
1686 }
1687
1688
1689 /*********************************************************************************** 
1690
1691         Constructs a new Java object
1692         arguments that are to be passed to the constructor are placed in 
1693         args array of jvalues 
1694
1695 ***********************************************************************************/
1696
1697 jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args)
1698 {
1699         STATISTICS(jniinvokation());
1700
1701         log_text("JNI-Call: NewObjectA: IMPLEMENT ME!");
1702
1703         return NewLocalRef(env, NULL);
1704 }
1705
1706
1707 /* GetObjectClass **************************************************************
1708
1709  Returns the class of an object.
1710
1711 *******************************************************************************/
1712
1713 jclass GetObjectClass(JNIEnv *env, jobject obj)
1714 {
1715         classinfo *c;
1716
1717         STATISTICS(jniinvokation());
1718         
1719         if (!obj || !obj->vftbl)
1720                 return NULL;
1721
1722         c = obj->vftbl->class;
1723
1724         return (jclass) NewLocalRef(env, (jobject) c);
1725 }
1726
1727
1728 /* IsInstanceOf ****************************************************************
1729
1730    Tests whether an object is an instance of a class.
1731
1732 *******************************************************************************/
1733
1734 jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
1735 {
1736         STATISTICS(jniinvokation());
1737
1738         return Java_java_lang_VMClass_isInstance(env,
1739                                                                                          NULL,
1740                                                                                          (java_lang_Class *) clazz,
1741                                                                                          (java_lang_Object *) obj);
1742 }
1743
1744
1745 /***************** converts a java.lang.reflect.Field to a field ID ***************/
1746  
1747 jfieldID FromReflectedField(JNIEnv* env, jobject field)
1748 {
1749         java_lang_reflect_Field *f;
1750         classinfo *c;
1751         jfieldID fid;   /* the JNI-fieldid of the wrapping object */
1752
1753         STATISTICS(jniinvokation());
1754
1755         /*log_text("JNI-Call: FromReflectedField");*/
1756
1757         f=(java_lang_reflect_Field *)field;
1758         if (f==0) return 0;
1759         c=(classinfo*)(f->declaringClass);
1760         if ( (f->slot<0) || (f->slot>=c->fieldscount)) {
1761                 /*this usually means a severe internal cacao error or somebody
1762                 tempered around with the reflected method*/
1763                 log_text("error illegal slot for field in class(FromReflectedField)");
1764                 assert(0);
1765         }
1766         fid=&(c->fields[f->slot]);
1767         return fid;
1768 }
1769
1770
1771 /* ToReflectedMethod ***********************************************************
1772
1773    Converts a method ID derived from cls to an instance of the
1774    java.lang.reflect.Method class or to an instance of the
1775    java.lang.reflect.Constructor class.
1776
1777 *******************************************************************************/
1778
1779 jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
1780 {
1781         STATISTICS(jniinvokation());
1782
1783         log_text("JNI-Call: ToReflectedMethod: IMPLEMENT ME!");
1784
1785         return NULL;
1786 }
1787
1788
1789 /* ToReflectedField ************************************************************
1790
1791    Converts a field ID derived from cls to an instance of the
1792    java.lang.reflect.Field class.
1793
1794 *******************************************************************************/
1795
1796 jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1797                                                  jboolean isStatic)
1798 {
1799         STATISTICS(jniinvokation());
1800
1801         log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
1802
1803         return NULL;
1804 }
1805
1806
1807 /* Calling Instance Methods ***************************************************/
1808
1809 /* GetMethodID *****************************************************************
1810
1811    Returns the method ID for an instance (nonstatic) method of a class
1812    or interface. The method may be defined in one of the clazz's
1813    superclasses and inherited by clazz. The method is determined by
1814    its name and signature.
1815
1816    GetMethodID() causes an uninitialized class to be initialized.
1817
1818 *******************************************************************************/
1819
1820 jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name,
1821                                           const char *sig)
1822 {
1823         classinfo  *c;
1824         utf        *uname;
1825         utf        *udesc;
1826         methodinfo *m;
1827
1828         STATISTICS(jniinvokation());
1829
1830         c = (classinfo *) clazz;
1831
1832         if (!c)
1833                 return NULL;
1834
1835         if (!(c->state & CLASS_INITIALIZED))
1836                 if (!initialize_class(c))
1837                         return NULL;
1838
1839         /* try to get the method of the class or one of it's superclasses */
1840
1841         uname = utf_new_char((char *) name);
1842         udesc = utf_new_char((char *) sig);
1843
1844         m = class_resolvemethod(clazz, uname, udesc);
1845
1846         if ((m == NULL) || (m->flags & ACC_STATIC)) {
1847                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
1848
1849                 return NULL;
1850         }
1851
1852         return m;
1853 }
1854
1855
1856 /* JNI-functions for calling instance methods *********************************/
1857
1858 jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1859 {
1860         java_objectheader* ret;
1861         va_list            ap;
1862
1863         va_start(ap, methodID);
1864         ret = _Jv_jni_CallObjectMethod(obj, obj->vftbl, methodID, ap);
1865         va_end(ap);
1866
1867         return NewLocalRef(env, ret);
1868 }
1869
1870
1871 jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
1872 {
1873         java_objectheader* ret;
1874
1875         ret = _Jv_jni_CallObjectMethod(obj, obj->vftbl, methodID, args);
1876
1877         return NewLocalRef(env, ret);
1878 }
1879
1880
1881 jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
1882 {
1883         log_text("JNI-Call: CallObjectMethodA: IMPLEMENT ME!");
1884
1885         return NewLocalRef(env, NULL);
1886 }
1887
1888
1889 jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1890 {
1891         va_list  ap;
1892         jboolean ret;
1893
1894         va_start(ap, methodID);
1895         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
1896                                                                 PRIMITIVETYPE_BOOLEAN);
1897         va_end(ap);
1898
1899         return ret;
1900 }
1901
1902
1903 jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
1904 {
1905         jboolean ret;
1906
1907         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
1908                                                                 PRIMITIVETYPE_BOOLEAN);
1909
1910         return ret;
1911 }
1912
1913
1914 jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args)
1915 {
1916         log_text("JNI-Call: CallBooleanMethodA");
1917
1918         return 0;
1919 }
1920
1921
1922 jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1923 {
1924         va_list ap;
1925         jbyte   ret;
1926
1927         va_start(ap, methodID);
1928         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
1929                                                                 PRIMITIVETYPE_BYTE);
1930         va_end(ap);
1931
1932         return ret;
1933
1934 }
1935
1936 jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
1937 {
1938         jbyte ret;
1939
1940         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
1941                                                                 PRIMITIVETYPE_BYTE);
1942
1943         return ret;
1944 }
1945
1946
1947 jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
1948 {
1949         log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!");
1950
1951         return 0;
1952 }
1953
1954
1955 jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1956 {
1957         va_list ap;
1958         jchar   ret;
1959
1960         va_start(ap, methodID);
1961         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
1962                                                                 PRIMITIVETYPE_CHAR);
1963         va_end(ap);
1964
1965         return ret;
1966 }
1967
1968
1969 jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
1970 {
1971         jchar ret;
1972
1973         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
1974                                                                 PRIMITIVETYPE_CHAR);
1975
1976         return ret;
1977 }
1978
1979
1980 jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
1981 {
1982         log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!");
1983
1984         return 0;
1985 }
1986
1987
1988 jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1989 {
1990         va_list ap;
1991         jshort  ret;
1992
1993         va_start(ap, methodID);
1994         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
1995                                                                 PRIMITIVETYPE_SHORT);
1996         va_end(ap);
1997
1998         return ret;
1999 }
2000
2001
2002 jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
2003 {
2004         jshort ret;
2005
2006         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
2007                                                                 PRIMITIVETYPE_SHORT);
2008
2009         return ret;
2010 }
2011
2012
2013 jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
2014 {
2015         log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!");
2016
2017         return 0;
2018 }
2019
2020
2021
2022 jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2023 {
2024         va_list ap;
2025         jint    ret;
2026
2027         va_start(ap, methodID);
2028         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, ap,
2029                                                                 PRIMITIVETYPE_INT);
2030         va_end(ap);
2031
2032         return ret;
2033 }
2034
2035
2036 jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
2037 {
2038         jint ret;
2039
2040         ret = _Jv_jni_CallIntMethod(obj, obj->vftbl, methodID, args,
2041                                                                 PRIMITIVETYPE_INT);
2042
2043         return ret;
2044 }
2045
2046
2047 jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
2048 {
2049         log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!");
2050
2051         return 0;
2052 }
2053
2054
2055
2056 jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2057 {
2058         va_list ap;
2059         jlong   ret;
2060
2061         va_start(ap, methodID);
2062         ret = _Jv_jni_CallLongMethod(obj, obj->vftbl, methodID, ap);
2063         va_end(ap);
2064
2065         return ret;
2066 }
2067
2068
2069 jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
2070 {
2071         jlong ret;
2072
2073         ret = _Jv_jni_CallLongMethod(obj, obj->vftbl, methodID, args);
2074
2075         return ret;
2076 }
2077
2078
2079 jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
2080 {
2081         log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!");
2082
2083         return 0;
2084 }
2085
2086
2087
2088 jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2089 {
2090         va_list ap;
2091         jfloat  ret;
2092
2093         va_start(ap, methodID);
2094         ret = _Jv_jni_CallFloatMethod(obj, obj->vftbl, methodID, ap);
2095         va_end(ap);
2096
2097         return ret;
2098 }
2099
2100
2101 jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
2102 {
2103         jfloat ret;
2104
2105         ret = _Jv_jni_CallFloatMethod(obj, obj->vftbl, methodID, args);
2106
2107         return ret;
2108 }
2109
2110
2111 jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
2112 {
2113         log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!");
2114
2115         return 0;
2116 }
2117
2118
2119
2120 jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2121 {
2122         va_list ap;
2123         jdouble ret;
2124
2125         va_start(ap, methodID);
2126         ret = _Jv_jni_CallDoubleMethod(obj, obj->vftbl, methodID, ap);
2127         va_end(ap);
2128
2129         return ret;
2130 }
2131
2132
2133 jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
2134 {
2135         jdouble ret;
2136
2137         ret = _Jv_jni_CallDoubleMethod(obj, obj->vftbl, methodID, args);
2138
2139         return ret;
2140 }
2141
2142
2143 jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
2144 {
2145         log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!");
2146
2147         return 0;
2148 }
2149
2150
2151
2152 void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2153 {
2154         va_list ap;
2155
2156         va_start(ap, methodID);
2157         _Jv_jni_CallVoidMethod(obj, obj->vftbl, methodID, ap);
2158         va_end(ap);
2159 }
2160
2161
2162 void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
2163 {
2164         _Jv_jni_CallVoidMethod(obj, obj->vftbl, methodID, args);
2165 }
2166
2167
2168 void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
2169 {
2170         log_text("JNI-Call: CallVoidMethodA: IMPLEMENT ME!");
2171 }
2172
2173
2174
2175 jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2176 {
2177         java_objectheader *ret;
2178         va_list            ap;
2179
2180         va_start(ap, methodID);
2181         ret = _Jv_jni_CallObjectMethod(obj, clazz->vftbl, methodID, ap);
2182         va_end(ap);
2183
2184         return NewLocalRef(env, ret);
2185 }
2186
2187
2188 jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2189 {
2190         java_objectheader* ret;
2191
2192         ret = _Jv_jni_CallObjectMethod(obj, clazz->vftbl, methodID, args);
2193
2194         return NewLocalRef(env, ret);
2195 }
2196
2197
2198 jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2199 {
2200         log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
2201
2202         return NewLocalRef(env, NULL);
2203 }
2204
2205
2206
2207 jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2208 {
2209         va_list  ap;
2210         jboolean ret;
2211
2212         va_start(ap, methodID);
2213         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
2214                                                                 PRIMITIVETYPE_BOOLEAN);
2215         va_end(ap);
2216
2217         return ret;
2218
2219 }
2220
2221
2222 jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2223 {
2224         jboolean ret;
2225
2226         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
2227                                                                 PRIMITIVETYPE_BOOLEAN);
2228
2229         return ret;
2230 }
2231
2232
2233 jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2234 {
2235         log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!");
2236
2237         return 0;
2238 }
2239
2240
2241 jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2242 {
2243         va_list ap;
2244         jbyte   ret;
2245
2246         va_start(ap, methodID);
2247         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
2248                                                                 PRIMITIVETYPE_BYTE);
2249         va_end(ap);
2250
2251         return ret;
2252 }
2253
2254
2255 jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2256 {
2257         jbyte ret;
2258
2259         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
2260                                                                 PRIMITIVETYPE_BYTE);
2261
2262         return ret;
2263 }
2264
2265
2266 jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2267 {
2268         log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!");
2269
2270         return 0;
2271 }
2272
2273
2274
2275 jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2276 {
2277         va_list ap;
2278         jchar   ret;
2279
2280         va_start(ap, methodID);
2281         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
2282                                                                 PRIMITIVETYPE_CHAR);
2283         va_end(ap);
2284
2285         return ret;
2286 }
2287
2288
2289 jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2290 {
2291         jchar ret;
2292
2293         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
2294                                                                 PRIMITIVETYPE_CHAR);
2295
2296         return ret;
2297 }
2298
2299
2300 jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2301 {
2302         log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!");
2303
2304         return 0;
2305 }
2306
2307
2308
2309 jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2310 {
2311         va_list ap;
2312         jshort  ret;
2313
2314         va_start(ap, methodID);
2315         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
2316                                                                 PRIMITIVETYPE_SHORT);
2317         va_end(ap);
2318
2319         return ret;
2320 }
2321
2322
2323 jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2324 {
2325         jshort ret;
2326
2327         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
2328                                                                 PRIMITIVETYPE_SHORT);
2329
2330         return ret;
2331 }
2332
2333
2334 jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2335 {
2336         log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!");
2337
2338         return 0;
2339 }
2340
2341
2342
2343 jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2344 {
2345         va_list ap;
2346         jint    ret;
2347
2348         va_start(ap, methodID);
2349         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, ap,
2350                                                                 PRIMITIVETYPE_INT);
2351         va_end(ap);
2352
2353         return ret;
2354 }
2355
2356
2357 jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2358 {
2359         jint ret;
2360
2361         ret = _Jv_jni_CallIntMethod(obj, clazz->vftbl, methodID, args,
2362                                                                 PRIMITIVETYPE_INT);
2363
2364         return ret;
2365 }
2366
2367
2368 jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2369 {
2370         log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!");
2371
2372         return 0;
2373 }
2374
2375
2376
2377 jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2378 {
2379         va_list ap;
2380         jlong   ret;
2381
2382         va_start(ap, methodID);
2383         ret = _Jv_jni_CallLongMethod(obj, clazz->vftbl, methodID, ap);
2384         va_end(ap);
2385
2386         return ret;
2387 }
2388
2389
2390 jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2391 {
2392         jlong ret;
2393
2394         ret = _Jv_jni_CallLongMethod(obj, clazz->vftbl, methodID, args);
2395
2396         return 0;
2397 }
2398
2399
2400 jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2401 {
2402         log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!");
2403
2404         return 0;
2405 }
2406
2407
2408
2409 jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2410 {
2411         va_list ap;
2412         jfloat  ret;
2413
2414         va_start(ap, methodID);
2415         ret = _Jv_jni_CallFloatMethod(obj, clazz->vftbl, methodID, ap);
2416         va_end(ap);
2417
2418         return ret;
2419 }
2420
2421
2422 jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2423 {
2424         jfloat ret;
2425
2426         ret = _Jv_jni_CallFloatMethod(obj, clazz->vftbl, methodID, args);
2427
2428         return ret;
2429 }
2430
2431
2432 jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2433 {
2434         STATISTICS(jniinvokation());
2435
2436         log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!");
2437
2438         return 0;
2439 }
2440
2441
2442
2443 jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2444 {
2445         va_list ap;
2446         jdouble ret;
2447
2448         va_start(ap, methodID);
2449         ret = _Jv_jni_CallDoubleMethod(obj, clazz->vftbl, methodID, ap);
2450         va_end(ap);
2451
2452         return ret;
2453 }
2454
2455
2456 jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2457 {
2458         jdouble ret;
2459
2460         ret = _Jv_jni_CallDoubleMethod(obj, clazz->vftbl, methodID, args);
2461
2462         return ret;
2463 }
2464
2465
2466 jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args)
2467 {
2468         log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!");
2469
2470         return 0;
2471 }
2472
2473
2474
2475 void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...)
2476 {
2477         va_list ap;
2478
2479         va_start(ap, methodID);
2480         _Jv_jni_CallVoidMethod(obj, clazz->vftbl, methodID, ap);
2481         va_end(ap);
2482 }
2483
2484
2485 void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args)
2486 {
2487         _Jv_jni_CallVoidMethod(obj, clazz->vftbl, methodID, args);
2488 }
2489
2490
2491 void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args)
2492 {
2493         log_text("JNI-Call: CallNonvirtualVoidMethodA: IMPLEMENT ME!");
2494 }
2495
2496
2497 /* Accessing Fields of Objects ************************************************/
2498
2499 /* GetFieldID ******************************************************************
2500
2501    Returns the field ID for an instance (nonstatic) field of a
2502    class. The field is specified by its name and signature. The
2503    Get<type>Field and Set<type>Field families of accessor functions
2504    use field IDs to retrieve object fields.
2505
2506 *******************************************************************************/
2507
2508 jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
2509                                         const char *sig) 
2510 {
2511         fieldinfo *f;
2512         utf       *uname;
2513         utf       *udesc;
2514
2515         STATISTICS(jniinvokation());
2516
2517         uname = utf_new_char((char *) name);
2518         udesc = utf_new_char((char *) sig);
2519
2520         f = class_findfield(clazz, uname, udesc); 
2521         
2522         if (!f)
2523                 *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);  
2524
2525         return f;
2526 }
2527
2528
2529 /* Get<type>Field Routines *****************************************************
2530
2531    This family of accessor routines returns the value of an instance
2532    (nonstatic) field of an object. The field to access is specified by
2533    a field ID obtained by calling GetFieldID().
2534
2535 *******************************************************************************/
2536
2537 jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
2538 {
2539         java_objectheader *o;
2540
2541         STATISTICS(jniinvokation());
2542
2543         o = GET_FIELD(obj, java_objectheader*, fieldID);
2544
2545         return NewLocalRef(env, o);
2546 }
2547
2548
2549 jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID)
2550 {
2551         s4 i;
2552
2553         STATISTICS(jniinvokation());
2554
2555         i = GET_FIELD(obj, s4, fieldID);
2556
2557         return (jboolean) i;
2558 }
2559
2560
2561 jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID)
2562 {
2563         s4 i;
2564
2565         STATISTICS(jniinvokation());
2566
2567         i = GET_FIELD(obj, s4, fieldID);
2568
2569         return (jbyte) i;
2570 }
2571
2572
2573 jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID)
2574 {
2575         s4 i;
2576
2577         STATISTICS(jniinvokation());
2578
2579         i = GET_FIELD(obj, s4, fieldID);
2580
2581         return (jchar) i;
2582 }
2583
2584
2585 jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID)
2586 {
2587         s4 i;
2588
2589         STATISTICS(jniinvokation());
2590
2591         i = GET_FIELD(obj, s4, fieldID);
2592
2593         return (jshort) i;
2594 }
2595
2596
2597 jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID)
2598 {
2599         s4 i;
2600
2601         STATISTICS(jniinvokation());
2602
2603         i = GET_FIELD(obj, s4, fieldID);
2604
2605         return i;
2606 }
2607
2608
2609 jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID)
2610 {
2611         s8 l;
2612
2613         STATISTICS(jniinvokation());
2614
2615         l = GET_FIELD(obj, s8, fieldID);
2616
2617         return l;
2618 }
2619
2620
2621 jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID)
2622 {
2623         float f;
2624
2625         STATISTICS(jniinvokation());
2626
2627         f = GET_FIELD(obj, float, fieldID);
2628
2629         return f;
2630 }
2631
2632
2633 jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID)
2634 {
2635         double d;
2636
2637         STATISTICS(jniinvokation());
2638
2639         d = GET_FIELD(obj, double, fieldID);
2640
2641         return d;
2642 }
2643
2644
2645 /* Set<type>Field Routines *****************************************************
2646
2647    This family of accessor routines sets the value of an instance
2648    (nonstatic) field of an object. The field to access is specified by
2649    a field ID obtained by calling GetFieldID().
2650
2651 *******************************************************************************/
2652
2653 void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)
2654 {
2655         STATISTICS(jniinvokation());
2656
2657         SET_FIELD(obj, java_objectheader*, fieldID, value);
2658 }
2659
2660
2661 void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean value)
2662 {
2663         STATISTICS(jniinvokation());
2664
2665         SET_FIELD(obj, s4, fieldID, value);
2666 }
2667
2668
2669 void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value)
2670 {
2671         STATISTICS(jniinvokation());
2672
2673         SET_FIELD(obj, s4, fieldID, value);
2674 }
2675
2676
2677 void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value)
2678 {
2679         STATISTICS(jniinvokation());
2680
2681         SET_FIELD(obj, s4, fieldID, value);
2682 }
2683
2684
2685 void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value)
2686 {
2687         STATISTICS(jniinvokation());
2688
2689         SET_FIELD(obj, s4, fieldID, value);
2690 }
2691
2692
2693 void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value)
2694 {
2695         STATISTICS(jniinvokation());
2696
2697         SET_FIELD(obj, s4, fieldID, value);
2698 }
2699
2700
2701 void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value)
2702 {
2703         STATISTICS(jniinvokation());
2704
2705         SET_FIELD(obj, s8, fieldID, value);
2706 }
2707
2708
2709 void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value)
2710 {
2711         STATISTICS(jniinvokation());
2712
2713         SET_FIELD(obj, float, fieldID, value);
2714 }
2715
2716
2717 void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value)
2718 {
2719         STATISTICS(jniinvokation());
2720
2721         SET_FIELD(obj, double, fieldID, value);
2722 }
2723
2724
2725 /* Calling Static Methods *****************************************************/
2726
2727 /* GetStaticMethodID ***********************************************************
2728
2729    Returns the method ID for a static method of a class. The method is
2730    specified by its name and signature.
2731
2732    GetStaticMethodID() causes an uninitialized class to be
2733    initialized.
2734
2735 *******************************************************************************/
2736
2737 jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
2738                                                         const char *sig)
2739 {
2740         classinfo  *c;
2741         utf        *uname;
2742         utf        *udesc;
2743         methodinfo *m;
2744
2745         STATISTICS(jniinvokation());
2746
2747         c = (classinfo *) clazz;
2748
2749         if (!c)
2750                 return NULL;
2751
2752         if (!(c->state & CLASS_INITIALIZED))
2753                 if (!initialize_class(c))
2754                         return NULL;
2755
2756         /* try to get the static method of the class */
2757
2758         uname = utf_new_char((char *) name);
2759         udesc = utf_new_char((char *) sig);
2760
2761         m = class_resolvemethod(c, uname, udesc);
2762
2763         if ((m == NULL) || !(m->flags & ACC_STATIC)) {
2764                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
2765
2766                 return NULL;
2767         }
2768
2769         return m;
2770 }
2771
2772
2773 jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2774 {
2775         java_objectheader *ret;
2776         va_list            ap;
2777
2778         va_start(ap, methodID);
2779         ret = _Jv_jni_CallObjectMethod(NULL, NULL, methodID, ap);
2780         va_end(ap);
2781
2782         return NewLocalRef(env, ret);
2783 }
2784
2785
2786 jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
2787 {
2788         java_objectheader *ret;
2789
2790         ret = _Jv_jni_CallObjectMethod(NULL, NULL, methodID, args);
2791
2792         return NewLocalRef(env, ret);
2793 }
2794
2795
2796 jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2797 {
2798         log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!");
2799
2800         return NewLocalRef(env, NULL);
2801 }
2802
2803
2804 jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2805 {
2806         va_list  ap;
2807         jboolean ret;
2808
2809         va_start(ap, methodID);
2810         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap,
2811                                                                 PRIMITIVETYPE_BOOLEAN);
2812         va_end(ap);
2813
2814         return ret;
2815 }
2816
2817
2818 jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
2819 {
2820         jboolean ret;
2821
2822         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args,
2823                                                                 PRIMITIVETYPE_BOOLEAN);
2824
2825         return ret;
2826 }
2827
2828
2829 jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2830 {
2831         log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!");
2832
2833         return 0;
2834 }
2835
2836
2837 jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2838 {
2839         va_list ap;
2840         jbyte   ret;
2841
2842         va_start(ap, methodID);
2843         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_BYTE);
2844         va_end(ap);
2845
2846         return ret;
2847 }
2848
2849
2850 jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
2851 {
2852         jbyte ret;
2853
2854         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_BYTE);
2855
2856         return ret;
2857 }
2858
2859
2860 jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2861 {
2862         log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!");
2863
2864         return 0;
2865 }
2866
2867
2868 jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2869 {
2870         va_list ap;
2871         jchar   ret;
2872
2873         va_start(ap, methodID);
2874         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_CHAR);
2875         va_end(ap);
2876
2877         return ret;
2878 }
2879
2880
2881 jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
2882 {
2883         jchar ret;
2884
2885         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_CHAR);
2886
2887         return ret;
2888 }
2889
2890
2891 jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2892 {
2893         log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!");
2894
2895         return 0;
2896 }
2897
2898
2899 jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2900 {
2901         va_list ap;
2902         jshort  ret;
2903
2904         va_start(ap, methodID);
2905         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_SHORT);
2906         va_end(ap);
2907
2908         return ret;
2909 }
2910
2911
2912 jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
2913 {
2914         jshort ret;
2915
2916         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args,
2917                                                                 PRIMITIVETYPE_SHORT);
2918
2919         return ret;
2920 }
2921
2922
2923 jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2924 {
2925         log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!");
2926
2927         return 0;
2928 }
2929
2930
2931 jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2932 {
2933         va_list ap;
2934         jint    ret;
2935
2936         va_start(ap, methodID);
2937         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, ap, PRIMITIVETYPE_INT);
2938         va_end(ap);
2939
2940         return ret;
2941 }
2942
2943
2944 jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
2945 {
2946         jint ret;
2947
2948         ret = _Jv_jni_CallIntMethod(NULL, NULL, methodID, args, PRIMITIVETYPE_INT);
2949
2950         return ret;
2951 }
2952
2953
2954 jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2955 {
2956         log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!");
2957
2958         return 0;
2959 }
2960
2961
2962 jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2963 {
2964         va_list ap;
2965         jlong   ret;
2966
2967         va_start(ap, methodID);
2968         ret = _Jv_jni_CallLongMethod(NULL, NULL, methodID, ap);
2969         va_end(ap);
2970
2971         return ret;
2972 }
2973
2974
2975 jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
2976                                                         va_list args)
2977 {
2978         jlong ret;
2979         
2980         ret = _Jv_jni_CallLongMethod(NULL, NULL, methodID, args);
2981
2982         return ret;
2983 }
2984
2985
2986 jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
2987 {
2988         log_text("JNI-Call: CallStaticLongMethodA: IMPLEMENT ME!");
2989
2990         return 0;
2991 }
2992
2993
2994
2995 jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
2996 {
2997         va_list ap;
2998         jfloat  ret;
2999
3000         va_start(ap, methodID);
3001         ret = _Jv_jni_CallFloatMethod(NULL, NULL, methodID, ap);
3002         va_end(ap);
3003
3004         return ret;
3005 }
3006
3007
3008 jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
3009 {
3010         jfloat ret;
3011
3012         ret = _Jv_jni_CallFloatMethod(NULL, NULL, methodID, args);
3013
3014         return ret;
3015 }
3016
3017
3018 jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
3019 {
3020         log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!");
3021
3022         return 0;
3023 }
3024
3025
3026 jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
3027 {
3028         va_list ap;
3029         jdouble ret;
3030
3031         va_start(ap, methodID);
3032         ret = _Jv_jni_CallDoubleMethod(NULL, NULL, methodID, ap);
3033         va_end(ap);
3034
3035         return ret;
3036 }
3037
3038
3039 jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
3040 {
3041         jdouble ret;
3042
3043         ret = _Jv_jni_CallDoubleMethod(NULL, NULL, methodID, args);
3044
3045         return ret;
3046 }
3047
3048
3049 jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args)
3050 {
3051         log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!");
3052
3053         return 0;
3054 }
3055
3056
3057 void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
3058 {
3059         va_list ap;
3060
3061         va_start(ap, methodID);
3062         _Jv_jni_CallVoidMethod(NULL, NULL, methodID, ap);
3063         va_end(ap);
3064 }
3065
3066
3067 void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
3068 {
3069         _Jv_jni_CallVoidMethod(NULL, NULL, methodID, args);
3070 }
3071
3072
3073 void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue * args)
3074 {
3075         log_text("JNI-Call: CallStaticVoidMethodA: IMPLEMENT ME!");
3076 }
3077
3078
3079 /* Accessing Static Fields ****************************************************/
3080
3081 /* GetStaticFieldID ************************************************************
3082
3083    Returns the field ID for a static field of a class. The field is
3084    specified by its name and signature. The GetStatic<type>Field and
3085    SetStatic<type>Field families of accessor functions use field IDs
3086    to retrieve static fields.
3087
3088 *******************************************************************************/
3089
3090 jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig)
3091 {
3092         jfieldID f;
3093
3094         STATISTICS(jniinvokation());
3095
3096         f = class_findfield(clazz,
3097                                                 utf_new_char((char *) name),
3098                                                 utf_new_char((char *) sig));
3099         
3100         if (!f)
3101                 *exceptionptr = new_exception(string_java_lang_NoSuchFieldError);
3102
3103         return f;
3104 }
3105
3106
3107 /* GetStatic<type>Field ********************************************************
3108
3109    This family of accessor routines returns the value of a static
3110    field of an object.
3111
3112 *******************************************************************************/
3113
3114 jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3115 {
3116         STATISTICS(jniinvokation());
3117
3118         if (!(clazz->state & CLASS_INITIALIZED))
3119                 if (!initialize_class(clazz))
3120                         return NULL;
3121
3122         return NewLocalRef(env, fieldID->value.a);
3123 }
3124
3125
3126 jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3127 {
3128         STATISTICS(jniinvokation());
3129
3130         if (!(clazz->state & CLASS_INITIALIZED))
3131                 if (!initialize_class(clazz))
3132                         return false;
3133
3134         return fieldID->value.i;       
3135 }
3136
3137
3138 jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3139 {
3140         STATISTICS(jniinvokation());
3141
3142         if (!(clazz->state & CLASS_INITIALIZED))
3143                 if (!initialize_class(clazz))
3144                         return 0;
3145
3146         return fieldID->value.i;       
3147 }
3148
3149
3150 jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3151 {
3152         STATISTICS(jniinvokation());
3153
3154         if (!(clazz->state & CLASS_INITIALIZED))
3155                 if (!initialize_class(clazz))
3156                         return 0;
3157
3158         return fieldID->value.i;       
3159 }
3160
3161
3162 jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3163 {
3164         STATISTICS(jniinvokation());
3165
3166         if (!(clazz->state & CLASS_INITIALIZED))
3167                 if (!initialize_class(clazz))
3168                         return 0;
3169
3170         return fieldID->value.i;       
3171 }
3172
3173
3174 jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3175 {
3176         STATISTICS(jniinvokation());
3177
3178         if (!(clazz->state & CLASS_INITIALIZED))
3179                 if (!initialize_class(clazz))
3180                         return 0;
3181
3182         return fieldID->value.i;       
3183 }
3184
3185
3186 jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3187 {
3188         STATISTICS(jniinvokation());
3189
3190         if (!(clazz->state & CLASS_INITIALIZED))
3191                 if (!initialize_class(clazz))
3192                         return 0;
3193
3194         return fieldID->value.l;
3195 }
3196
3197
3198 jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3199 {
3200         STATISTICS(jniinvokation());
3201
3202         if (!(clazz->state & CLASS_INITIALIZED))
3203                 if (!initialize_class(clazz))
3204                         return 0.0;
3205
3206         return fieldID->value.f;
3207 }
3208
3209
3210 jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3211 {
3212         STATISTICS(jniinvokation());
3213
3214         if (!(clazz->state & CLASS_INITIALIZED))
3215                 if (!initialize_class(clazz))
3216                         return 0.0;
3217
3218         return fieldID->value.d;
3219 }
3220
3221
3222 /*  SetStatic<type>Field *******************************************************
3223
3224         This family of accessor routines sets the value of a static field
3225         of an object.
3226
3227 *******************************************************************************/
3228
3229 void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)
3230 {
3231         STATISTICS(jniinvokation());
3232
3233         if (!(clazz->state & CLASS_INITIALIZED))
3234                 if (!initialize_class(clazz))
3235                         return;
3236
3237         fieldID->value.a = value;
3238 }
3239
3240
3241 void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value)
3242 {
3243         STATISTICS(jniinvokation());
3244
3245         if (!(clazz->state & CLASS_INITIALIZED))
3246                 if (!initialize_class(clazz))
3247                         return;
3248
3249         fieldID->value.i = value;
3250 }
3251
3252
3253 void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value)
3254 {
3255         STATISTICS(jniinvokation());
3256
3257         if (!(clazz->state & CLASS_INITIALIZED))
3258                 if (!initialize_class(clazz))
3259                         return;
3260
3261         fieldID->value.i = value;
3262 }
3263
3264
3265 void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value)
3266 {
3267         STATISTICS(jniinvokation());
3268
3269         if (!(clazz->state & CLASS_INITIALIZED))
3270                 if (!initialize_class(clazz))
3271                         return;
3272
3273         fieldID->value.i = value;
3274 }
3275
3276
3277 void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value)
3278 {
3279         STATISTICS(jniinvokation());
3280
3281         if (!(clazz->state & CLASS_INITIALIZED))
3282                 if (!initialize_class(clazz))
3283                         return;
3284
3285         fieldID->value.i = value;
3286 }
3287
3288
3289 void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value)
3290 {
3291         STATISTICS(jniinvokation());
3292
3293         if (!(clazz->state & CLASS_INITIALIZED))
3294                 if (!initialize_class(clazz))
3295                         return;
3296
3297         fieldID->value.i = value;
3298 }
3299
3300
3301 void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value)
3302 {
3303         STATISTICS(jniinvokation());
3304
3305         if (!(clazz->state & CLASS_INITIALIZED))
3306                 if (!initialize_class(clazz))
3307                         return;
3308
3309         fieldID->value.l = value;
3310 }
3311
3312
3313 void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value)
3314 {
3315         STATISTICS(jniinvokation());
3316
3317         if (!(clazz->state & CLASS_INITIALIZED))
3318                 if (!initialize_class(clazz))
3319                         return;
3320
3321         fieldID->value.f = value;
3322 }
3323
3324
3325 void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value)
3326 {
3327         STATISTICS(jniinvokation());
3328
3329         if (!(clazz->state & CLASS_INITIALIZED))
3330                 if (!initialize_class(clazz))
3331                         return;
3332
3333         fieldID->value.d = value;
3334 }
3335
3336
3337 /* String Operations **********************************************************/
3338
3339 /* NewString *******************************************************************
3340
3341    Create new java.lang.String object from an array of Unicode
3342    characters.
3343
3344 *******************************************************************************/
3345
3346 jstring NewString(JNIEnv *env, const jchar *buf, jsize len)
3347 {
3348         java_lang_String *s;
3349         java_chararray   *a;
3350         u4                i;
3351
3352         STATISTICS(jniinvokation());
3353         
3354         s = (java_lang_String *) builtin_new(class_java_lang_String);
3355         a = builtin_newarray_char(len);
3356
3357         /* javastring or characterarray could not be created */
3358         if (!a || !s)
3359                 return NULL;
3360
3361         /* copy text */
3362         for (i = 0; i < len; i++)
3363                 a->data[i] = buf[i];
3364
3365         s->value = a;
3366         s->offset = 0;
3367         s->count = len;
3368
3369         return (jstring) NewLocalRef(env, (jobject) s);
3370 }
3371
3372
3373 static jchar emptyStringJ[]={0,0};
3374
3375 /* GetStringLength *************************************************************
3376
3377    Returns the length (the count of Unicode characters) of a Java
3378    string.
3379
3380 *******************************************************************************/
3381
3382 jsize GetStringLength(JNIEnv *env, jstring str)
3383 {
3384         return ((java_lang_String *) str)->count;
3385 }
3386
3387
3388 /********************  convertes javastring to u2-array ****************************/
3389         
3390 u2 *javastring_tou2(jstring so) 
3391 {
3392         java_lang_String *s;
3393         java_chararray   *a;
3394         u2               *stringbuffer;
3395         u4                i;
3396
3397         STATISTICS(jniinvokation());
3398         
3399         s = (java_lang_String *) so;
3400
3401         if (!s)
3402                 return NULL;
3403
3404         a = s->value;
3405
3406         if (!a)
3407                 return NULL;
3408
3409         /* allocate memory */
3410
3411         stringbuffer = MNEW(u2, s->count + 1);
3412
3413         /* copy text */
3414
3415         for (i = 0; i < s->count; i++)
3416                 stringbuffer[i] = a->data[s->offset + i];
3417         
3418         /* terminate string */
3419
3420         stringbuffer[i] = '\0';
3421
3422         return stringbuffer;
3423 }
3424
3425
3426 /* GetStringChars **************************************************************
3427
3428    Returns a pointer to the array of Unicode characters of the
3429    string. This pointer is valid until ReleaseStringchars() is called.
3430
3431 *******************************************************************************/
3432
3433 const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
3434 {       
3435         jchar *jc;
3436
3437         STATISTICS(jniinvokation());
3438
3439         jc = javastring_tou2(str);
3440
3441         if (jc) {
3442                 if (isCopy)
3443                         *isCopy = JNI_TRUE;
3444
3445                 return jc;
3446         }
3447
3448         if (isCopy)
3449                 *isCopy = JNI_TRUE;
3450
3451         return emptyStringJ;
3452 }
3453
3454
3455 /* ReleaseStringChars **********************************************************
3456
3457    Informs the VM that the native code no longer needs access to
3458    chars. The chars argument is a pointer obtained from string using
3459    GetStringChars().
3460
3461 *******************************************************************************/
3462
3463 void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
3464 {
3465         STATISTICS(jniinvokation());
3466
3467         if (chars == emptyStringJ)
3468                 return;
3469
3470         MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1);
3471 }
3472
3473
3474 /* NewStringUTF ****************************************************************
3475
3476    Constructs a new java.lang.String object from an array of UTF-8 characters.
3477
3478 *******************************************************************************/
3479
3480 jstring NewStringUTF(JNIEnv *env, const char *bytes)
3481 {
3482         java_lang_String *s;
3483
3484         STATISTICS(jniinvokation());
3485
3486         s = javastring_new(utf_new_char(bytes));
3487
3488     return (jstring) NewLocalRef(env, (jobject) s);
3489 }
3490
3491
3492 /****************** returns the utf8 length in bytes of a string *******************/
3493
3494 jsize GetStringUTFLength (JNIEnv *env, jstring string)
3495 {   
3496     java_lang_String *s = (java_lang_String*) string;
3497
3498         STATISTICS(jniinvokation());
3499
3500     return (jsize) u2_utflength(s->value->data, s->count); 
3501 }
3502
3503
3504 /* GetStringUTFChars ***********************************************************
3505
3506    Returns a pointer to an array of UTF-8 characters of the
3507    string. This array is valid until it is released by
3508    ReleaseStringUTFChars().
3509
3510 *******************************************************************************/
3511
3512 const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
3513 {
3514         utf *u;
3515
3516         STATISTICS(jniinvokation());
3517
3518         if (!string)
3519                 return "";
3520
3521         if (isCopy)
3522                 *isCopy = JNI_TRUE;
3523         
3524         u = javastring_toutf((java_lang_String *) string, false);
3525
3526         if (u)
3527                 return u->text;
3528
3529         return "";
3530 }
3531
3532
3533 /* ReleaseStringUTFChars *******************************************************
3534
3535    Informs the VM that the native code no longer needs access to
3536    utf. The utf argument is a pointer derived from string using
3537    GetStringUTFChars().
3538
3539 *******************************************************************************/
3540
3541 void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
3542 {
3543         STATISTICS(jniinvokation());
3544
3545     /* XXX we don't release utf chars right now, perhaps that should be done 
3546            later. Since there is always one reference the garbage collector will
3547            never get them */
3548 }
3549
3550
3551 /* Array Operations ***********************************************************/
3552
3553 /* GetArrayLength **************************************************************
3554
3555    Returns the number of elements in the array.
3556
3557 *******************************************************************************/
3558
3559 jsize GetArrayLength(JNIEnv *env, jarray array)
3560 {
3561         STATISTICS(jniinvokation());
3562
3563         return array->size;
3564 }
3565
3566
3567 /* NewObjectArray **************************************************************
3568
3569    Constructs a new array holding objects in class elementClass. All
3570    elements are initially set to initialElement.
3571
3572 *******************************************************************************/
3573
3574 jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)
3575 {
3576         java_objectarray *oa;
3577         s4                i;
3578
3579         STATISTICS(jniinvokation());
3580
3581         if (length < 0) {
3582                 exceptions_throw_negativearraysizeexception();
3583                 return NULL;
3584         }
3585
3586     oa = builtin_anewarray(length, elementClass);
3587
3588         if (!oa)
3589                 return NULL;
3590
3591         /* set all elements to initialElement */
3592
3593         for (i = 0; i < length; i++)
3594                 oa->data[i] = initialElement;
3595
3596         return (jobjectArray) NewLocalRef(env, (jobject) oa);
3597 }
3598
3599
3600 jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)
3601 {
3602     jobject o;
3603
3604         STATISTICS(jniinvokation());
3605
3606         if (index >= array->header.size) {
3607                 exceptions_throw_arrayindexoutofboundsexception();
3608                 return NULL;
3609         }
3610
3611         o = array->data[index];
3612     
3613     return NewLocalRef(env, o);
3614 }
3615
3616
3617 void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val)
3618 {
3619         java_objectarray  *oa;
3620         java_objectheader *o;
3621
3622         STATISTICS(jniinvokation());
3623
3624         oa = (java_objectarray *) array;
3625         o  = (java_objectheader *) val;
3626
3627     if (index >= array->header.size) {
3628                 exceptions_throw_arrayindexoutofboundsexception();
3629                 return;
3630         }
3631
3632         /* check if the class of value is a subclass of the element class
3633            of the array */
3634
3635         if (!builtin_canstore(oa, o)) {
3636                 *exceptionptr = new_exception(string_java_lang_ArrayStoreException);
3637
3638                 return;
3639         }
3640
3641         array->data[index] = val;
3642 }
3643
3644
3645 jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
3646 {
3647         java_booleanarray *ba;
3648
3649         STATISTICS(jniinvokation());
3650
3651         if (len < 0) {
3652                 exceptions_throw_negativearraysizeexception();
3653                 return NULL;
3654         }
3655
3656         ba = builtin_newarray_boolean(len);
3657
3658         return (jbooleanArray) NewLocalRef(env, (jobject) ba);
3659 }
3660
3661
3662 jbyteArray NewByteArray(JNIEnv *env, jsize len)
3663 {
3664         java_bytearray *ba;
3665
3666         STATISTICS(jniinvokation());
3667
3668         if (len < 0) {
3669                 exceptions_throw_negativearraysizeexception();
3670                 return NULL;
3671         }
3672
3673         ba = builtin_newarray_byte(len);
3674
3675         return (jbyteArray) NewLocalRef(env, (jobject) ba);
3676 }
3677
3678
3679 jcharArray NewCharArray(JNIEnv *env, jsize len)
3680 {
3681         java_chararray *ca;
3682
3683         STATISTICS(jniinvokation());
3684
3685         if (len < 0) {
3686                 exceptions_throw_negativearraysizeexception();
3687                 return NULL;
3688         }
3689
3690         ca = builtin_newarray_char(len);
3691
3692         return (jcharArray) NewLocalRef(env, (jobject) ca);
3693 }
3694
3695
3696 jshortArray NewShortArray(JNIEnv *env, jsize len)
3697 {
3698         java_shortarray *sa;
3699
3700         STATISTICS(jniinvokation());
3701
3702         if (len < 0) {
3703                 exceptions_throw_negativearraysizeexception();
3704                 return NULL;
3705         }
3706
3707         sa = builtin_newarray_short(len);
3708
3709         return (jshortArray) NewLocalRef(env, (jobject) sa);
3710 }
3711
3712
3713 jintArray NewIntArray(JNIEnv *env, jsize len)
3714 {
3715         java_intarray *ia;
3716
3717         STATISTICS(jniinvokation());
3718
3719         if (len < 0) {
3720                 exceptions_throw_negativearraysizeexception();
3721                 return NULL;
3722         }
3723
3724         ia = builtin_newarray_int(len);
3725
3726         return (jintArray) NewLocalRef(env, (jobject) ia);
3727 }
3728
3729
3730 jlongArray NewLongArray(JNIEnv *env, jsize len)
3731 {
3732         java_longarray *la;
3733
3734         STATISTICS(jniinvokation());
3735
3736         if (len < 0) {
3737                 exceptions_throw_negativearraysizeexception();
3738                 return NULL;
3739         }
3740
3741         la = builtin_newarray_long(len);
3742
3743         return (jlongArray) NewLocalRef(env, (jobject) la);
3744 }
3745
3746
3747 jfloatArray NewFloatArray(JNIEnv *env, jsize len)
3748 {
3749         java_floatarray *fa;
3750
3751         STATISTICS(jniinvokation());
3752
3753         if (len < 0) {
3754                 exceptions_throw_negativearraysizeexception();
3755                 return NULL;
3756         }
3757
3758         fa = builtin_newarray_float(len);
3759
3760         return (jfloatArray) NewLocalRef(env, (jobject) fa);
3761 }
3762
3763
3764 jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
3765 {
3766         java_doublearray *da;
3767
3768         STATISTICS(jniinvokation());
3769
3770         if (len < 0) {
3771                 exceptions_throw_negativearraysizeexception();
3772                 return NULL;
3773         }
3774
3775         da = builtin_newarray_double(len);
3776
3777         return (jdoubleArray) NewLocalRef(env, (jobject) da);
3778 }
3779
3780
3781 /* Get<PrimitiveType>ArrayElements *********************************************
3782
3783    A family of functions that returns the body of the primitive array.
3784
3785 *******************************************************************************/
3786
3787 jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
3788                                                                   jboolean *isCopy)
3789 {
3790         STATISTICS(jniinvokation());
3791
3792     if (isCopy)
3793                 *isCopy = JNI_FALSE;
3794
3795     return array->data;
3796 }
3797
3798
3799 jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy)
3800 {
3801         STATISTICS(jniinvokation());
3802
3803     if (isCopy)
3804                 *isCopy = JNI_FALSE;
3805
3806     return array->data;
3807 }
3808
3809
3810 jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy)
3811 {
3812         STATISTICS(jniinvokation());
3813
3814     if (isCopy)
3815                 *isCopy = JNI_FALSE;
3816
3817     return array->data;
3818 }
3819
3820
3821 jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy)
3822 {
3823         STATISTICS(jniinvokation());
3824
3825     if (isCopy)
3826                 *isCopy = JNI_FALSE;
3827
3828     return array->data;
3829 }
3830
3831
3832 jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
3833 {
3834         STATISTICS(jniinvokation());
3835
3836     if (isCopy)
3837                 *isCopy = JNI_FALSE;
3838
3839     return array->data;
3840 }
3841
3842
3843 jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy)
3844 {
3845         STATISTICS(jniinvokation());
3846
3847     if (isCopy)
3848                 *isCopy = JNI_FALSE;
3849
3850     return array->data;
3851 }
3852
3853
3854 jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy)
3855 {
3856         STATISTICS(jniinvokation());
3857
3858     if (isCopy)
3859                 *isCopy = JNI_FALSE;
3860
3861     return array->data;
3862 }
3863
3864
3865 jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
3866                                                                 jboolean *isCopy)
3867 {
3868         STATISTICS(jniinvokation());
3869
3870     if (isCopy)
3871                 *isCopy = JNI_FALSE;
3872
3873     return array->data;
3874 }
3875
3876
3877 /* Release<PrimitiveType>ArrayElements *****************************************
3878
3879    A family of functions that informs the VM that the native code no
3880    longer needs access to elems. The elems argument is a pointer
3881    derived from array using the corresponding
3882    Get<PrimitiveType>ArrayElements() function. If necessary, this
3883    function copies back all changes made to elems to the original
3884    array.
3885
3886 *******************************************************************************/
3887
3888 void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
3889                                                                  jboolean *elems, jint mode)
3890 {
3891         STATISTICS(jniinvokation());
3892
3893         if (elems != array->data) {
3894                 switch (mode) {
3895                 case JNI_COMMIT:
3896                         MCOPY(array->data, elems, jboolean, array->header.size);
3897                         break;
3898                 case 0:
3899                         MCOPY(array->data, elems, jboolean, array->header.size);
3900                         /* XXX TWISTI how should it be freed? */
3901                         break;
3902                 case JNI_ABORT:
3903                         /* XXX TWISTI how should it be freed? */
3904                         break;
3905                 }
3906         }
3907 }
3908
3909
3910 void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
3911                                                           jint mode)
3912 {
3913         STATISTICS(jniinvokation());
3914
3915         if (elems != array->data) {
3916                 switch (mode) {
3917                 case JNI_COMMIT:
3918                         MCOPY(array->data, elems, jboolean, array->header.size);
3919                         break;
3920                 case 0:
3921                         MCOPY(array->data, elems, jboolean, array->header.size);
3922                         /* XXX TWISTI how should it be freed? */
3923                         break;
3924                 case JNI_ABORT:
3925                         /* XXX TWISTI how should it be freed? */
3926                         break;
3927                 }
3928         }
3929 }
3930
3931
3932 void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
3933                                                           jint mode)
3934 {
3935         STATISTICS(jniinvokation());
3936
3937         if (elems != array->data) {
3938                 switch (mode) {
3939                 case JNI_COMMIT:
3940                         MCOPY(array->data, elems, jboolean, array->header.size);
3941                         break;
3942                 case 0:
3943                         MCOPY(array->data, elems, jboolean, array->header.size);
3944                         /* XXX TWISTI how should it be freed? */
3945                         break;
3946                 case JNI_ABORT:
3947                         /* XXX TWISTI how should it be freed? */
3948                         break;
3949                 }
3950         }
3951 }
3952
3953
3954 void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
3955                                                            jint mode)
3956 {
3957         STATISTICS(jniinvokation());
3958
3959         if (elems != array->data) {
3960                 switch (mode) {
3961                 case JNI_COMMIT:
3962                         MCOPY(array->data, elems, jboolean, array->header.size);
3963                         break;
3964                 case 0:
3965                         MCOPY(array->data, elems, jboolean, array->header.size);
3966                         /* XXX TWISTI how should it be freed? */
3967                         break;
3968                 case JNI_ABORT:
3969                         /* XXX TWISTI how should it be freed? */
3970                         break;
3971                 }
3972         }
3973 }
3974
3975
3976 void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
3977                                                          jint mode)
3978 {
3979         STATISTICS(jniinvokation());
3980
3981         if (elems != array->data) {
3982                 switch (mode) {
3983                 case JNI_COMMIT:
3984                         MCOPY(array->data, elems, jboolean, array->header.size);
3985                         break;
3986                 case 0:
3987                         MCOPY(array->data, elems, jboolean, array->header.size);
3988                         /* XXX TWISTI how should it be freed? */
3989                         break;
3990                 case JNI_ABORT:
3991                         /* XXX TWISTI how should it be freed? */
3992                         break;
3993                 }
3994         }
3995 }
3996
3997
3998 void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
3999                                                           jint mode)
4000 {
4001         STATISTICS(jniinvokation());
4002
4003         if (elems != array->data) {
4004                 switch (mode) {
4005                 case JNI_COMMIT:
4006                         MCOPY(array->data, elems, jboolean, array->header.size);
4007                         break;
4008                 case 0:
4009                         MCOPY(array->data, elems, jboolean, array->header.size);
4010                         /* XXX TWISTI how should it be freed? */
4011                         break;
4012                 case JNI_ABORT:
4013                         /* XXX TWISTI how should it be freed? */
4014                         break;
4015                 }
4016         }
4017 }
4018
4019
4020 void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
4021                                                            jint mode)
4022 {
4023         STATISTICS(jniinvokation());
4024
4025         if (elems != array->data) {
4026                 switch (mode) {
4027                 case JNI_COMMIT:
4028                         MCOPY(array->data, elems, jboolean, array->header.size);
4029                         break;
4030                 case 0:
4031                         MCOPY(array->data, elems, jboolean, array->header.size);
4032                         /* XXX TWISTI how should it be freed? */
4033                         break;
4034                 case JNI_ABORT:
4035                         /* XXX TWISTI how should it be freed? */
4036                         break;
4037                 }
4038         }
4039 }
4040
4041
4042 void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
4043                                                                 jdouble *elems, jint mode)
4044 {
4045         STATISTICS(jniinvokation());
4046
4047         if (elems != array->data) {
4048                 switch (mode) {
4049                 case JNI_COMMIT:
4050                         MCOPY(array->data, elems, jboolean, array->header.size);
4051                         break;
4052                 case 0:
4053                         MCOPY(array->data, elems, jboolean, array->header.size);
4054                         /* XXX TWISTI how should it be freed? */
4055                         break;
4056                 case JNI_ABORT:
4057                         /* XXX TWISTI how should it be freed? */
4058                         break;
4059                 }
4060         }
4061 }
4062
4063
4064 /*  Get<PrimitiveType>ArrayRegion **********************************************
4065
4066         A family of functions that copies a region of a primitive array
4067         into a buffer.
4068
4069 *******************************************************************************/
4070
4071 void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
4072                                                    jsize len, jboolean *buf)
4073 {
4074         STATISTICS(jniinvokation());
4075
4076     if (start < 0 || len < 0 || start + len > array->header.size)
4077                 exceptions_throw_arrayindexoutofboundsexception();
4078     else
4079                 MCOPY(buf, &array->data[start], jboolean, len);
4080 }
4081
4082
4083 void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
4084                                                 jbyte *buf)
4085 {
4086         STATISTICS(jniinvokation());
4087
4088     if (start < 0 || len < 0 || start + len > array->header.size) 
4089                 exceptions_throw_arrayindexoutofboundsexception();
4090     else
4091                 MCOPY(buf, &array->data[start], jbyte, len);
4092 }
4093
4094
4095 void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
4096                                                 jchar *buf)
4097 {
4098         STATISTICS(jniinvokation());
4099
4100     if (start < 0 || len < 0 || start + len > array->header.size)
4101                 exceptions_throw_arrayindexoutofboundsexception();
4102     else
4103                 MCOPY(buf, &array->data[start], jchar, len);
4104 }
4105
4106
4107 void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
4108                                                  jsize len, jshort *buf)
4109 {
4110         STATISTICS(jniinvokation());
4111
4112     if (start < 0 || len < 0 || start + len > array->header.size)
4113                 exceptions_throw_arrayindexoutofboundsexception();
4114     else        
4115                 MCOPY(buf, &array->data[start], jshort, len);
4116 }
4117
4118
4119 void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
4120                                            jint *buf)
4121 {
4122         STATISTICS(jniinvokation());
4123
4124     if (start < 0 || len < 0 || start + len > array->header.size)
4125                 exceptions_throw_arrayindexoutofboundsexception();
4126     else
4127                 MCOPY(buf, &array->data[start], jint, len);
4128 }
4129
4130
4131 void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
4132                                                 jlong *buf)
4133 {
4134         STATISTICS(jniinvokation());
4135
4136     if (start < 0 || len < 0 || start + len > array->header.size)
4137                 exceptions_throw_arrayindexoutofboundsexception();
4138     else
4139                 MCOPY(buf, &array->data[start], jlong, len);
4140 }
4141
4142
4143 void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
4144                                                  jsize len, jfloat *buf)
4145 {
4146         STATISTICS(jniinvokation());
4147
4148     if (start < 0 || len < 0 || start + len > array->header.size)
4149                 exceptions_throw_arrayindexoutofboundsexception();
4150     else
4151                 MCOPY(buf, &array->data[start], jfloat, len);
4152 }
4153
4154
4155 void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
4156                                                   jsize len, jdouble *buf)
4157 {
4158         STATISTICS(jniinvokation());
4159
4160     if (start < 0 || len < 0 || start+len>array->header.size)
4161                 exceptions_throw_arrayindexoutofboundsexception();
4162     else
4163                 MCOPY(buf, &array->data[start], jdouble, len);
4164 }
4165
4166
4167 /*  Set<PrimitiveType>ArrayRegion **********************************************
4168
4169         A family of functions that copies back a region of a primitive
4170         array from a buffer.
4171
4172 *******************************************************************************/
4173
4174 void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
4175                                                    jsize len, jboolean *buf)
4176 {
4177         STATISTICS(jniinvokation());
4178
4179     if (start < 0 || len < 0 || start + len > array->header.size)
4180                 exceptions_throw_arrayindexoutofboundsexception();
4181     else
4182                 MCOPY(&array->data[start], buf, jboolean, len);
4183 }
4184
4185
4186 void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
4187                                                 jbyte *buf)
4188 {
4189         STATISTICS(jniinvokation());
4190
4191     if (start < 0 || len < 0 || start + len > array->header.size)
4192                 exceptions_throw_arrayindexoutofboundsexception();
4193     else
4194                 MCOPY(&array->data[start], buf, jbyte, len);
4195 }
4196
4197
4198 void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
4199                                                 jchar *buf)
4200 {
4201         STATISTICS(jniinvokation());
4202
4203     if (start < 0 || len < 0 || start + len > array->header.size)
4204                 exceptions_throw_arrayindexoutofboundsexception();
4205     else
4206                 MCOPY(&array->data[start], buf, jchar, len);
4207 }
4208
4209
4210 void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
4211                                                  jsize len, jshort *buf)
4212 {
4213         STATISTICS(jniinvokation());
4214
4215     if (start < 0 || len < 0 || start + len > array->header.size)
4216                 exceptions_throw_arrayindexoutofboundsexception();
4217     else
4218                 MCOPY(&array->data[start], buf, jshort, len);
4219 }
4220
4221
4222 void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
4223                                            jint *buf)
4224 {
4225         STATISTICS(jniinvokation());
4226
4227     if (start < 0 || len < 0 || start + len > array->header.size)
4228                 exceptions_throw_arrayindexoutofboundsexception();
4229     else
4230                 MCOPY(&array->data[start], buf, jint, len);
4231 }
4232
4233
4234 void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
4235                                                 jlong *buf)
4236 {
4237         STATISTICS(jniinvokation());
4238
4239     if (start < 0 || len < 0 || start + len > array->header.size)
4240                 exceptions_throw_arrayindexoutofboundsexception();
4241     else
4242                 MCOPY(&array->data[start], buf, jlong, len);
4243 }
4244
4245
4246 void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
4247                                                  jsize len, jfloat *buf)
4248 {
4249         STATISTICS(jniinvokation());
4250
4251     if (start < 0 || len < 0 || start + len > array->header.size)
4252                 exceptions_throw_arrayindexoutofboundsexception();
4253     else
4254                 MCOPY(&array->data[start], buf, jfloat, len);
4255 }
4256
4257
4258 void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
4259                                                   jsize len, jdouble *buf)
4260 {
4261         STATISTICS(jniinvokation());
4262
4263     if (start < 0 || len < 0 || start + len > array->header.size)
4264                 exceptions_throw_arrayindexoutofboundsexception();
4265     else
4266                 MCOPY(&array->data[start], buf, jdouble, len);
4267 }
4268
4269
4270 /* Registering Native Methods *************************************************/
4271
4272 /* RegisterNatives *************************************************************
4273
4274    Registers native methods with the class specified by the clazz
4275    argument. The methods parameter specifies an array of
4276    JNINativeMethod structures that contain the names, signatures, and
4277    function pointers of the native methods. The nMethods parameter
4278    specifies the number of native methods in the array.
4279
4280 *******************************************************************************/
4281
4282 jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
4283                                          jint nMethods)
4284 {
4285         STATISTICS(jniinvokation());
4286
4287     log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!");
4288
4289     return 0;
4290 }
4291
4292
4293 /* UnregisterNatives ***********************************************************
4294
4295    Unregisters native methods of a class. The class goes back to the
4296    state before it was linked or registered with its native method
4297    functions.
4298
4299    This function should not be used in normal native code. Instead, it
4300    provides special programs a way to reload and relink native
4301    libraries.
4302
4303 *******************************************************************************/
4304
4305 jint UnregisterNatives(JNIEnv *env, jclass clazz)
4306 {
4307         STATISTICS(jniinvokation());
4308
4309         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
4310
4311     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
4312
4313     return 0;
4314 }
4315
4316
4317 /* Monitor Operations *********************************************************/
4318
4319 /* MonitorEnter ****************************************************************
4320
4321    Enters the monitor associated with the underlying Java object
4322    referred to by obj.
4323
4324 *******************************************************************************/
4325
4326 jint MonitorEnter(JNIEnv *env, jobject obj)
4327 {
4328         STATISTICS(jniinvokation());
4329
4330         if (!obj) {
4331                 exceptions_throw_nullpointerexception();
4332                 return JNI_ERR;
4333         }
4334
4335 #if defined(USE_THREADS)
4336         builtin_monitorenter(obj);
4337 #endif
4338
4339         return JNI_OK;
4340 }
4341
4342
4343 /* MonitorExit *****************************************************************
4344
4345    The current thread must be the owner of the monitor associated with
4346    the underlying Java object referred to by obj. The thread
4347    decrements the counter indicating the number of times it has
4348    entered this monitor. If the value of the counter becomes zero, the
4349    current thread releases the monitor.
4350
4351 *******************************************************************************/
4352
4353 jint MonitorExit(JNIEnv *env, jobject obj)
4354 {
4355         STATISTICS(jniinvokation());
4356
4357         if (!obj) {
4358                 exceptions_throw_nullpointerexception();
4359                 return JNI_ERR;
4360         }
4361
4362 #if defined(USE_THREADS)
4363         builtin_monitorexit(obj);
4364 #endif
4365
4366         return JNI_OK;
4367 }
4368
4369
4370 /* JavaVM Interface ***********************************************************/
4371
4372 /* GetJavaVM *******************************************************************
4373
4374    Returns the Java VM interface (used in the Invocation API)
4375    associated with the current thread. The result is placed at the
4376    location pointed to by the second argument, vm.
4377
4378 *******************************************************************************/
4379
4380 jint GetJavaVM(JNIEnv *env, JavaVM **vm)
4381 {
4382         STATISTICS(jniinvokation());
4383
4384     *vm = &ptr_jvm;
4385
4386         return 0;
4387 }
4388
4389
4390 void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
4391 {
4392         STATISTICS(jniinvokation());
4393
4394         log_text("JNI-Call: GetStringRegion: IMPLEMENT ME!");
4395 }
4396
4397
4398 void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
4399 {
4400         STATISTICS(jniinvokation());
4401
4402         log_text("JNI-Call: GetStringUTFRegion: IMPLEMENT ME!");
4403 }
4404
4405
4406 /* GetPrimitiveArrayCritical ***************************************************
4407
4408    Obtain a direct pointer to array elements.
4409
4410 *******************************************************************************/
4411
4412 void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
4413 {
4414         java_bytearray *ba;
4415         jbyte          *bp;
4416
4417         ba = (java_bytearray *) array;
4418
4419         /* do the same as Kaffe does */
4420
4421         bp = GetByteArrayElements(env, ba, isCopy);
4422
4423         return (void *) bp;
4424 }
4425
4426
4427 /* ReleasePrimitiveArrayCritical ***********************************************
4428
4429    No specific documentation.
4430
4431 *******************************************************************************/
4432
4433 void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray,
4434                                                                    jint mode)
4435 {
4436         STATISTICS(jniinvokation());
4437
4438         /* do the same as Kaffe does */
4439
4440         ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray, mode);
4441 }
4442
4443
4444 /* GetStringCritical ***********************************************************
4445
4446    The semantics of these two functions are similar to the existing
4447    Get/ReleaseStringChars functions.
4448
4449 *******************************************************************************/
4450
4451 const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)
4452 {
4453         STATISTICS(jniinvokation());
4454
4455         return GetStringChars(env, string, isCopy);
4456 }
4457
4458
4459 void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring)
4460 {
4461         STATISTICS(jniinvokation());
4462
4463         ReleaseStringChars(env, string, cstring);
4464 }
4465
4466
4467 jweak NewWeakGlobalRef(JNIEnv* env, jobject obj)
4468 {
4469         STATISTICS(jniinvokation());
4470
4471         log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!");
4472
4473         return obj;
4474 }
4475
4476
4477 void DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
4478 {
4479         STATISTICS(jniinvokation());
4480
4481         log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME");
4482 }
4483
4484
4485 /* NewGlobalRef ****************************************************************
4486
4487    Creates a new global reference to the object referred to by the obj
4488    argument.
4489
4490 *******************************************************************************/
4491     
4492 jobject NewGlobalRef(JNIEnv* env, jobject lobj)
4493 {
4494         java_objectheader *o;
4495         java_lang_Integer *refcount;
4496         java_objectheader *newval;
4497
4498         STATISTICS(jniinvokation());
4499
4500 #if defined(USE_THREADS)
4501         builtin_monitorenter(*global_ref_table);
4502 #endif
4503         
4504         ASM_CALLJAVAFUNCTION_ADR(o, getmid, *global_ref_table, lobj, NULL, NULL);
4505
4506         refcount = (java_lang_Integer *) o;
4507
4508         if (refcount == NULL) {
4509                 newval = native_new_and_init_int(class_java_lang_Integer, 1);
4510
4511                 if (newval == NULL) {
4512 #if defined(USE_THREADS)
4513                         builtin_monitorexit(*global_ref_table);
4514 #endif
4515                         return NULL;
4516                 }
4517
4518                 ASM_CALLJAVAFUNCTION(putmid, *global_ref_table, lobj, newval, NULL);
4519
4520         } else {
4521                 /* we can access the object itself, as we are in a
4522            synchronized section */
4523
4524                 refcount->value++;
4525         }
4526
4527 #if defined(USE_THREADS)
4528         builtin_monitorexit(*global_ref_table);
4529 #endif
4530
4531         return lobj;
4532 }
4533
4534
4535 /* DeleteGlobalRef *************************************************************
4536
4537    Deletes the global reference pointed to by globalRef.
4538
4539 *******************************************************************************/
4540
4541 void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
4542 {
4543         java_objectheader *o;
4544         java_lang_Integer *refcount;
4545         s4                 val;
4546
4547         STATISTICS(jniinvokation());
4548
4549 #if defined(USE_THREADS)
4550         builtin_monitorenter(*global_ref_table);
4551 #endif
4552
4553         ASM_CALLJAVAFUNCTION_ADR(o, getmid, *global_ref_table, globalRef, NULL,
4554                                                          NULL);
4555
4556         refcount = (java_lang_Integer *) o;
4557
4558         if (refcount == NULL) {
4559                 log_text("JNI-DeleteGlobalRef: unable to find global reference");
4560                 return;
4561         }
4562
4563         /* we can access the object itself, as we are in a synchronized
4564            section */
4565
4566         val = refcount->value - 1;
4567
4568         if (val == 0) {
4569                 ASM_CALLJAVAFUNCTION(removemid, *global_ref_table, refcount, NULL,
4570                                                          NULL);
4571
4572         } else {
4573                 /* we do not create a new object, but set the new value into
4574            the old one */
4575
4576                 refcount->value = val;
4577         }
4578
4579 #if defined(USE_THREADS)
4580         builtin_monitorexit(*global_ref_table);
4581 #endif
4582 }
4583
4584
4585 /* ExceptionCheck **************************************************************
4586
4587    Returns JNI_TRUE when there is a pending exception; otherwise,
4588    returns JNI_FALSE.
4589
4590 *******************************************************************************/
4591
4592 jboolean ExceptionCheck(JNIEnv *env)
4593 {
4594         STATISTICS(jniinvokation());
4595
4596         return *exceptionptr ? JNI_TRUE : JNI_FALSE;
4597 }
4598
4599
4600 /* New JNI 1.4 functions ******************************************************/
4601
4602 /* NewDirectByteBuffer *********************************************************
4603
4604    Allocates and returns a direct java.nio.ByteBuffer referring to the
4605    block of memory starting at the memory address address and
4606    extending capacity bytes.
4607
4608 *******************************************************************************/
4609
4610 jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
4611 {
4612         java_objectheader       *nbuf;
4613 #if SIZEOF_VOID_P == 8
4614         gnu_classpath_Pointer64 *paddress;
4615 #else
4616         gnu_classpath_Pointer32 *paddress;
4617 #endif
4618
4619         STATISTICS(jniinvokation());
4620
4621         /* alocate a gnu.classpath.Pointer{32,64} object */
4622
4623 #if SIZEOF_VOID_P == 8
4624         if (!(paddress = (gnu_classpath_Pointer64 *)
4625                   builtin_new(class_gnu_classpath_Pointer64)))
4626 #else
4627         if (!(paddress = (gnu_classpath_Pointer32 *)
4628                   builtin_new(class_gnu_classpath_Pointer32)))
4629 #endif
4630                 return NULL;
4631
4632         /* fill gnu.classpath.Pointer{32,64} with address */
4633
4634         paddress->data = (ptrint) address;
4635
4636         /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
4637
4638         nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
4639                                                          dbbirw_init, NULL, paddress,
4640                                                          (jint) capacity, (jint) capacity, (jint) 0);
4641
4642         /* add local reference and return the value */
4643
4644         return NewLocalRef(env, nbuf);
4645 }
4646
4647
4648 /* GetDirectBufferAddress ******************************************************
4649
4650    Fetches and returns the starting address of the memory region
4651    referenced by the given direct java.nio.Buffer.
4652
4653 *******************************************************************************/
4654
4655 void *GetDirectBufferAddress(JNIEnv *env, jobject buf)
4656 {
4657         java_nio_DirectByteBufferImpl *nbuf;
4658 #if SIZEOF_VOID_P == 8
4659         gnu_classpath_Pointer64       *address;
4660 #else
4661         gnu_classpath_Pointer32       *address;
4662 #endif
4663
4664         STATISTICS(jniinvokation());
4665
4666         if (!builtin_instanceof(buf, class_java_nio_Buffer))
4667                 return NULL;
4668
4669         nbuf = (java_nio_DirectByteBufferImpl *) buf;
4670
4671 #if SIZEOF_VOID_P == 8
4672         address = (gnu_classpath_Pointer64 *) nbuf->address;
4673 #else
4674         address = (gnu_classpath_Pointer32 *) nbuf->address;
4675 #endif
4676
4677         return (void *) address->data;
4678 }
4679
4680
4681 /* GetDirectBufferCapacity *****************************************************
4682
4683    Fetches and returns the capacity in bytes of the memory region
4684    referenced by the given direct java.nio.Buffer.
4685
4686 *******************************************************************************/
4687
4688 jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
4689 {
4690         java_nio_Buffer *nbuf;
4691
4692         STATISTICS(jniinvokation());
4693
4694         if (!builtin_instanceof(buf, class_java_nio_DirectByteBufferImpl))
4695                 return -1;
4696
4697         nbuf = (java_nio_Buffer *) buf;
4698
4699         return (jlong) nbuf->cap;
4700 }
4701
4702
4703 jint DestroyJavaVM(JavaVM *vm)
4704 {
4705         STATISTICS(jniinvokation());
4706
4707         log_text("JNI-Call: DestroyJavaVM: IMPLEMENT ME!");
4708
4709         return 0;
4710 }
4711
4712
4713 /* AttachCurrentThread *********************************************************
4714
4715    Attaches the current thread to a Java VM. Returns a JNI interface
4716    pointer in the JNIEnv argument.
4717
4718    Trying to attach a thread that is already attached is a no-op.
4719
4720    A native thread cannot be attached simultaneously to two Java VMs.
4721
4722    When a thread is attached to the VM, the context class loader is
4723    the bootstrap loader.
4724
4725 *******************************************************************************/
4726
4727 jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args)
4728 {
4729         STATISTICS(jniinvokation());
4730
4731         log_text("JNI-Call: AttachCurrentThread: IMPLEMENT ME!");
4732
4733 #if !defined(HAVE___THREAD)
4734 /*      cacao_thread_attach();*/
4735 #else
4736         #error "No idea how to implement that. Perhaps Stefan knows"
4737 #endif
4738
4739         *env = &ptr_env;
4740
4741         return 0;
4742 }
4743
4744
4745 jint DetachCurrentThread(JavaVM *vm)
4746 {
4747         STATISTICS(jniinvokation());
4748
4749         log_text("JNI-Call: DetachCurrentThread: IMPLEMENT ME!");
4750
4751         return 0;
4752 }
4753
4754
4755 /* GetEnv **********************************************************************
4756
4757    If the current thread is not attached to the VM, sets *env to NULL,
4758    and returns JNI_EDETACHED. If the specified version is not
4759    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
4760    sets *env to the appropriate interface, and returns JNI_OK.
4761
4762 *******************************************************************************/
4763
4764 jint GetEnv(JavaVM *vm, void **env, jint version)
4765 {
4766         STATISTICS(jniinvokation());
4767
4768 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4769         if (thread_getself() == NULL) {
4770                 *env = NULL;
4771
4772                 return JNI_EDETACHED;
4773         }
4774 #endif
4775
4776         if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) ||
4777                 (version == JNI_VERSION_1_4)) {
4778                 *env = &ptr_env;
4779
4780                 return JNI_OK;
4781         }
4782
4783 #if defined(ENABLE_JVMTI)
4784         if (version == JVMTI_VERSION_1_0) {
4785                 *env = (void *) new_jvmtienv();
4786
4787                 if (env != NULL)
4788                         return JNI_OK;
4789         }
4790 #endif
4791         
4792         *env = NULL;
4793
4794         return JNI_EVERSION;
4795 }
4796
4797
4798
4799 jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
4800 {
4801         STATISTICS(jniinvokation());
4802
4803         log_text("JNI-Call: AttachCurrentThreadAsDaemon: IMPLEMENT ME!");
4804
4805         return 0;
4806 }
4807
4808
4809 /* JNI invocation table *******************************************************/
4810
4811 const struct JNIInvokeInterface JNI_JavaVMTable = {
4812         NULL,
4813         NULL,
4814         NULL,
4815
4816         DestroyJavaVM,
4817         AttachCurrentThread,
4818         DetachCurrentThread,
4819         GetEnv,
4820         AttachCurrentThreadAsDaemon
4821 };
4822
4823
4824 /* JNI function table *********************************************************/
4825
4826 struct JNINativeInterface JNI_JNIEnvTable = {
4827         NULL,
4828         NULL,
4829         NULL,
4830         NULL,    
4831         &GetVersion,
4832
4833         &DefineClass,
4834         &FindClass,
4835         &FromReflectedMethod,
4836         &FromReflectedField,
4837         &ToReflectedMethod,
4838         &GetSuperclass,
4839         &IsAssignableFrom,
4840         &ToReflectedField,
4841
4842         &Throw,
4843         &ThrowNew,
4844         &ExceptionOccurred,
4845         &ExceptionDescribe,
4846         &ExceptionClear,
4847         &FatalError,
4848         &PushLocalFrame,
4849         &PopLocalFrame,
4850
4851         &NewGlobalRef,
4852         &DeleteGlobalRef,
4853         &DeleteLocalRef,
4854         &IsSameObject,
4855         &NewLocalRef,
4856         &EnsureLocalCapacity,
4857
4858         &AllocObject,
4859         &NewObject,
4860         &NewObjectV,
4861         &NewObjectA,
4862
4863         &GetObjectClass,
4864         &IsInstanceOf,
4865
4866         &GetMethodID,
4867
4868         &CallObjectMethod,
4869         &CallObjectMethodV,
4870         &CallObjectMethodA,
4871         &CallBooleanMethod,
4872         &CallBooleanMethodV,
4873         &CallBooleanMethodA,
4874         &CallByteMethod,
4875         &CallByteMethodV,
4876         &CallByteMethodA,
4877         &CallCharMethod,
4878         &CallCharMethodV,
4879         &CallCharMethodA,
4880         &CallShortMethod,
4881         &CallShortMethodV,
4882         &CallShortMethodA,
4883         &CallIntMethod,
4884         &CallIntMethodV,
4885         &CallIntMethodA,
4886         &CallLongMethod,
4887         &CallLongMethodV,
4888         &CallLongMethodA,
4889         &CallFloatMethod,
4890         &CallFloatMethodV,
4891         &CallFloatMethodA,
4892         &CallDoubleMethod,
4893         &CallDoubleMethodV,
4894         &CallDoubleMethodA,
4895         &CallVoidMethod,
4896         &CallVoidMethodV,
4897         &CallVoidMethodA,
4898
4899         &CallNonvirtualObjectMethod,
4900         &CallNonvirtualObjectMethodV,
4901         &CallNonvirtualObjectMethodA,
4902         &CallNonvirtualBooleanMethod,
4903         &CallNonvirtualBooleanMethodV,
4904         &CallNonvirtualBooleanMethodA,
4905         &CallNonvirtualByteMethod,
4906         &CallNonvirtualByteMethodV,
4907         &CallNonvirtualByteMethodA,
4908         &CallNonvirtualCharMethod,
4909         &CallNonvirtualCharMethodV,
4910         &CallNonvirtualCharMethodA,
4911         &CallNonvirtualShortMethod,
4912         &CallNonvirtualShortMethodV,
4913         &CallNonvirtualShortMethodA,
4914         &CallNonvirtualIntMethod,
4915         &CallNonvirtualIntMethodV,
4916         &CallNonvirtualIntMethodA,
4917         &CallNonvirtualLongMethod,
4918         &CallNonvirtualLongMethodV,
4919         &CallNonvirtualLongMethodA,
4920         &CallNonvirtualFloatMethod,
4921         &CallNonvirtualFloatMethodV,
4922         &CallNonvirtualFloatMethodA,
4923         &CallNonvirtualDoubleMethod,
4924         &CallNonvirtualDoubleMethodV,
4925         &CallNonvirtualDoubleMethodA,
4926         &CallNonvirtualVoidMethod,
4927         &CallNonvirtualVoidMethodV,
4928         &CallNonvirtualVoidMethodA,
4929
4930         &GetFieldID,
4931
4932         &GetObjectField,
4933         &GetBooleanField,
4934         &GetByteField,
4935         &GetCharField,
4936         &GetShortField,
4937         &GetIntField,
4938         &GetLongField,
4939         &GetFloatField,
4940         &GetDoubleField,
4941         &SetObjectField,
4942         &SetBooleanField,
4943         &SetByteField,
4944         &SetCharField,
4945         &SetShortField,
4946         &SetIntField,
4947         &SetLongField,
4948         &SetFloatField,
4949         &SetDoubleField,
4950
4951         &GetStaticMethodID,
4952
4953         &CallStaticObjectMethod,
4954         &CallStaticObjectMethodV,
4955         &CallStaticObjectMethodA,
4956         &CallStaticBooleanMethod,
4957         &CallStaticBooleanMethodV,
4958         &CallStaticBooleanMethodA,
4959         &CallStaticByteMethod,
4960         &CallStaticByteMethodV,
4961         &CallStaticByteMethodA,
4962         &CallStaticCharMethod,
4963         &CallStaticCharMethodV,
4964         &CallStaticCharMethodA,
4965         &CallStaticShortMethod,
4966         &CallStaticShortMethodV,
4967         &CallStaticShortMethodA,
4968         &CallStaticIntMethod,
4969         &CallStaticIntMethodV,
4970         &CallStaticIntMethodA,
4971         &CallStaticLongMethod,
4972         &CallStaticLongMethodV,
4973         &CallStaticLongMethodA,
4974         &CallStaticFloatMethod,
4975         &CallStaticFloatMethodV,
4976         &CallStaticFloatMethodA,
4977         &CallStaticDoubleMethod,
4978         &CallStaticDoubleMethodV,
4979         &CallStaticDoubleMethodA,
4980         &CallStaticVoidMethod,
4981         &CallStaticVoidMethodV,
4982         &CallStaticVoidMethodA,
4983
4984         &GetStaticFieldID,
4985
4986         &GetStaticObjectField,
4987         &GetStaticBooleanField,
4988         &GetStaticByteField,
4989         &GetStaticCharField,
4990         &GetStaticShortField,
4991         &GetStaticIntField,
4992         &GetStaticLongField,
4993         &GetStaticFloatField,
4994         &GetStaticDoubleField,
4995         &SetStaticObjectField,
4996         &SetStaticBooleanField,
4997         &SetStaticByteField,
4998         &SetStaticCharField,
4999         &SetStaticShortField,
5000         &SetStaticIntField,
5001         &SetStaticLongField,
5002         &SetStaticFloatField,
5003         &SetStaticDoubleField,
5004
5005         &NewString,
5006         &GetStringLength,
5007         &GetStringChars,
5008         &ReleaseStringChars,
5009
5010         &NewStringUTF,
5011         &GetStringUTFLength,
5012         &GetStringUTFChars,
5013         &ReleaseStringUTFChars,
5014
5015         &GetArrayLength,
5016
5017         &NewObjectArray,
5018         &GetObjectArrayElement,
5019         &SetObjectArrayElement,
5020
5021         &NewBooleanArray,
5022         &NewByteArray,
5023         &NewCharArray,
5024         &NewShortArray,
5025         &NewIntArray,
5026         &NewLongArray,
5027         &NewFloatArray,
5028         &NewDoubleArray,
5029
5030         &GetBooleanArrayElements,
5031         &GetByteArrayElements,
5032         &GetCharArrayElements,
5033         &GetShortArrayElements,
5034         &GetIntArrayElements,
5035         &GetLongArrayElements,
5036         &GetFloatArrayElements,
5037         &GetDoubleArrayElements,
5038
5039         &ReleaseBooleanArrayElements,
5040         &ReleaseByteArrayElements,
5041         &ReleaseCharArrayElements,
5042         &ReleaseShortArrayElements,
5043         &ReleaseIntArrayElements,
5044         &ReleaseLongArrayElements,
5045         &ReleaseFloatArrayElements,
5046         &ReleaseDoubleArrayElements,
5047
5048         &GetBooleanArrayRegion,
5049         &GetByteArrayRegion,
5050         &GetCharArrayRegion,
5051         &GetShortArrayRegion,
5052         &GetIntArrayRegion,
5053         &GetLongArrayRegion,
5054         &GetFloatArrayRegion,
5055         &GetDoubleArrayRegion,
5056         &SetBooleanArrayRegion,
5057         &SetByteArrayRegion,
5058         &SetCharArrayRegion,
5059         &SetShortArrayRegion,
5060         &SetIntArrayRegion,
5061         &SetLongArrayRegion,
5062         &SetFloatArrayRegion,
5063         &SetDoubleArrayRegion,
5064
5065         &RegisterNatives,
5066         &UnregisterNatives,
5067
5068         &MonitorEnter,
5069         &MonitorExit,
5070
5071         &GetJavaVM,
5072
5073         /* new JNI 1.2 functions */
5074
5075         &GetStringRegion,
5076         &GetStringUTFRegion,
5077
5078         &GetPrimitiveArrayCritical,
5079         &ReleasePrimitiveArrayCritical,
5080
5081         &GetStringCritical,
5082         &ReleaseStringCritical,
5083
5084         &NewWeakGlobalRef,
5085         &DeleteWeakGlobalRef,
5086
5087         &ExceptionCheck,
5088
5089         /* new JNI 1.4 functions */
5090
5091         &NewDirectByteBuffer,
5092         &GetDirectBufferAddress,
5093         &GetDirectBufferCapacity
5094 };
5095
5096
5097 /* Invocation API Functions ***************************************************/
5098
5099 /* JNI_GetDefaultJavaVMInitArgs ************************************************
5100
5101    Returns a default configuration for the Java VM.
5102
5103 *******************************************************************************/
5104
5105 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
5106 {
5107         JDK1_1InitArgs *_vm_args = (JDK1_1InitArgs *) vm_args;
5108
5109         /* GNU classpath currently supports JNI 1.2 */
5110
5111         _vm_args->version = JNI_VERSION_1_2;
5112
5113         return 0;
5114 }
5115
5116
5117 /* JNI_GetCreatedJavaVMs *******************************************************
5118
5119    Returns all Java VMs that have been created. Pointers to VMs are written in
5120    the buffer vmBuf in the order they are created. At most bufLen number of
5121    entries will be written. The total number of created VMs is returned in
5122    *nVMs.
5123
5124 *******************************************************************************/
5125
5126 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
5127 {
5128         log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!");
5129
5130         return 0;
5131 }
5132
5133
5134 /* JNI_CreateJavaVM ************************************************************
5135
5136    Loads and initializes a Java VM. The current thread becomes the main thread.
5137    Sets the env argument to the JNI interface pointer of the main thread.
5138
5139 *******************************************************************************/
5140
5141 jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args)
5142 {
5143         const struct JNIInvokeInterface *vm;
5144         struct JNINativeInterface *env;
5145
5146         vm = &JNI_JavaVMTable;
5147         env = &JNI_JNIEnvTable;
5148
5149         *p_vm = (JavaVM *) vm;
5150         *p_env = (JNIEnv *) env;
5151
5152         return 0;
5153 }
5154
5155
5156 /*
5157  * These are local overrides for various environment variables in Emacs.
5158  * Please do not remove this and leave it at the end of the file, where
5159  * Emacs will automagically detect them.
5160  * ---------------------------------------------------------------------
5161  * Local variables:
5162  * mode: c
5163  * indent-tabs-mode: t
5164  * c-basic-offset: 4
5165  * tab-width: 4
5166  * End:
5167  */