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