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