* src/native/jni.c (stdint.h): Added.
[cacao.git] / src / native / jni.c
1 /* src/native/jni.c - implementation of the Java Native Interface functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: jni.c 8069 2007-06-13 14:08:24Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <string.h>
35
36 #include "vm/types.h"
37
38 #include "mm/gc-common.h"
39 #include "mm/memory.h"
40 #include "native/jni.h"
41 #include "native/native.h"
42
43 #if defined(ENABLE_JAVASE)
44 # if defined(WITH_CLASSPATH_GNU)
45 #  include "native/include/gnu_classpath_Pointer.h"
46
47 #  if SIZEOF_VOID_P == 8
48 #   include "native/include/gnu_classpath_Pointer64.h"
49 #  else
50 #   include "native/include/gnu_classpath_Pointer32.h"
51 #  endif
52 # endif
53 #endif
54
55 #include "native/include/java_lang_Object.h"
56 #include "native/include/java_lang_Byte.h"
57 #include "native/include/java_lang_Character.h"
58 #include "native/include/java_lang_Short.h"
59 #include "native/include/java_lang_Integer.h"
60 #include "native/include/java_lang_Boolean.h"
61 #include "native/include/java_lang_Long.h"
62 #include "native/include/java_lang_Float.h"
63 #include "native/include/java_lang_Double.h"
64 #include "native/include/java_lang_String.h"
65 #include "native/include/java_lang_Throwable.h"
66
67 #if defined(ENABLE_JAVASE)
68 # include "native/include/java_lang_ClassLoader.h"
69
70 # include "native/include/java_lang_reflect_Constructor.h"
71 # include "native/include/java_lang_reflect_Field.h"
72 # include "native/include/java_lang_reflect_Method.h"
73
74 # include "native/include/java_nio_Buffer.h"
75 # include "native/include/java_nio_DirectByteBufferImpl.h"
76 #endif
77
78 #if defined(ENABLE_JVMTI)
79 # include "native/jvmti/cacaodbg.h"
80 #endif
81
82 #include "native/vm/java_lang_Class.h"
83
84 #if defined(ENABLE_JAVASE)
85 # include "native/vm/java_lang_ClassLoader.h"
86 #endif
87
88 #include "threads/lock-common.h"
89 #include "threads/threads-common.h"
90
91 #include "toolbox/logging.h"
92
93 #include "vm/builtin.h"
94 #include "vm/exceptions.h"
95 #include "vm/global.h"
96 #include "vm/initialize.h"
97 #include "vm/resolve.h"
98 #include "vm/stringlocal.h"
99 #include "vm/vm.h"
100
101 #include "vm/jit/asmpart.h"
102 #include "vm/jit/jit.h"
103 #include "vm/jit/stacktrace.h"
104
105 #include "vmcore/loader.h"
106 #include "vmcore/options.h"
107 #include "vmcore/primitive.h"
108 #include "vmcore/statistics.h"
109
110
111 /* global variables ***********************************************************/
112
113 /* global reference table *****************************************************/
114
115 /* hashsize must be power of 2 */
116
117 #define HASHTABLE_GLOBAL_REF_SIZE    64 /* initial size of globalref-hash     */
118
119 static hashtable *hashtable_global_ref; /* hashtable for globalrefs           */
120
121
122 /* direct buffer stuff ********************************************************/
123
124 #if defined(ENABLE_JAVASE)
125 static classinfo *class_java_nio_Buffer;
126 static classinfo *class_java_nio_DirectByteBufferImpl;
127 static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
128
129 # if defined(WITH_CLASSPATH_GNU)
130 #  if SIZEOF_VOID_P == 8
131 static classinfo *class_gnu_classpath_Pointer64;
132 #  else
133 static classinfo *class_gnu_classpath_Pointer32;
134 #  endif
135 # endif
136
137 static methodinfo *dbbirw_init;
138 #endif
139
140
141 /* local reference table ******************************************************/
142
143 #if !defined(ENABLE_THREADS)
144 localref_table *_no_threads_localref_table;
145 #endif
146
147
148 /* accessing instance fields macros *******************************************/
149
150 #define SET_FIELD(o,type,f,value) \
151     *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) = (type) (value)
152
153 #define GET_FIELD(o,type,f) \
154     *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset))
155
156
157 /* some forward declarations **************************************************/
158
159 jobject _Jv_JNI_NewLocalRef(JNIEnv *env, jobject ref);
160 jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity);
161
162
163 /* jni_init ********************************************************************
164
165    Initialize the JNI subsystem.
166
167 *******************************************************************************/
168
169 bool jni_init(void)
170 {
171         /* create global ref hashtable */
172
173         hashtable_global_ref = NEW(hashtable);
174
175         hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
176
177
178 #if defined(ENABLE_JAVASE)
179         /* direct buffer stuff */
180
181         if (!(class_java_nio_Buffer =
182                   load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
183                 !link_class(class_java_nio_Buffer))
184                 return false;
185
186         if (!(class_java_nio_DirectByteBufferImpl =
187                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
188                 !link_class(class_java_nio_DirectByteBufferImpl))
189                 return false;
190
191         if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
192                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
193                 !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
194                 return false;
195
196         if (!(dbbirw_init =
197                 class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
198                                                         utf_init,
199                                                         utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
200                 return false;
201
202 # if defined(WITH_CLASSPATH_GNU)
203 #  if SIZEOF_VOID_P == 8
204         if (!(class_gnu_classpath_Pointer64 =
205                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
206                 !link_class(class_gnu_classpath_Pointer64))
207                 return false;
208 #  else
209         if (!(class_gnu_classpath_Pointer32 =
210                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
211                 !link_class(class_gnu_classpath_Pointer32))
212                 return false;
213 #  endif
214 # endif
215 #endif /* defined(ENABLE_JAVASE) */
216
217         return true;
218 }
219
220
221 /* jni_init_localref_table *****************************************************
222
223    Initializes the local references table of the current thread.
224
225 *******************************************************************************/
226
227 bool jni_init_localref_table(void)
228 {
229         localref_table *lrt;
230
231         lrt = GCNEW(localref_table);
232
233         if (lrt == NULL)
234                 return false;
235
236         lrt->capacity    = LOCALREFTABLE_CAPACITY;
237         lrt->used        = 0;
238         lrt->localframes = 1;
239         lrt->prev        = LOCALREFTABLE;
240
241         /* clear the references array (memset is faster then a for-loop) */
242
243         MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
244
245         LOCALREFTABLE = lrt;
246
247         return true;
248 }
249
250
251 /* _Jv_jni_vmargs_from_objectarray *********************************************
252
253    XXX
254
255 *******************************************************************************/
256
257 static bool _Jv_jni_vmargs_from_objectarray(java_objectheader *o,
258                                                                                         methoddesc *descr,
259                                                                                         vm_arg *vmargs,
260                                                                                         java_objectarray *params)
261 {
262         java_objectheader *param;
263         int32_t            paramcount;
264         typedesc          *paramtypes;
265         classinfo         *c;
266         int32_t            i;
267         int32_t            j;
268         int64_t            value;
269
270         paramcount = descr->paramcount;
271         paramtypes = descr->paramtypes;
272
273         /* if method is non-static fill first block and skip `this' pointer */
274
275         i = 0;
276
277         if (o != NULL) {
278                 /* this pointer */
279                 vmargs[0].type   = TYPE_ADR;
280                 vmargs[0].data.l = (u8) (ptrint) o;
281
282                 paramtypes++;
283                 paramcount--;
284                 i++;
285         }
286
287         for (j = 0; j < paramcount; i++, j++, paramtypes++) {
288                 switch (paramtypes->type) {
289                 /* primitive types */
290                 case TYPE_INT:
291                 case TYPE_LNG:
292                 case TYPE_FLT:
293                 case TYPE_DBL:
294                         param = params->data[j];
295
296                         if (param == NULL)
297                                 goto illegal_arg;
298
299                         /* internally used data type */
300                         vmargs[i].type = paramtypes->type;
301
302                         /* convert the value according to its declared type */
303
304                         c = param->vftbl->class;
305
306                         switch (paramtypes->decltype) {
307                         case PRIMITIVETYPE_BOOLEAN:
308                                 if (c == class_java_lang_Boolean)
309                                         value = (int64_t) ((java_lang_Boolean *) param)->value;
310                                 else
311                                         goto illegal_arg;
312
313                                 vmargs[i].data.l = value;
314                                 break;
315
316                         case PRIMITIVETYPE_BYTE:
317                                 if (c == class_java_lang_Byte)
318                                         value = (int64_t) ((java_lang_Byte *) param)->value;
319                                 else
320                                         goto illegal_arg;
321
322                                 vmargs[i].data.l = value;
323                                 break;
324
325                         case PRIMITIVETYPE_CHAR:
326                                 if (c == class_java_lang_Character)
327                                         value = (int64_t) ((java_lang_Character *) param)->value;
328                                 else
329                                         goto illegal_arg;
330
331                                 vmargs[i].data.l = value;
332                                 break;
333
334                         case PRIMITIVETYPE_SHORT:
335                                 if (c == class_java_lang_Short)
336                                         value = (int64_t) ((java_lang_Short *) param)->value;
337                                 else if (c == class_java_lang_Byte)
338                                         value = (int64_t) ((java_lang_Byte *) param)->value;
339                                 else
340                                         goto illegal_arg;
341
342                                 vmargs[i].data.l = value;
343                                 break;
344
345                         case PRIMITIVETYPE_INT:
346                                 if (c == class_java_lang_Integer)
347                                         value = (int64_t) ((java_lang_Integer *) param)->value;
348                                 else if (c == class_java_lang_Short)
349                                         value = (int64_t) ((java_lang_Short *) param)->value;
350                                 else if (c == class_java_lang_Byte)
351                                         value = (int64_t) ((java_lang_Byte *) param)->value;
352                                 else
353                                         goto illegal_arg;
354
355                                 vmargs[i].data.l = value;
356                                 break;
357
358                         case PRIMITIVETYPE_LONG:
359                                 if (c == class_java_lang_Long)
360                                         value = (int64_t) ((java_lang_Long *) param)->value;
361                                 else if (c == class_java_lang_Integer)
362                                         value = (int64_t) ((java_lang_Integer *) param)->value;
363                                 else if (c == class_java_lang_Short)
364                                         value = (int64_t) ((java_lang_Short *) param)->value;
365                                 else if (c == class_java_lang_Byte)
366                                         value = (int64_t) ((java_lang_Byte *) param)->value;
367                                 else
368                                         goto illegal_arg;
369
370                                 vmargs[i].data.l = value;
371                                 break;
372
373                         case PRIMITIVETYPE_FLOAT:
374                                 if (c == class_java_lang_Float)
375                                         vmargs[i].data.f = (jfloat) ((java_lang_Float *) param)->value;
376                                 else
377                                         goto illegal_arg;
378                                 break;
379
380                         case PRIMITIVETYPE_DOUBLE:
381                                 if (c == class_java_lang_Double)
382                                         vmargs[i].data.d = (jdouble) ((java_lang_Double *) param)->value;
383                                 else if (c == class_java_lang_Float)
384                                         vmargs[i].data.f = (jfloat) ((java_lang_Float *) param)->value;
385                                 else
386                                         goto illegal_arg;
387                                 break;
388
389                         default:
390                                 goto illegal_arg;
391                         }
392                         break;
393                 
394                 case TYPE_ADR:
395                         if (!resolve_class_from_typedesc(paramtypes, true, true, &c))
396                                 return false;
397
398                         if (params->data[j] != 0) {
399                                 if (paramtypes->arraydim > 0) {
400                                         if (!builtin_arrayinstanceof(params->data[j], c))
401                                                 goto illegal_arg;
402
403                                 } else {
404                                         if (!builtin_instanceof(params->data[j], c))
405                                                 goto illegal_arg;
406                                 }
407                         }
408
409                         vmargs[i].type   = TYPE_ADR;
410                         vmargs[i].data.l = (u8) (ptrint) params->data[j];
411                         break;
412
413                 default:
414                         goto illegal_arg;
415                 }
416         }
417
418 /*      if (rettype) */
419 /*              *rettype = descr->returntype.decltype; */
420
421         return true;
422
423 illegal_arg:
424         exceptions_throw_illegalargumentexception();
425         return false;
426 }
427
428
429 /* _Jv_jni_CallObjectMethod ****************************************************
430
431    Internal function to call Java Object methods.
432
433 *******************************************************************************/
434
435 static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o,
436                                                                                                    vftbl_t *vftbl,
437                                                                                                    methodinfo *m, va_list ap)
438 {
439         methodinfo        *resm;
440         java_objectheader *ro;
441
442         STATISTICS(jniinvokation());
443
444         if (m == NULL) {
445                 exceptions_throw_nullpointerexception();
446                 return NULL;
447         }
448
449         /* Class initialization is done by the JIT compiler.  This is ok
450            since a static method always belongs to the declaring class. */
451
452         if (m->flags & ACC_STATIC) {
453                 /* For static methods we reset the object. */
454
455                 if (o != NULL)
456                         o = NULL;
457
458                 /* for convenience */
459
460                 resm = m;
461
462         } else {
463                 /* For instance methods we make a virtual function table lookup. */
464
465                 resm = method_vftbl_lookup(vftbl, m);
466         }
467
468         STATISTICS(jnicallXmethodnvokation());
469
470         ro = vm_call_method_valist(resm, o, ap);
471
472         return ro;
473 }
474
475
476 /* _Jv_jni_CallObjectMethodA ***************************************************
477
478    Internal function to call Java Object methods.
479
480 *******************************************************************************/
481
482 static java_objectheader *_Jv_jni_CallObjectMethodA(java_objectheader *o,
483                                                                                                         vftbl_t *vftbl,
484                                                                                                         methodinfo *m, jvalue *args)
485 {
486         methodinfo        *resm;
487         java_objectheader *ro;
488
489         STATISTICS(jniinvokation());
490
491         if (m == NULL) {
492                 exceptions_throw_nullpointerexception();
493                 return NULL;
494         }
495
496         /* Class initialization is done by the JIT compiler.  This is ok
497            since a static method always belongs to the declaring class. */
498
499         if (m->flags & ACC_STATIC) {
500                 /* For static methods we reset the object. */
501
502                 if (o != NULL)
503                         o = NULL;
504
505                 /* for convenience */
506
507                 resm = m;
508
509         } else {
510                 /* For instance methods we make a virtual function table lookup. */
511
512                 resm = method_vftbl_lookup(vftbl, m);
513         }
514
515         STATISTICS(jnicallXmethodnvokation());
516
517         ro = vm_call_method_jvalue(resm, o, args);
518
519         return ro;
520 }
521
522
523 /* _Jv_jni_CallIntMethod *******************************************************
524
525    Internal function to call Java integer class methods (boolean,
526    byte, char, short, int).
527
528 *******************************************************************************/
529
530 static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl,
531                                                                   methodinfo *m, va_list ap)
532 {
533         methodinfo *resm;
534         jint        i;
535
536         STATISTICS(jniinvokation());
537
538         if (m == NULL) {
539                 exceptions_throw_nullpointerexception();
540                 return 0;
541         }
542         
543         /* Class initialization is done by the JIT compiler.  This is ok
544            since a static method always belongs to the declaring class. */
545
546         if (m->flags & ACC_STATIC) {
547                 /* For static methods we reset the object. */
548
549                 if (o != NULL)
550                         o = NULL;
551
552                 /* for convenience */
553
554                 resm = m;
555
556         } else {
557                 /* For instance methods we make a virtual function table lookup. */
558
559                 resm = method_vftbl_lookup(vftbl, m);
560         }
561
562         STATISTICS(jnicallXmethodnvokation());
563
564         i = vm_call_method_int_valist(resm, o, ap);
565
566         return i;
567 }
568
569
570 /* _Jv_jni_CallIntMethodA ******************************************************
571
572    Internal function to call Java integer class methods (boolean,
573    byte, char, short, int).
574
575 *******************************************************************************/
576
577 static jint _Jv_jni_CallIntMethodA(java_objectheader *o, vftbl_t *vftbl,
578                                                                    methodinfo *m, jvalue *args)
579 {
580         methodinfo *resm;
581         jint        i;
582
583         STATISTICS(jniinvokation());
584
585         if (m == NULL) {
586                 exceptions_throw_nullpointerexception();
587                 return 0;
588         }
589         
590         /* Class initialization is done by the JIT compiler.  This is ok
591            since a static method always belongs to the declaring class. */
592
593         if (m->flags & ACC_STATIC) {
594                 /* For static methods we reset the object. */
595
596                 if (o != NULL)
597                         o = NULL;
598
599                 /* for convenience */
600
601                 resm = m;
602
603         } else {
604                 /* For instance methods we make a virtual function table lookup. */
605
606                 resm = method_vftbl_lookup(vftbl, m);
607         }
608
609         STATISTICS(jnicallXmethodnvokation());
610
611         i = vm_call_method_int_jvalue(resm, o, args);
612
613         return i;
614 }
615
616
617 /* _Jv_jni_CallLongMethod ******************************************************
618
619    Internal function to call Java long methods.
620
621 *******************************************************************************/
622
623 static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl,
624                                                                         methodinfo *m, va_list ap)
625 {
626         methodinfo *resm;
627         jlong       l;
628
629         STATISTICS(jniinvokation());
630
631         if (m == NULL) {
632                 exceptions_throw_nullpointerexception();
633                 return 0;
634         }
635
636         /* Class initialization is done by the JIT compiler.  This is ok
637            since a static method always belongs to the declaring class. */
638
639         if (m->flags & ACC_STATIC) {
640                 /* For static methods we reset the object. */
641
642                 if (o != NULL)
643                         o = NULL;
644
645                 /* for convenience */
646
647                 resm = m;
648
649         } else {
650                 /* For instance methods we make a virtual function table lookup. */
651
652                 resm = method_vftbl_lookup(vftbl, m);
653         }
654
655         STATISTICS(jnicallXmethodnvokation());
656
657         l = vm_call_method_long_valist(resm, o, ap);
658
659         return l;
660 }
661
662
663 /* _Jv_jni_CallLongMethodA *****************************************************
664
665    Internal function to call Java long methods.
666
667 *******************************************************************************/
668
669 static jlong _Jv_jni_CallLongMethodA(java_objectheader *o, vftbl_t *vftbl,
670                                                                          methodinfo *m, jvalue *args)
671 {
672         methodinfo *resm;
673         jlong       l;
674
675         STATISTICS(jniinvokation());
676
677         if (m == NULL) {
678                 exceptions_throw_nullpointerexception();
679                 return 0;
680         }
681
682         /* Class initialization is done by the JIT compiler.  This is ok
683            since a static method always belongs to the declaring class. */
684
685         if (m->flags & ACC_STATIC) {
686                 /* For static methods we reset the object. */
687
688                 if (o != NULL)
689                         o = NULL;
690
691                 /* for convenience */
692
693                 resm = m;
694         }
695         else {
696                 /* For instance methods we make a virtual function table lookup. */
697
698                 resm = method_vftbl_lookup(vftbl, m);
699         }
700
701         STATISTICS(jnicallXmethodnvokation());
702
703         l = vm_call_method_long_jvalue(resm, o, args);
704
705         return l;
706 }
707
708
709 /* _Jv_jni_CallFloatMethod *****************************************************
710
711    Internal function to call Java float methods.
712
713 *******************************************************************************/
714
715 static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl,
716                                                                           methodinfo *m, va_list ap)
717 {
718         methodinfo *resm;
719         jfloat      f;
720
721         /* Class initialization is done by the JIT compiler.  This is ok
722            since a static method always belongs to the declaring class. */
723
724         if (m->flags & ACC_STATIC) {
725                 /* For static methods we reset the object. */
726
727                 if (o != NULL)
728                         o = NULL;
729
730                 /* for convenience */
731
732                 resm = m;
733
734         } else {
735                 /* For instance methods we make a virtual function table lookup. */
736
737                 resm = method_vftbl_lookup(vftbl, m);
738         }
739
740         STATISTICS(jnicallXmethodnvokation());
741
742         f = vm_call_method_float_valist(resm, o, ap);
743
744         return f;
745 }
746
747
748 /* _Jv_jni_CallFloatMethodA ****************************************************
749
750    Internal function to call Java float methods.
751
752 *******************************************************************************/
753
754 static jfloat _Jv_jni_CallFloatMethodA(java_objectheader *o, vftbl_t *vftbl,
755                                                                            methodinfo *m, jvalue *args)
756 {
757         methodinfo *resm;
758         jfloat      f;
759
760         /* Class initialization is done by the JIT compiler.  This is ok
761            since a static method always belongs to the declaring class. */
762
763         if (m->flags & ACC_STATIC) {
764                 /* For static methods we reset the object. */
765
766                 if (o != NULL)
767                         o = NULL;
768
769                 /* for convenience */
770
771                 resm = m;
772         }
773         else {
774                 /* For instance methods we make a virtual function table lookup. */
775
776                 resm = method_vftbl_lookup(vftbl, m);
777         }
778
779         STATISTICS(jnicallXmethodnvokation());
780
781         f = vm_call_method_float_jvalue(resm, o, args);
782
783         return f;
784 }
785
786
787 /* _Jv_jni_CallDoubleMethod ****************************************************
788
789    Internal function to call Java double methods.
790
791 *******************************************************************************/
792
793 static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl,
794                                                                                 methodinfo *m, va_list ap)
795 {
796         methodinfo *resm;
797         jdouble     d;
798
799         /* Class initialization is done by the JIT compiler.  This is ok
800            since a static method always belongs to the declaring class. */
801
802         if (m->flags & ACC_STATIC) {
803                 /* For static methods we reset the object. */
804
805                 if (o != NULL)
806                         o = NULL;
807
808                 /* for convenience */
809
810                 resm = m;
811
812         } else {
813                 /* For instance methods we make a virtual function table lookup. */
814
815                 resm = method_vftbl_lookup(vftbl, m);
816         }
817
818         d = vm_call_method_double_valist(resm, o, ap);
819
820         return d;
821 }
822
823
824 /* _Jv_jni_CallDoubleMethodA ***************************************************
825
826    Internal function to call Java double methods.
827
828 *******************************************************************************/
829
830 static jdouble _Jv_jni_CallDoubleMethodA(java_objectheader *o, vftbl_t *vftbl,
831                                                                                  methodinfo *m, jvalue *args)
832 {
833         methodinfo *resm;
834         jdouble     d;
835
836         /* Class initialization is done by the JIT compiler.  This is ok
837            since a static method always belongs to the declaring class. */
838
839         if (m->flags & ACC_STATIC) {
840                 /* For static methods we reset the object. */
841
842                 if (o != NULL)
843                         o = NULL;
844
845                 /* for convenience */
846
847                 resm = m;
848         }
849         else {
850                 /* For instance methods we make a virtual function table lookup. */
851
852                 resm = method_vftbl_lookup(vftbl, m);
853         }
854
855         d = vm_call_method_double_jvalue(resm, o, args);
856
857         return d;
858 }
859
860
861 /* _Jv_jni_CallVoidMethod ******************************************************
862
863    Internal function to call Java void methods.
864
865 *******************************************************************************/
866
867 static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl,
868                                                                    methodinfo *m, va_list ap)
869 {       
870         methodinfo *resm;
871
872         if (m == NULL) {
873                 exceptions_throw_nullpointerexception();
874                 return;
875         }
876
877         /* Class initialization is done by the JIT compiler.  This is ok
878            since a static method always belongs to the declaring class. */
879
880         if (m->flags & ACC_STATIC) {
881                 /* For static methods we reset the object. */
882
883                 if (o != NULL)
884                         o = NULL;
885
886                 /* for convenience */
887
888                 resm = m;
889
890         } else {
891                 /* For instance methods we make a virtual function table lookup. */
892
893                 resm = method_vftbl_lookup(vftbl, m);
894         }
895
896         STATISTICS(jnicallXmethodnvokation());
897
898         (void) vm_call_method_valist(resm, o, ap);
899 }
900
901
902 /* _Jv_jni_CallVoidMethodA *****************************************************
903
904    Internal function to call Java void methods.
905
906 *******************************************************************************/
907
908 static void _Jv_jni_CallVoidMethodA(java_objectheader *o, vftbl_t *vftbl,
909                                                                         methodinfo *m, jvalue *args)
910 {       
911         methodinfo *resm;
912
913         if (m == NULL) {
914                 exceptions_throw_nullpointerexception();
915                 return;
916         }
917
918         /* Class initialization is done by the JIT compiler.  This is ok
919            since a static method always belongs to the declaring class. */
920
921         if (m->flags & ACC_STATIC) {
922                 /* For static methods we reset the object. */
923
924                 if (o != NULL)
925                         o = NULL;
926
927                 /* for convenience */
928
929                 resm = m;
930
931         } else {
932                 /* For instance methods we make a virtual function table lookup. */
933
934                 resm = method_vftbl_lookup(vftbl, m);
935         }
936
937         STATISTICS(jnicallXmethodnvokation());
938
939         (void) vm_call_method_jvalue(resm, o, args);
940 }
941
942
943 /* _Jv_jni_invokeNative ********************************************************
944
945    Invoke a method on the given object with the given arguments.
946
947    For instance methods OBJ must be != NULL and the method is looked up
948    in the vftbl of the object.
949
950    For static methods, OBJ is ignored.
951
952 *******************************************************************************/
953
954 java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
955                                                                                 java_objectarray *params)
956 {
957         methodinfo        *resm;
958         vm_arg            *vmargs;
959         java_objectheader *ro;
960         s4                 argcount;
961         s4                 paramcount;
962         java_objectheader *xptr;
963
964         if (m == NULL) {
965                 exceptions_throw_nullpointerexception();
966                 return NULL;
967         }
968
969         argcount = m->parseddesc->paramcount;
970         paramcount = argcount;
971
972         /* if method is non-static, remove the `this' pointer */
973
974         if (!(m->flags & ACC_STATIC))
975                 paramcount--;
976
977         /* For instance methods the object has to be an instance of the
978            class the method belongs to. For static methods the obj
979            parameter is ignored. */
980
981         if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
982                 exceptions_throw_illegalargumentexception();
983                 return NULL;
984         }
985
986         /* check if we got the right number of arguments */
987
988         if (((params == NULL) && (paramcount != 0)) ||
989                 (params && (params->header.size != paramcount))) 
990         {
991                 exceptions_throw_illegalargumentexception();
992                 return NULL;
993         }
994
995         /* for instance methods we need an object */
996
997         if (!(m->flags & ACC_STATIC) && (o == NULL)) {
998                 /* XXX not sure if that is the correct exception */
999                 exceptions_throw_nullpointerexception();
1000                 return NULL;
1001         }
1002
1003         /* for static methods, zero object to make subsequent code simpler */
1004         if (m->flags & ACC_STATIC)
1005                 o = NULL;
1006
1007         if (o != NULL) {
1008                 /* for instance methods we must do a vftbl lookup */
1009                 resm = method_vftbl_lookup(o->vftbl, m);
1010         }
1011         else {
1012                 /* for static methods, just for convenience */
1013                 resm = m;
1014         }
1015
1016         vmargs = MNEW(vm_arg, argcount);
1017
1018         if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params)) {
1019                 MFREE(vmargs, vm_arg, argcount);
1020                 return NULL;
1021         }
1022
1023         switch (resm->parseddesc->returntype.decltype) {
1024         case TYPE_VOID:
1025                 (void) vm_call_method_vmarg(resm, argcount, vmargs);
1026
1027                 ro = NULL;
1028                 break;
1029
1030         case PRIMITIVETYPE_BOOLEAN: {
1031                 s4 i;
1032                 java_lang_Boolean *bo;
1033
1034                 i = vm_call_method_int_vmarg(resm, argcount, vmargs);
1035
1036                 ro = builtin_new(class_java_lang_Boolean);
1037
1038                 /* setting the value of the object direct */
1039
1040                 bo = (java_lang_Boolean *) ro;
1041                 bo->value = i;
1042         }
1043         break;
1044
1045         case PRIMITIVETYPE_BYTE: {
1046                 s4 i;
1047                 java_lang_Byte *bo;
1048
1049                 i = vm_call_method_int_vmarg(resm, argcount, vmargs);
1050
1051                 ro = builtin_new(class_java_lang_Byte);
1052
1053                 /* setting the value of the object direct */
1054
1055                 bo = (java_lang_Byte *) ro;
1056                 bo->value = i;
1057         }
1058         break;
1059
1060         case PRIMITIVETYPE_CHAR: {
1061                 s4 i;
1062                 java_lang_Character *co;
1063
1064                 i = vm_call_method_int_vmarg(resm, argcount, vmargs);
1065
1066                 ro = builtin_new(class_java_lang_Character);
1067
1068                 /* setting the value of the object direct */
1069
1070                 co = (java_lang_Character *) ro;
1071                 co->value = i;
1072         }
1073         break;
1074
1075         case PRIMITIVETYPE_SHORT: {
1076                 s4 i;
1077                 java_lang_Short *so;
1078
1079                 i = vm_call_method_int_vmarg(resm, argcount, vmargs);
1080
1081                 ro = builtin_new(class_java_lang_Short);
1082
1083                 /* setting the value of the object direct */
1084
1085                 so = (java_lang_Short *) ro;
1086                 so->value = i;
1087         }
1088         break;
1089
1090         case PRIMITIVETYPE_INT: {
1091                 s4 i;
1092                 java_lang_Integer *io;
1093
1094                 i = vm_call_method_int_vmarg(resm, argcount, vmargs);
1095
1096                 ro = builtin_new(class_java_lang_Integer);
1097
1098                 /* setting the value of the object direct */
1099
1100                 io = (java_lang_Integer *) ro;
1101                 io->value = i;
1102         }
1103         break;
1104
1105         case PRIMITIVETYPE_LONG: {
1106                 s8 l;
1107                 java_lang_Long *lo;
1108
1109                 l = vm_call_method_long_vmarg(resm, argcount, vmargs);
1110
1111                 ro = builtin_new(class_java_lang_Long);
1112
1113                 /* setting the value of the object direct */
1114
1115                 lo = (java_lang_Long *) ro;
1116                 lo->value = l;
1117         }
1118         break;
1119
1120         case PRIMITIVETYPE_FLOAT: {
1121                 float f;
1122                 java_lang_Float *fo;
1123
1124                 f = vm_call_method_float_vmarg(resm, argcount, vmargs);
1125
1126                 ro = builtin_new(class_java_lang_Float);
1127
1128                 /* setting the value of the object direct */
1129
1130                 fo = (java_lang_Float *) ro;
1131                 fo->value = f;
1132         }
1133         break;
1134
1135         case PRIMITIVETYPE_DOUBLE: {
1136                 double d;
1137                 java_lang_Double *_do;
1138
1139                 d = vm_call_method_double_vmarg(resm, argcount, vmargs);
1140
1141                 ro = builtin_new(class_java_lang_Double);
1142
1143                 /* setting the value of the object direct */
1144
1145                 _do = (java_lang_Double *) ro;
1146                 _do->value = d;
1147         }
1148         break;
1149
1150         case TYPE_ADR:
1151                 ro = vm_call_method_vmarg(resm, argcount, vmargs);
1152                 break;
1153
1154         default:
1155                 /* if this happens the exception has already been set by
1156                    fill_callblock_from_objectarray */
1157
1158                 MFREE(vmargs, vm_arg, argcount);
1159
1160                 return NULL;
1161         }
1162
1163         MFREE(vmargs, vm_arg, argcount);
1164
1165         xptr = exceptions_get_exception();
1166
1167         if (xptr != NULL) {
1168                 /* clear exception pointer, we are calling JIT code again */
1169
1170                 exceptions_clear_exception();
1171
1172                 exceptions_throw_invocationtargetexception(xptr);
1173         }
1174
1175         return ro;
1176 }
1177
1178
1179 /* GetVersion ******************************************************************
1180
1181    Returns the major version number in the higher 16 bits and the
1182    minor version number in the lower 16 bits.
1183
1184 *******************************************************************************/
1185
1186 jint _Jv_JNI_GetVersion(JNIEnv *env)
1187 {
1188         STATISTICS(jniinvokation());
1189
1190         /* we support JNI 1.4 */
1191
1192         return JNI_VERSION_1_4;
1193 }
1194
1195
1196 /* Class Operations ***********************************************************/
1197
1198 /* DefineClass *****************************************************************
1199
1200    Loads a class from a buffer of raw class data. The buffer
1201    containing the raw class data is not referenced by the VM after the
1202    DefineClass call returns, and it may be discarded if desired.
1203
1204 *******************************************************************************/
1205
1206 jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
1207                                                    const jbyte *buf, jsize bufLen)
1208 {
1209 #if defined(ENABLE_JAVASE)
1210         java_lang_ClassLoader *cl;
1211         java_lang_String      *s;
1212         java_bytearray        *ba;
1213         jclass                 c;
1214
1215         STATISTICS(jniinvokation());
1216
1217         cl = (java_lang_ClassLoader *) loader;
1218         s  = (java_lang_String *) javastring_new_from_utf_string(name);
1219         ba = (java_bytearray *) buf;
1220
1221         c = (jclass) _Jv_java_lang_ClassLoader_defineClass(cl, s, ba, 0, bufLen,
1222                                                                                                            NULL);
1223
1224         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
1225 #else
1226         vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
1227
1228         /* keep compiler happy */
1229
1230         return 0;
1231 #endif
1232 }
1233
1234
1235 /* FindClass *******************************************************************
1236
1237    This function loads a locally-defined class. It searches the
1238    directories and zip files specified by the CLASSPATH environment
1239    variable for the class with the specified name.
1240
1241 *******************************************************************************/
1242
1243 jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
1244 {
1245 #if defined(ENABLE_JAVASE)
1246         utf       *u;
1247         classinfo *cc;
1248         classinfo *c;
1249
1250         STATISTICS(jniinvokation());
1251
1252         u = utf_new_char_classname((char *) name);
1253
1254         /* Check stacktrace for classloader, if one found use it,
1255            otherwise use the system classloader. */
1256
1257         /* Quote from the JNI documentation:
1258          
1259            In the Java 2 Platform, FindClass locates the class loader
1260            associated with the current native method.  If the native code
1261            belongs to a system class, no class loader will be
1262            involved. Otherwise, the proper class loader will be invoked to
1263            load and link the named class. When FindClass is called through
1264            the Invocation Interface, there is no current native method or
1265            its associated class loader. In that case, the result of
1266            ClassLoader.getBaseClassLoader is used." */
1267
1268         cc = stacktrace_getCurrentClass();
1269
1270         if (cc == NULL)
1271                 c = load_class_from_sysloader(u);
1272         else
1273                 c = load_class_from_classloader(u, cc->classloader);
1274
1275         if (c == NULL)
1276                 return NULL;
1277
1278         if (!link_class(c))
1279                 return NULL;
1280
1281         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
1282 #else
1283         vm_abort("_Jv_JNI_FindClass: not implemented in this configuration");
1284
1285         /* keep compiler happy */
1286
1287         return NULL;
1288 #endif
1289 }
1290   
1291
1292 /* GetSuperclass ***************************************************************
1293
1294    If clazz represents any class other than the class Object, then
1295    this function returns the object that represents the superclass of
1296    the class specified by clazz.
1297
1298 *******************************************************************************/
1299  
1300 jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
1301 {
1302         classinfo *c;
1303
1304         STATISTICS(jniinvokation());
1305
1306         c = ((classinfo *) sub)->super.cls;
1307
1308         if (!c)
1309                 return NULL;
1310
1311         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
1312 }
1313   
1314  
1315 /* IsAssignableFrom ************************************************************
1316
1317    Determines whether an object of sub can be safely cast to sup.
1318
1319 *******************************************************************************/
1320
1321 jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
1322 {
1323         java_lang_Class *csup;
1324         java_lang_Class *csub;
1325
1326         csup = (java_lang_Class *) sup;
1327         csub = (java_lang_Class *) sub;
1328
1329         STATISTICS(jniinvokation());
1330
1331         return _Jv_java_lang_Class_isAssignableFrom(csup, csub);
1332 }
1333
1334
1335 /* Throw ***********************************************************************
1336
1337    Causes a java.lang.Throwable object to be thrown.
1338
1339 *******************************************************************************/
1340
1341 jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
1342 {
1343         java_objectheader *o;
1344
1345         STATISTICS(jniinvokation());
1346
1347         o = (java_objectheader *) obj;
1348
1349         exceptions_set_exception(o);
1350
1351         return JNI_OK;
1352 }
1353
1354
1355 /* ThrowNew ********************************************************************
1356
1357    Constructs an exception object from the specified class with the
1358    message specified by message and causes that exception to be
1359    thrown.
1360
1361 *******************************************************************************/
1362
1363 jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
1364 {
1365         classinfo         *c;
1366         java_objectheader *o;
1367         java_objectheader *s;
1368
1369         STATISTICS(jniinvokation());
1370
1371         c = (classinfo *) clazz;
1372         s = javastring_new_from_utf_string(msg);
1373
1374         /* instantiate exception object */
1375
1376         o = native_new_and_init_string(c, s);
1377
1378         if (o == NULL)
1379                 return -1;
1380
1381         exceptions_set_exception(o);
1382
1383         return 0;
1384 }
1385
1386
1387 /* ExceptionOccurred ***********************************************************
1388
1389    Determines if an exception is being thrown. The exception stays
1390    being thrown until either the native code calls ExceptionClear(),
1391    or the Java code handles the exception.
1392
1393 *******************************************************************************/
1394
1395 jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
1396 {
1397         java_objectheader *o;
1398
1399         STATISTICS(jniinvokation());
1400
1401         o = exceptions_get_exception();
1402
1403         return _Jv_JNI_NewLocalRef(env, (jthrowable) o);
1404 }
1405
1406
1407 /* ExceptionDescribe ***********************************************************
1408
1409    Prints an exception and a backtrace of the stack to a system
1410    error-reporting channel, such as stderr. This is a convenience
1411    routine provided for debugging.
1412
1413 *******************************************************************************/
1414
1415 void _Jv_JNI_ExceptionDescribe(JNIEnv *env)
1416 {
1417         java_objectheader *o;
1418         methodinfo        *m;
1419
1420         STATISTICS(jniinvokation());
1421
1422         o = exceptions_get_exception();
1423
1424         if (o == NULL) {
1425                 /* clear exception, because we are calling jit code again */
1426
1427                 exceptions_clear_exception();
1428
1429                 /* get printStackTrace method from exception class */
1430
1431                 m = class_resolveclassmethod(o->vftbl->class,
1432                                                                          utf_printStackTrace,
1433                                                                          utf_void__void,
1434                                                                          NULL,
1435                                                                          true);
1436
1437                 if (m == NULL)
1438                         /* XXX what should we do? */
1439                         return;
1440
1441                 /* print the stacktrace */
1442
1443                 (void) vm_call_method(m, o);
1444         }
1445 }
1446
1447
1448 /* ExceptionClear **************************************************************
1449
1450    Clears any exception that is currently being thrown. If no
1451    exception is currently being thrown, this routine has no effect.
1452
1453 *******************************************************************************/
1454
1455 void _Jv_JNI_ExceptionClear(JNIEnv *env)
1456 {
1457         STATISTICS(jniinvokation());
1458
1459         exceptions_clear_exception();
1460 }
1461
1462
1463 /* FatalError ******************************************************************
1464
1465    Raises a fatal error and does not expect the VM to recover. This
1466    function does not return.
1467
1468 *******************************************************************************/
1469
1470 void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
1471 {
1472         STATISTICS(jniinvokation());
1473
1474         /* this seems to be the best way */
1475
1476         vm_abort("JNI Fatal error: %s", msg);
1477 }
1478
1479
1480 /* PushLocalFrame **************************************************************
1481
1482    Creates a new local reference frame, in which at least a given
1483    number of local references can be created.
1484
1485 *******************************************************************************/
1486
1487 jint _Jv_JNI_PushLocalFrame(JNIEnv* env, jint capacity)
1488 {
1489         s4              additionalrefs;
1490         localref_table *lrt;
1491         localref_table *nlrt;
1492
1493         STATISTICS(jniinvokation());
1494
1495         if (capacity <= 0)
1496                 return -1;
1497
1498         /* Allocate new local reference table on Java heap.  Calculate the
1499            additional memory we have to allocate. */
1500
1501         if (capacity > LOCALREFTABLE_CAPACITY)
1502                 additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
1503         else
1504                 additionalrefs = 0;
1505
1506         nlrt = GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
1507
1508         if (nlrt == NULL)
1509                 return -1;
1510
1511         /* get current local reference table from thread */
1512
1513         lrt = LOCALREFTABLE;
1514
1515         /* Set up the new local reference table and add it to the local
1516            frames chain. */
1517
1518         nlrt->capacity    = capacity;
1519         nlrt->used        = 0;
1520         nlrt->localframes = lrt->localframes + 1;
1521         nlrt->prev        = lrt;
1522
1523         /* store new local reference table in thread */
1524
1525         LOCALREFTABLE = nlrt;
1526
1527         return 0;
1528 }
1529
1530
1531 /* PopLocalFrame ***************************************************************
1532
1533    Pops off the current local reference frame, frees all the local
1534    references, and returns a local reference in the previous local
1535    reference frame for the given result object.
1536
1537 *******************************************************************************/
1538
1539 jobject _Jv_JNI_PopLocalFrame(JNIEnv* env, jobject result)
1540 {
1541         localref_table *lrt;
1542         localref_table *plrt;
1543         s4              localframes;
1544
1545         STATISTICS(jniinvokation());
1546
1547         /* get current local reference table from thread */
1548
1549         lrt = LOCALREFTABLE;
1550
1551         localframes = lrt->localframes;
1552
1553         /* Don't delete the top local frame, as this one is allocated in
1554            the native stub on the stack and is freed automagically on
1555            return. */
1556
1557         if (localframes == 1)
1558                 return _Jv_JNI_NewLocalRef(env, result);
1559
1560         /* release all current local frames */
1561
1562         for (; localframes >= 1; localframes--) {
1563                 /* get previous frame */
1564
1565                 plrt = lrt->prev;
1566
1567                 /* clear all reference entries */
1568
1569                 MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1570
1571                 lrt->prev = NULL;
1572
1573                 /* set new local references table */
1574
1575                 lrt = plrt;
1576         }
1577
1578         /* store new local reference table in thread */
1579
1580         LOCALREFTABLE = lrt;
1581
1582         /* add local reference and return the value */
1583
1584         return _Jv_JNI_NewLocalRef(env, result);
1585 }
1586
1587
1588 /* DeleteLocalRef **************************************************************
1589
1590    Deletes the local reference pointed to by localRef.
1591
1592 *******************************************************************************/
1593
1594 void _Jv_JNI_DeleteLocalRef(JNIEnv *env, jobject localRef)
1595 {
1596         java_objectheader *o;
1597         localref_table    *lrt;
1598         s4                 i;
1599
1600         STATISTICS(jniinvokation());
1601
1602         o = (java_objectheader *) localRef;
1603
1604         /* get local reference table (thread specific) */
1605
1606         lrt = LOCALREFTABLE;
1607
1608         /* go through all local frames */
1609
1610         for (; lrt != NULL; lrt = lrt->prev) {
1611
1612                 /* and try to remove the reference */
1613
1614                 for (i = 0; i < lrt->capacity; i++) {
1615                         if (lrt->refs[i] == o) {
1616                                 lrt->refs[i] = NULL;
1617                                 lrt->used--;
1618
1619                                 return;
1620                         }
1621                 }
1622         }
1623
1624         /* this should not happen */
1625
1626 /*      if (opt_checkjni) */
1627 /*      FatalError(env, "Bad global or local ref passed to JNI"); */
1628         log_text("JNI-DeleteLocalRef: Local ref passed to JNI not found");
1629 }
1630
1631
1632 /* IsSameObject ****************************************************************
1633
1634    Tests whether two references refer to the same Java object.
1635
1636 *******************************************************************************/
1637
1638 jboolean _Jv_JNI_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
1639 {
1640         STATISTICS(jniinvokation());
1641
1642         if (ref1 == ref2)
1643                 return JNI_TRUE;
1644         else
1645                 return JNI_FALSE;
1646 }
1647
1648
1649 /* NewLocalRef *****************************************************************
1650
1651    Creates a new local reference that refers to the same object as ref.
1652
1653 *******************************************************************************/
1654
1655 jobject _Jv_JNI_NewLocalRef(JNIEnv *env, jobject ref)
1656 {
1657         localref_table *lrt;
1658         s4              i;
1659
1660         STATISTICS(jniinvokation());
1661
1662         if (ref == NULL)
1663                 return NULL;
1664
1665         /* get local reference table (thread specific) */
1666
1667         lrt = LOCALREFTABLE;
1668
1669         /* Check if we have space for the requested reference?  No,
1670            allocate a new frame.  This is actually not what the spec says,
1671            but for compatibility reasons... */
1672
1673         if (lrt->used == lrt->capacity) {
1674                 if (_Jv_JNI_EnsureLocalCapacity(env, 16) != 0)
1675                         return NULL;
1676
1677                 /* get the new local reference table */
1678
1679                 lrt = LOCALREFTABLE;
1680         }
1681
1682         /* insert the reference */
1683
1684         for (i = 0; i < lrt->capacity; i++) {
1685                 if (lrt->refs[i] == NULL) {
1686                         lrt->refs[i] = (java_objectheader *) ref;
1687                         lrt->used++;
1688
1689                         return ref;
1690                 }
1691         }
1692
1693         /* should not happen, just to be sure */
1694
1695         assert(0);
1696
1697         /* keep compiler happy */
1698
1699         return NULL;
1700 }
1701
1702
1703 /* EnsureLocalCapacity *********************************************************
1704
1705    Ensures that at least a given number of local references can be
1706    created in the current thread
1707
1708 *******************************************************************************/
1709
1710 jint _Jv_JNI_EnsureLocalCapacity(JNIEnv* env, jint capacity)
1711 {
1712         localref_table *lrt;
1713
1714         STATISTICS(jniinvokation());
1715
1716         /* get local reference table (thread specific) */
1717
1718         lrt = LOCALREFTABLE;
1719
1720         /* check if capacity elements are available in the local references table */
1721
1722         if ((lrt->used + capacity) > lrt->capacity)
1723                 return _Jv_JNI_PushLocalFrame(env, capacity);
1724
1725         return 0;
1726 }
1727
1728
1729 /* AllocObject *****************************************************************
1730
1731    Allocates a new Java object without invoking any of the
1732    constructors for the object. Returns a reference to the object.
1733
1734 *******************************************************************************/
1735
1736 jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
1737 {
1738         classinfo         *c;
1739         java_objectheader *o;
1740
1741         STATISTICS(jniinvokation());
1742
1743         c = (classinfo *) clazz;
1744
1745         if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
1746                 exceptions_throw_instantiationexception(c);
1747                 return NULL;
1748         }
1749                 
1750         o = builtin_new(c);
1751
1752         return _Jv_JNI_NewLocalRef(env, o);
1753 }
1754
1755
1756 /* NewObject *******************************************************************
1757
1758    Programmers place all arguments that are to be passed to the
1759    constructor immediately following the methodID
1760    argument. NewObject() accepts these arguments and passes them to
1761    the Java method that the programmer wishes to invoke.
1762
1763 *******************************************************************************/
1764
1765 jobject _Jv_JNI_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
1766 {
1767         java_objectheader *o;
1768         methodinfo        *m;
1769         va_list            ap;
1770
1771         STATISTICS(jniinvokation());
1772
1773         m = (methodinfo *) methodID;
1774
1775         /* create object */
1776
1777         o = builtin_new(clazz);
1778         
1779         if (o == NULL)
1780                 return NULL;
1781
1782         /* call constructor */
1783
1784         va_start(ap, methodID);
1785         _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
1786         va_end(ap);
1787
1788         return _Jv_JNI_NewLocalRef(env, o);
1789 }
1790
1791
1792 /* NewObjectV ******************************************************************
1793
1794    Programmers place all arguments that are to be passed to the
1795    constructor in an args argument of type va_list that immediately
1796    follows the methodID argument. NewObjectV() accepts these
1797    arguments, and, in turn, passes them to the Java method that the
1798    programmer wishes to invoke.
1799
1800 *******************************************************************************/
1801
1802 jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1803                                                    va_list args)
1804 {
1805         java_objectheader *o;
1806         methodinfo        *m;
1807
1808         STATISTICS(jniinvokation());
1809
1810         m = (methodinfo *) methodID;
1811
1812         /* create object */
1813
1814         o = builtin_new(clazz);
1815         
1816         if (o == NULL)
1817                 return NULL;
1818
1819         /* call constructor */
1820
1821         _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
1822
1823         return _Jv_JNI_NewLocalRef(env, o);
1824 }
1825
1826
1827 /* NewObjectA ***************************************************************** 
1828
1829    Programmers place all arguments that are to be passed to the
1830    constructor in an args array of jvalues that immediately follows
1831    the methodID argument. NewObjectA() accepts the arguments in this
1832    array, and, in turn, passes them to the Java method that the
1833    programmer wishes to invoke.
1834
1835 *******************************************************************************/
1836
1837 jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1838                                                    jvalue *args)
1839 {
1840         java_objectheader *o;
1841         methodinfo        *m;
1842
1843         STATISTICS(jniinvokation());
1844
1845         m = (methodinfo *) methodID;
1846
1847         /* create object */
1848
1849         o = builtin_new(clazz);
1850         
1851         if (o == NULL)
1852                 return NULL;
1853
1854         /* call constructor */
1855
1856         _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
1857
1858         return _Jv_JNI_NewLocalRef(env, o);
1859 }
1860
1861
1862 /* GetObjectClass **************************************************************
1863
1864  Returns the class of an object.
1865
1866 *******************************************************************************/
1867
1868 jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
1869 {
1870         java_objectheader *o;
1871         classinfo         *c;
1872
1873         STATISTICS(jniinvokation());
1874
1875         o = (java_objectheader *) obj;
1876
1877         if ((o == NULL) || (o->vftbl == NULL))
1878                 return NULL;
1879
1880         c = o->vftbl->class;
1881
1882         return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
1883 }
1884
1885
1886 /* IsInstanceOf ****************************************************************
1887
1888    Tests whether an object is an instance of a class.
1889
1890 *******************************************************************************/
1891
1892 jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
1893 {
1894         java_lang_Class  *c;
1895         java_lang_Object *o;
1896
1897         STATISTICS(jniinvokation());
1898
1899         c = (java_lang_Class *) clazz;
1900         o = (java_lang_Object *) obj;
1901
1902         return _Jv_java_lang_Class_isInstance(c, o);
1903 }
1904
1905
1906 /* Reflection Support *********************************************************/
1907
1908 /* FromReflectedMethod *********************************************************
1909
1910    Converts java.lang.reflect.Method or java.lang.reflect.Constructor
1911    object to a method ID.
1912   
1913 *******************************************************************************/
1914   
1915 jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
1916 {
1917 #if defined(ENABLE_JAVASE)
1918         methodinfo *mi;
1919         classinfo  *c;
1920         s4          slot;
1921
1922         STATISTICS(jniinvokation());
1923
1924         if (method == NULL)
1925                 return NULL;
1926         
1927         if (builtin_instanceof(method, class_java_lang_reflect_Method)) {
1928                 java_lang_reflect_Method *rm;
1929
1930                 rm = (java_lang_reflect_Method *) method;
1931                 c = (classinfo *) (rm->declaringClass);
1932                 slot = rm->slot;
1933         }
1934         else if (builtin_instanceof(method, class_java_lang_reflect_Constructor)) {
1935                 java_lang_reflect_Constructor *rc;
1936
1937                 rc = (java_lang_reflect_Constructor *) method;
1938                 c = (classinfo *) (rc->clazz);
1939                 slot = rc->slot;
1940         }
1941         else
1942                 return NULL;
1943
1944         mi = &(c->methods[slot]);
1945
1946         return (jmethodID) mi;
1947 #else
1948         vm_abort("_Jv_JNI_FromReflectedMethod: not implemented in this configuration");
1949
1950         /* keep compiler happy */
1951
1952         return NULL;
1953 #endif
1954 }
1955
1956
1957 /* FromReflectedField **********************************************************
1958
1959    Converts a java.lang.reflect.Field to a field ID.
1960
1961 *******************************************************************************/
1962  
1963 jfieldID _Jv_JNI_FromReflectedField(JNIEnv* env, jobject field)
1964 {
1965 #if defined(ENABLE_JAVASE)
1966         java_lang_reflect_Field *rf;
1967         classinfo               *c;
1968         fieldinfo               *f;
1969
1970         STATISTICS(jniinvokation());
1971
1972         rf = (java_lang_reflect_Field *) field;
1973
1974         if (rf == NULL)
1975                 return NULL;
1976
1977         c = (classinfo *) rf->declaringClass;
1978
1979         f = &(c->fields[rf->slot]);
1980
1981         return (jfieldID) f;
1982 #else
1983         vm_abort("_Jv_JNI_FromReflectedField: not implemented in this configuration");
1984
1985         /* keep compiler happy */
1986
1987         return NULL;
1988 #endif
1989 }
1990
1991
1992 /* ToReflectedMethod ***********************************************************
1993
1994    Converts a method ID derived from cls to an instance of the
1995    java.lang.reflect.Method class or to an instance of the
1996    java.lang.reflect.Constructor class.
1997
1998 *******************************************************************************/
1999
2000 jobject _Jv_JNI_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
2001                                                                   jboolean isStatic)
2002 {
2003         STATISTICS(jniinvokation());
2004
2005         log_text("JNI-Call: ToReflectedMethod: IMPLEMENT ME!");
2006
2007         return NULL;
2008 }
2009
2010
2011 /* ToReflectedField ************************************************************
2012
2013    Converts a field ID derived from cls to an instance of the
2014    java.lang.reflect.Field class.
2015
2016 *******************************************************************************/
2017
2018 jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
2019                                                                  jboolean isStatic)
2020 {
2021         STATISTICS(jniinvokation());
2022
2023         log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
2024
2025         return NULL;
2026 }
2027
2028
2029 /* Calling Instance Methods ***************************************************/
2030
2031 /* GetMethodID *****************************************************************
2032
2033    Returns the method ID for an instance (nonstatic) method of a class
2034    or interface. The method may be defined in one of the clazz's
2035    superclasses and inherited by clazz. The method is determined by
2036    its name and signature.
2037
2038    GetMethodID() causes an uninitialized class to be initialized.
2039
2040 *******************************************************************************/
2041
2042 jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
2043                                                           const char *sig)
2044 {
2045         classinfo  *c;
2046         utf        *uname;
2047         utf        *udesc;
2048         methodinfo *m;
2049
2050         STATISTICS(jniinvokation());
2051
2052         c = (classinfo *) clazz;
2053
2054         if (!c)
2055                 return NULL;
2056
2057         if (!(c->state & CLASS_INITIALIZED))
2058                 if (!initialize_class(c))
2059                         return NULL;
2060
2061         /* try to get the method of the class or one of it's superclasses */
2062
2063         uname = utf_new_char((char *) name);
2064         udesc = utf_new_char((char *) sig);
2065
2066         m = class_resolvemethod(clazz, uname, udesc);
2067
2068         if ((m == NULL) || (m->flags & ACC_STATIC)) {
2069                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
2070
2071                 return NULL;
2072         }
2073
2074         return (jmethodID) m;
2075 }
2076
2077
2078 /* JNI-functions for calling instance methods *********************************/
2079
2080 jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
2081                                                                  ...)
2082 {
2083         java_objectheader *o;
2084         methodinfo        *m;
2085         java_objectheader *ret;
2086         va_list            ap;
2087
2088         o = (java_objectheader *) obj;
2089         m = (methodinfo *) methodID;
2090
2091         va_start(ap, methodID);
2092         ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, ap);
2093         va_end(ap);
2094
2095         return _Jv_JNI_NewLocalRef(env, ret);
2096 }
2097
2098
2099 jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2100                                                                   va_list args)
2101 {
2102         java_objectheader *o;
2103         methodinfo        *m;
2104         java_objectheader *ret;
2105
2106         o = (java_objectheader *) obj;
2107         m = (methodinfo *) methodID;
2108
2109         ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args);
2110
2111         return _Jv_JNI_NewLocalRef(env, ret);
2112 }
2113
2114
2115 jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2116                                                                   jvalue *args)
2117 {
2118         java_objectheader *o;
2119         methodinfo        *m;
2120         java_objectheader *ret;
2121
2122         o = (java_objectheader *) obj;
2123         m = (methodinfo *) methodID;
2124
2125         ret = _Jv_jni_CallObjectMethodA(o, o->vftbl, m, args);
2126
2127         return _Jv_JNI_NewLocalRef(env, ret);
2128 }
2129
2130
2131 jboolean _Jv_JNI_CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID,
2132                                                                    ...)
2133 {
2134         java_objectheader *o;
2135         methodinfo        *m;
2136         va_list            ap;
2137         jboolean           b;
2138
2139         o = (java_objectheader *) obj;
2140         m = (methodinfo *) methodID;
2141
2142         va_start(ap, methodID);
2143         b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
2144         va_end(ap);
2145
2146         return b;
2147 }
2148
2149
2150 jboolean _Jv_JNI_CallBooleanMethodV(JNIEnv *env, jobject obj,
2151                                                                         jmethodID methodID, va_list args)
2152 {
2153         java_objectheader *o;
2154         methodinfo        *m;
2155         jboolean           b;
2156
2157         o = (java_objectheader *) obj;
2158         m = (methodinfo *) methodID;
2159
2160         b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
2161
2162         return b;
2163 }
2164
2165
2166 jboolean _Jv_JNI_CallBooleanMethodA(JNIEnv *env, jobject obj,
2167                                                                         jmethodID methodID, jvalue *args)
2168 {
2169         java_objectheader *o;
2170         methodinfo        *m;
2171         jboolean           b;
2172
2173         o = (java_objectheader *) obj;
2174         m = (methodinfo *) methodID;
2175
2176         b = _Jv_jni_CallIntMethodA(o, o->vftbl, m, args);
2177
2178         return b;
2179 }
2180
2181
2182 jbyte _Jv_JNI_CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2183 {
2184         java_objectheader *o;
2185         methodinfo        *m;
2186         va_list            ap;
2187         jbyte              b;
2188
2189         o = (java_objectheader *) obj;
2190         m = (methodinfo *) methodID;
2191
2192         va_start(ap, methodID);
2193         b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
2194         va_end(ap);
2195
2196         return b;
2197
2198 }
2199
2200
2201 jbyte _Jv_JNI_CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2202                                                           va_list args)
2203 {
2204         java_objectheader *o;
2205         methodinfo        *m;
2206         jbyte              b;
2207
2208         o = (java_objectheader *) obj;
2209         m = (methodinfo *) methodID;
2210
2211         b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
2212
2213         return b;
2214 }
2215
2216
2217 jbyte _Jv_JNI_CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2218                                                           jvalue *args)
2219 {
2220         log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!");
2221
2222         return 0;
2223 }
2224
2225
2226 jchar _Jv_JNI_CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2227 {
2228         java_objectheader *o;
2229         methodinfo        *m;
2230         va_list            ap;
2231         jchar              c;
2232
2233         o = (java_objectheader *) obj;
2234         m = (methodinfo *) methodID;
2235
2236         va_start(ap, methodID);
2237         c = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
2238         va_end(ap);
2239
2240         return c;
2241 }
2242
2243
2244 jchar _Jv_JNI_CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2245                                                           va_list args)
2246 {
2247         java_objectheader *o;
2248         methodinfo        *m;
2249         jchar              c;
2250
2251         o = (java_objectheader *) obj;
2252         m = (methodinfo *) methodID;
2253
2254         c = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
2255
2256         return c;
2257 }
2258
2259
2260 jchar _Jv_JNI_CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2261                                                           jvalue *args)
2262 {
2263         log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!");
2264
2265         return 0;
2266 }
2267
2268
2269 jshort _Jv_JNI_CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID,
2270                                                            ...)
2271 {
2272         java_objectheader *o;
2273         methodinfo        *m;
2274         va_list            ap;
2275         jshort             s;
2276
2277         o = (java_objectheader *) obj;
2278         m = (methodinfo *) methodID;
2279
2280         va_start(ap, methodID);
2281         s = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
2282         va_end(ap);
2283
2284         return s;
2285 }
2286
2287
2288 jshort _Jv_JNI_CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2289                                                                 va_list args)
2290 {
2291         java_objectheader *o;
2292         methodinfo        *m;
2293         jshort             s;
2294
2295         o = (java_objectheader *) obj;
2296         m = (methodinfo *) methodID;
2297
2298         s = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
2299
2300         return s;
2301 }
2302
2303
2304 jshort _Jv_JNI_CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2305                                                                 jvalue *args)
2306 {
2307         log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!");
2308
2309         return 0;
2310 }
2311
2312
2313
2314 jint _Jv_JNI_CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2315 {
2316         java_objectheader *o;
2317         methodinfo        *m;
2318         va_list            ap;
2319         jint               i;
2320
2321         o = (java_objectheader *) obj;
2322         m = (methodinfo *) methodID;
2323
2324         va_start(ap, methodID);
2325         i = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap);
2326         va_end(ap);
2327
2328         return i;
2329 }
2330
2331
2332 jint _Jv_JNI_CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2333                                                         va_list args)
2334 {
2335         java_objectheader *o;
2336         methodinfo        *m;
2337         jint               i;
2338
2339         o = (java_objectheader *) obj;
2340         m = (methodinfo *) methodID;
2341
2342         i = _Jv_jni_CallIntMethod(o, o->vftbl, m, args);
2343
2344         return i;
2345 }
2346
2347
2348 jint _Jv_JNI_CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2349                                                         jvalue *args)
2350 {
2351         log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!");
2352
2353         return 0;
2354 }
2355
2356
2357
2358 jlong _Jv_JNI_CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2359 {
2360         java_objectheader *o;
2361         methodinfo        *m;
2362         va_list            ap;
2363         jlong              l;
2364
2365         o = (java_objectheader *) obj;
2366         m = (methodinfo *) methodID;
2367
2368         va_start(ap, methodID);
2369         l = _Jv_jni_CallLongMethod(o, o->vftbl, m, ap);
2370         va_end(ap);
2371
2372         return l;
2373 }
2374
2375
2376 jlong _Jv_JNI_CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2377                                                           va_list args)
2378 {
2379         java_objectheader *o;
2380         methodinfo        *m;
2381         jlong              l;
2382
2383         o = (java_objectheader *) obj;
2384         m = (methodinfo *) methodID;
2385
2386         l = _Jv_jni_CallLongMethod(o, o->vftbl, m, args);
2387
2388         return l;
2389 }
2390
2391
2392 jlong _Jv_JNI_CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2393                                                           jvalue *args)
2394 {
2395         log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!");
2396
2397         return 0;
2398 }
2399
2400
2401
2402 jfloat _Jv_JNI_CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID,
2403                                                            ...)
2404 {
2405         java_objectheader *o;
2406         methodinfo        *m;
2407         va_list            ap;
2408         jfloat             f;
2409
2410         o = (java_objectheader *) obj;
2411         m = (methodinfo *) methodID;
2412
2413         va_start(ap, methodID);
2414         f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, ap);
2415         va_end(ap);
2416
2417         return f;
2418 }
2419
2420
2421 jfloat _Jv_JNI_CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2422                                                                 va_list args)
2423 {
2424         java_objectheader *o;
2425         methodinfo        *m;
2426         jfloat             f;
2427
2428         o = (java_objectheader *) obj;
2429         m = (methodinfo *) methodID;
2430
2431         f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, args);
2432
2433         return f;
2434 }
2435
2436
2437 jfloat _Jv_JNI_CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2438                                                                 jvalue *args)
2439 {
2440         log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!");
2441
2442         return 0;
2443 }
2444
2445
2446
2447 jdouble _Jv_JNI_CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID,
2448                                                                  ...)
2449 {
2450         java_objectheader *o;
2451         methodinfo        *m;
2452         va_list            ap;
2453         jdouble            d;
2454
2455         o = (java_objectheader *) obj;
2456         m = (methodinfo *) methodID;
2457
2458         va_start(ap, methodID);
2459         d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, ap);
2460         va_end(ap);
2461
2462         return d;
2463 }
2464
2465
2466 jdouble _Jv_JNI_CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2467                                                                   va_list args)
2468 {
2469         java_objectheader *o;
2470         methodinfo        *m;
2471         jdouble            d;
2472
2473         o = (java_objectheader *) obj;
2474         m = (methodinfo *) methodID;
2475
2476         d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, args);
2477
2478         return d;
2479 }
2480
2481
2482 jdouble _Jv_JNI_CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2483                                                                   jvalue *args)
2484 {
2485         log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!");
2486
2487         return 0;
2488 }
2489
2490
2491
2492 void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
2493 {
2494         java_objectheader *o;
2495         methodinfo        *m;
2496         va_list            ap;
2497
2498         o = (java_objectheader *) obj;
2499         m = (methodinfo *) methodID;
2500
2501         va_start(ap, methodID);
2502         _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap);
2503         va_end(ap);
2504 }
2505
2506
2507 void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
2508                                                          va_list args)
2509 {
2510         java_objectheader *o;
2511         methodinfo        *m;
2512
2513         o = (java_objectheader *) obj;
2514         m = (methodinfo *) methodID;
2515
2516         _Jv_jni_CallVoidMethod(o, o->vftbl, m, args);
2517 }
2518
2519
2520 void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
2521                                                          jvalue *args)
2522 {
2523         java_objectheader *o;
2524         methodinfo        *m;
2525
2526         o = (java_objectheader *) obj;
2527         m = (methodinfo *) methodID;
2528
2529         _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args);
2530 }
2531
2532
2533
2534 jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
2535                                                                                    jclass clazz, jmethodID methodID,
2536                                                                                    ...)
2537 {
2538         java_objectheader *o;
2539         classinfo         *c;
2540         methodinfo        *m;
2541         java_objectheader *r;
2542         va_list            ap;
2543
2544         o = (java_objectheader *) obj;
2545         c = (classinfo *) clazz;
2546         m = (methodinfo *) methodID;
2547
2548         va_start(ap, methodID);
2549         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
2550         va_end(ap);
2551
2552         return _Jv_JNI_NewLocalRef(env, r);
2553 }
2554
2555
2556 jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
2557                                                                                         jclass clazz, jmethodID methodID,
2558                                                                                         va_list args)
2559 {
2560         java_objectheader *o;
2561         classinfo         *c;
2562         methodinfo        *m;
2563         java_objectheader *r;
2564
2565         o = (java_objectheader *) obj;
2566         c = (classinfo *) clazz;
2567         m = (methodinfo *) methodID;
2568
2569         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
2570
2571         return _Jv_JNI_NewLocalRef(env, r);
2572 }
2573
2574
2575 jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
2576                                                                                         jclass clazz, jmethodID methodID,
2577                                                                                         jvalue *args)
2578 {
2579         log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
2580
2581         return _Jv_JNI_NewLocalRef(env, NULL);
2582 }
2583
2584
2585
2586 jboolean _Jv_JNI_CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj,
2587                                                                                          jclass clazz, jmethodID methodID,
2588                                                                                          ...)
2589 {
2590         java_objectheader *o;
2591         classinfo         *c;
2592         methodinfo        *m;
2593         va_list            ap;
2594         jboolean           b;
2595
2596         o = (java_objectheader *) obj;
2597         c = (classinfo *) clazz;
2598         m = (methodinfo *) methodID;
2599
2600         va_start(ap, methodID);
2601         b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
2602         va_end(ap);
2603
2604         return b;
2605 }
2606
2607
2608 jboolean _Jv_JNI_CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj,
2609                                                                                           jclass clazz, jmethodID methodID,
2610                                                                                           va_list args)
2611 {
2612         java_objectheader *o;
2613         classinfo         *c;
2614         methodinfo        *m;
2615         jboolean           b;
2616
2617         o = (java_objectheader *) obj;
2618         c = (classinfo *) clazz;
2619         m = (methodinfo *) methodID;
2620
2621         b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
2622
2623         return b;
2624 }
2625
2626
2627 jboolean _Jv_JNI_CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj,
2628                                                                                           jclass clazz, jmethodID methodID,
2629                                                                                           jvalue *args)
2630 {
2631         log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!");
2632
2633         return 0;
2634 }
2635
2636
2637 jbyte _Jv_JNI_CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz,
2638                                                                            jmethodID methodID, ...)
2639 {
2640         java_objectheader *o;
2641         classinfo         *c;
2642         methodinfo        *m;
2643         va_list            ap;
2644         jbyte              b;
2645
2646         o = (java_objectheader *) obj;
2647         c = (classinfo *) clazz;
2648         m = (methodinfo *) methodID;
2649
2650         va_start(ap, methodID);
2651         b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
2652         va_end(ap);
2653
2654         return b;
2655 }
2656
2657
2658 jbyte _Jv_JNI_CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz,
2659                                                                                 jmethodID methodID, va_list args)
2660 {
2661         java_objectheader *o;
2662         classinfo         *c;
2663         methodinfo        *m;
2664         jbyte              b;
2665
2666         o = (java_objectheader *) obj;
2667         c = (classinfo *) clazz;
2668         m = (methodinfo *) methodID;
2669
2670         b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
2671
2672         return b;
2673 }
2674
2675
2676 jbyte _Jv_JNI_CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, 
2677                                                                                 jmethodID methodID, jvalue *args)
2678 {
2679         log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!");
2680
2681         return 0;
2682 }
2683
2684
2685
2686 jchar _Jv_JNI_CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz,
2687                                                                            jmethodID methodID, ...)
2688 {
2689         java_objectheader *o;
2690         classinfo         *c;
2691         methodinfo        *m;
2692         va_list            ap;
2693         jchar              ch;
2694
2695         o = (java_objectheader *) obj;
2696         c = (classinfo *) clazz;
2697         m = (methodinfo *) methodID;
2698
2699         va_start(ap, methodID);
2700         ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
2701         va_end(ap);
2702
2703         return ch;
2704 }
2705
2706
2707 jchar _Jv_JNI_CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz,
2708                                                                                 jmethodID methodID, va_list args)
2709 {
2710         java_objectheader *o;
2711         classinfo         *c;
2712         methodinfo        *m;
2713         jchar              ch;
2714
2715         o = (java_objectheader *) obj;
2716         c = (classinfo *) clazz;
2717         m = (methodinfo *) methodID;
2718
2719         ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
2720
2721         return ch;
2722 }
2723
2724
2725 jchar _Jv_JNI_CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz,
2726                                                                                 jmethodID methodID, jvalue *args)
2727 {
2728         log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!");
2729
2730         return 0;
2731 }
2732
2733
2734
2735 jshort _Jv_JNI_CallNonvirtualShortMethod(JNIEnv *env, jobject obj,
2736                                                                                  jclass clazz, jmethodID methodID, ...)
2737 {
2738         java_objectheader *o;
2739         classinfo         *c;
2740         methodinfo        *m;
2741         va_list            ap;
2742         jshort             s;
2743
2744         o = (java_objectheader *) obj;
2745         c = (classinfo *) clazz;
2746         m = (methodinfo *) methodID;
2747
2748         va_start(ap, methodID);
2749         s = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
2750         va_end(ap);
2751
2752         return s;
2753 }
2754
2755
2756 jshort _Jv_JNI_CallNonvirtualShortMethodV(JNIEnv *env, jobject obj,
2757                                                                                   jclass clazz, jmethodID methodID,
2758                                                                                   va_list args)
2759 {
2760         java_objectheader *o;
2761         classinfo         *c;
2762         methodinfo        *m;
2763         jshort             s;
2764
2765         o = (java_objectheader *) obj;
2766         c = (classinfo *) clazz;
2767         m = (methodinfo *) methodID;
2768
2769         s = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
2770
2771         return s;
2772 }
2773
2774
2775 jshort _Jv_JNI_CallNonvirtualShortMethodA(JNIEnv *env, jobject obj,
2776                                                                                   jclass clazz, jmethodID methodID,
2777                                                                                   jvalue *args)
2778 {
2779         log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!");
2780
2781         return 0;
2782 }
2783
2784
2785
2786 jint _Jv_JNI_CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz,
2787                                                                          jmethodID methodID, ...)
2788 {
2789         java_objectheader *o;
2790         classinfo         *c;
2791         methodinfo        *m;
2792         va_list            ap;
2793         jint               i;
2794
2795         o = (java_objectheader *) obj;
2796         c = (classinfo *) clazz;
2797         m = (methodinfo *) methodID;
2798
2799         va_start(ap, methodID);
2800         i = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap);
2801         va_end(ap);
2802
2803         return i;
2804 }
2805
2806
2807 jint _Jv_JNI_CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz,
2808                                                                           jmethodID methodID, va_list args)
2809 {
2810         java_objectheader *o;
2811         classinfo         *c;
2812         methodinfo        *m;
2813         jint               i;
2814
2815         o = (java_objectheader *) obj;
2816         c = (classinfo *) clazz;
2817         m = (methodinfo *) methodID;
2818
2819         i = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);
2820
2821         return i;
2822 }
2823
2824
2825 jint _Jv_JNI_CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz,
2826                                                                           jmethodID methodID, jvalue *args)
2827 {
2828         log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!");
2829
2830         return 0;
2831 }
2832
2833
2834
2835 jlong _Jv_JNI_CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz,
2836                                                                            jmethodID methodID, ...)
2837 {
2838         java_objectheader *o;
2839         classinfo         *c;
2840         methodinfo        *m;
2841         va_list            ap;
2842         jlong              l;
2843
2844         o = (java_objectheader *) obj;
2845         c = (classinfo *) clazz;
2846         m = (methodinfo *) methodID;
2847
2848         va_start(ap, methodID);
2849         l = _Jv_jni_CallLongMethod(o, c->vftbl, m, ap);
2850         va_end(ap);
2851
2852         return l;
2853 }
2854
2855
2856 jlong _Jv_JNI_CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz,
2857                                                                                 jmethodID methodID, va_list args)
2858 {
2859         java_objectheader *o;
2860         classinfo         *c;
2861         methodinfo        *m;
2862         jlong              l;
2863
2864         o = (java_objectheader *) obj;
2865         c = (classinfo *) clazz;
2866         m = (methodinfo *) methodID;
2867
2868         l = _Jv_jni_CallLongMethod(o, c->vftbl, m, args);
2869
2870         return l;
2871 }
2872
2873
2874 jlong _Jv_JNI_CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz,
2875                                                                                 jmethodID methodID, jvalue *args)
2876 {
2877         log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!");
2878
2879         return 0;
2880 }
2881
2882
2883
2884 jfloat _Jv_JNI_CallNonvirtualFloatMethod(JNIEnv *env, jobject obj,
2885                                                                                  jclass clazz, jmethodID methodID, ...)
2886 {
2887         java_objectheader *o;
2888         classinfo         *c;
2889         methodinfo        *m;
2890         va_list            ap;
2891         jfloat             f;
2892
2893         o = (java_objectheader *) obj;
2894         c = (classinfo *) clazz;
2895         m = (methodinfo *) methodID;
2896
2897         va_start(ap, methodID);
2898         f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, ap);
2899         va_end(ap);
2900
2901         return f;
2902 }
2903
2904
2905 jfloat _Jv_JNI_CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj,
2906                                                                                   jclass clazz, jmethodID methodID,
2907                                                                                   va_list args)
2908 {
2909         java_objectheader *o;
2910         classinfo         *c;
2911         methodinfo        *m;
2912         jfloat             f;
2913
2914         o = (java_objectheader *) obj;
2915         c = (classinfo *) clazz;
2916         m = (methodinfo *) methodID;
2917
2918         f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, args);
2919
2920         return f;
2921 }
2922
2923
2924 jfloat _Jv_JNI_CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj,
2925                                                                                   jclass clazz, jmethodID methodID,
2926                                                                                   jvalue *args)
2927 {
2928         log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!");
2929
2930         return 0;
2931 }
2932
2933
2934
2935 jdouble _Jv_JNI_CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj,
2936                                                                                    jclass clazz, jmethodID methodID,
2937                                                                                    ...)
2938 {
2939         java_objectheader *o;
2940         classinfo         *c;
2941         methodinfo        *m;
2942         va_list            ap;
2943         jdouble            d;
2944
2945         o = (java_objectheader *) obj;
2946         c = (classinfo *) clazz;
2947         m = (methodinfo *) methodID;
2948
2949         va_start(ap, methodID);
2950         d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, ap);
2951         va_end(ap);
2952
2953         return d;
2954 }
2955
2956
2957 jdouble _Jv_JNI_CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj,
2958                                                                                         jclass clazz, jmethodID methodID,
2959                                                                                         va_list args)
2960 {
2961         java_objectheader *o;
2962         classinfo         *c;
2963         methodinfo        *m;
2964         jdouble            d;
2965
2966         o = (java_objectheader *) obj;
2967         c = (classinfo *) clazz;
2968         m = (methodinfo *) methodID;
2969
2970         d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, args);
2971
2972         return d;
2973 }
2974
2975
2976 jdouble _Jv_JNI_CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj,
2977                                                                                         jclass clazz, jmethodID methodID,
2978                                                                                         jvalue *args)
2979 {
2980         log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!");
2981
2982         return 0;
2983 }
2984
2985
2986
2987 void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
2988                                                                           jmethodID methodID, ...)
2989 {
2990         java_objectheader *o;
2991         classinfo         *c;
2992         methodinfo        *m;
2993         va_list            ap;
2994
2995         o = (java_objectheader *) obj;
2996         c = (classinfo *) clazz;
2997         m = (methodinfo *) methodID;
2998
2999         va_start(ap, methodID);
3000         _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
3001         va_end(ap);
3002 }
3003
3004
3005 void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
3006                                                                            jmethodID methodID, va_list args)
3007 {
3008         java_objectheader *o;
3009         classinfo         *c;
3010         methodinfo        *m;
3011
3012         o = (java_objectheader *) obj;
3013         c = (classinfo *) clazz;
3014         m = (methodinfo *) methodID;
3015
3016         _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
3017 }
3018
3019
3020 void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
3021                                                                            jmethodID methodID, jvalue * args)
3022 {       
3023         java_objectheader *o;
3024         classinfo         *c;
3025         methodinfo        *m;
3026
3027         o = (java_objectheader *) obj;
3028         c = (classinfo *) clazz;
3029         m = (methodinfo *) methodID;
3030
3031         _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
3032 }
3033
3034
3035 /* Accessing Fields of Objects ************************************************/
3036
3037 /* GetFieldID ******************************************************************
3038
3039    Returns the field ID for an instance (nonstatic) field of a
3040    class. The field is specified by its name and signature. The
3041    Get<type>Field and Set<type>Field families of accessor functions
3042    use field IDs to retrieve object fields.
3043
3044 *******************************************************************************/
3045
3046 jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
3047                                                         const char *sig) 
3048 {
3049         classinfo *c;
3050         fieldinfo *f;
3051         utf       *uname;
3052         utf       *udesc;
3053
3054         STATISTICS(jniinvokation());
3055
3056         c = (classinfo *) clazz;
3057
3058         uname = utf_new_char((char *) name);
3059         udesc = utf_new_char((char *) sig);
3060
3061         f = class_findfield(clazz, uname, udesc); 
3062         
3063         if (f == NULL)
3064                 exceptions_throw_nosuchfielderror(c, uname);  
3065
3066         return (jfieldID) f;
3067 }
3068
3069
3070 /* Get<type>Field Routines *****************************************************
3071
3072    This family of accessor routines returns the value of an instance
3073    (nonstatic) field of an object. The field to access is specified by
3074    a field ID obtained by calling GetFieldID().
3075
3076 *******************************************************************************/
3077
3078 jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
3079 {
3080         java_objectheader *o;
3081
3082         STATISTICS(jniinvokation());
3083
3084         o = GET_FIELD(obj, java_objectheader*, fieldID);
3085
3086         return _Jv_JNI_NewLocalRef(env, o);
3087 }
3088
3089
3090 jboolean _Jv_JNI_GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID)
3091 {
3092         s4 i;
3093
3094         STATISTICS(jniinvokation());
3095
3096         i = GET_FIELD(obj, s4, fieldID);
3097
3098         return (jboolean) i;
3099 }
3100
3101
3102 jbyte _Jv_JNI_GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID)
3103 {
3104         s4 i;
3105
3106         STATISTICS(jniinvokation());
3107
3108         i = GET_FIELD(obj, s4, fieldID);
3109
3110         return (jbyte) i;
3111 }
3112
3113
3114 jchar _Jv_JNI_GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID)
3115 {
3116         s4 i;
3117
3118         STATISTICS(jniinvokation());
3119
3120         i = GET_FIELD(obj, s4, fieldID);
3121
3122         return (jchar) i;
3123 }
3124
3125
3126 jshort _Jv_JNI_GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID)
3127 {
3128         s4 i;
3129
3130         STATISTICS(jniinvokation());
3131
3132         i = GET_FIELD(obj, s4, fieldID);
3133
3134         return (jshort) i;
3135 }
3136
3137
3138 jint _Jv_JNI_GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID)
3139 {
3140         java_objectheader *o;
3141         fieldinfo         *f;
3142         s4                 i;
3143
3144         STATISTICS(jniinvokation());
3145
3146         o = (java_objectheader *) obj;
3147         f = (fieldinfo *) fieldID;
3148
3149         i = GET_FIELD(o, s4, f);
3150
3151         return i;
3152 }
3153
3154
3155 jlong _Jv_JNI_GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID)
3156 {
3157         s8 l;
3158
3159         STATISTICS(jniinvokation());
3160
3161         l = GET_FIELD(obj, s8, fieldID);
3162
3163         return l;
3164 }
3165
3166
3167 jfloat _Jv_JNI_GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID)
3168 {
3169         float f;
3170
3171         STATISTICS(jniinvokation());
3172
3173         f = GET_FIELD(obj, float, fieldID);
3174
3175         return f;
3176 }
3177
3178
3179 jdouble _Jv_JNI_GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID)
3180 {
3181         double d;
3182
3183         STATISTICS(jniinvokation());
3184
3185         d = GET_FIELD(obj, double, fieldID);
3186
3187         return d;
3188 }
3189
3190
3191 /* Set<type>Field Routines *****************************************************
3192
3193    This family of accessor routines sets the value of an instance
3194    (nonstatic) field of an object. The field to access is specified by
3195    a field ID obtained by calling GetFieldID().
3196
3197 *******************************************************************************/
3198
3199 void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
3200                                                         jobject value)
3201 {
3202         STATISTICS(jniinvokation());
3203
3204         SET_FIELD(obj, java_objectheader*, fieldID, value);
3205 }
3206
3207
3208 void _Jv_JNI_SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID,
3209                                                          jboolean value)
3210 {
3211         STATISTICS(jniinvokation());
3212
3213         SET_FIELD(obj, s4, fieldID, value);
3214 }
3215
3216
3217 void _Jv_JNI_SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID,
3218                                                   jbyte value)
3219 {
3220         STATISTICS(jniinvokation());
3221
3222         SET_FIELD(obj, s4, fieldID, value);
3223 }
3224
3225
3226 void _Jv_JNI_SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID,
3227                                                   jchar value)
3228 {
3229         STATISTICS(jniinvokation());
3230
3231         SET_FIELD(obj, s4, fieldID, value);
3232 }
3233
3234
3235 void _Jv_JNI_SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID,
3236                                                    jshort value)
3237 {
3238         STATISTICS(jniinvokation());
3239
3240         SET_FIELD(obj, s4, fieldID, value);
3241 }
3242
3243
3244 void _Jv_JNI_SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value)
3245 {
3246         STATISTICS(jniinvokation());
3247
3248         SET_FIELD(obj, s4, fieldID, value);
3249 }
3250
3251
3252 void _Jv_JNI_SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID,
3253                                                   jlong value)
3254 {
3255         STATISTICS(jniinvokation());
3256
3257         SET_FIELD(obj, s8, fieldID, value);
3258 }
3259
3260
3261 void _Jv_JNI_SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID,
3262                                                    jfloat value)
3263 {
3264         STATISTICS(jniinvokation());
3265
3266         SET_FIELD(obj, float, fieldID, value);
3267 }
3268
3269
3270 void _Jv_JNI_SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID,
3271                                                         jdouble value)
3272 {
3273         STATISTICS(jniinvokation());
3274
3275         SET_FIELD(obj, double, fieldID, value);
3276 }
3277
3278
3279 /* Calling Static Methods *****************************************************/
3280
3281 /* GetStaticMethodID ***********************************************************
3282
3283    Returns the method ID for a static method of a class. The method is
3284    specified by its name and signature.
3285
3286    GetStaticMethodID() causes an uninitialized class to be
3287    initialized.
3288
3289 *******************************************************************************/
3290
3291 jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
3292                                                                         const char *sig)
3293 {
3294         classinfo  *c;
3295         utf        *uname;
3296         utf        *udesc;
3297         methodinfo *m;
3298
3299         STATISTICS(jniinvokation());
3300
3301         c = (classinfo *) clazz;
3302
3303         if (!c)
3304                 return NULL;
3305
3306         if (!(c->state & CLASS_INITIALIZED))
3307                 if (!initialize_class(c))
3308                         return NULL;
3309
3310         /* try to get the static method of the class */
3311
3312         uname = utf_new_char((char *) name);
3313         udesc = utf_new_char((char *) sig);
3314
3315         m = class_resolvemethod(c, uname, udesc);
3316
3317         if ((m == NULL) || !(m->flags & ACC_STATIC)) {
3318                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
3319
3320                 return NULL;
3321         }
3322
3323         return (jmethodID) m;
3324 }
3325
3326
3327 jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
3328                                                                            jmethodID methodID, ...)
3329 {
3330         methodinfo        *m;
3331         java_objectheader *o;
3332         va_list            ap;
3333
3334         m = (methodinfo *) methodID;
3335
3336         va_start(ap, methodID);
3337         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
3338         va_end(ap);
3339
3340         return _Jv_JNI_NewLocalRef(env, o);
3341 }
3342
3343
3344 jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
3345                                                                                 jmethodID methodID, va_list args)
3346 {
3347         methodinfo        *m;
3348         java_objectheader *o;
3349
3350         m = (methodinfo *) methodID;
3351
3352         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
3353
3354         return _Jv_JNI_NewLocalRef(env, o);
3355 }
3356
3357
3358 jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
3359                                                                                 jmethodID methodID, jvalue *args)
3360 {
3361         methodinfo        *m;
3362         java_objectheader *o;
3363
3364         m = (methodinfo *) methodID;
3365
3366         o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
3367
3368         return _Jv_JNI_NewLocalRef(env, o);
3369 }
3370
3371
3372 jboolean _Jv_JNI_CallStaticBooleanMethod(JNIEnv *env, jclass clazz,
3373                                                                                  jmethodID methodID, ...)
3374 {
3375         methodinfo *m;
3376         va_list     ap;
3377         jboolean    b;
3378
3379         m = (methodinfo *) methodID;
3380
3381         va_start(ap, methodID);
3382         b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
3383         va_end(ap);
3384
3385         return b;
3386 }
3387
3388
3389 jboolean _Jv_JNI_CallStaticBooleanMethodV(JNIEnv *env, jclass clazz,
3390                                                                                   jmethodID methodID, va_list args)
3391 {
3392         methodinfo *m;
3393         jboolean    b;
3394
3395         m = (methodinfo *) methodID;
3396
3397         b = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
3398
3399         return b;
3400 }
3401
3402
3403 jboolean _Jv_JNI_CallStaticBooleanMethodA(JNIEnv *env, jclass clazz,
3404                                                                                   jmethodID methodID, jvalue *args)
3405 {
3406         methodinfo *m;
3407         jboolean    b;
3408
3409         m = (methodinfo *) methodID;
3410
3411         b = _Jv_jni_CallIntMethodA(NULL, NULL, m, args);
3412
3413         return b;
3414 }
3415
3416
3417 jbyte _Jv_JNI_CallStaticByteMethod(JNIEnv *env, jclass clazz,
3418                                                                    jmethodID methodID, ...)
3419 {
3420         methodinfo *m;
3421         va_list     ap;
3422         jbyte       b;
3423
3424         m = (methodinfo *) methodID;
3425
3426         va_start(ap, methodID);
3427         b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
3428         va_end(ap);
3429
3430         return b;
3431 }
3432
3433
3434 jbyte _Jv_JNI_CallStaticByteMethodV(JNIEnv *env, jclass clazz,
3435                                                                         jmethodID methodID, va_list args)
3436 {
3437         methodinfo *m;
3438         jbyte       b;
3439
3440         m = (methodinfo *) methodID;
3441
3442         b = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
3443
3444         return b;
3445 }
3446
3447
3448 jbyte _Jv_JNI_CallStaticByteMethodA(JNIEnv *env, jclass clazz,
3449                                                                         jmethodID methodID, jvalue *args)
3450 {
3451         methodinfo *m;
3452         jbyte       b;
3453
3454         m = (methodinfo *) methodID;
3455
3456         b = _Jv_jni_CallIntMethodA(NULL, NULL, m, args);
3457
3458         return b;
3459 }
3460
3461
3462 jchar _Jv_JNI_CallStaticCharMethod(JNIEnv *env, jclass clazz,
3463                                                                    jmethodID methodID, ...)
3464 {
3465         methodinfo *m;
3466         va_list     ap;
3467         jchar       c;
3468
3469         m = (methodinfo *) methodID;
3470
3471         va_start(ap, methodID);
3472         c = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
3473         va_end(ap);
3474
3475         return c;
3476 }
3477
3478
3479 jchar _Jv_JNI_CallStaticCharMethodV(JNIEnv *env, jclass clazz,
3480                                                                         jmethodID methodID, va_list args)
3481 {
3482         methodinfo *m;
3483         jchar       c;
3484
3485         m = (methodinfo *) methodID;
3486
3487         c = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
3488
3489         return c;
3490 }
3491
3492
3493 jchar _Jv_JNI_CallStaticCharMethodA(JNIEnv *env, jclass clazz,
3494                                                                         jmethodID methodID, jvalue *args)
3495 {
3496         methodinfo *m;
3497         jchar       c;
3498
3499         m = (methodinfo *) methodID;
3500
3501         c = _Jv_jni_CallIntMethodA(NULL, NULL, m, args);
3502
3503         return c;
3504 }
3505
3506
3507 jshort _Jv_JNI_CallStaticShortMethod(JNIEnv *env, jclass clazz,
3508                                                                          jmethodID methodID, ...)
3509 {
3510         methodinfo *m;
3511         va_list     ap;
3512         jshort      s;
3513
3514         m = (methodinfo *) methodID;
3515
3516         va_start(ap, methodID);
3517         s = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
3518         va_end(ap);
3519
3520         return s;
3521 }
3522
3523
3524 jshort _Jv_JNI_CallStaticShortMethodV(JNIEnv *env, jclass clazz,
3525                                                                           jmethodID methodID, va_list args)
3526 {
3527         methodinfo *m;
3528         jshort      s;
3529
3530         m = (methodinfo *) methodID;
3531
3532         s = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
3533
3534         return s;
3535 }
3536
3537
3538 jshort _Jv_JNI_CallStaticShortMethodA(JNIEnv *env, jclass clazz,
3539                                                                           jmethodID methodID, jvalue *args)
3540 {
3541         methodinfo *m;
3542         jshort      s;
3543
3544         m = (methodinfo *) methodID;
3545
3546         s = _Jv_jni_CallIntMethodA(NULL, NULL, m, args);
3547
3548         return s;
3549 }
3550
3551
3552 jint _Jv_JNI_CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
3553                                                                  ...)
3554 {
3555         methodinfo *m;
3556         va_list     ap;
3557         jint        i;
3558
3559         m = (methodinfo *) methodID;
3560
3561         va_start(ap, methodID);
3562         i = _Jv_jni_CallIntMethod(NULL, NULL, m, ap);
3563         va_end(ap);
3564
3565         return i;
3566 }
3567
3568
3569 jint _Jv_JNI_CallStaticIntMethodV(JNIEnv *env, jclass clazz,
3570                                                                   jmethodID methodID, va_list args)
3571 {
3572         methodinfo *m;
3573         jint        i;
3574
3575         m = (methodinfo *) methodID;
3576
3577         i = _Jv_jni_CallIntMethod(NULL, NULL, m, args);
3578
3579         return i;
3580 }
3581
3582
3583 jint _Jv_JNI_CallStaticIntMethodA(JNIEnv *env, jclass clazz,
3584                                                                   jmethodID methodID, jvalue *args)
3585 {
3586         methodinfo *m;
3587         jint        i;
3588
3589         m = (methodinfo *) methodID;
3590
3591         i = _Jv_jni_CallIntMethodA(NULL, NULL, m, args);
3592
3593         return i;
3594 }
3595
3596
3597 jlong _Jv_JNI_CallStaticLongMethod(JNIEnv *env, jclass clazz,
3598                                                                    jmethodID methodID, ...)
3599 {
3600         methodinfo *m;
3601         va_list     ap;
3602         jlong       l;
3603
3604         m = (methodinfo *) methodID;
3605
3606         va_start(ap, methodID);
3607         l = _Jv_jni_CallLongMethod(NULL, NULL, m, ap);
3608         va_end(ap);
3609
3610         return l;
3611 }
3612
3613
3614 jlong _Jv_JNI_CallStaticLongMethodV(JNIEnv *env, jclass clazz,
3615                                                                         jmethodID methodID, va_list args)
3616 {
3617         methodinfo *m;
3618         jlong       l;
3619         
3620         m = (methodinfo *) methodID;
3621
3622         l = _Jv_jni_CallLongMethod(NULL, NULL, m, args);
3623
3624         return l;
3625 }
3626
3627
3628 jlong _Jv_JNI_CallStaticLongMethodA(JNIEnv *env, jclass clazz,
3629                                                                         jmethodID methodID, jvalue *args)
3630 {
3631         methodinfo *m;
3632         jlong       l;
3633
3634         m = (methodinfo *) methodID;
3635
3636         l = _Jv_jni_CallLongMethodA(NULL, NULL, m, args);
3637
3638         return l;
3639 }
3640
3641
3642
3643 jfloat _Jv_JNI_CallStaticFloatMethod(JNIEnv *env, jclass clazz,
3644                                                                          jmethodID methodID, ...)
3645 {
3646         methodinfo *m;
3647         va_list     ap;
3648         jfloat      f;
3649
3650         m = (methodinfo *) methodID;
3651
3652         va_start(ap, methodID);
3653         f = _Jv_jni_CallFloatMethod(NULL, NULL, m, ap);
3654         va_end(ap);
3655
3656         return f;
3657 }
3658
3659
3660 jfloat _Jv_JNI_CallStaticFloatMethodV(JNIEnv *env, jclass clazz,
3661                                                                           jmethodID methodID, va_list args)
3662 {
3663         methodinfo *m;
3664         jfloat      f;
3665
3666         m = (methodinfo *) methodID;
3667
3668         f = _Jv_jni_CallFloatMethod(NULL, NULL, m, args);
3669
3670         return f;
3671 }
3672
3673
3674 jfloat _Jv_JNI_CallStaticFloatMethodA(JNIEnv *env, jclass clazz,
3675                                                                           jmethodID methodID, jvalue *args)
3676 {
3677         methodinfo *m;
3678         jfloat      f;
3679
3680         m = (methodinfo *) methodID;
3681
3682         f = _Jv_jni_CallFloatMethodA(NULL, NULL, m, args);
3683
3684         return f;
3685 }
3686
3687
3688 jdouble _Jv_JNI_CallStaticDoubleMethod(JNIEnv *env, jclass clazz,
3689                                                                            jmethodID methodID, ...)
3690 {
3691         methodinfo *m;
3692         va_list     ap;
3693         jdouble     d;
3694
3695         m = (methodinfo *) methodID;
3696
3697         va_start(ap, methodID);
3698         d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, ap);
3699         va_end(ap);
3700
3701         return d;
3702 }
3703
3704
3705 jdouble _Jv_JNI_CallStaticDoubleMethodV(JNIEnv *env, jclass clazz,
3706                                                                                 jmethodID methodID, va_list args)
3707 {
3708         methodinfo *m;
3709         jdouble     d;
3710
3711         m = (methodinfo *) methodID;
3712
3713         d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, args);
3714
3715         return d;
3716 }
3717
3718
3719 jdouble _Jv_JNI_CallStaticDoubleMethodA(JNIEnv *env, jclass clazz,
3720                                                                                 jmethodID methodID, jvalue *args)
3721 {
3722         methodinfo *m;
3723         jdouble     d;
3724
3725         m = (methodinfo *) methodID;
3726
3727         d = _Jv_jni_CallDoubleMethodA(NULL, NULL, m, args);
3728
3729         return d;
3730 }
3731
3732
3733 void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
3734                                                                   jmethodID methodID, ...)
3735 {
3736         methodinfo *m;
3737         va_list     ap;
3738
3739         m = (methodinfo *) methodID;
3740
3741         va_start(ap, methodID);
3742         _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
3743         va_end(ap);
3744 }
3745
3746
3747 void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
3748                                                                    jmethodID methodID, va_list args)
3749 {
3750         methodinfo *m;
3751
3752         m = (methodinfo *) methodID;
3753
3754         _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
3755 }
3756
3757
3758 void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
3759                                                                    jmethodID methodID, jvalue * args)
3760 {
3761         methodinfo *m;
3762
3763         m = (methodinfo *) methodID;
3764
3765         _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
3766 }
3767
3768
3769 /* Accessing Static Fields ****************************************************/
3770
3771 /* GetStaticFieldID ************************************************************
3772
3773    Returns the field ID for a static field of a class. The field is
3774    specified by its name and signature. The GetStatic<type>Field and
3775    SetStatic<type>Field families of accessor functions use field IDs
3776    to retrieve static fields.
3777
3778 *******************************************************************************/
3779
3780 jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
3781                                                                   const char *sig)
3782 {
3783         classinfo *c;
3784         fieldinfo *f;
3785         utf       *uname;
3786         utf       *usig;
3787
3788         STATISTICS(jniinvokation());
3789
3790         c = (classinfo *) clazz;
3791
3792         uname = utf_new_char((char *) name);
3793         usig  = utf_new_char((char *) sig);
3794
3795         f = class_findfield(clazz, uname, usig);
3796         
3797         if (f == NULL)
3798                 exceptions_throw_nosuchfielderror(c, uname);
3799
3800         return (jfieldID) f;
3801 }
3802
3803
3804 /* GetStatic<type>Field ********************************************************
3805
3806    This family of accessor routines returns the value of a static
3807    field of an object.
3808
3809 *******************************************************************************/
3810
3811 jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
3812                                                                          jfieldID fieldID)
3813 {
3814         classinfo *c;
3815         fieldinfo *f;
3816
3817         STATISTICS(jniinvokation());
3818
3819         c = (classinfo *) clazz;
3820         f = (fieldinfo *) fieldID;
3821
3822         if (!(c->state & CLASS_INITIALIZED))
3823                 if (!initialize_class(c))
3824                         return NULL;
3825
3826         return _Jv_JNI_NewLocalRef(env, f->value.a);
3827 }
3828
3829
3830 jboolean _Jv_JNI_GetStaticBooleanField(JNIEnv *env, jclass clazz,
3831                                                                            jfieldID fieldID)
3832 {
3833         classinfo *c;
3834         fieldinfo *f;
3835
3836         STATISTICS(jniinvokation());
3837
3838         c = (classinfo *) clazz;
3839         f = (fieldinfo *) fieldID;
3840
3841         if (!(c->state & CLASS_INITIALIZED))
3842                 if (!initialize_class(c))
3843                         return false;
3844
3845         return f->value.i;
3846 }
3847
3848
3849 jbyte _Jv_JNI_GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3850 {
3851         classinfo *c;
3852         fieldinfo *f;
3853
3854         STATISTICS(jniinvokation());
3855
3856         c = (classinfo *) clazz;
3857         f = (fieldinfo *) fieldID;
3858
3859         if (!(c->state & CLASS_INITIALIZED))
3860                 if (!initialize_class(c))
3861                         return 0;
3862
3863         return f->value.i;
3864 }
3865
3866
3867 jchar _Jv_JNI_GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3868 {
3869         classinfo *c;
3870         fieldinfo *f;
3871
3872         STATISTICS(jniinvokation());
3873
3874         c = (classinfo *) clazz;
3875         f = (fieldinfo *) fieldID;
3876
3877         if (!(c->state & CLASS_INITIALIZED))
3878                 if (!initialize_class(c))
3879                         return 0;
3880
3881         return f->value.i;
3882 }
3883
3884
3885 jshort _Jv_JNI_GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3886 {
3887         classinfo *c;
3888         fieldinfo *f;
3889
3890         STATISTICS(jniinvokation());
3891
3892         c = (classinfo *) clazz;
3893         f = (fieldinfo *) fieldID;
3894
3895         if (!(c->state & CLASS_INITIALIZED))
3896                 if (!initialize_class(c))
3897                         return 0;
3898
3899         return f->value.i;
3900 }
3901
3902
3903 jint _Jv_JNI_GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3904 {
3905         classinfo *c;
3906         fieldinfo *f;
3907
3908         STATISTICS(jniinvokation());
3909
3910         c = (classinfo *) clazz;
3911         f = (fieldinfo *) fieldID;
3912
3913         if (!(c->state & CLASS_INITIALIZED))
3914                 if (!initialize_class(c))
3915                         return 0;
3916
3917         return f->value.i;
3918 }
3919
3920
3921 jlong _Jv_JNI_GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3922 {
3923         classinfo *c;
3924         fieldinfo *f;
3925
3926         STATISTICS(jniinvokation());
3927
3928         c = (classinfo *) clazz;
3929         f = (fieldinfo *) fieldID;
3930
3931         if (!(c->state & CLASS_INITIALIZED))
3932                 if (!initialize_class(c))
3933                         return 0;
3934
3935         return f->value.l;
3936 }
3937
3938
3939 jfloat _Jv_JNI_GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID)
3940 {
3941         classinfo *c;
3942         fieldinfo *f;
3943
3944         STATISTICS(jniinvokation());
3945
3946         c = (classinfo *) clazz;
3947         f = (fieldinfo *) fieldID;
3948
3949         if (!(c->state & CLASS_INITIALIZED))
3950                 if (!initialize_class(c))
3951                         return 0.0;
3952
3953         return f->value.f;
3954 }
3955
3956
3957 jdouble _Jv_JNI_GetStaticDoubleField(JNIEnv *env, jclass clazz,
3958                                                                          jfieldID fieldID)
3959 {
3960         classinfo *c;
3961         fieldinfo *f;
3962
3963         STATISTICS(jniinvokation());
3964
3965         c = (classinfo *) clazz;
3966         f = (fieldinfo *) fieldID;
3967
3968         if (!(c->state & CLASS_INITIALIZED))
3969                 if (!initialize_class(c))
3970                         return 0.0;
3971
3972         return f->value.d;
3973 }
3974
3975
3976 /*  SetStatic<type>Field *******************************************************
3977
3978         This family of accessor routines sets the value of a static field
3979         of an object.
3980
3981 *******************************************************************************/
3982
3983 void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
3984                                                                   jobject value)
3985 {
3986         classinfo *c;
3987         fieldinfo *f;
3988
3989         STATISTICS(jniinvokation());
3990
3991         c = (classinfo *) clazz;
3992         f = (fieldinfo *) fieldID;
3993
3994         if (!(c->state & CLASS_INITIALIZED))
3995                 if (!initialize_class(c))
3996                         return;
3997
3998         f->value.a = value;
3999 }
4000
4001
4002 void _Jv_JNI_SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4003                                                                    jboolean value)
4004 {
4005         classinfo *c;
4006         fieldinfo *f;
4007
4008         STATISTICS(jniinvokation());
4009
4010         c = (classinfo *) clazz;
4011         f = (fieldinfo *) fieldID;
4012
4013         if (!(c->state & CLASS_INITIALIZED))
4014                 if (!initialize_class(c))
4015                         return;
4016
4017         f->value.i = value;
4018 }
4019
4020
4021 void _Jv_JNI_SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4022                                                                 jbyte value)
4023 {
4024         classinfo *c;
4025         fieldinfo *f;
4026
4027         STATISTICS(jniinvokation());
4028
4029         c = (classinfo *) clazz;
4030         f = (fieldinfo *) fieldID;
4031
4032         if (!(c->state & CLASS_INITIALIZED))
4033                 if (!initialize_class(c))
4034                         return;
4035
4036         f->value.i = value;
4037 }
4038
4039
4040 void _Jv_JNI_SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4041                                                                 jchar value)
4042 {
4043         classinfo *c;
4044         fieldinfo *f;
4045
4046         STATISTICS(jniinvokation());
4047
4048         c = (classinfo *) clazz;
4049         f = (fieldinfo *) fieldID;
4050
4051         if (!(c->state & CLASS_INITIALIZED))
4052                 if (!initialize_class(c))
4053                         return;
4054
4055         f->value.i = value;
4056 }
4057
4058
4059 void _Jv_JNI_SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4060                                                                  jshort value)
4061 {
4062         classinfo *c;
4063         fieldinfo *f;
4064
4065         STATISTICS(jniinvokation());
4066
4067         c = (classinfo *) clazz;
4068         f = (fieldinfo *) fieldID;
4069
4070         if (!(c->state & CLASS_INITIALIZED))
4071                 if (!initialize_class(c))
4072                         return;
4073
4074         f->value.i = value;
4075 }
4076
4077
4078 void _Jv_JNI_SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4079                                                            jint value)
4080 {
4081         classinfo *c;
4082         fieldinfo *f;
4083
4084         STATISTICS(jniinvokation());
4085
4086         c = (classinfo *) clazz;
4087         f = (fieldinfo *) fieldID;
4088
4089         if (!(c->state & CLASS_INITIALIZED))
4090                 if (!initialize_class(c))
4091                         return;
4092
4093         f->value.i = value;
4094 }
4095
4096
4097 void _Jv_JNI_SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4098                                                                 jlong value)
4099 {
4100         classinfo *c;
4101         fieldinfo *f;
4102
4103         STATISTICS(jniinvokation());
4104
4105         c = (classinfo *) clazz;
4106         f = (fieldinfo *) fieldID;
4107
4108         if (!(c->state & CLASS_INITIALIZED))
4109                 if (!initialize_class(c))
4110                         return;
4111
4112         f->value.l = value;
4113 }
4114
4115
4116 void _Jv_JNI_SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4117                                                                  jfloat value)
4118 {
4119         classinfo *c;
4120         fieldinfo *f;
4121
4122         STATISTICS(jniinvokation());
4123
4124         c = (classinfo *) clazz;
4125         f = (fieldinfo *) fieldID;
4126
4127         if (!(c->state & CLASS_INITIALIZED))
4128                 if (!initialize_class(c))
4129                         return;
4130
4131         f->value.f = value;
4132 }
4133
4134
4135 void _Jv_JNI_SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID,
4136                                                                   jdouble value)
4137 {
4138         classinfo *c;
4139         fieldinfo *f;
4140
4141         STATISTICS(jniinvokation());
4142
4143         c = (classinfo *) clazz;
4144         f = (fieldinfo *) fieldID;
4145
4146         if (!(c->state & CLASS_INITIALIZED))
4147                 if (!initialize_class(c))
4148                         return;
4149
4150         f->value.d = value;
4151 }
4152
4153
4154 /* String Operations **********************************************************/
4155
4156 /* NewString *******************************************************************
4157
4158    Create new java.lang.String object from an array of Unicode
4159    characters.
4160
4161 *******************************************************************************/
4162
4163 jstring _Jv_JNI_NewString(JNIEnv *env, const jchar *buf, jsize len)
4164 {
4165         java_lang_String *s;
4166         java_chararray   *a;
4167         u4                i;
4168
4169         STATISTICS(jniinvokation());
4170         
4171         s = (java_lang_String *) builtin_new(class_java_lang_String);
4172         a = builtin_newarray_char(len);
4173
4174         /* javastring or characterarray could not be created */
4175         if ((a == NULL) || (s == NULL))
4176                 return NULL;
4177
4178         /* copy text */
4179         for (i = 0; i < len; i++)
4180                 a->data[i] = buf[i];
4181
4182         s->value  = a;
4183         s->offset = 0;
4184         s->count  = len;
4185
4186         return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
4187 }
4188
4189
4190 static jchar emptyStringJ[]={0,0};
4191
4192 /* GetStringLength *************************************************************
4193
4194    Returns the length (the count of Unicode characters) of a Java
4195    string.
4196
4197 *******************************************************************************/
4198
4199 jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
4200 {
4201         return ((java_lang_String *) str)->count;
4202 }
4203
4204
4205 /********************  convertes javastring to u2-array ****************************/
4206         
4207 u2 *javastring_tou2(jstring so) 
4208 {
4209         java_lang_String *s;
4210         java_chararray   *a;
4211         u2               *stringbuffer;
4212         u4                i;
4213
4214         STATISTICS(jniinvokation());
4215         
4216         s = (java_lang_String *) so;
4217
4218         if (!s)
4219                 return NULL;
4220
4221         a = s->value;
4222
4223         if (!a)
4224                 return NULL;
4225
4226         /* allocate memory */
4227
4228         stringbuffer = MNEW(u2, s->count + 1);
4229
4230         /* copy text */
4231
4232         for (i = 0; i < s->count; i++)
4233                 stringbuffer[i] = a->data[s->offset + i];
4234         
4235         /* terminate string */
4236
4237         stringbuffer[i] = '\0';
4238
4239         return stringbuffer;
4240 }
4241
4242
4243 /* GetStringChars **************************************************************
4244
4245    Returns a pointer to the array of Unicode characters of the
4246    string. This pointer is valid until ReleaseStringChars() is called.
4247
4248 *******************************************************************************/
4249
4250 const jchar *_Jv_JNI_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
4251 {       
4252         jchar *jc;
4253
4254         STATISTICS(jniinvokation());
4255
4256         jc = javastring_tou2(str);
4257
4258         if (jc) {
4259                 if (isCopy)
4260                         *isCopy = JNI_TRUE;
4261
4262                 return jc;
4263         }
4264
4265         if (isCopy)
4266                 *isCopy = JNI_TRUE;
4267
4268         return emptyStringJ;
4269 }
4270
4271
4272 /* ReleaseStringChars **********************************************************
4273
4274    Informs the VM that the native code no longer needs access to
4275    chars. The chars argument is a pointer obtained from string using
4276    GetStringChars().
4277
4278 *******************************************************************************/
4279
4280 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
4281 {
4282         STATISTICS(jniinvokation());
4283
4284         if (chars == emptyStringJ)
4285                 return;
4286
4287         MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1);
4288 }
4289
4290
4291 /* NewStringUTF ****************************************************************
4292
4293    Constructs a new java.lang.String object from an array of UTF-8
4294    characters.
4295
4296 *******************************************************************************/
4297
4298 jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
4299 {
4300         java_lang_String *s;
4301
4302         STATISTICS(jniinvokation());
4303
4304         s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
4305
4306     return (jstring) _Jv_JNI_NewLocalRef(env, (jobject) s);
4307 }
4308
4309
4310 /****************** returns the utf8 length in bytes of a string *******************/
4311
4312 jsize _Jv_JNI_GetStringUTFLength (JNIEnv *env, jstring string)
4313 {   
4314     java_lang_String *s = (java_lang_String*) string;
4315
4316         STATISTICS(jniinvokation());
4317
4318     return (jsize) u2_utflength(s->value->data, s->count); 
4319 }
4320
4321
4322 /* GetStringUTFChars ***********************************************************
4323
4324    Returns a pointer to an array of UTF-8 characters of the
4325    string. This array is valid until it is released by
4326    ReleaseStringUTFChars().
4327
4328 *******************************************************************************/
4329
4330 const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
4331                                                                           jboolean *isCopy)
4332 {
4333         utf *u;
4334
4335         STATISTICS(jniinvokation());
4336
4337         if (string == NULL)
4338                 return "";
4339
4340         if (isCopy)
4341                 *isCopy = JNI_TRUE;
4342         
4343         u = javastring_toutf((java_objectheader *) string, false);
4344
4345         if (u != NULL)
4346                 return u->text;
4347
4348         return "";
4349 }
4350
4351
4352 /* ReleaseStringUTFChars *******************************************************
4353
4354    Informs the VM that the native code no longer needs access to
4355    utf. The utf argument is a pointer derived from string using
4356    GetStringUTFChars().
4357
4358 *******************************************************************************/
4359
4360 void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
4361 {
4362         STATISTICS(jniinvokation());
4363
4364     /* XXX we don't release utf chars right now, perhaps that should be done 
4365            later. Since there is always one reference the garbage collector will
4366            never get them */
4367 }
4368
4369
4370 /* Array Operations ***********************************************************/
4371
4372 /* GetArrayLength **************************************************************
4373
4374    Returns the number of elements in the array.
4375
4376 *******************************************************************************/
4377
4378 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
4379 {
4380         java_arrayheader *a;
4381
4382         STATISTICS(jniinvokation());
4383
4384         a = (java_arrayheader *) array;
4385
4386         return a->size;
4387 }
4388
4389
4390 /* NewObjectArray **************************************************************
4391
4392    Constructs a new array holding objects in class elementClass. All
4393    elements are initially set to initialElement.
4394
4395 *******************************************************************************/
4396
4397 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
4398                                                                         jclass elementClass, jobject initialElement)
4399 {
4400         java_objectarray *oa;
4401         s4                i;
4402
4403         STATISTICS(jniinvokation());
4404
4405         if (length < 0) {
4406                 exceptions_throw_negativearraysizeexception();
4407                 return NULL;
4408         }
4409
4410     oa = builtin_anewarray(length, elementClass);
4411
4412         if (oa == NULL)
4413                 return NULL;
4414
4415         /* set all elements to initialElement */
4416
4417         for (i = 0; i < length; i++)
4418                 oa->data[i] = initialElement;
4419
4420         return (jobjectArray) _Jv_JNI_NewLocalRef(env, (jobject) oa);
4421 }
4422
4423
4424 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
4425                                                                           jsize index)
4426 {
4427         java_objectarray *oa;
4428         jobject           o;
4429
4430         STATISTICS(jniinvokation());
4431
4432         oa = (java_objectarray *) array;
4433
4434         if (index >= oa->header.size) {
4435                 exceptions_throw_arrayindexoutofboundsexception();
4436                 return NULL;
4437         }
4438
4439         o = oa->data[index];
4440
4441         return _Jv_JNI_NewLocalRef(env, o);
4442 }
4443
4444
4445 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
4446                                                                    jsize index, jobject val)
4447 {
4448         java_objectarray  *oa;
4449         java_objectheader *o;
4450
4451         STATISTICS(jniinvokation());
4452
4453         oa = (java_objectarray *) array;
4454         o  = (java_objectheader *) val;
4455
4456         if (index >= oa->header.size) {
4457                 exceptions_throw_arrayindexoutofboundsexception();
4458                 return;
4459         }
4460
4461         /* check if the class of value is a subclass of the element class
4462            of the array */
4463
4464         if (!builtin_canstore(oa, o))
4465                 return;
4466
4467         oa->data[index] = val;
4468 }
4469
4470
4471 jbooleanArray _Jv_JNI_NewBooleanArray(JNIEnv *env, jsize len)
4472 {
4473         java_booleanarray *ba;
4474
4475         STATISTICS(jniinvokation());
4476
4477         if (len < 0) {
4478                 exceptions_throw_negativearraysizeexception();
4479                 return NULL;
4480         }
4481
4482         ba = builtin_newarray_boolean(len);
4483
4484         return (jbooleanArray) _Jv_JNI_NewLocalRef(env, (jobject) ba);
4485 }
4486
4487
4488 jbyteArray _Jv_JNI_NewByteArray(JNIEnv *env, jsize len)
4489 {
4490         java_bytearray *ba;
4491
4492         STATISTICS(jniinvokation());
4493
4494         if (len < 0) {
4495                 exceptions_throw_negativearraysizeexception();
4496                 return NULL;
4497         }
4498
4499         ba = builtin_newarray_byte(len);
4500
4501         return (jbyteArray) _Jv_JNI_NewLocalRef(env, (jobject) ba);
4502 }
4503
4504
4505 jcharArray _Jv_JNI_NewCharArray(JNIEnv *env, jsize len)
4506 {
4507         java_chararray *ca;
4508
4509         STATISTICS(jniinvokation());
4510
4511         if (len < 0) {
4512                 exceptions_throw_negativearraysizeexception();
4513                 return NULL;
4514         }
4515
4516         ca = builtin_newarray_char(len);
4517
4518         return (jcharArray) _Jv_JNI_NewLocalRef(env, (jobject) ca);
4519 }
4520
4521
4522 jshortArray _Jv_JNI_NewShortArray(JNIEnv *env, jsize len)
4523 {
4524         java_shortarray *sa;
4525
4526         STATISTICS(jniinvokation());
4527
4528         if (len < 0) {
4529                 exceptions_throw_negativearraysizeexception();
4530                 return NULL;
4531         }
4532
4533         sa = builtin_newarray_short(len);
4534
4535         return (jshortArray) _Jv_JNI_NewLocalRef(env, (jobject) sa);
4536 }
4537
4538
4539 jintArray _Jv_JNI_NewIntArray(JNIEnv *env, jsize len)
4540 {
4541         java_intarray *ia;
4542
4543         STATISTICS(jniinvokation());
4544
4545         if (len < 0) {
4546                 exceptions_throw_negativearraysizeexception();
4547                 return NULL;
4548         }
4549
4550         ia = builtin_newarray_int(len);
4551
4552         return (jintArray) _Jv_JNI_NewLocalRef(env, (jobject) ia);
4553 }
4554
4555
4556 jlongArray _Jv_JNI_NewLongArray(JNIEnv *env, jsize len)
4557 {
4558         java_longarray *la;
4559
4560         STATISTICS(jniinvokation());
4561
4562         if (len < 0) {
4563                 exceptions_throw_negativearraysizeexception();
4564                 return NULL;
4565         }
4566
4567         la = builtin_newarray_long(len);
4568
4569         return (jlongArray) _Jv_JNI_NewLocalRef(env, (jobject) la);
4570 }
4571
4572
4573 jfloatArray _Jv_JNI_NewFloatArray(JNIEnv *env, jsize len)
4574 {
4575         java_floatarray *fa;
4576
4577         STATISTICS(jniinvokation());
4578
4579         if (len < 0) {
4580                 exceptions_throw_negativearraysizeexception();
4581                 return NULL;
4582         }
4583
4584         fa = builtin_newarray_float(len);
4585
4586         return (jfloatArray) _Jv_JNI_NewLocalRef(env, (jobject) fa);
4587 }
4588
4589
4590 jdoubleArray _Jv_JNI_NewDoubleArray(JNIEnv *env, jsize len)
4591 {
4592         java_doublearray *da;
4593
4594         STATISTICS(jniinvokation());
4595
4596         if (len < 0) {
4597                 exceptions_throw_negativearraysizeexception();
4598                 return NULL;
4599         }
4600
4601         da = builtin_newarray_double(len);
4602
4603         return (jdoubleArray) _Jv_JNI_NewLocalRef(env, (jobject) da);
4604 }
4605
4606
4607 /* Get<PrimitiveType>ArrayElements *********************************************
4608
4609    A family of functions that returns the body of the primitive array.
4610
4611 *******************************************************************************/
4612
4613 jboolean *_Jv_JNI_GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
4614                                                                                   jboolean *isCopy)
4615 {
4616         java_booleanarray *ba;
4617
4618         STATISTICS(jniinvokation());
4619
4620         ba = (java_booleanarray *) array;
4621
4622         if (isCopy)
4623                 *isCopy = JNI_FALSE;
4624
4625         return ba->data;
4626 }
4627
4628
4629 jbyte *_Jv_JNI_GetByteArrayElements(JNIEnv *env, jbyteArray array,
4630                                                                         jboolean *isCopy)
4631 {
4632         java_bytearray *ba;
4633
4634         STATISTICS(jniinvokation());
4635
4636         ba = (java_bytearray *) array;
4637
4638         if (isCopy)
4639                 *isCopy = JNI_FALSE;
4640
4641         return ba->data;
4642 }
4643
4644
4645 jchar *_Jv_JNI_GetCharArrayElements(JNIEnv *env, jcharArray array,
4646                                                                         jboolean *isCopy)
4647 {
4648         java_chararray *ca;
4649
4650         STATISTICS(jniinvokation());
4651
4652         ca = (java_chararray *) array;
4653
4654         if (isCopy)
4655                 *isCopy = JNI_FALSE;
4656
4657         return ca->data;
4658 }
4659
4660
4661 jshort *_Jv_JNI_GetShortArrayElements(JNIEnv *env, jshortArray array,
4662                                                                           jboolean *isCopy)
4663 {
4664         java_shortarray *sa;
4665
4666         STATISTICS(jniinvokation());
4667
4668         sa = (java_shortarray *) array;
4669
4670         if (isCopy)
4671                 *isCopy = JNI_FALSE;
4672
4673         return sa->data;
4674 }
4675
4676
4677 jint *_Jv_JNI_GetIntArrayElements(JNIEnv *env, jintArray array,
4678                                                                   jboolean *isCopy)
4679 {
4680         java_intarray *ia;
4681
4682         STATISTICS(jniinvokation());
4683
4684         ia = (java_intarray *) array;
4685
4686         if (isCopy)
4687                 *isCopy = JNI_FALSE;
4688
4689         return ia->data;
4690 }
4691
4692
4693 jlong *_Jv_JNI_GetLongArrayElements(JNIEnv *env, jlongArray array,
4694                                                                         jboolean *isCopy)
4695 {
4696         java_longarray *la;
4697
4698         STATISTICS(jniinvokation());
4699
4700         la = (java_longarray *) array;
4701
4702         if (isCopy)
4703                 *isCopy = JNI_FALSE;
4704
4705         /* We cast this one to prevent a compiler warning on 64-bit
4706            systems since GNU Classpath typedef jlong to long long. */
4707
4708         return (jlong *) la->data;
4709 }
4710
4711
4712 jfloat *_Jv_JNI_GetFloatArrayElements(JNIEnv *env, jfloatArray array,
4713                                                                           jboolean *isCopy)
4714 {
4715         java_floatarray *fa;
4716
4717         STATISTICS(jniinvokation());
4718
4719         fa = (java_floatarray *) array;
4720
4721         if (isCopy)
4722                 *isCopy = JNI_FALSE;
4723
4724         return fa->data;
4725 }
4726
4727
4728 jdouble *_Jv_JNI_GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
4729                                                                                 jboolean *isCopy)
4730 {
4731         java_doublearray *da;
4732
4733         STATISTICS(jniinvokation());
4734
4735         da = (java_doublearray *) array;
4736
4737         if (isCopy)
4738                 *isCopy = JNI_FALSE;
4739
4740         return da->data;
4741 }
4742
4743
4744 /* Release<PrimitiveType>ArrayElements *****************************************
4745
4746    A family of functions that informs the VM that the native code no
4747    longer needs access to elems. The elems argument is a pointer
4748    derived from array using the corresponding
4749    Get<PrimitiveType>ArrayElements() function. If necessary, this
4750    function copies back all changes made to elems to the original
4751    array.
4752
4753 *******************************************************************************/
4754
4755 void _Jv_JNI_ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
4756                                                                                  jboolean *elems, jint mode)
4757 {
4758         java_booleanarray *ba;
4759
4760         STATISTICS(jniinvokation());
4761
4762         ba = (java_booleanarray *) array;
4763
4764         if (elems != ba->data) {
4765                 switch (mode) {
4766                 case JNI_COMMIT:
4767                         MCOPY(ba->data, elems, u1, ba->header.size);
4768                         break;
4769                 case 0:
4770                         MCOPY(ba->data, elems, u1, ba->header.size);
4771                         /* XXX TWISTI how should it be freed? */
4772                         break;
4773                 case JNI_ABORT:
4774                         /* XXX TWISTI how should it be freed? */
4775                         break;
4776                 }
4777         }
4778 }
4779
4780
4781 void _Jv_JNI_ReleaseByteArrayElements(JNIEnv *env, jbyteArray array,
4782                                                                           jbyte *elems, jint mode)
4783 {
4784         java_bytearray *ba;
4785
4786         STATISTICS(jniinvokation());
4787
4788         ba = (java_bytearray *) array;
4789
4790         if (elems != ba->data) {
4791                 switch (mode) {
4792                 case JNI_COMMIT:
4793                         MCOPY(ba->data, elems, s1, ba->header.size);
4794                         break;
4795                 case 0:
4796                         MCOPY(ba->data, elems, s1, ba->header.size);
4797                         /* XXX TWISTI how should it be freed? */
4798                         break;
4799                 case JNI_ABORT:
4800                         /* XXX TWISTI how should it be freed? */
4801                         break;
4802                 }
4803         }
4804 }
4805
4806
4807 void _Jv_JNI_ReleaseCharArrayElements(JNIEnv *env, jcharArray array,
4808                                                                           jchar *elems, jint mode)
4809 {
4810         java_chararray *ca;
4811
4812         STATISTICS(jniinvokation());
4813
4814         ca = (java_chararray *) array;
4815
4816         if (elems != ca->data) {
4817                 switch (mode) {
4818                 case JNI_COMMIT:
4819                         MCOPY(ca->data, elems, u2, ca->header.size);
4820                         break;
4821                 case 0:
4822                         MCOPY(ca->data, elems, u2, ca->header.size);
4823                         /* XXX TWISTI how should it be freed? */
4824                         break;
4825                 case JNI_ABORT:
4826                         /* XXX TWISTI how should it be freed? */
4827                         break;
4828                 }
4829         }
4830 }
4831
4832
4833 void _Jv_JNI_ReleaseShortArrayElements(JNIEnv *env, jshortArray array,
4834                                                                            jshort *elems, jint mode)
4835 {
4836         java_shortarray *sa;
4837
4838         STATISTICS(jniinvokation());
4839
4840         sa = (java_shortarray *) array;
4841
4842         if (elems != sa->data) {
4843                 switch (mode) {
4844                 case JNI_COMMIT:
4845                         MCOPY(sa->data, elems, s2, sa->header.size);
4846                         break;
4847                 case 0:
4848                         MCOPY(sa->data, elems, s2, sa->header.size);
4849                         /* XXX TWISTI how should it be freed? */
4850                         break;
4851                 case JNI_ABORT:
4852                         /* XXX TWISTI how should it be freed? */
4853                         break;
4854                 }
4855         }
4856 }
4857
4858
4859 void _Jv_JNI_ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
4860                                                                          jint mode)
4861 {
4862         java_intarray *ia;
4863
4864         STATISTICS(jniinvokation());
4865
4866         ia = (java_intarray *) array;
4867
4868         if (elems != ia->data) {
4869                 switch (mode) {
4870                 case JNI_COMMIT:
4871                         MCOPY(ia->data, elems, s4, ia->header.size);
4872                         break;
4873                 case 0:
4874                         MCOPY(ia->data, elems, s4, ia->header.size);
4875                         /* XXX TWISTI how should it be freed? */
4876                         break;
4877                 case JNI_ABORT:
4878                         /* XXX TWISTI how should it be freed? */
4879                         break;
4880                 }
4881         }
4882 }
4883
4884
4885 void _Jv_JNI_ReleaseLongArrayElements(JNIEnv *env, jlongArray array,
4886                                                                           jlong *elems, jint mode)
4887 {
4888         java_longarray *la;
4889
4890         STATISTICS(jniinvokation());
4891
4892         la = (java_longarray *) array;
4893
4894         /* We cast this one to prevent a compiler warning on 64-bit
4895            systems since GNU Classpath typedef jlong to long long. */
4896
4897         if ((s8 *) elems != la->data) {
4898                 switch (mode) {
4899                 case JNI_COMMIT:
4900                         MCOPY(la->data, elems, s8, la->header.size);
4901                         break;
4902                 case 0:
4903                         MCOPY(la->data, elems, s8, la->header.size);
4904                         /* XXX TWISTI how should it be freed? */
4905                         break;
4906                 case JNI_ABORT:
4907                         /* XXX TWISTI how should it be freed? */
4908                         break;
4909                 }
4910         }
4911 }
4912
4913
4914 void _Jv_JNI_ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array,
4915                                                                            jfloat *elems, jint mode)
4916 {
4917         java_floatarray *fa;
4918
4919         STATISTICS(jniinvokation());
4920
4921         fa = (java_floatarray *) array;
4922
4923         if (elems != fa->data) {
4924                 switch (mode) {
4925                 case JNI_COMMIT:
4926                         MCOPY(fa->data, elems, float, fa->header.size);
4927                         break;
4928                 case 0:
4929                         MCOPY(fa->data, elems, float, fa->header.size);
4930                         /* XXX TWISTI how should it be freed? */
4931                         break;
4932                 case JNI_ABORT:
4933                         /* XXX TWISTI how should it be freed? */
4934                         break;
4935                 }
4936         }
4937 }
4938
4939
4940 void _Jv_JNI_ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
4941                                                                                 jdouble *elems, jint mode)
4942 {
4943         java_doublearray *da;
4944
4945         STATISTICS(jniinvokation());
4946
4947         da = (java_doublearray *) array;
4948
4949         if (elems != da->data) {
4950                 switch (mode) {
4951                 case JNI_COMMIT:
4952                         MCOPY(da->data, elems, double, da->header.size);
4953                         break;
4954                 case 0:
4955                         MCOPY(da->data, elems, double, da->header.size);
4956                         /* XXX TWISTI how should it be freed? */
4957                         break;
4958                 case JNI_ABORT:
4959                         /* XXX TWISTI how should it be freed? */
4960                         break;
4961                 }
4962         }
4963 }
4964
4965
4966 /*  Get<PrimitiveType>ArrayRegion **********************************************
4967
4968         A family of functions that copies a region of a primitive array
4969         into a buffer.
4970
4971 *******************************************************************************/
4972
4973 void _Jv_JNI_GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array,
4974                                                                    jsize start, jsize len, jboolean *buf)
4975 {
4976         java_booleanarray *ba;
4977
4978         STATISTICS(jniinvokation());
4979
4980         ba = (java_booleanarray *) array;
4981
4982     if ((start < 0) || (len < 0) || (start + len > ba->header.size))
4983                 exceptions_throw_arrayindexoutofboundsexception();
4984     else
4985                 MCOPY(buf, &ba->data[start], u1, len);
4986 }
4987
4988
4989 void _Jv_JNI_GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start,
4990                                                                 jsize len, jbyte *buf)
4991 {
4992         java_bytearray *ba;
4993
4994         STATISTICS(jniinvokation());
4995
4996         ba = (java_bytearray *) array;
4997
4998         if ((start < 0) || (len < 0) || (start + len > ba->header.size))
4999                 exceptions_throw_arrayindexoutofboundsexception();
5000         else
5001                 MCOPY(buf, &ba->data[start], s1, len);
5002 }
5003
5004
5005 void _Jv_JNI_GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start,
5006                                                                 jsize len, jchar *buf)
5007 {
5008         java_chararray *ca;
5009
5010         STATISTICS(jniinvokation());
5011
5012         ca = (java_chararray *) array;
5013
5014         if ((start < 0) || (len < 0) || (start + len > ca->header.size))
5015                 exceptions_throw_arrayindexoutofboundsexception();
5016         else
5017                 MCOPY(buf, &ca->data[start], u2, len);
5018 }
5019
5020
5021 void _Jv_JNI_GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
5022                                                                  jsize len, jshort *buf)
5023 {
5024         java_shortarray *sa;
5025
5026         STATISTICS(jniinvokation());
5027
5028         sa = (java_shortarray *) array;
5029
5030         if ((start < 0) || (len < 0) || (start + len > sa->header.size))
5031                 exceptions_throw_arrayindexoutofboundsexception();
5032         else    
5033                 MCOPY(buf, &sa->data[start], s2, len);
5034 }
5035
5036
5037 void _Jv_JNI_GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start,
5038                                                            jsize len, jint *buf)
5039 {
5040         java_intarray *ia;
5041
5042         STATISTICS(jniinvokation());
5043
5044         ia = (java_intarray *) array;
5045
5046         if ((start < 0) || (len < 0) || (start + len > ia->header.size))
5047                 exceptions_throw_arrayindexoutofboundsexception();
5048         else
5049                 MCOPY(buf, &ia->data[start], s4, len);
5050 }
5051
5052
5053 void _Jv_JNI_GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start,
5054                                                                 jsize len, jlong *buf)
5055 {
5056         java_longarray *la;
5057
5058         STATISTICS(jniinvokation());
5059
5060         la = (java_longarray *) array;
5061
5062         if ((start < 0) || (len < 0) || (start + len > la->header.size))
5063                 exceptions_throw_arrayindexoutofboundsexception();
5064         else
5065                 MCOPY(buf, &la->data[start], s8, len);
5066 }
5067
5068
5069 void _Jv_JNI_GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
5070                                                                  jsize len, jfloat *buf)
5071 {
5072         java_floatarray *fa;
5073
5074         STATISTICS(jniinvokation());
5075
5076         fa = (java_floatarray *) array;
5077
5078         if ((start < 0) || (len < 0) || (start + len > fa->header.size))
5079                 exceptions_throw_arrayindexoutofboundsexception();
5080         else
5081                 MCOPY(buf, &fa->data[start], float, len);
5082 }
5083
5084
5085 void _Jv_JNI_GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
5086                                                                   jsize len, jdouble *buf)
5087 {
5088         java_doublearray *da;
5089
5090         STATISTICS(jniinvokation());
5091
5092         da = (java_doublearray *) array;
5093
5094         if ((start < 0) || (len < 0) || (start + len > da->header.size))
5095                 exceptions_throw_arrayindexoutofboundsexception();
5096         else
5097                 MCOPY(buf, &da->data[start], double, len);
5098 }
5099
5100
5101 /*  Set<PrimitiveType>ArrayRegion **********************************************
5102
5103         A family of functions that copies back a region of a primitive
5104         array from a buffer.
5105
5106 *******************************************************************************/
5107
5108 void _Jv_JNI_SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array,
5109                                                                    jsize start, jsize len, jboolean *buf)
5110 {
5111         java_booleanarray *ba;
5112
5113         STATISTICS(jniinvokation());
5114
5115         ba = (java_booleanarray *) array;
5116
5117         if ((start < 0) || (len < 0) || (start + len > ba->header.size))
5118                 exceptions_throw_arrayindexoutofboundsexception();
5119         else
5120                 MCOPY(&ba->data[start], buf, u1, len);
5121 }
5122
5123
5124 void _Jv_JNI_SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start,
5125                                                                 jsize len, jbyte *buf)
5126 {
5127         java_bytearray *ba;
5128
5129         STATISTICS(jniinvokation());
5130
5131         ba = (java_bytearray *) array;
5132
5133         if ((start < 0) || (len < 0) || (start + len > ba->header.size))
5134                 exceptions_throw_arrayindexoutofboundsexception();
5135         else
5136                 MCOPY(&ba->data[start], buf, s1, len);
5137 }
5138
5139
5140 void _Jv_JNI_SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start,
5141                                                                 jsize len, jchar *buf)
5142 {
5143         java_chararray *ca;
5144
5145         STATISTICS(jniinvokation());
5146
5147         ca = (java_chararray *) array;
5148
5149         if ((start < 0) || (len < 0) || (start + len > ca->header.size))
5150                 exceptions_throw_arrayindexoutofboundsexception();
5151         else
5152                 MCOPY(&ca->data[start], buf, u2, len);
5153 }
5154
5155
5156 void _Jv_JNI_SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
5157                                                                  jsize len, jshort *buf)
5158 {
5159         java_shortarray *sa;
5160
5161         STATISTICS(jniinvokation());
5162
5163         sa = (java_shortarray *) array;
5164
5165         if ((start < 0) || (len < 0) || (start + len > sa->header.size))
5166                 exceptions_throw_arrayindexoutofboundsexception();
5167         else
5168                 MCOPY(&sa->data[start], buf, s2, len);
5169 }
5170
5171
5172 void _Jv_JNI_SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start,
5173                                                            jsize len, jint *buf)
5174 {
5175         java_intarray *ia;
5176
5177         STATISTICS(jniinvokation());
5178
5179         ia = (java_intarray *) array;
5180
5181         if ((start < 0) || (len < 0) || (start + len > ia->header.size))
5182                 exceptions_throw_arrayindexoutofboundsexception();
5183         else
5184                 MCOPY(&ia->data[start], buf, s4, len);
5185 }
5186
5187
5188 void _Jv_JNI_SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start,
5189                                                                 jsize len, jlong *buf)
5190 {
5191         java_longarray *la;
5192
5193         STATISTICS(jniinvokation());
5194
5195         la = (java_longarray *) array;
5196
5197         if ((start < 0) || (len < 0) || (start + len > la->header.size))
5198                 exceptions_throw_arrayindexoutofboundsexception();
5199         else
5200                 MCOPY(&la->data[start], buf, s8, len);
5201 }
5202
5203
5204 void _Jv_JNI_SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
5205                                                                  jsize len, jfloat *buf)
5206 {
5207         java_floatarray *fa;
5208
5209         STATISTICS(jniinvokation());
5210
5211         fa = (java_floatarray *) array;
5212
5213         if ((start < 0) || (len < 0) || (start + len > fa->header.size))
5214                 exceptions_throw_arrayindexoutofboundsexception();
5215         else
5216                 MCOPY(&fa->data[start], buf, float, len);
5217 }
5218
5219
5220 void _Jv_JNI_SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
5221                                                                   jsize len, jdouble *buf)
5222 {
5223         java_doublearray *da;
5224
5225         STATISTICS(jniinvokation());
5226
5227         da = (java_doublearray *) array;
5228
5229         if ((start < 0) || (len < 0) || (start + len > da->header.size))
5230                 exceptions_throw_arrayindexoutofboundsexception();
5231         else
5232                 MCOPY(&da->data[start], buf, double, len);
5233 }
5234
5235
5236 /* Registering Native Methods *************************************************/
5237
5238 /* RegisterNatives *************************************************************
5239
5240    Registers native methods with the class specified by the clazz
5241    argument. The methods parameter specifies an array of
5242    JNINativeMethod structures that contain the names, signatures, and
5243    function pointers of the native methods. The nMethods parameter
5244    specifies the number of native methods in the array.
5245
5246 *******************************************************************************/
5247
5248 jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
5249                                                          const JNINativeMethod *methods, jint nMethods)
5250 {
5251         STATISTICS(jniinvokation());
5252
5253     log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!");
5254         /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
5255         if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
5256         */
5257
5258     return 0;
5259 }
5260
5261
5262 /* UnregisterNatives ***********************************************************
5263
5264    Unregisters native methods of a class. The class goes back to the
5265    state before it was linked or registered with its native method
5266    functions.
5267
5268    This function should not be used in normal native code. Instead, it
5269    provides special programs a way to reload and relink native
5270    libraries.
5271
5272 *******************************************************************************/
5273
5274 jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
5275 {
5276         STATISTICS(jniinvokation());
5277
5278         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
5279
5280     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
5281
5282     return 0;
5283 }
5284
5285
5286 /* Monitor Operations *********************************************************/
5287
5288 /* MonitorEnter ****************************************************************
5289
5290    Enters the monitor associated with the underlying Java object
5291    referred to by obj.
5292
5293 *******************************************************************************/
5294
5295 jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
5296 {
5297         STATISTICS(jniinvokation());
5298
5299         if (obj == NULL) {
5300                 exceptions_throw_nullpointerexception();
5301                 return JNI_ERR;
5302         }
5303
5304         LOCK_MONITOR_ENTER(obj);
5305
5306         return JNI_OK;
5307 }
5308
5309
5310 /* MonitorExit *****************************************************************
5311
5312    The current thread must be the owner of the monitor associated with
5313    the underlying Java object referred to by obj. The thread
5314    decrements the counter indicating the number of times it has
5315    entered this monitor. If the value of the counter becomes zero, the
5316    current thread releases the monitor.
5317
5318 *******************************************************************************/
5319
5320 jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
5321 {
5322         STATISTICS(jniinvokation());
5323
5324         if (obj == NULL) {
5325                 exceptions_throw_nullpointerexception();
5326                 return JNI_ERR;
5327         }
5328
5329         LOCK_MONITOR_EXIT(obj);
5330
5331         return JNI_OK;
5332 }
5333
5334
5335 /* JavaVM Interface ***********************************************************/
5336
5337 /* GetJavaVM *******************************************************************
5338
5339    Returns the Java VM interface (used in the Invocation API)
5340    associated with the current thread. The result is placed at the
5341    location pointed to by the second argument, vm.
5342
5343 *******************************************************************************/
5344
5345 jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **vm)
5346 {
5347         STATISTICS(jniinvokation());
5348
5349     *vm = (JavaVM *) _Jv_jvm;
5350
5351         return 0;
5352 }
5353
5354
5355 /* GetStringRegion *************************************************************
5356
5357    Copies len number of Unicode characters beginning at offset start
5358    to the given buffer buf.
5359
5360    Throws StringIndexOutOfBoundsException on index overflow.
5361
5362 *******************************************************************************/
5363
5364 void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
5365                                                          jchar *buf)
5366 {
5367         java_lang_String *s;
5368         java_chararray   *ca;
5369
5370         STATISTICS(jniinvokation());
5371
5372         s  = (java_lang_String *) str;
5373         ca = s->value;
5374
5375         if ((start < 0) || (len < 0) || (start > s->count) ||
5376                 (start + len > s->count)) {
5377                 exceptions_throw_stringindexoutofboundsexception();
5378                 return;
5379         }
5380
5381         MCOPY(buf, &ca->data[start], u2, len);
5382 }
5383
5384
5385 void _Jv_JNI_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
5386                                                                 jsize len, char *buf)
5387 {
5388         STATISTICS(jniinvokation());
5389
5390         log_text("JNI-Call: GetStringUTFRegion: IMPLEMENT ME!");
5391 }
5392
5393
5394 /* GetPrimitiveArrayCritical ***************************************************
5395
5396    Obtain a direct pointer to array elements.
5397
5398 *******************************************************************************/
5399
5400 void *_Jv_JNI_GetPrimitiveArrayCritical(JNIEnv *env, jarray array,
5401                                                                                 jboolean *isCopy)
5402 {
5403         java_bytearray *ba;
5404         jbyte          *bp;
5405
5406         ba = (java_bytearray *) array;
5407
5408         /* do the same as Kaffe does */
5409
5410         bp = _Jv_JNI_GetByteArrayElements(env, ba, isCopy);
5411
5412         return (void *) bp;
5413 }
5414
5415
5416 /* ReleasePrimitiveArrayCritical ***********************************************
5417
5418    No specific documentation.
5419
5420 *******************************************************************************/
5421
5422 void _Jv_JNI_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array,
5423                                                                                    void *carray, jint mode)
5424 {
5425         STATISTICS(jniinvokation());
5426
5427         /* do the same as Kaffe does */
5428
5429         _Jv_JNI_ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray,
5430                                                                          mode);
5431 }
5432
5433
5434 /* GetStringCritical ***********************************************************
5435
5436    The semantics of these two functions are similar to the existing
5437    Get/ReleaseStringChars functions.
5438
5439 *******************************************************************************/
5440
5441 const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
5442                                                                            jboolean *isCopy)
5443 {
5444         STATISTICS(jniinvokation());
5445
5446         return _Jv_JNI_GetStringChars(env, string, isCopy);
5447 }
5448
5449
5450 void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
5451                                                                    const jchar *cstring)
5452 {
5453         STATISTICS(jniinvokation());
5454
5455         _Jv_JNI_ReleaseStringChars(env, string, cstring);
5456 }
5457
5458
5459 jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
5460 {
5461         STATISTICS(jniinvokation());
5462
5463         log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!");
5464
5465         return obj;
5466 }
5467
5468
5469 void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
5470 {
5471         STATISTICS(jniinvokation());
5472
5473         log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME");
5474 }
5475
5476
5477 /* NewGlobalRef ****************************************************************
5478
5479    Creates a new global reference to the object referred to by the obj
5480    argument.
5481
5482 *******************************************************************************/
5483     
5484 jobject _Jv_JNI_NewGlobalRef(JNIEnv* env, jobject obj)
5485 {
5486         hashtable_global_ref_entry *gre;
5487         u4   key;                           /* hashkey                            */
5488         u4   slot;                          /* slot in hashtable                  */
5489
5490         STATISTICS(jniinvokation());
5491
5492         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
5493
5494         /* normally addresses are aligned to 4, 8 or 16 bytes */
5495
5496         key  = ((u4) (ptrint) obj) >> 4;           /* align to 16-byte boundaries */
5497         slot = key & (hashtable_global_ref->size - 1);
5498         gre  = hashtable_global_ref->ptr[slot];
5499         
5500         /* search external hash chain for the entry */
5501
5502         while (gre) {
5503                 if (gre->o == obj) {
5504                         /* global object found, increment the reference */
5505
5506                         gre->refs++;
5507
5508                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
5509
5510                         return obj;
5511                 }
5512
5513                 gre = gre->hashlink;                /* next element in external chain */
5514         }
5515
5516         /* global ref not found, create a new one */
5517
5518         gre = NEW(hashtable_global_ref_entry);
5519
5520         gre->o    = obj;
5521         gre->refs = 1;
5522
5523         /* insert entry into hashtable */
5524
5525         gre->hashlink = hashtable_global_ref->ptr[slot];
5526
5527         hashtable_global_ref->ptr[slot] = gre;
5528
5529         /* update number of hashtable-entries */
5530
5531         hashtable_global_ref->entries++;
5532
5533         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
5534
5535         return obj;
5536 }
5537
5538
5539 /* DeleteGlobalRef *************************************************************
5540
5541    Deletes the global reference pointed to by globalRef.
5542
5543 *******************************************************************************/
5544
5545 void _Jv_JNI_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
5546 {
5547         hashtable_global_ref_entry *gre;
5548         hashtable_global_ref_entry *prevgre;
5549         u4   key;                           /* hashkey                            */
5550         u4   slot;                          /* slot in hashtable                  */
5551
5552         STATISTICS(jniinvokation());
5553
5554         LOCK_MONITOR_ENTER(hashtable_global_ref->header);
5555
5556         /* normally addresses are aligned to 4, 8 or 16 bytes */
5557
5558         key  = ((u4) (ptrint) globalRef) >> 4;     /* align to 16-byte boundaries */
5559         slot = key & (hashtable_global_ref->size - 1);
5560         gre  = hashtable_global_ref->ptr[slot];
5561
5562         /* initialize prevgre */
5563
5564         prevgre = NULL;
5565
5566         /* search external hash chain for the entry */
5567
5568         while (gre) {
5569                 if (gre->o == globalRef) {
5570                         /* global object found, decrement the reference count */
5571
5572                         gre->refs--;
5573
5574                         /* if reference count is 0, remove the entry */
5575
5576                         if (gre->refs == 0) {
5577                                 /* special handling if it's the first in the chain */
5578
5579                                 if (prevgre == NULL)
5580                                         hashtable_global_ref->ptr[slot] = gre->hashlink;
5581                                 else
5582                                         prevgre->hashlink = gre->hashlink;
5583
5584                                 FREE(gre, hashtable_global_ref_entry);
5585                         }
5586
5587                         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
5588
5589                         return;
5590                 }
5591
5592                 prevgre = gre;                    /* save current pointer for removal */
5593                 gre     = gre->hashlink;            /* next element in external chain */
5594         }
5595
5596         log_println("JNI-DeleteGlobalRef: global reference not found");
5597
5598         LOCK_MONITOR_EXIT(hashtable_global_ref->header);
5599 }
5600
5601
5602 /* ExceptionCheck **************************************************************
5603
5604    Returns JNI_TRUE when there is a pending exception; otherwise,
5605    returns JNI_FALSE.
5606
5607 *******************************************************************************/
5608
5609 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
5610 {
5611         java_objectheader *o;
5612
5613         STATISTICS(jniinvokation());
5614
5615         o = exceptions_get_exception();
5616
5617         return (o != NULL) ? JNI_TRUE : JNI_FALSE;
5618 }
5619
5620
5621 /* New JNI 1.4 functions ******************************************************/
5622
5623 /* NewDirectByteBuffer *********************************************************
5624
5625    Allocates and returns a direct java.nio.ByteBuffer referring to the
5626    block of memory starting at the memory address address and
5627    extending capacity bytes.
5628
5629 *******************************************************************************/
5630
5631 jobject _Jv_JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
5632 {
5633 #if defined(ENABLE_JAVASE)
5634         java_objectheader       *nbuf;
5635 # if SIZEOF_VOID_P == 8
5636         gnu_classpath_Pointer64 *paddress;
5637 # else
5638         gnu_classpath_Pointer32 *paddress;
5639 # endif
5640
5641         STATISTICS(jniinvokation());
5642
5643         /* alocate a gnu.classpath.Pointer{32,64} object */
5644
5645 # if SIZEOF_VOID_P == 8
5646         if (!(paddress = (gnu_classpath_Pointer64 *)
5647                   builtin_new(class_gnu_classpath_Pointer64)))
5648 # else
5649         if (!(paddress = (gnu_classpath_Pointer32 *)
5650                   builtin_new(class_gnu_classpath_Pointer32)))
5651 # endif
5652                 return NULL;
5653
5654         /* fill gnu.classpath.Pointer{32,64} with address */
5655
5656         paddress->data = (ptrint) address;
5657
5658         /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
5659
5660         nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
5661                                                          (jmethodID) dbbirw_init, NULL, paddress,
5662                                                          (jint) capacity, (jint) capacity, (jint) 0);
5663
5664         /* add local reference and return the value */
5665
5666         return _Jv_JNI_NewLocalRef(env, nbuf);
5667 #else
5668         vm_abort("_Jv_JNI_NewDirectByteBuffer: not implemented in this configuration");
5669
5670         /* keep compiler happy */
5671
5672         return NULL;
5673 #endif
5674 }
5675
5676
5677 /* GetDirectBufferAddress ******************************************************
5678
5679    Fetches and returns the starting address of the memory region
5680    referenced by the given direct java.nio.Buffer.
5681
5682 *******************************************************************************/
5683
5684 void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
5685 {
5686 #if defined(ENABLE_JAVASE)
5687         java_nio_DirectByteBufferImpl *nbuf;
5688 # if SIZEOF_VOID_P == 8
5689         gnu_classpath_Pointer64       *address;
5690 # else
5691         gnu_classpath_Pointer32       *address;
5692 # endif
5693
5694         STATISTICS(jniinvokation());
5695
5696         if (!builtin_instanceof(buf, class_java_nio_Buffer))
5697                 return NULL;
5698
5699         nbuf = (java_nio_DirectByteBufferImpl *) buf;
5700
5701 # if SIZEOF_VOID_P == 8
5702         address = (gnu_classpath_Pointer64 *) nbuf->address;
5703 # else
5704         address = (gnu_classpath_Pointer32 *) nbuf->address;
5705 # endif
5706
5707         if (address == NULL)
5708                 return NULL;
5709
5710         return (void *) address->data;
5711 #else
5712         vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
5713
5714         /* keep compiler happy */
5715
5716         return NULL;
5717 #endif
5718 }
5719
5720
5721 /* GetDirectBufferCapacity *****************************************************
5722
5723    Fetches and returns the capacity in bytes of the memory region
5724    referenced by the given direct java.nio.Buffer.
5725
5726 *******************************************************************************/
5727
5728 jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
5729 {
5730 #if defined(ENABLE_JAVASE)
5731         java_nio_Buffer *nbuf;
5732
5733         STATISTICS(jniinvokation());
5734
5735         if (!builtin_instanceof(buf, class_java_nio_DirectByteBufferImpl))
5736                 return -1;
5737
5738         nbuf = (java_nio_Buffer *) buf;
5739
5740         return (jlong) nbuf->cap;
5741 #else
5742         vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
5743
5744         /* keep compiler happy */
5745
5746         return 0;
5747 #endif
5748 }
5749
5750
5751 /* DestroyJavaVM ***************************************************************
5752
5753    Unloads a Java VM and reclaims its resources. Only the main thread
5754    can unload the VM. The system waits until the main thread is only
5755    remaining user thread before it destroys the VM.
5756
5757 *******************************************************************************/
5758
5759 jint _Jv_JNI_DestroyJavaVM(JavaVM *vm)
5760 {
5761         s4 status;
5762
5763         STATISTICS(jniinvokation());
5764
5765     status = vm_destroy(vm);
5766
5767         return status;
5768 }
5769
5770
5771 /* AttachCurrentThread *********************************************************
5772
5773    Attaches the current thread to a Java VM. Returns a JNI interface
5774    pointer in the JNIEnv argument.
5775
5776    Trying to attach a thread that is already attached is a no-op.
5777
5778    A native thread cannot be attached simultaneously to two Java VMs.
5779
5780    When a thread is attached to the VM, the context class loader is
5781    the bootstrap loader.
5782
5783 *******************************************************************************/
5784
5785 static s4 jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
5786 {
5787         JavaVMAttachArgs *vm_aargs;
5788
5789 #if defined(ENABLE_THREADS)
5790         if (threads_get_current_threadobject() == NULL) {
5791                 vm_aargs = (JavaVMAttachArgs *) thr_args;
5792
5793                 if (vm_aargs != NULL) {
5794                         if ((vm_aargs->version != JNI_VERSION_1_2) &&
5795                                 (vm_aargs->version != JNI_VERSION_1_4))
5796                                 return JNI_EVERSION;
5797                 }
5798
5799                 if (!threads_attach_current_thread(vm_aargs, false))
5800                         return JNI_ERR;
5801
5802                 if (!jni_init_localref_table())
5803                         return JNI_ERR;
5804         }
5805 #endif
5806
5807         *p_env = _Jv_env;
5808
5809         return JNI_OK;
5810 }
5811
5812
5813 jint _Jv_JNI_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
5814 {
5815         STATISTICS(jniinvokation());
5816
5817         return jni_attach_current_thread(p_env, thr_args, false);
5818 }
5819
5820
5821 /* DetachCurrentThread *********************************************************
5822
5823    Detaches the current thread from a Java VM. All Java monitors held
5824    by this thread are released. All Java threads waiting for this
5825    thread to die are notified.
5826
5827    In JDK 1.1, the main thread cannot be detached from the VM. It must
5828    call DestroyJavaVM to unload the entire VM.
5829
5830    In the JDK, the main thread can be detached from the VM.
5831
5832    The main thread, which is the thread that created the Java VM,
5833    cannot be detached from the VM. Instead, the main thread must call
5834    JNI_DestroyJavaVM() to unload the entire VM.
5835
5836 *******************************************************************************/
5837
5838 jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
5839 {
5840 #if defined(ENABLE_THREADS)
5841         threadobject *thread;
5842
5843         STATISTICS(jniinvokation());
5844
5845         thread = threads_get_current_threadobject();
5846
5847         if (thread == NULL)
5848                 return JNI_ERR;
5849
5850         if (!threads_detach_thread(thread))
5851                 return JNI_ERR;
5852 #endif
5853
5854         return JNI_OK;
5855 }
5856
5857
5858 /* GetEnv **********************************************************************
5859
5860    If the current thread is not attached to the VM, sets *env to NULL,
5861    and returns JNI_EDETACHED. If the specified version is not
5862    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
5863    sets *env to the appropriate interface, and returns JNI_OK.
5864
5865 *******************************************************************************/
5866
5867 jint _Jv_JNI_GetEnv(JavaVM *vm, void **env, jint version)
5868 {
5869         STATISTICS(jniinvokation());
5870
5871 #if defined(ENABLE_THREADS)
5872         if (threads_get_current_threadobject() == NULL) {
5873                 *env = NULL;
5874
5875                 return JNI_EDETACHED;
5876         }
5877 #endif
5878
5879         /* check the JNI version */
5880
5881         switch (version) {
5882         case JNI_VERSION_1_1:
5883         case JNI_VERSION_1_2:
5884         case JNI_VERSION_1_4:
5885                 *env = _Jv_env;
5886                 return JNI_OK;
5887
5888         default:
5889                 ;
5890         }
5891
5892 #if defined(ENABLE_JVMTI)
5893         if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
5894                 == JVMTI_VERSION_INTERFACE_JVMTI) {
5895
5896                 *env = (void *) jvmti_new_environment();
5897
5898                 if (env != NULL)
5899                         return JNI_OK;
5900         }
5901 #endif
5902         
5903         *env = NULL;
5904
5905         return JNI_EVERSION;
5906 }
5907
5908
5909 /* AttachCurrentThreadAsDaemon *************************************************
5910
5911    Same semantics as AttachCurrentThread, but the newly-created
5912    java.lang.Thread instance is a daemon.
5913
5914    If the thread has already been attached via either
5915    AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
5916    simply sets the value pointed to by penv to the JNIEnv of the
5917    current thread. In this case neither AttachCurrentThread nor this
5918    routine have any effect on the daemon status of the thread.
5919
5920 *******************************************************************************/
5921
5922 jint _Jv_JNI_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
5923 {
5924         STATISTICS(jniinvokation());
5925
5926         return jni_attach_current_thread(penv, args, true);
5927 }
5928
5929
5930 /* JNI invocation table *******************************************************/
5931
5932 const struct JNIInvokeInterface _Jv_JNIInvokeInterface = {
5933         NULL,
5934         NULL,
5935         NULL,
5936
5937         _Jv_JNI_DestroyJavaVM,
5938         _Jv_JNI_AttachCurrentThread,
5939         _Jv_JNI_DetachCurrentThread,
5940         _Jv_JNI_GetEnv,
5941         _Jv_JNI_AttachCurrentThreadAsDaemon
5942 };
5943
5944
5945 /* JNI function table *********************************************************/
5946
5947 struct JNINativeInterface _Jv_JNINativeInterface = {
5948         NULL,
5949         NULL,
5950         NULL,
5951         NULL,    
5952         _Jv_JNI_GetVersion,
5953
5954         _Jv_JNI_DefineClass,
5955         _Jv_JNI_FindClass,
5956         _Jv_JNI_FromReflectedMethod,
5957         _Jv_JNI_FromReflectedField,
5958         _Jv_JNI_ToReflectedMethod,
5959         _Jv_JNI_GetSuperclass,
5960         _Jv_JNI_IsAssignableFrom,
5961         _Jv_JNI_ToReflectedField,
5962
5963         _Jv_JNI_Throw,
5964         _Jv_JNI_ThrowNew,
5965         _Jv_JNI_ExceptionOccurred,
5966         _Jv_JNI_ExceptionDescribe,
5967         _Jv_JNI_ExceptionClear,
5968         _Jv_JNI_FatalError,
5969         _Jv_JNI_PushLocalFrame,
5970         _Jv_JNI_PopLocalFrame,
5971
5972         _Jv_JNI_NewGlobalRef,
5973         _Jv_JNI_DeleteGlobalRef,
5974         _Jv_JNI_DeleteLocalRef,
5975         _Jv_JNI_IsSameObject,
5976         _Jv_JNI_NewLocalRef,
5977         _Jv_JNI_EnsureLocalCapacity,
5978
5979         _Jv_JNI_AllocObject,
5980         _Jv_JNI_NewObject,
5981         _Jv_JNI_NewObjectV,
5982         _Jv_JNI_NewObjectA,
5983
5984         _Jv_JNI_GetObjectClass,
5985         _Jv_JNI_IsInstanceOf,
5986
5987         _Jv_JNI_GetMethodID,
5988
5989         _Jv_JNI_CallObjectMethod,
5990         _Jv_JNI_CallObjectMethodV,
5991         _Jv_JNI_CallObjectMethodA,
5992         _Jv_JNI_CallBooleanMethod,
5993         _Jv_JNI_CallBooleanMethodV,
5994         _Jv_JNI_CallBooleanMethodA,
5995         _Jv_JNI_CallByteMethod,
5996         _Jv_JNI_CallByteMethodV,
5997         _Jv_JNI_CallByteMethodA,
5998         _Jv_JNI_CallCharMethod,
5999         _Jv_JNI_CallCharMethodV,
6000         _Jv_JNI_CallCharMethodA,
6001         _Jv_JNI_CallShortMethod,
6002         _Jv_JNI_CallShortMethodV,
6003         _Jv_JNI_CallShortMethodA,
6004         _Jv_JNI_CallIntMethod,
6005         _Jv_JNI_CallIntMethodV,
6006         _Jv_JNI_CallIntMethodA,
6007         _Jv_JNI_CallLongMethod,
6008         _Jv_JNI_CallLongMethodV,
6009         _Jv_JNI_CallLongMethodA,
6010         _Jv_JNI_CallFloatMethod,
6011         _Jv_JNI_CallFloatMethodV,
6012         _Jv_JNI_CallFloatMethodA,
6013         _Jv_JNI_CallDoubleMethod,
6014         _Jv_JNI_CallDoubleMethodV,
6015         _Jv_JNI_CallDoubleMethodA,
6016         _Jv_JNI_CallVoidMethod,
6017         _Jv_JNI_CallVoidMethodV,
6018         _Jv_JNI_CallVoidMethodA,
6019
6020         _Jv_JNI_CallNonvirtualObjectMethod,
6021         _Jv_JNI_CallNonvirtualObjectMethodV,
6022         _Jv_JNI_CallNonvirtualObjectMethodA,
6023         _Jv_JNI_CallNonvirtualBooleanMethod,
6024         _Jv_JNI_CallNonvirtualBooleanMethodV,
6025         _Jv_JNI_CallNonvirtualBooleanMethodA,
6026         _Jv_JNI_CallNonvirtualByteMethod,
6027         _Jv_JNI_CallNonvirtualByteMethodV,
6028         _Jv_JNI_CallNonvirtualByteMethodA,
6029         _Jv_JNI_CallNonvirtualCharMethod,
6030         _Jv_JNI_CallNonvirtualCharMethodV,
6031         _Jv_JNI_CallNonvirtualCharMethodA,
6032         _Jv_JNI_CallNonvirtualShortMethod,
6033         _Jv_JNI_CallNonvirtualShortMethodV,
6034         _Jv_JNI_CallNonvirtualShortMethodA,
6035         _Jv_JNI_CallNonvirtualIntMethod,
6036         _Jv_JNI_CallNonvirtualIntMethodV,
6037         _Jv_JNI_CallNonvirtualIntMethodA,
6038         _Jv_JNI_CallNonvirtualLongMethod,
6039         _Jv_JNI_CallNonvirtualLongMethodV,
6040         _Jv_JNI_CallNonvirtualLongMethodA,
6041         _Jv_JNI_CallNonvirtualFloatMethod,
6042         _Jv_JNI_CallNonvirtualFloatMethodV,
6043         _Jv_JNI_CallNonvirtualFloatMethodA,
6044         _Jv_JNI_CallNonvirtualDoubleMethod,
6045         _Jv_JNI_CallNonvirtualDoubleMethodV,
6046         _Jv_JNI_CallNonvirtualDoubleMethodA,
6047         _Jv_JNI_CallNonvirtualVoidMethod,
6048         _Jv_JNI_CallNonvirtualVoidMethodV,
6049         _Jv_JNI_CallNonvirtualVoidMethodA,
6050
6051         _Jv_JNI_GetFieldID,
6052
6053         _Jv_JNI_GetObjectField,
6054         _Jv_JNI_GetBooleanField,
6055         _Jv_JNI_GetByteField,
6056         _Jv_JNI_GetCharField,
6057         _Jv_JNI_GetShortField,
6058         _Jv_JNI_GetIntField,
6059         _Jv_JNI_GetLongField,
6060         _Jv_JNI_GetFloatField,
6061         _Jv_JNI_GetDoubleField,
6062         _Jv_JNI_SetObjectField,
6063         _Jv_JNI_SetBooleanField,
6064         _Jv_JNI_SetByteField,
6065         _Jv_JNI_SetCharField,
6066         _Jv_JNI_SetShortField,
6067         _Jv_JNI_SetIntField,
6068         _Jv_JNI_SetLongField,
6069         _Jv_JNI_SetFloatField,
6070         _Jv_JNI_SetDoubleField,
6071
6072         _Jv_JNI_GetStaticMethodID,
6073
6074         _Jv_JNI_CallStaticObjectMethod,
6075         _Jv_JNI_CallStaticObjectMethodV,
6076         _Jv_JNI_CallStaticObjectMethodA,
6077         _Jv_JNI_CallStaticBooleanMethod,
6078         _Jv_JNI_CallStaticBooleanMethodV,
6079         _Jv_JNI_CallStaticBooleanMethodA,
6080         _Jv_JNI_CallStaticByteMethod,
6081         _Jv_JNI_CallStaticByteMethodV,
6082         _Jv_JNI_CallStaticByteMethodA,
6083         _Jv_JNI_CallStaticCharMethod,
6084         _Jv_JNI_CallStaticCharMethodV,
6085         _Jv_JNI_CallStaticCharMethodA,
6086         _Jv_JNI_CallStaticShortMethod,
6087         _Jv_JNI_CallStaticShortMethodV,
6088         _Jv_JNI_CallStaticShortMethodA,
6089         _Jv_JNI_CallStaticIntMethod,
6090         _Jv_JNI_CallStaticIntMethodV,
6091         _Jv_JNI_CallStaticIntMethodA,
6092         _Jv_JNI_CallStaticLongMethod,
6093         _Jv_JNI_CallStaticLongMethodV,
6094         _Jv_JNI_CallStaticLongMethodA,
6095         _Jv_JNI_CallStaticFloatMethod,
6096         _Jv_JNI_CallStaticFloatMethodV,
6097         _Jv_JNI_CallStaticFloatMethodA,
6098         _Jv_JNI_CallStaticDoubleMethod,
6099         _Jv_JNI_CallStaticDoubleMethodV,
6100         _Jv_JNI_CallStaticDoubleMethodA,
6101         _Jv_JNI_CallStaticVoidMethod,
6102         _Jv_JNI_CallStaticVoidMethodV,
6103         _Jv_JNI_CallStaticVoidMethodA,
6104
6105         _Jv_JNI_GetStaticFieldID,
6106
6107         _Jv_JNI_GetStaticObjectField,
6108         _Jv_JNI_GetStaticBooleanField,
6109         _Jv_JNI_GetStaticByteField,
6110         _Jv_JNI_GetStaticCharField,
6111         _Jv_JNI_GetStaticShortField,
6112         _Jv_JNI_GetStaticIntField,
6113         _Jv_JNI_GetStaticLongField,
6114         _Jv_JNI_GetStaticFloatField,
6115         _Jv_JNI_GetStaticDoubleField,
6116         _Jv_JNI_SetStaticObjectField,
6117         _Jv_JNI_SetStaticBooleanField,
6118         _Jv_JNI_SetStaticByteField,
6119         _Jv_JNI_SetStaticCharField,
6120         _Jv_JNI_SetStaticShortField,
6121         _Jv_JNI_SetStaticIntField,
6122         _Jv_JNI_SetStaticLongField,
6123         _Jv_JNI_SetStaticFloatField,
6124         _Jv_JNI_SetStaticDoubleField,
6125
6126         _Jv_JNI_NewString,
6127         _Jv_JNI_GetStringLength,
6128         _Jv_JNI_GetStringChars,
6129         _Jv_JNI_ReleaseStringChars,
6130
6131         _Jv_JNI_NewStringUTF,
6132         _Jv_JNI_GetStringUTFLength,
6133         _Jv_JNI_GetStringUTFChars,
6134         _Jv_JNI_ReleaseStringUTFChars,
6135
6136         _Jv_JNI_GetArrayLength,
6137
6138         _Jv_JNI_NewObjectArray,
6139         _Jv_JNI_GetObjectArrayElement,
6140         _Jv_JNI_SetObjectArrayElement,
6141
6142         _Jv_JNI_NewBooleanArray,
6143         _Jv_JNI_NewByteArray,
6144         _Jv_JNI_NewCharArray,
6145         _Jv_JNI_NewShortArray,
6146         _Jv_JNI_NewIntArray,
6147         _Jv_JNI_NewLongArray,
6148         _Jv_JNI_NewFloatArray,
6149         _Jv_JNI_NewDoubleArray,
6150
6151         _Jv_JNI_GetBooleanArrayElements,
6152         _Jv_JNI_GetByteArrayElements,
6153         _Jv_JNI_GetCharArrayElements,
6154         _Jv_JNI_GetShortArrayElements,
6155         _Jv_JNI_GetIntArrayElements,
6156         _Jv_JNI_GetLongArrayElements,
6157         _Jv_JNI_GetFloatArrayElements,
6158         _Jv_JNI_GetDoubleArrayElements,
6159
6160         _Jv_JNI_ReleaseBooleanArrayElements,
6161         _Jv_JNI_ReleaseByteArrayElements,
6162         _Jv_JNI_ReleaseCharArrayElements,
6163         _Jv_JNI_ReleaseShortArrayElements,
6164         _Jv_JNI_ReleaseIntArrayElements,
6165         _Jv_JNI_ReleaseLongArrayElements,
6166         _Jv_JNI_ReleaseFloatArrayElements,
6167         _Jv_JNI_ReleaseDoubleArrayElements,
6168
6169         _Jv_JNI_GetBooleanArrayRegion,
6170         _Jv_JNI_GetByteArrayRegion,
6171         _Jv_JNI_GetCharArrayRegion,
6172         _Jv_JNI_GetShortArrayRegion,
6173         _Jv_JNI_GetIntArrayRegion,
6174         _Jv_JNI_GetLongArrayRegion,
6175         _Jv_JNI_GetFloatArrayRegion,
6176         _Jv_JNI_GetDoubleArrayRegion,
6177         _Jv_JNI_SetBooleanArrayRegion,
6178         _Jv_JNI_SetByteArrayRegion,
6179         _Jv_JNI_SetCharArrayRegion,
6180         _Jv_JNI_SetShortArrayRegion,
6181         _Jv_JNI_SetIntArrayRegion,
6182         _Jv_JNI_SetLongArrayRegion,
6183         _Jv_JNI_SetFloatArrayRegion,
6184         _Jv_JNI_SetDoubleArrayRegion,
6185
6186         _Jv_JNI_RegisterNatives,
6187         _Jv_JNI_UnregisterNatives,
6188
6189         _Jv_JNI_MonitorEnter,
6190         _Jv_JNI_MonitorExit,
6191
6192         _Jv_JNI_GetJavaVM,
6193
6194         /* new JNI 1.2 functions */
6195
6196         _Jv_JNI_GetStringRegion,
6197         _Jv_JNI_GetStringUTFRegion,
6198
6199         _Jv_JNI_GetPrimitiveArrayCritical,
6200         _Jv_JNI_ReleasePrimitiveArrayCritical,
6201
6202         _Jv_JNI_GetStringCritical,
6203         _Jv_JNI_ReleaseStringCritical,
6204
6205         _Jv_JNI_NewWeakGlobalRef,
6206         _Jv_JNI_DeleteWeakGlobalRef,
6207
6208         _Jv_JNI_ExceptionCheck,
6209
6210         /* new JNI 1.4 functions */
6211
6212         _Jv_JNI_NewDirectByteBuffer,
6213         _Jv_JNI_GetDirectBufferAddress,
6214         _Jv_JNI_GetDirectBufferCapacity
6215 };
6216
6217
6218 /* Invocation API Functions ***************************************************/
6219
6220 /* JNI_GetDefaultJavaVMInitArgs ************************************************
6221
6222    Returns a default configuration for the Java VM.
6223
6224 *******************************************************************************/
6225
6226 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
6227 {
6228         JavaVMInitArgs *_vm_args;
6229
6230         _vm_args = (JavaVMInitArgs *) vm_args;
6231
6232         /* GNU classpath currently supports JNI 1.2 */
6233
6234         switch (_vm_args->version) {
6235     case JNI_VERSION_1_1:
6236                 _vm_args->version = JNI_VERSION_1_1;
6237                 break;
6238
6239     case JNI_VERSION_1_2:
6240     case JNI_VERSION_1_4:
6241                 _vm_args->ignoreUnrecognized = JNI_FALSE;
6242                 _vm_args->options = NULL;
6243                 _vm_args->nOptions = 0;
6244                 break;
6245
6246     default:
6247                 return -1;
6248         }
6249   
6250         return 0;
6251 }
6252
6253
6254 /* JNI_GetCreatedJavaVMs *******************************************************
6255
6256    Returns all Java VMs that have been created. Pointers to VMs are written in
6257    the buffer vmBuf in the order they are created. At most bufLen number of
6258    entries will be written. The total number of created VMs is returned in
6259    *nVMs.
6260
6261 *******************************************************************************/
6262
6263 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
6264 {
6265         log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!");
6266
6267         return 0;
6268 }
6269
6270
6271 /* JNI_CreateJavaVM ************************************************************
6272
6273    Loads and initializes a Java VM. The current thread becomes the main thread.
6274    Sets the env argument to the JNI interface pointer of the main thread.
6275
6276 *******************************************************************************/
6277
6278 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
6279 {
6280         /* actually create the JVM */
6281
6282         if (!vm_createjvm(p_vm, p_env, vm_args))
6283                 return JNI_ERR;
6284
6285         return JNI_OK;
6286 }
6287
6288
6289 /*
6290  * These are local overrides for various environment variables in Emacs.
6291  * Please do not remove this and leave it at the end of the file, where
6292  * Emacs will automagically detect them.
6293  * ---------------------------------------------------------------------
6294  * Local variables:
6295  * mode: c
6296  * indent-tabs-mode: t
6297  * c-basic-offset: 4
6298  * tab-width: 4
6299  * End:
6300  * vim:noexpandtab:sw=4:ts=4:
6301  */