001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.jni;
014    
015    import java.lang.reflect.Constructor;
016    import java.lang.reflect.Field;
017    import java.lang.reflect.Method;
018    import java.nio.Buffer;
019    import org.jikesrvm.ArchitectureSpecific.JNIHelpers;
020    import org.jikesrvm.VM;
021    import org.jikesrvm.Properties;
022    import org.jikesrvm.SizeConstants;
023    import org.jikesrvm.classloader.RVMArray;
024    import org.jikesrvm.classloader.Atom;
025    import org.jikesrvm.classloader.RVMClass;
026    import org.jikesrvm.classloader.RVMClassLoader;
027    import org.jikesrvm.classloader.RVMField;
028    import org.jikesrvm.classloader.MemberReference;
029    import org.jikesrvm.classloader.RVMMethod;
030    import org.jikesrvm.classloader.NativeMethod;
031    import org.jikesrvm.classloader.RVMType;
032    import org.jikesrvm.classloader.TypeReference;
033    import org.jikesrvm.classloader.UTF8Convert;
034    import org.jikesrvm.mm.mminterface.MemoryManager;
035    import org.jikesrvm.objectmodel.ObjectModel;
036    import org.jikesrvm.runtime.BootRecord;
037    import org.jikesrvm.runtime.Magic;
038    import org.jikesrvm.runtime.Memory;
039    import org.jikesrvm.runtime.Reflection;
040    import org.jikesrvm.runtime.RuntimeEntrypoints;
041    import org.jikesrvm.util.AddressInputStream;
042    
043    import static org.jikesrvm.runtime.SysCall.sysCall;
044    import org.vmmagic.pragma.NativeBridge;
045    import org.vmmagic.unboxed.Address;
046    import org.vmmagic.unboxed.AddressArray;
047    import org.vmmagic.unboxed.Offset;
048    
049    /**
050     * This class implements the 232 JNI functions.
051     * All methods here will be specially compiled with the necessary prolog to
052     * perform the transition from native code (Linux/AIX/OSX convention) to RVM.
053     * For this reason, no Java methods (including the JNI methods here) can call
054     * any methods in this class from within Java.  These JNI methods are to
055     * be invoked from native C or C++.   They're all declared private to enforce
056     * this discipline.  <br>
057     *
058     * The first argument for all the functions is the JNIEnvironment object
059     * of the thread. <br>
060     *
061     * The second argument is a JREF index for either the RVMClass object
062     * or the object instance itself.  To get the actual object, we use
063     * the access method in JNIEnvironment and cast the reference as
064     * needed. <br>
065     *
066     * NOTE:
067     * <ol>
068     * <li> JREF index refers to the index into the side table of references
069     * maintained by the JNIEnvironment for each thread. Except for some cases
070     * of array access, no references are passed directly to the native code;
071     * rather, the references are kept in the table and the index is passed to the
072     * native procedure.  The JREF index are used by the JNI code to retrieve the
073     * corresponding reference. </li>
074     *
075     * <li> Strings from C are seen as raw address (int) and need to be cloned as
076     * Java Strings </li>
077     *
078     * <li> Because of many of the transformation above, the method signature of the
079     * JNI functions may not match its definition in the jni.h file </li>
080     *
081     * <li> For exception handling, all JNI functions are wrapped in Try/Catch block
082     * to catch all exception generated during JNI call, then these exceptions
083     * or the appropriate exception to be thrown according to the spec is recorded
084     * in JNIEnvironment.pendingException.  When the native code returns to the
085     * the Java caller, the epilogue in the glue code will check for the pending
086     * exception and deliver it to the caller as if executing an athrow bytecode
087     * in the caller. </li>
088     * </ol>
089     *
090     * Known Problems with our JNI implementation:
091     * <ol>
092     * <li>We can not return a global reference (whether weak
093     *     or strong) from a JNI function.  We can only return local refs.
094     * <li>We do not implement all of the invocation API; we don't support the
095     *      concept of a regular native program that links with "libjava" and
096     *      creates and destroys virtual machines.
097     * <li>Similarly, we can not attach and detach a native threads to and from
098     *     the VM.
099     * <li>We don't really free local refs when we call the
100     *      {@link #PopLocalFrame} method.
101     * </ol>
102     */
103    @SuppressWarnings({"unused", "UnusedDeclaration"})
104    // methods are called from native code
105    @NativeBridge
106    public class JNIFunctions implements SizeConstants {
107      // one message for each JNI function called from native
108      public static final boolean traceJNI = Properties.verboseJNI;
109    
110      // number of JNI function entries
111      public static final int FUNCTIONCOUNT = 232; // JNI 1.4
112    
113      /**
114       * GetVersion: the version of the JNI
115       * @param env A JREF index for the JNI environment object
116       * @return 0x00010004 for JNI 1.4, 0x00010002 for JNI 1.2,
117       *        0x00010001 for JNI 1.1,
118       */
119      private static int GetVersion(JNIEnvironment env) {
120        if (traceJNI) VM.sysWrite("JNI called: GetVersion  \n");
121        RuntimeEntrypoints.checkJNICountDownToGC();
122    
123        return 0x00010004;          // JNI 1.4
124      }
125    
126      /**
127       * DefineClass:  Loads a class from a buffer of raw class data.
128       * @param env A JREF index for the JNI environment object
129       * @param classNameAddress a raw address to a null-terminated string in C for the class name
130       * @param classLoader a JREF index for the class loader assigned to the defined class
131       * @param data buffer containing the <tt>.class</tt> file
132       * @param dataLen buffer length
133       * @return a JREF index for the Java Class object, or 0 if not found
134       * @exception ClassFormatError if the class data does not specify a valid class
135       * @exception ClassCircularityError (not implemented)
136       * @exception OutOfMemoryError (not implemented)
137       */
138      private static int DefineClass(JNIEnvironment env, Address classNameAddress, int classLoader, Address data,
139                                     int dataLen) {
140        if (traceJNI) VM.sysWrite("JNI called: DefineClass  \n");
141        RuntimeEntrypoints.checkJNICountDownToGC();
142    
143        try {
144          String classString = null;
145          if (!classNameAddress.isZero()) {
146            JNIHelpers.createStringFromC(classNameAddress);
147          }
148          ClassLoader cl;
149          if (classLoader == 0) {
150            cl = RVMClass.getClassLoaderFromStackFrame(1);
151          } else {
152            cl = (ClassLoader) env.getJNIRef(classLoader);
153          }
154          AddressInputStream reader = new AddressInputStream(data, Offset.fromIntZeroExtend(dataLen));
155    
156          final RVMType vmType = RVMClassLoader.defineClassInternal(classString, reader, cl);
157          return env.pushJNIRef(vmType.getClassForType());
158        } catch (Throwable unexpected) {
159          if (traceJNI) unexpected.printStackTrace(System.err);
160          env.recordException(unexpected);
161          return 0;
162        }
163    
164      }
165    
166      /**
167       * FindClass:  given a class name, find its RVMClass, or 0 if not found
168       * @param env A JREF index for the JNI environment object
169       * @param classNameAddress a raw address to a null-terminated string in C for the class name
170       * @return a JREF index for the Java Class object, or 0 if not found
171       * @exception ClassFormatError (not implemented)
172       * @exception ClassCircularityError (not implemented)
173       * @exception NoClassDefFoundError if the class cannot be found
174       * @exception OutOfMemoryError (not implemented)
175       * @exception ExceptionInInitializerError (not implemented)
176       */
177      private static int FindClass(JNIEnvironment env, Address classNameAddress) {
178        if (traceJNI) VM.sysWrite("JNI called: FindClass  \n");
179        RuntimeEntrypoints.checkJNICountDownToGC();
180    
181        String classString = null;
182        try {
183          classString = JNIHelpers.createStringFromC(classNameAddress);
184          classString = classString.replace('/', '.');
185          if (classString.startsWith("L") && classString.endsWith(";")) {
186            classString = classString.substring(1, classString.length() - 1);
187          }
188          if (traceJNI) VM.sysWriteln(classString);
189          ClassLoader cl = RVMClass.getClassLoaderFromStackFrame(1);
190          Class<?> matchedClass = Class.forName(classString.replace('/', '.'), true, cl);
191          int result = env.pushJNIRef(matchedClass);
192          if (traceJNI) VM.sysWriteln("FindClass returning ",result);
193          return result;
194        } catch (ClassNotFoundException e) {
195          if (traceJNI) e.printStackTrace(System.err);
196          env.recordException(new NoClassDefFoundError(classString));
197          return 0;
198        } catch (Throwable unexpected) {
199          if (traceJNI) {
200            if (VM.fullyBooted) {
201              unexpected.printStackTrace(System.err);
202            } else {
203              VM.sysWrite("Unexpected exception ", unexpected.getClass().toString());
204              VM.sysWriteln(" to early in VM boot up to print ", unexpected.getMessage());
205            }
206          }
207          env.recordException(unexpected);
208          return 0;
209        }
210      }
211    
212      /**
213       * GetSuperclass: find the superclass given a class
214       * @param env A JREF index for the JNI environment object
215       * @param classJREF a JREF index for the class object
216       * @return a JREF index for the super class object, or 0 if the given class
217       *         is java.lang.Object or an interface
218       */
219      private static int GetSuperclass(JNIEnvironment env, int classJREF) {
220        if (traceJNI) VM.sysWrite("JNI called: GetSuperclass  \n");
221        RuntimeEntrypoints.checkJNICountDownToGC();
222    
223        try {
224          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
225          Class<?> supercls = cls.getSuperclass();
226          return supercls == null ? 0 : env.pushJNIRef(supercls);
227        } catch (Throwable unexpected) {
228          if (traceJNI) unexpected.printStackTrace(System.err);
229          env.recordException(unexpected);
230          return 0;
231        }
232      }
233    
234      /**
235       * IsAssignableFrom:  determine if an an object of class or interface cls1
236       * can be cast to the class or interface cls2
237       * @param env A JREF index for the JNI environment object
238       * @param firstClassJREF a JREF index for the first class object
239       * @param secondClassJREF a JREF index for the second class object
240       * @return true if cls1 can be assigned to cls2
241       */
242      private static boolean IsAssignableFrom(JNIEnvironment env, int firstClassJREF, int secondClassJREF) {
243        if (traceJNI) VM.sysWrite("JNI called: IsAssignableFrom  \n");
244        RuntimeEntrypoints.checkJNICountDownToGC();
245    
246        try {
247          Class<?> cls1 = (Class<?>) env.getJNIRef(firstClassJREF);
248          Class<?> cls2 = (Class<?>) env.getJNIRef(secondClassJREF);
249          return !(cls1 == null || cls2 == null) && cls2.isAssignableFrom(cls1);
250        } catch (Throwable unexpected) {
251          if (traceJNI) unexpected.printStackTrace(System.err);
252          env.recordException(unexpected);
253          return false;
254        }
255      }
256    
257      /**
258       * Throw:  register a {@link Throwable} object as a pending exception, to be
259       *         delivered on return to the Java caller
260       * @param env A JREF index for the JNI environment object
261       * @param exceptionJREF A JREF index for the {@link Throwable} object to be
262       *        thrown
263       * @return 0 if successful, -1 if not
264       */
265      private static int Throw(JNIEnvironment env, int exceptionJREF) {
266        if (traceJNI) VM.sysWrite("JNI called: Throw  \n");
267        RuntimeEntrypoints.checkJNICountDownToGC();
268    
269        try {
270          env.recordException((Throwable) env.getJNIRef(exceptionJREF));
271          return 0;
272        } catch (Throwable unexpected) {
273          if (traceJNI) unexpected.printStackTrace(System.err);
274          env.recordException(unexpected);
275          return -1;
276        }
277      }
278    
279      /**
280       * ThrowNew
281       * @param env A JREF index for the JNI environment object
282       * @param throwableClassJREF a JREF index for the class object of the exception
283       * @param exceptionNameAddress an address of the string in C
284       * @return 0 if successful, -1 otherwise
285       */
286      private static int ThrowNew(JNIEnvironment env, int throwableClassJREF, Address exceptionNameAddress) {
287        if (traceJNI) VM.sysWrite("JNI called: ThrowNew  \n");
288        RuntimeEntrypoints.checkJNICountDownToGC();
289    
290        try {
291          Class<?> cls = (Class<?>) env.getJNIRef(throwableClassJREF);
292          // find the constructor that has a string as a parameter
293          Class<?>[] argClasses = new Class[1];
294          argClasses[0] = RVMType.JavaLangStringType.getClassForType();
295          Constructor<?> constMethod = cls.getConstructor(argClasses);
296          // prepare the parameter list for reflective invocation
297          Object[] argObjs = new Object[1];
298          argObjs[0] = JNIHelpers.createStringFromC(exceptionNameAddress);
299    
300          // invoke the constructor to obtain a new Throwable object
301          env.recordException((Throwable) constMethod.newInstance(argObjs));
302          return 0;
303        } catch (Throwable unexpected) {
304          if (traceJNI) unexpected.printStackTrace(System.err);
305          env.recordException(unexpected);
306          return -1;
307        }
308    
309      }
310    
311      /**
312       * ExceptionOccurred
313       * @param env A JREF index for the JNI environment object
314       * @return a JREF index for the pending exception or null if nothing pending
315       */
316      private static int ExceptionOccurred(JNIEnvironment env) {
317        if (traceJNI) VM.sysWrite("JNI called: ExceptionOccurred  \n");
318        RuntimeEntrypoints.checkJNICountDownToGC();
319    
320        try {
321          Throwable e = env.getException();
322          if (e == null) {
323            return 0;
324          } else {
325            if (traceJNI) System.err.println(e.toString());
326            return env.pushJNIRef(e);
327          }
328        } catch (Throwable unexpected) {
329          if (traceJNI) unexpected.printStackTrace(System.err);
330          env.recordException(unexpected);
331          return env.pushJNIRef(unexpected);
332        }
333      }
334    
335      /**
336       * ExceptionDescribe: print the exception description and the stack trace back,
337       *                    then clear the exception
338       * @param env A JREF index for the JNI environment object
339       */
340      private static void ExceptionDescribe(JNIEnvironment env) {
341        if (traceJNI) VM.sysWrite("JNI called: ExceptionDescribe  \n");
342        RuntimeEntrypoints.checkJNICountDownToGC();
343    
344        try {
345          Throwable e = env.getException();
346          if (e != null) {
347            env.recordException(null);
348            e.printStackTrace(System.err);
349          }
350        } catch (Throwable unexpected) {
351          if (traceJNI) unexpected.printStackTrace(System.err);
352          env.recordException(null);            // clear old exception and register new one
353          env.recordException(unexpected);
354        }
355      }
356    
357      /**
358       * ExceptionClear
359       * @param env A JREF index for the JNI environment object
360       */
361      private static void ExceptionClear(JNIEnvironment env) {
362        if (traceJNI) VM.sysWrite("JNI called: ExceptionClear  \n");
363        RuntimeEntrypoints.checkJNICountDownToGC();
364    
365        try {
366          env.recordException(null);
367        } catch (Throwable unexpected) {
368          if (traceJNI) unexpected.printStackTrace(System.err);
369          env.recordException(null);            // clear old exception and register new one
370          env.recordException(unexpected);
371        }
372      }
373    
374      /**
375       * FatalError: print a message and terminate the VM
376       * @param env A JREF index for the JNI environment object
377       * @param messageAddress an address of the string in C
378       */
379      private static void FatalError(JNIEnvironment env, Address messageAddress) {
380        if (traceJNI) VM.sysWrite("JNI called: FatalError  \n");
381        RuntimeEntrypoints.checkJNICountDownToGC();
382    
383        try {
384          VM.sysWrite(JNIHelpers.createStringFromC(messageAddress));
385          System.exit(VM.EXIT_STATUS_JNI_TROUBLE);
386        } catch (Throwable unexpected) {
387          if (traceJNI) unexpected.printStackTrace(System.err);
388          System.exit(VM.EXIT_STATUS_RECURSIVELY_SHUTTING_DOWN);
389        }
390      }
391    
392      private static int NewGlobalRef(JNIEnvironment env, int objectJREF) {
393        if (traceJNI) VM.sysWrite("JNI called: NewGlobalRef\n");
394        RuntimeEntrypoints.checkJNICountDownToGC();
395    
396        try {
397          Object obj1 = env.getJNIRef(objectJREF);
398          return JNIGlobalRefTable.newGlobalRef(obj1);
399        } catch (Throwable unexpected) {
400          if (traceJNI) unexpected.printStackTrace(System.err);
401          env.recordException(unexpected);
402          return 0;
403        }
404      }
405    
406      private static void DeleteGlobalRef(JNIEnvironment env, int refJREF) {
407        if (traceJNI) VM.sysWrite("JNI called: DeleteGlobalRef\n");
408        RuntimeEntrypoints.checkJNICountDownToGC();
409    
410        try {
411          JNIGlobalRefTable.deleteGlobalRef(refJREF);
412        } catch (Throwable unexpected) {
413          if (traceJNI) unexpected.printStackTrace(System.err);
414          env.recordException(unexpected);
415        }
416      }
417    
418      private static void DeleteLocalRef(JNIEnvironment env, int objJREF) {
419        if (traceJNI) VM.sysWrite("JNI called: DeleteLocalRef\n");
420        RuntimeEntrypoints.checkJNICountDownToGC();
421    
422        try {
423          env.deleteJNIRef(objJREF);
424        } catch (ArrayIndexOutOfBoundsException e) {
425          VM.sysFail("JNI refs array confused, or DeleteLocalRef gave us a bad JREF argument:", objJREF);
426        } catch (Throwable unexpected) {
427          if (traceJNI) unexpected.printStackTrace(System.err);
428          env.recordException(unexpected);
429        }
430      }
431    
432      /**
433       * IsSameObject: determine if two references point to the same object
434       * @param env A JREF index for the JNI environment object
435       * @param obj1JREF A JREF index for the first object
436       * @param obj2JREF A JREF index for the second object
437       * @return <code>true</code> if it's the same object, false otherwise
438       */
439      private static boolean IsSameObject(JNIEnvironment env, int obj1JREF, int obj2JREF) {
440        if (traceJNI) VM.sysWrite("JNI called: IsSameObject  \n");
441        RuntimeEntrypoints.checkJNICountDownToGC();
442    
443        try {
444          Object obj1 = env.getJNIRef(obj1JREF);
445          Object obj2 = env.getJNIRef(obj2JREF);
446          return obj1 == obj2;
447        } catch (Throwable unexpected) {
448          if (traceJNI) unexpected.printStackTrace(System.err);
449          env.recordException(null);            // clear old exception and register new one
450          env.recordException(unexpected);
451          return false;
452        }
453      }
454    
455      /**
456       * AllocObject:  allocate the space for an object without running any constructor
457       *               the header is filled and the fields are initialized to null
458       * @param env A JREF index for the JNI environment object
459       * @param classJREF a JREF index for the class object
460       * @return a JREF index for the uninitialized object
461       * @exception InstantiationException if the class is abstract or is an interface
462       * @exception OutOfMemoryError if no more memory to allocate
463       */
464      private static int AllocObject(JNIEnvironment env, int classJREF) throws InstantiationException, OutOfMemoryError {
465        if (traceJNI) VM.sysWrite("JNI called: AllocObject  \n");
466        RuntimeEntrypoints.checkJNICountDownToGC();
467    
468        try {
469          Class<?> javaCls = (Class<?>) env.getJNIRef(classJREF);
470          RVMType type = java.lang.JikesRVMSupport.getTypeForClass(javaCls);
471          if (type.isArrayType() || type.isPrimitiveType() || type.isUnboxedType()) {
472            env.recordException(new InstantiationException());
473            return 0;
474          }
475          RVMClass cls = type.asClass();
476          if (cls.isAbstract() || cls.isInterface()) {
477            env.recordException(new InstantiationException());
478            return 0;
479          }
480          Object newObj = RuntimeEntrypoints.resolvedNewScalar(cls);
481          return env.pushJNIRef(newObj);
482        } catch (Throwable unexpected) {
483          if (traceJNI) unexpected.printStackTrace(System.err);
484          env.recordException(unexpected);
485          return 0;
486        }
487      }
488    
489      /**
490       * NewObject: create a new object instance
491       * NOTE:  the vararg's are not visible in the method signature here;
492       *        they are saved in the caller frame and the glue frame
493       * @param env A JREF index for the JNI environment object
494       * @param classJREF a JREF index for the class object
495       * @param methodID id of a MethodReference
496       * @return the new object instance
497       * @exception InstantiationException if the class is abstract or is an interface
498       * @exception OutOfMemoryError if no more memory to allocate
499       */
500      private static int NewObject(JNIEnvironment env, int classJREF, int methodID) throws Exception {
501        if (traceJNI) VM.sysWrite("JNI called: NewObject  \n");
502        RuntimeEntrypoints.checkJNICountDownToGC();
503    
504        try {
505          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
506          RVMClass vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass();
507    
508          if (vmcls.isAbstract() || vmcls.isInterface()) {
509            env.recordException(new InstantiationException());
510            return 0;
511          }
512    
513          Object newobj = JNIHelpers.invokeInitializer(cls, methodID, Address.zero(), false, true);
514    
515          return env.pushJNIRef(newobj);
516        } catch (Throwable unexpected) {
517          if (traceJNI) unexpected.printStackTrace(System.err);
518          env.recordException(unexpected);
519          return 0;
520        }
521      }
522    
523      /**
524       * NewObjectV: create a new object instance
525       * @param env A JREF index for the JNI environment object
526       * @param classJREF a JREF index for the class object
527       * @param methodID id of a MethodReference
528       * @param argAddress a raw address to a variable argument list, each element is 1-word or
529       *                   2-words of the appropriate type for the constructor invocation
530       * @return the new object instance
531       * @exception InstantiationException if the class is abstract or is an interface
532       * @exception OutOfMemoryError if no more memory to allocate
533       */
534      private static int NewObjectV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
535          throws Exception {
536        if (traceJNI) VM.sysWrite("JNI called: NewObjectV  \n");
537        RuntimeEntrypoints.checkJNICountDownToGC();
538    
539        try {
540          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
541          RVMClass vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass();
542          if (vmcls.isAbstract() || vmcls.isInterface()) {
543            env.recordException(new InstantiationException());
544            return 0;
545          }
546    
547          Object newobj = JNIHelpers.invokeInitializer(cls, methodID, argAddress, false, false);
548    
549          return env.pushJNIRef(newobj);
550        } catch (Throwable unexpected) {
551          if (traceJNI) unexpected.printStackTrace(System.err);
552          env.recordException(unexpected);
553          return 0;
554        }
555      }
556    
557      /**
558       * NewObjectA: create a new object instance
559       * @param env A JREF index for the JNI environment object
560       * @param classJREF a JREF index for the class object
561       * @param methodID id of a MethodReference
562       * @param argAddress a raw address to an array of unions in C, each element is 2-word and
563       *                   hold an argument of the appropriate type for the constructor invocation
564       * @exception InstantiationException if the class is abstract or is an interface
565       * @exception OutOfMemoryError if no more memory to allocate
566       * @return the new object instance
567       */
568      private static int NewObjectA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
569          throws Exception {
570        if (traceJNI) VM.sysWrite("JNI called: NewObjectA  \n");
571        RuntimeEntrypoints.checkJNICountDownToGC();
572    
573        try {
574          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
575          RVMClass vmcls = java.lang.JikesRVMSupport.getTypeForClass(cls).asClass();
576    
577          if (vmcls.isAbstract() || vmcls.isInterface()) {
578            env.recordException(new InstantiationException());
579            return 0;
580          }
581    
582          Object newobj = JNIHelpers.invokeInitializer(cls, methodID, argAddress, true, false);
583    
584          return env.pushJNIRef(newobj);
585        } catch (Throwable unexpected) {
586          if (traceJNI) unexpected.printStackTrace(System.err);
587          env.recordException(unexpected);
588          return 0;
589        }
590      }
591    
592      /**
593       * GetObjectClass
594       * @param env A JREF index for the JNI environment object
595       * @param objJREF a JREF index for the object to check
596       * @return a JREF index for the Class object
597       */
598      private static int GetObjectClass(JNIEnvironment env, int objJREF) {
599        if (traceJNI) VM.sysWrite("JNI called: GetObjectClass  \n");
600        RuntimeEntrypoints.checkJNICountDownToGC();
601    
602        try {
603          Object obj = env.getJNIRef(objJREF);
604          return env.pushJNIRef(obj.getClass());
605        } catch (Throwable unexpected) {
606          if (traceJNI) unexpected.printStackTrace(System.err);
607          env.recordException(unexpected);
608          return 0;
609        }
610      }
611    
612      /**
613       * IsInstanceOf: determine if an object is an instance of the class
614       * @param env A JREF index for the JNI environment object
615       * @param objJREF a JREF index for the object to check
616       * @param classJREF a JREF index for the class to check
617       * @return true if the object is an instance of the class
618       */
619      private static int IsInstanceOf(JNIEnvironment env, int objJREF, int classJREF) {
620        if (traceJNI) VM.sysWrite("JNI called: IsInstanceOf  \n");
621        RuntimeEntrypoints.checkJNICountDownToGC();
622    
623        try {
624          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
625          Object obj = env.getJNIRef(objJREF);
626          if (obj == null) return 0; // null instanceof T is always false
627          RVMType RHStype = ObjectModel.getObjectType(obj);
628          RVMType LHStype = java.lang.JikesRVMSupport.getTypeForClass(cls);
629          return (LHStype == RHStype || RuntimeEntrypoints.isAssignableWith(LHStype, RHStype)) ? 1 : 0;
630        } catch (Throwable unexpected) {
631          if (traceJNI) unexpected.printStackTrace(System.err);
632          env.recordException(unexpected);
633          return 0;
634        }
635      }
636    
637      /**
638       * GetMethodID:  get the virtual method ID given the name and the signature
639       * @param env A JREF index for the JNI environment object
640       * @param classJREF a JREF index for the class object
641       * @param methodNameAddress a raw address to a null-terminated string in C for the method name
642       * @param methodSigAddress a raw address to a null-terminated string in C for the method signature
643       * @return id of a MethodReference
644       * @exception NoSuchMethodError if the method cannot be found
645       * @exception ExceptionInInitializerError if the class or interface static initializer fails
646       * @exception OutOfMemoryError if the system runs out of memory
647       */
648      private static int GetMethodID(JNIEnvironment env, int classJREF, Address methodNameAddress,
649                                     Address methodSigAddress) {
650        if (traceJNI) VM.sysWrite("JNI called: GetMethodID  \n");
651        RuntimeEntrypoints.checkJNICountDownToGC();
652    
653        try {
654          // obtain the names as String from the native space
655          String methodString = JNIHelpers.createStringFromC(methodNameAddress);
656          Atom methodName = Atom.findOrCreateAsciiAtom(methodString);
657          String sigString = JNIHelpers.createStringFromC(methodSigAddress);
658          Atom sigName = Atom.findOrCreateAsciiAtom(sigString);
659    
660          // get the target class
661          Class<?> jcls = (Class<?>) env.getJNIRef(classJREF);
662          RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls);
663          if (!type.isClassType()) {
664            env.recordException(new NoSuchMethodError());
665            return 0;
666          }
667    
668          RVMClass klass = type.asClass();
669          if (!klass.isInitialized()) {
670            RuntimeEntrypoints.initializeClassForDynamicLink(klass);
671          }
672    
673          // Find the target method
674          final RVMMethod meth;
675          if (methodString.equals("<init>")) {
676            meth = klass.findInitializerMethod(sigName);
677          } else {
678            meth = klass.findVirtualMethod(methodName, sigName);
679          }
680    
681          if (meth == null) {
682            env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName));
683            return 0;
684          }
685    
686          if (traceJNI) VM.sysWrite("got method " + meth + "\n");
687          return meth.getId();
688        } catch (Throwable unexpected) {
689          if (traceJNI) unexpected.printStackTrace(System.err);
690          env.recordException(unexpected);
691          return 0;
692        }
693      }
694    
695      /**
696       * CallObjectMethod:  invoke a virtual method that returns an object
697       *                           arguments passed using the vararg ... style
698       * NOTE:  the vararg's are not visible in the method signature here;
699       *        they are saved in the caller frame and the glue frame
700       * @param env A JREF index for the JNI environment object
701       * @param objJREF a JREF index for the object instance
702       * @param methodID id of a MethodReference
703       * @return the JREF index for the object returned from the method invocation
704       */
705      private static int CallObjectMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
706        if (traceJNI) VM.sysWrite("JNI called: CallObjectMethod  \n");
707        RuntimeEntrypoints.checkJNICountDownToGC();
708    
709        try {
710          Object obj = env.getJNIRef(objJREF);
711          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, null, false);
712          return env.pushJNIRef(returnObj);
713        } catch (Throwable unexpected) {
714          if (traceJNI) unexpected.printStackTrace(System.err);
715          env.recordException(unexpected);
716          return 0;
717        }
718      }
719    
720      /**
721       * CallObjectMethodV:  invoke a virtual method that returns an object
722       * @param env A JREF index for the JNI environment object
723       * @param objJREF a JREF index for the object instance
724       * @param methodID id of a MethodReference
725       * @param argAddress a raw address to a variable argument list, each element is
726       *              1-word or 2-words of the appropriate type for the method invocation
727       * @return the JREF index for the object returned from the method invocation
728       */
729      private static int CallObjectMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
730          throws Exception {
731        if (traceJNI) VM.sysWrite("JNI called: CallObjectMethodV  \n");
732        RuntimeEntrypoints.checkJNICountDownToGC();
733    
734        try {
735          Object obj = env.getJNIRef(objJREF);
736          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, null, false);
737          return env.pushJNIRef(returnObj);
738        } catch (Throwable unexpected) {
739          if (traceJNI) unexpected.printStackTrace(System.err);
740          env.recordException(unexpected);
741          return 0;
742        }
743      }
744    
745      /**
746       * CallObjectMethodA:  invoke a virtual method that returns an object value
747       * @param env A JREF index for the JNI environment object
748       * @param objJREF a JREF index for the object instance
749       * @param methodID id of a MethodReference
750       * @param argAddress a raw address to an array of unions in C, each element is 2-word
751       *        and hold an argument of the appropriate type for the method invocation
752       * @return the JREF index for the object returned from the method invocation
753       */
754      private static int CallObjectMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
755          throws Exception {
756        if (traceJNI) VM.sysWrite("JNI called: CallObjectMethodA  \n");
757        RuntimeEntrypoints.checkJNICountDownToGC();
758    
759        try {
760          Object obj = env.getJNIRef(objJREF);
761          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, null, false);
762          return env.pushJNIRef(returnObj);
763        } catch (Throwable unexpected) {
764          if (traceJNI) unexpected.printStackTrace(System.err);
765          env.recordException(unexpected);
766          return 0;
767        }
768      }
769    
770      /**
771       * CallBooleanMethod:  invoke a virtual method that returns a boolean value
772       *                           arguments passed using the vararg ... style
773       * NOTE:  the vararg's are not visible in the method signature here;
774       *        they are saved in the caller frame and the glue frame
775       * @param env A JREF index for the JNI environment object
776       * @param objJREF a JREF index for the object instance
777       * @param methodID id of a MethodReference
778       * @return the boolean value returned from the method invocation
779       */
780      private static boolean CallBooleanMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
781        if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethod  \n");
782        RuntimeEntrypoints.checkJNICountDownToGC();
783    
784        try {
785          Object obj = env.getJNIRef(objJREF);
786          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Boolean, false);
787          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
788        } catch (Throwable unexpected) {
789          if (traceJNI) unexpected.printStackTrace(System.err);
790          env.recordException(unexpected);
791          return false;
792        }
793      }
794    
795      /**
796       * CallBooleanMethodV:  invoke a virtual method that returns a boolean value
797       * @param env A JREF index for the JNI environment object
798       * @param objJREF a JREF index for the object instance
799       * @param methodID id of a MethodReference
800       * @param argAddress a raw address to a variable argument list, each element is
801       *              1-word or 2-words of the appropriate type for the method invocation
802       * @return the boolean value returned from the method invocation
803       */
804      private static boolean CallBooleanMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
805          throws Exception {
806        if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethodV  \n");
807        RuntimeEntrypoints.checkJNICountDownToGC();
808    
809        try {
810          Object obj = env.getJNIRef(objJREF);
811          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Boolean, false);
812          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
813        } catch (Throwable unexpected) {
814          if (traceJNI) unexpected.printStackTrace(System.err);
815          env.recordException(unexpected);
816          return false;
817        }
818      }
819    
820      /**
821       * CallBooleanMethodA:  invoke a virtual method that returns a boolean value
822       * @param env A JREF index for the JNI environment object
823       * @param objJREF a JREF index for the object instance
824       * @param methodID id of a MethodReference
825       * @param argAddress a raw address to an array of unions in C, each element is 2-word
826       *        and hold an argument of the appropriate type for the method invocation
827       * @return the boolean value returned from the method invocation
828       */
829      private static boolean CallBooleanMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
830          throws Exception {
831        if (traceJNI) VM.sysWrite("JNI called: CallBooleanMethodA  \n");
832        RuntimeEntrypoints.checkJNICountDownToGC();
833    
834        try {
835          Object obj = env.getJNIRef(objJREF);
836          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Boolean, false);
837          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
838        } catch (Throwable unexpected) {
839          if (traceJNI) unexpected.printStackTrace(System.err);
840          env.recordException(unexpected);
841          return false;
842        }
843      }
844    
845      /**
846       * CallByteMethod:  invoke a virtual method that returns a byte value
847       *                           arguments passed using the vararg ... style
848       * NOTE:  the vararg's are not visible in the method signature here;
849       *        they are saved in the caller frame and the glue frame
850       * @param env A JREF index for the JNI environment object
851       * @param objJREF a JREF index for the object instance
852       * @param methodID id of a MethodReference
853       * @return the byte value returned from the method invocation
854       */
855      private static byte CallByteMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
856        if (traceJNI) VM.sysWrite("JNI called: CallByteMethod  \n");
857        RuntimeEntrypoints.checkJNICountDownToGC();
858    
859        try {
860          Object obj = env.getJNIRef(objJREF);
861          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Byte, false);
862          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
863        } catch (Throwable unexpected) {
864          if (traceJNI) unexpected.printStackTrace(System.err);
865          env.recordException(unexpected);
866          return 0;
867        }
868      }
869    
870      /**
871       * CallByteMethodV:  invoke a virtual method that returns a byte value
872       * @param env A JREF index for the JNI environment object
873       * @param objJREF a JREF index for the object instance
874       * @param methodID id of a MethodReference
875       * @param argAddress a raw address to a variable argument list, each element is
876       *              1-word or 2-words of the appropriate type for the method invocation
877       * @return the byte value returned from the method invocation
878       */
879      private static byte CallByteMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
880          throws Exception {
881        if (traceJNI) VM.sysWrite("JNI called: CallByteMethodV  \n");
882        RuntimeEntrypoints.checkJNICountDownToGC();
883    
884        try {
885          Object obj = env.getJNIRef(objJREF);
886          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Byte, false);
887          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
888        } catch (Throwable unexpected) {
889          if (traceJNI) unexpected.printStackTrace(System.err);
890          env.recordException(unexpected);
891          return 0;
892        }
893      }
894    
895      /**
896       * CallByteMethodA:  invoke a virtual method that returns a byte value
897       * @param env A JREF index for the JNI environment object
898       * @param objJREF a JREF index for the object instance
899       * @param methodID id of a MethodReference
900       * @param argAddress a raw address to an array of unions in C, each element is 2-word
901       *        and hold an argument of the appropriate type for the method invocation
902       * @return the byte value returned from the method invocation
903       */
904      private static byte CallByteMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
905          throws Exception {
906        if (traceJNI) VM.sysWrite("JNI called: CallByteMethodA  \n");
907        RuntimeEntrypoints.checkJNICountDownToGC();
908    
909        try {
910          Object obj = env.getJNIRef(objJREF);
911          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Byte, false);
912          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
913        } catch (Throwable unexpected) {
914          if (traceJNI) unexpected.printStackTrace(System.err);
915          env.recordException(unexpected);
916          return 0;
917        }
918      }
919    
920      /**
921       * CallCharMethod:  invoke a virtual method that returns a char value
922       *                           arguments passed using the vararg ... style
923       * NOTE:  the vararg's are not visible in the method signature here;
924       *        they are saved in the caller frame and the glue frame
925       * @param env A JREF index for the JNI environment object
926       * @param objJREF a JREF index for the object instance
927       * @param methodID id of a MethodReference
928       * @return the char value returned from the method invocation
929       */
930      private static char CallCharMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
931        if (traceJNI) VM.sysWrite("JNI called: CallCharMethod  \n");
932        RuntimeEntrypoints.checkJNICountDownToGC();
933    
934        try {
935          Object obj = env.getJNIRef(objJREF);
936          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Char, false);
937          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
938        } catch (Throwable unexpected) {
939          if (traceJNI) unexpected.printStackTrace(System.err);
940          env.recordException(unexpected);
941          return 0;
942        }
943      }
944    
945      /**
946       * CallCharMethodV:  invoke a virtual method that returns a char value
947       * @param env A JREF index for the JNI environment object
948       * @param objJREF a JREF index for the object instance
949       * @param methodID id of a MethodReference
950       * @param argAddress a raw address to a variable argument list, each element is
951       *              1-word or 2-words of the appropriate type for the method invocation
952       * @return the char value returned from the method invocation
953       */
954      private static char CallCharMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
955          throws Exception {
956        if (traceJNI) VM.sysWrite("JNI called: CallCharMethodV  \n");
957        RuntimeEntrypoints.checkJNICountDownToGC();
958    
959        try {
960          Object obj = env.getJNIRef(objJREF);
961          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Char, false);
962          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
963        } catch (Throwable unexpected) {
964          if (traceJNI) unexpected.printStackTrace(System.err);
965          env.recordException(unexpected);
966          return 0;
967        }
968      }
969    
970      /**
971       * CallCharMethodA:  invoke a virtual method that returns a char value
972       * @param env A JREF index for the JNI environment object
973       * @param objJREF a JREF index for the object instance
974       * @param methodID id of a MethodReference
975       * @param argAddress a raw address to an array of unions in C, each element is 2-word
976       *        and hold an argument of the appropriate type for the method invocation
977       * @return the char value returned from the method invocation
978       */
979      private static char CallCharMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
980          throws Exception {
981        if (traceJNI) VM.sysWrite("JNI called: CallCharMethodA  \n");
982        RuntimeEntrypoints.checkJNICountDownToGC();
983    
984        try {
985          Object obj = env.getJNIRef(objJREF);
986          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Char, false);
987          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
988        } catch (Throwable unexpected) {
989          if (traceJNI) unexpected.printStackTrace(System.err);
990          env.recordException(unexpected);
991          return 0;
992        }
993      }
994    
995      /**
996       * CallShortMethod:  invoke a virtual method that returns a short value
997       *                           arguments passed using the vararg ... style
998       * NOTE:  the vararg's are not visible in the method signature here;
999       *        they are saved in the caller frame and the glue frame
1000       * @param env A JREF index for the JNI environment object
1001       * @param objJREF a JREF index for the object instance
1002       * @param methodID id of a MethodReference
1003       * @return the short value returned from the method invocation
1004       */
1005      private static short CallShortMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
1006        if (traceJNI) VM.sysWrite("JNI called: CallShortMethod  \n");
1007        RuntimeEntrypoints.checkJNICountDownToGC();
1008    
1009        try {
1010          Object obj = env.getJNIRef(objJREF);
1011          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Short, false);
1012          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
1013        } catch (Throwable unexpected) {
1014          if (traceJNI) unexpected.printStackTrace(System.err);
1015          env.recordException(unexpected);
1016          return 0;
1017        }
1018      }
1019    
1020      /**
1021       * CallShortMethodV:  invoke a virtual method that returns a short value
1022       * @param env A JREF index for the JNI environment object
1023       * @param objJREF a JREF index for the object instance
1024       * @param methodID id of a MethodReference
1025       * @param argAddress a raw address to a variable argument list, each element is
1026       *              1-word or 2-words of the appropriate type for the method invocation
1027       * @return the short value returned from the method invocation
1028       */
1029      private static short CallShortMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1030          throws Exception {
1031        if (traceJNI) VM.sysWrite("JNI called: CallShortMethodV  \n");
1032        RuntimeEntrypoints.checkJNICountDownToGC();
1033    
1034        try {
1035          Object obj = env.getJNIRef(objJREF);
1036          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Short, false);
1037          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
1038        } catch (Throwable unexpected) {
1039          if (traceJNI) unexpected.printStackTrace(System.err);
1040          env.recordException(unexpected);
1041          return 0;
1042        }
1043      }
1044    
1045      /**
1046       * CallShortMethodA:  invoke a virtual method that returns a short value
1047       * @param env A JREF index for the JNI environment object
1048       * @param objJREF a JREF index for the object instance
1049       * @param methodID id of a MethodReference
1050       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1051       *        and hold an argument of the appropriate type for the method invocation
1052       * @return the short value returned from the method invocation
1053       */
1054      private static short CallShortMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1055          throws Exception {
1056        if (traceJNI) VM.sysWrite("JNI called: CallShortMethodA  \n");
1057        RuntimeEntrypoints.checkJNICountDownToGC();
1058    
1059        try {
1060          Object obj = env.getJNIRef(objJREF);
1061          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Short, false);
1062          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
1063        } catch (Throwable unexpected) {
1064          if (traceJNI) unexpected.printStackTrace(System.err);
1065          env.recordException(unexpected);
1066          return 0;
1067        }
1068      }
1069    
1070      /**
1071       * CallIntMethod:  invoke a virtual method that returns a int value
1072       *                           arguments passed using the vararg ... style
1073       * NOTE:  the vararg's are not visible in the method signature here;
1074       *        they are saved in the caller frame and the glue frame
1075       * @param env A JREF index for the JNI environment object
1076       * @param objJREF a JREF index for the object instance
1077       * @param methodID id of a MethodReference
1078       * @return the int value returned from the method invocation
1079       */
1080      private static int CallIntMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
1081        if (traceJNI) VM.sysWrite("JNI called: CallIntMethod  \n");
1082        RuntimeEntrypoints.checkJNICountDownToGC();
1083    
1084        try {
1085          Object obj = env.getJNIRef(objJREF);
1086          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Int, false);
1087          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
1088        } catch (Throwable unexpected) {
1089          if (traceJNI) unexpected.printStackTrace(System.err);
1090          env.recordException(unexpected);
1091          return 0;
1092        }
1093      }
1094    
1095      /**
1096       * CallIntMethodV:  invoke a virtual method that returns an int value
1097       * @param env A JREF index for the JNI environment object
1098       * @param objJREF a JREF index for the object instance
1099       * @param methodID id of a MethodReference
1100       * @param argAddress a raw address to a variable argument list, each element is
1101       *              1-word or 2-words of the appropriate type for the method invocation
1102       * @return the int value returned from the method invocation
1103       */
1104      private static int CallIntMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1105          throws Exception {
1106        if (traceJNI) VM.sysWrite("JNI called: CallIntMethodV  \n");
1107        RuntimeEntrypoints.checkJNICountDownToGC();
1108    
1109        try {
1110          Object obj = env.getJNIRef(objJREF);
1111          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Int, false);
1112          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
1113        } catch (Throwable unexpected) {
1114          if (traceJNI) unexpected.printStackTrace(System.err);
1115          env.recordException(unexpected);
1116          return 0;
1117        }
1118      }
1119    
1120      /**
1121       * CallIntMethodA:  invoke a virtual method that returns an integer value
1122       * @param env A JREF index for the JNI environment object
1123       * @param objJREF a JREF index for the object instance
1124       * @param methodID id of a MethodReference
1125       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1126       *        and hold an argument of the appropriate type for the method invocation
1127       * @return the integer value returned from the method invocation
1128       */
1129      private static int CallIntMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1130          throws Exception {
1131        if (traceJNI) VM.sysWrite("JNI called: CallIntMethodA  \n");
1132        RuntimeEntrypoints.checkJNICountDownToGC();
1133    
1134        try {
1135          Object obj = env.getJNIRef(objJREF);
1136          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Int, false);
1137          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
1138        } catch (Throwable unexpected) {
1139          if (traceJNI) unexpected.printStackTrace(System.err);
1140          env.recordException(unexpected);
1141          return 0;
1142        }
1143      }
1144    
1145      /**
1146       * CallLongMethod:  invoke a virtual method that returns a long value
1147       *                           arguments passed using the vararg ... style
1148       * NOTE:  the vararg's are not visible in the method signature here;
1149       *        they are saved in the caller frame and the glue frame
1150       * @param env A JREF index for the JNI environment object
1151       * @param objJREF a JREF index for the object instance
1152       * @param methodID id of a MethodReference
1153       * @return the long value returned from the method invocation
1154       */
1155      private static long CallLongMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
1156        if (traceJNI) VM.sysWrite("JNI called: CallLongMethod  \n");
1157        RuntimeEntrypoints.checkJNICountDownToGC();
1158    
1159        try {
1160          Object obj = env.getJNIRef(objJREF);
1161          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Long, false);
1162          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
1163        } catch (Throwable unexpected) {
1164          if (traceJNI) unexpected.printStackTrace(System.err);
1165          env.recordException(unexpected);
1166          return 0;
1167        }
1168      }
1169    
1170      /**
1171       * CallLongMethodV:  invoke a virtual method that returns a long value
1172       * @param env A JREF index for the JNI environment object
1173       * @param objJREF a JREF index for the object instance
1174       * @param methodID id of a MethodReference
1175       * @param argAddress a raw address to a variable argument list, each element is
1176       *              1-word or 2-words of the appropriate type for the method invocation
1177       * @return the long value returned from the method invocation
1178       */
1179      private static long CallLongMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1180          throws Exception {
1181        if (traceJNI) VM.sysWrite("JNI called: CallLongMethodV  \n");
1182        RuntimeEntrypoints.checkJNICountDownToGC();
1183    
1184        try {
1185          Object obj = env.getJNIRef(objJREF);
1186          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Long, false);
1187          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
1188        } catch (Throwable unexpected) {
1189          if (traceJNI) unexpected.printStackTrace(System.err);
1190          env.recordException(unexpected);
1191          return 0;
1192        }
1193      }
1194    
1195      /**
1196       * CallLongMethodA:  invoke a virtual method that returns a long value
1197       * @param env A JREF index for the JNI environment object
1198       * @param objJREF a JREF index for the object instance
1199       * @param methodID id of a MethodReference
1200       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1201       *        and hold an argument of the appropriate type for the method invocation
1202       * @return the long value returned from the method invocation
1203       */
1204      private static long CallLongMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1205          throws Exception {
1206        if (traceJNI) VM.sysWrite("JNI called: CallLongMethodA  \n");
1207        RuntimeEntrypoints.checkJNICountDownToGC();
1208    
1209        try {
1210          Object obj = env.getJNIRef(objJREF);
1211          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Long, false);
1212          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
1213        } catch (Throwable unexpected) {
1214          if (traceJNI) unexpected.printStackTrace(System.err);
1215          env.recordException(unexpected);
1216          return 0;
1217        }
1218      }
1219    
1220      /**
1221       * CallFloatMethod:  invoke a virtual method that returns a float value
1222       *                           arguments passed using the vararg ... style
1223       * NOTE:  the vararg's are not visible in the method signature here;
1224       *        they are saved in the caller frame and the glue frame
1225       * @param env A JREF index for the JNI environment object
1226       * @param objJREF a JREF index for the object instance
1227       * @param methodID id of a MethodReference
1228       * @return the float value returned from the method invocation
1229       */
1230      private static float CallFloatMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
1231        if (traceJNI) VM.sysWrite("JNI called: CallFloatMethod  \n");
1232        RuntimeEntrypoints.checkJNICountDownToGC();
1233    
1234        try {
1235          Object obj = env.getJNIRef(objJREF);
1236          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Float, false);
1237          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
1238        } catch (Throwable unexpected) {
1239          if (traceJNI) unexpected.printStackTrace(System.err);
1240          env.recordException(unexpected);
1241          return 0;
1242        }
1243      }
1244    
1245      /**
1246       * CallFloatMethodV:  invoke a virtual method that returns a float value
1247       * @param env A JREF index for the JNI environment object
1248       * @param objJREF a JREF index for the object instance
1249       * @param methodID id of a MethodReference
1250       * @param argAddress a raw address to a variable argument list, each element is
1251       *              1-word or 2-words of the appropriate type for the method invocation
1252       * @return the float value returned from the method invocation
1253       */
1254      private static float CallFloatMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1255          throws Exception {
1256        if (traceJNI) VM.sysWrite("JNI called: CallFloatMethodV  \n");
1257        RuntimeEntrypoints.checkJNICountDownToGC();
1258    
1259        try {
1260          Object obj = env.getJNIRef(objJREF);
1261          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Float, false);
1262          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
1263        } catch (Throwable unexpected) {
1264          if (traceJNI) unexpected.printStackTrace(System.err);
1265          env.recordException(unexpected);
1266          return 0;
1267        }
1268      }
1269    
1270      /**
1271       * CallFloatMethodA:  invoke a virtual method that returns a float value
1272       * @param env A JREF index for the JNI environment object
1273       * @param objJREF a JREF index for the object instance
1274       * @param methodID id of a MethodReference
1275       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1276       *        and hold an argument of the appropriate type for the method invocation
1277       * @return the float value returned from the method invocation
1278       */
1279      private static float CallFloatMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1280          throws Exception {
1281        if (traceJNI) VM.sysWrite("JNI called: CallFloatMethodA  \n");
1282        RuntimeEntrypoints.checkJNICountDownToGC();
1283    
1284        try {
1285          Object obj = env.getJNIRef(objJREF);
1286          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Float, false);
1287          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
1288        } catch (Throwable unexpected) {
1289          if (traceJNI) unexpected.printStackTrace(System.err);
1290          env.recordException(unexpected);
1291          return 0;
1292        }
1293      }
1294    
1295      /**
1296       * CallDoubleMethod:  invoke a virtual method that returns a double value
1297       *                           arguments passed using the vararg ... style
1298       * NOTE:  the vararg's are not visible in the method signature here;
1299       *        they are saved in the caller frame and the glue frame
1300       * @param env A JREF index for the JNI environment object
1301       * @param objJREF a JREF index for the object instance
1302       * @param methodID id of a MethodReference
1303       * @return the double value returned from the method invocation
1304       */
1305      private static double CallDoubleMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
1306        if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethod  \n");
1307        RuntimeEntrypoints.checkJNICountDownToGC();
1308    
1309        try {
1310          Object obj = env.getJNIRef(objJREF);
1311          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Double, false);
1312          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
1313        } catch (Throwable unexpected) {
1314          if (traceJNI) unexpected.printStackTrace(System.err);
1315          env.recordException(unexpected);
1316          return 0;
1317        }
1318      }
1319    
1320      /**
1321       * CallDoubleMethodV:  invoke a virtual method that returns a double value
1322       * @param env A JREF index for the JNI environment object
1323       * @param objJREF a JREF index for the object instance
1324       * @param methodID id of a MethodReference
1325       * @param argAddress a raw address to a variable argument list, each element is
1326       *              1-word or 2-words of the appropriate type for the method invocation
1327       * @return the double value returned from the method invocation
1328       */
1329      private static double CallDoubleMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1330          throws Exception {
1331        if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethodV  \n");
1332        RuntimeEntrypoints.checkJNICountDownToGC();
1333    
1334        try {
1335          Object obj = env.getJNIRef(objJREF);
1336          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Double, false);
1337          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
1338        } catch (Throwable unexpected) {
1339          if (traceJNI) unexpected.printStackTrace(System.err);
1340          env.recordException(unexpected);
1341          return 0;
1342        }
1343      }
1344    
1345      /**
1346       * CallDoubleMethodA:  invoke a virtual method that returns a double value
1347       * @param env A JREF index for the JNI environment object
1348       * @param objJREF a JREF index for the object instance
1349       * @param methodID id of a MethodReference
1350       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1351       *        and hold an argument of the appropriate type for the method invocation
1352       * @return the double value returned from the method invocation
1353       */
1354      private static double CallDoubleMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1355          throws Exception {
1356        if (traceJNI) VM.sysWrite("JNI called: CallDoubleMethodA  \n");
1357        RuntimeEntrypoints.checkJNICountDownToGC();
1358    
1359        try {
1360          Object obj = env.getJNIRef(objJREF);
1361          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Double, false);
1362          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
1363        } catch (Throwable unexpected) {
1364          if (traceJNI) unexpected.printStackTrace(System.err);
1365          env.recordException(unexpected);
1366          return 0;
1367        }
1368      }
1369    
1370      /**
1371       * CallVoidMethod:  invoke a virtual method that returns a void value
1372       *                           arguments passed using the vararg ... style
1373       * NOTE:  the vararg's are not visible in the method signature here;
1374       *        they are saved in the caller frame and the glue frame
1375       * @param env A JREF index for the JNI environment object
1376       * @param objJREF a JREF index for the object instance
1377       * @param methodID id of a MethodReference
1378       */
1379      private static void CallVoidMethod(JNIEnvironment env, int objJREF, int methodID) throws Exception {
1380        if (traceJNI) VM.sysWrite("JNI called: CallVoidMethod  \n");
1381        RuntimeEntrypoints.checkJNICountDownToGC();
1382    
1383        try {
1384          Object obj = env.getJNIRef(objJREF);
1385          JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Void, false);
1386        } catch (Throwable unexpected) {
1387          if (traceJNI) unexpected.printStackTrace(System.err);
1388          env.recordException(unexpected);
1389        }
1390      }
1391    
1392      /**
1393       * CallVoidMethodV:  invoke a virtual method that returns void
1394       * @param env A JREF index for the JNI environment object
1395       * @param objJREF a JREF index for the object instance
1396       * @param methodID id of a MethodReference
1397       * @param argAddress a raw address to a variable argument list, each element is
1398       *              1-word or 2-words of the appropriate type for the method invocation
1399       */
1400      private static void CallVoidMethodV(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1401          throws Exception {
1402        if (traceJNI) VM.sysWrite("JNI called: CallVoidMethodV  \n");
1403        RuntimeEntrypoints.checkJNICountDownToGC();
1404    
1405        try {
1406          Object obj = env.getJNIRef(objJREF);
1407          JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Void, false);
1408        } catch (Throwable unexpected) {
1409          if (traceJNI) unexpected.printStackTrace(System.err);
1410          env.recordException(unexpected);
1411        }
1412      }
1413    
1414      /**
1415       * CallVoidMethodA:  invoke a virtual method that returns void
1416       * @param env A JREF index for the JNI environment object
1417       * @param objJREF a JREF index for the object instance
1418       * @param methodID id of a MethodReference
1419       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1420       *        and hold an argument of the appropriate type for the method invocation
1421       */
1422      private static void CallVoidMethodA(JNIEnvironment env, int objJREF, int methodID, Address argAddress)
1423          throws Exception {
1424        if (traceJNI) VM.sysWrite("JNI called: CallVoidMethodA  \n");
1425        RuntimeEntrypoints.checkJNICountDownToGC();
1426    
1427        try {
1428          Object obj = env.getJNIRef(objJREF);
1429          JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Void, false);
1430        } catch (Throwable unexpected) {
1431          if (traceJNI) unexpected.printStackTrace(System.err);
1432          env.recordException(unexpected);
1433        }
1434      }
1435    
1436      /**
1437       * CallNonvirtualObjectMethod:  invoke a virtual method that returns an object
1438       *                           arguments passed using the vararg ... style
1439       * NOTE:  the vararg's are not visible in the method signature here;
1440       *        they are saved in the caller frame and the glue frame
1441       * @param env A JREF index for the JNI environment object
1442       * @param objJREF a JREF index for the object instance
1443       * @param classJREF a JREF index for the class object that declares this method
1444       * @param methodID id of a MethodReference
1445       * @return the JREF index for the object returned from the method invocation
1446       */
1447      private static int CallNonvirtualObjectMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1448          throws Exception {
1449        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethod  \n");
1450        RuntimeEntrypoints.checkJNICountDownToGC();
1451    
1452        try {
1453          Object obj = env.getJNIRef(objJREF);
1454          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, null, true);
1455          return env.pushJNIRef(returnObj);
1456        } catch (Throwable unexpected) {
1457          if (traceJNI) unexpected.printStackTrace(System.err);
1458          env.recordException(unexpected);
1459          return 0;
1460        }
1461      }
1462    
1463      /**
1464       * CallNonvirtualObjectMethodV:  invoke a virtual method that returns an object
1465       * @param env A JREF index for the JNI environment object
1466       * @param objJREF a JREF index for the object instance
1467       * @param classJREF a JREF index for the class object that declares this method
1468       * @param methodID id of a MethodReference
1469       * @param argAddress a raw address to a variable argument list, each element is
1470       *              1-word or 2-words of the appropriate type for the method invocation
1471       * @return the JREF index for the object returned from the method invocation
1472       */
1473      private static int CallNonvirtualObjectMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1474                                                     Address argAddress) throws Exception {
1475        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethodV  \n");
1476        RuntimeEntrypoints.checkJNICountDownToGC();
1477    
1478        try {
1479          Object obj = env.getJNIRef(objJREF);
1480          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, null, true);
1481          return env.pushJNIRef(returnObj);
1482        } catch (Throwable unexpected) {
1483          if (traceJNI) unexpected.printStackTrace(System.err);
1484          env.recordException(unexpected);
1485          return 0;
1486        }
1487      }
1488    
1489      /**
1490       * CallNonvirtualNonvirtualObjectMethodA:  invoke a virtual method that returns an object value
1491       * @param env A JREF index for the JNI environment object
1492       * @param objJREF a JREF index for the object instance
1493       * @param classJREF a JREF index for the class object that declares this method
1494       * @param methodID id of a MethodReference
1495       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1496       *        and hold an argument of the appropriate type for the method invocation
1497       * @return the JREF index for the object returned from the method invocation
1498       */
1499      private static int CallNonvirtualObjectMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1500                                                     Address argAddress) throws Exception {
1501        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualObjectMethodA  \n");
1502        RuntimeEntrypoints.checkJNICountDownToGC();
1503    
1504        try {
1505          Object obj = env.getJNIRef(objJREF);
1506          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, null, true);
1507          return env.pushJNIRef(returnObj);
1508        } catch (Throwable unexpected) {
1509          if (traceJNI) unexpected.printStackTrace(System.err);
1510          env.recordException(unexpected);
1511          return 0;
1512        }
1513      }
1514    
1515      /**
1516       * CallNonvirtualBooleanMethod:  invoke a virtual method that returns a boolean value
1517       *                           arguments passed using the vararg ... style
1518       * NOTE:  the vararg's are not visible in the method signature here;
1519       *        they are saved in the caller frame and the glue frame
1520       * @param env A JREF index for the JNI environment object
1521       * @param objJREF a JREF index for the object instance
1522       * @param classJREF a JREF index for the class object that declares this method
1523       * @param methodID id of a MethodReference
1524       * @return the boolean value returned from the method invocation
1525       */
1526      private static boolean CallNonvirtualBooleanMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1527          throws Exception {
1528        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethod  \n");
1529        RuntimeEntrypoints.checkJNICountDownToGC();
1530    
1531        try {
1532          Object obj = env.getJNIRef(objJREF);
1533          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Boolean, true);
1534          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
1535        } catch (Throwable unexpected) {
1536          if (traceJNI) unexpected.printStackTrace(System.err);
1537          env.recordException(unexpected);
1538          return false;
1539        }
1540      }
1541    
1542      /**
1543       * CallNonvirtualBooleanMethodV:  invoke a virtual method that returns a boolean value
1544       * @param env A JREF index for the JNI environment object
1545       * @param objJREF a JREF index for the object instance
1546       * @param classJREF a JREF index for the class object that declares this method
1547       * @param methodID id of a MethodReference
1548       * @param argAddress a raw address to a variable argument list, each element is
1549       *              1-word or 2-words of the appropriate type for the method invocation
1550       * @return the boolean value returned from the method invocation
1551       */
1552      private static boolean CallNonvirtualBooleanMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1553                                                          Address argAddress) throws Exception {
1554        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethodV  \n");
1555        RuntimeEntrypoints.checkJNICountDownToGC();
1556    
1557        try {
1558          Object obj = env.getJNIRef(objJREF);
1559          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Boolean, true);
1560          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
1561        } catch (Throwable unexpected) {
1562          if (traceJNI) unexpected.printStackTrace(System.err);
1563          env.recordException(unexpected);
1564          return false;
1565        }
1566      }
1567    
1568      /**
1569       * CallNonvirtualBooleanMethodA:  invoke a virtual method that returns a boolean value
1570       * @param env A JREF index for the JNI environment object
1571       * @param objJREF a JREF index for the object instance
1572       * @param classJREF a JREF index for the class object that declares this method
1573       * @param methodID id of a MethodReference
1574       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1575       *        and hold an argument of the appropriate type for the method invocation
1576       * @return the boolean value returned from the method invocation
1577       */
1578      private static boolean CallNonvirtualBooleanMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1579                                                          Address argAddress) throws Exception {
1580        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualBooleanMethodA  \n");
1581        RuntimeEntrypoints.checkJNICountDownToGC();
1582    
1583        try {
1584          Object obj = env.getJNIRef(objJREF);
1585          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Boolean, true);
1586          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
1587        } catch (Throwable unexpected) {
1588          if (traceJNI) unexpected.printStackTrace(System.err);
1589          env.recordException(unexpected);
1590          return false;
1591        }
1592      }
1593    
1594      /**
1595       * CallNonvirtualByteMethod:  invoke a virtual method that returns a byte value
1596       *                           arguments passed using the vararg ... style
1597       * NOTE:  the vararg's are not visible in the method signature here;
1598       *        they are saved in the caller frame and the glue frame
1599       * @param env A JREF index for the JNI environment object
1600       * @param objJREF a JREF index for the object instance
1601       * @param classJREF a JREF index for the class object that declares this method
1602       * @param methodID id of a MethodReference
1603       * @return the byte value returned from the method invocation
1604       */
1605      private static byte CallNonvirtualByteMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1606          throws Exception {
1607        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethod  \n");
1608        RuntimeEntrypoints.checkJNICountDownToGC();
1609    
1610        try {
1611          Object obj = env.getJNIRef(objJREF);
1612          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Byte, true);
1613          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
1614        } catch (Throwable unexpected) {
1615          if (traceJNI) unexpected.printStackTrace(System.err);
1616          env.recordException(unexpected);
1617          return 0;
1618        }
1619      }
1620    
1621      /**
1622       * CallNonvirtualByteMethodV:  invoke a virtual method that returns a byte value
1623       * @param env A JREF index for the JNI environment object
1624       * @param objJREF a JREF index for the object instance
1625       * @param methodID id of a MethodReference
1626       * @param classJREF a JREF index for the class object that declares this method
1627       * @param argAddress a raw address to a variable argument list, each element is
1628       *              1-word or 2-words of the appropriate type for the method invocation
1629       * @return the byte value returned from the method invocation
1630       */
1631      private static byte CallNonvirtualByteMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1632                                                    Address argAddress) throws Exception {
1633        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethodV  \n");
1634        RuntimeEntrypoints.checkJNICountDownToGC();
1635    
1636        try {
1637          Object obj = env.getJNIRef(objJREF);
1638          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Byte, true);
1639          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
1640        } catch (Throwable unexpected) {
1641          if (traceJNI) unexpected.printStackTrace(System.err);
1642          env.recordException(unexpected);
1643          return 0;
1644        }
1645      }
1646    
1647      /**
1648       * CallNonvirtualByteMethodA:  invoke a virtual method that returns a byte value
1649       * @param env A JREF index for the JNI environment object
1650       * @param objJREF a JREF index for the object instance
1651       * @param methodID id of a MethodReference
1652       * @param classJREF a JREF index for the class object that declares this method
1653       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1654       *        and hold an argument of the appropriate type for the method invocation
1655       * @return the byte value returned from the method invocation
1656       */
1657      private static byte CallNonvirtualByteMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1658                                                    Address argAddress) throws Exception {
1659        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualByteMethodA  \n");
1660        RuntimeEntrypoints.checkJNICountDownToGC();
1661    
1662        try {
1663          Object obj = env.getJNIRef(objJREF);
1664          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Byte, true);
1665          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
1666        } catch (Throwable unexpected) {
1667          if (traceJNI) unexpected.printStackTrace(System.err);
1668          env.recordException(unexpected);
1669          return 0;
1670        }
1671      }
1672    
1673      /**
1674       * CallNonvirtualCharMethod:  invoke a virtual method that returns a char value
1675       *                           arguments passed using the vararg ... style
1676       * NOTE:  the vararg's are not visible in the method signature here;
1677       *        they are saved in the caller frame and the glue frame
1678       * @param env A JREF index for the JNI environment object
1679       * @param objJREF a JREF index for the object instance
1680       * @param classJREF a JREF index for the class object that declares this method
1681       * @param methodID id of a MethodReference
1682       * @return the char value returned from the method invocation
1683       */
1684      private static char CallNonvirtualCharMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1685          throws Exception {
1686        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethod  \n");
1687        RuntimeEntrypoints.checkJNICountDownToGC();
1688    
1689        try {
1690          Object obj = env.getJNIRef(objJREF);
1691          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Char, true);
1692          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
1693        } catch (Throwable unexpected) {
1694          if (traceJNI) unexpected.printStackTrace(System.err);
1695          env.recordException(unexpected);
1696          return 0;
1697        }
1698      }
1699    
1700      /**
1701       * CallNonvirtualCharMethodV:  invoke a virtual method that returns a char value
1702       * @param env A JREF index for the JNI environment object
1703       * @param objJREF a JREF index for the object instance
1704       * @param classJREF a JREF index for the class object that declares this method
1705       * @param methodID id of a MethodReference
1706       * @param argAddress a raw address to a variable argument list, each element is
1707       *              1-word or 2-words of the appropriate type for the method invocation
1708       * @return the char value returned from the method invocation
1709       */
1710      private static char CallNonvirtualCharMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1711                                                    Address argAddress) throws Exception {
1712        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethodV  \n");
1713        RuntimeEntrypoints.checkJNICountDownToGC();
1714    
1715        try {
1716          Object obj = env.getJNIRef(objJREF);
1717          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Char, true);
1718          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
1719        } catch (Throwable unexpected) {
1720          if (traceJNI) unexpected.printStackTrace(System.err);
1721          env.recordException(unexpected);
1722          return 0;
1723        }
1724      }
1725    
1726      /**
1727       * CallNonvirtualCharMethodA:  invoke a virtual method that returns a char value
1728       * @param env A JREF index for the JNI environment object
1729       * @param objJREF a JREF index for the object instance
1730       * @param classJREF a JREF index for the class object that declares this method
1731       * @param methodID id of a MethodReference
1732       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1733       *        and hold an argument of the appropriate type for the method invocation
1734       * @return the char value returned from the method invocation
1735       */
1736      private static char CallNonvirtualCharMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1737                                                    Address argAddress) throws Exception {
1738        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualCharMethodA  \n");
1739        RuntimeEntrypoints.checkJNICountDownToGC();
1740    
1741        try {
1742          Object obj = env.getJNIRef(objJREF);
1743          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Char, true);
1744          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
1745        } catch (Throwable unexpected) {
1746          if (traceJNI) unexpected.printStackTrace(System.err);
1747          env.recordException(unexpected);
1748          return 0;
1749        }
1750      }
1751    
1752      /**
1753       * CallNonvirtualShortMethod:  invoke a virtual method that returns a short value
1754       *                           arguments passed using the vararg ... style
1755       * NOTE:  the vararg's are not visible in the method signature here;
1756       *        they are saved in the caller frame and the glue frame
1757       * @param env A JREF index for the JNI environment object
1758       * @param objJREF a JREF index for the object instance
1759       * @param classJREF a JREF index for the class object that declares this method
1760       * @param methodID id of a MethodReference
1761       * @return the short value returned from the method invocation
1762       */
1763      private static short CallNonvirtualShortMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1764          throws Exception {
1765        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethod  \n");
1766        RuntimeEntrypoints.checkJNICountDownToGC();
1767    
1768        try {
1769          Object obj = env.getJNIRef(objJREF);
1770          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Short, true);
1771          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
1772        } catch (Throwable unexpected) {
1773          if (traceJNI) unexpected.printStackTrace(System.err);
1774          env.recordException(unexpected);
1775          return 0;
1776        }
1777      }
1778    
1779      /**
1780       * CallNonvirtualShortMethodV:  invoke a virtual method that returns a short value
1781       * @param env A JREF index for the JNI environment object
1782       * @param objJREF a JREF index for the object instance
1783       * @param classJREF a JREF index for the class object that declares this method
1784       * @param methodID id of a MethodReference
1785       * @param argAddress a raw address to a variable argument list, each element is
1786       *              1-word or 2-words of the appropriate type for the method invocation
1787       * @return the short value returned from the method invocation
1788       */
1789      private static short CallNonvirtualShortMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1790                                                      Address argAddress) throws Exception {
1791        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethodV  \n");
1792        RuntimeEntrypoints.checkJNICountDownToGC();
1793    
1794        try {
1795          Object obj = env.getJNIRef(objJREF);
1796          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Short, true);
1797          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
1798        } catch (Throwable unexpected) {
1799          if (traceJNI) unexpected.printStackTrace(System.err);
1800          env.recordException(unexpected);
1801          return 0;
1802        }
1803      }
1804    
1805      /**
1806       * CallNonvirtualShortMethodA:  invoke a virtual method that returns a short value
1807       * @param env A JREF index for the JNI environment object
1808       * @param objJREF a JREF index for the object instance
1809       * @param classJREF a JREF index for the class object that declares this method
1810       * @param methodID id of a MethodReference
1811       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1812       *        and hold an argument of the appropriate type for the method invocation
1813       * @return the short value returned from the method invocation
1814       */
1815      private static short CallNonvirtualShortMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1816                                                      Address argAddress) throws Exception {
1817        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualShortMethodA  \n");
1818        RuntimeEntrypoints.checkJNICountDownToGC();
1819    
1820        try {
1821          Object obj = env.getJNIRef(objJREF);
1822          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Short, true);
1823          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
1824        } catch (Throwable unexpected) {
1825          if (traceJNI) unexpected.printStackTrace(System.err);
1826          env.recordException(unexpected);
1827          return 0;
1828        }
1829      }
1830    
1831      /**
1832       * CallNonvirtualIntMethod:  invoke a virtual method that returns a int value
1833       *                           arguments passed using the vararg ... style
1834       * NOTE:  the vararg's are not visible in the method signature here;
1835       *        they are saved in the caller frame and the glue frame
1836       * @param env A JREF index for the JNI environment object
1837       * @param objJREF a JREF index for the object instance
1838       * @param classJREF a JREF index for the class object that declares this method
1839       * @param methodID id of a MethodReference
1840       * @return the int value returned from the method invocation
1841       */
1842      private static int CallNonvirtualIntMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1843          throws Exception {
1844        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethod  \n");
1845        RuntimeEntrypoints.checkJNICountDownToGC();
1846    
1847        try {
1848          Object obj = env.getJNIRef(objJREF);
1849          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Int, true);
1850          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
1851        } catch (Throwable unexpected) {
1852          if (traceJNI) unexpected.printStackTrace(System.err);
1853          env.recordException(unexpected);
1854          return 0;
1855        }
1856      }
1857    
1858      /**
1859       * CallNonvirtualIntMethodV:  invoke a virtual method that returns an int value
1860       * @param env A JREF index for the JNI environment object
1861       * @param objJREF a JREF index for the object instance
1862       * @param classJREF a JREF index for the class object that declares this method
1863       * @param methodID id of a MethodReference
1864       * @param argAddress a raw address to a variable argument list, each element is
1865       *              1-word or 2-words of the appropriate type for the method invocation
1866       * @return the int value returned from the method invocation
1867       */
1868      private static int CallNonvirtualIntMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1869                                                  Address argAddress) throws Exception {
1870        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethodV  \n");
1871        RuntimeEntrypoints.checkJNICountDownToGC();
1872    
1873        try {
1874          Object obj = env.getJNIRef(objJREF);
1875          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Int, true);
1876          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
1877        } catch (Throwable unexpected) {
1878          if (traceJNI) unexpected.printStackTrace(System.err);
1879          env.recordException(unexpected);
1880          return 0;
1881        }
1882      }
1883    
1884      /**
1885       * CallNonvirtualIntMethodA:  invoke a virtual method that returns an integer value
1886       * @param env A JREF index for the JNI environment object
1887       * @param objJREF a JREF index for the object instance
1888       * @param classJREF a JREF index for the class object that declares this method
1889       * @param methodID id of a MethodReference
1890       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1891       *        and hold an argument of the appropriate type for the method invocation
1892       * @return the integer value returned from the method invocation
1893       */
1894      private static int CallNonvirtualIntMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1895                                                  Address argAddress) throws Exception {
1896        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualIntMethodA  \n");
1897        RuntimeEntrypoints.checkJNICountDownToGC();
1898    
1899        try {
1900          Object obj = env.getJNIRef(objJREF);
1901          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Int, true);
1902          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
1903        } catch (Throwable unexpected) {
1904          if (traceJNI) unexpected.printStackTrace(System.err);
1905          env.recordException(unexpected);
1906          return 0;
1907        }
1908      }
1909    
1910      /**
1911       * CallNonvirtualLongMethod:  invoke a virtual method that returns a long value
1912       *                           arguments passed using the vararg ... style
1913       * NOTE:  the vararg's are not visible in the method signature here;
1914       *        they are saved in the caller frame and the glue frame
1915       * @param env A JREF index for the JNI environment object
1916       * @param objJREF a JREF index for the object instance
1917       * @param classJREF a JREF index for the class object that declares this method
1918       * @param methodID id of a MethodReference
1919       * @return the long value returned from the method invocation
1920       */
1921      private static long CallNonvirtualLongMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
1922          throws Exception {
1923        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethod  \n");
1924        RuntimeEntrypoints.checkJNICountDownToGC();
1925    
1926        try {
1927          Object obj = env.getJNIRef(objJREF);
1928          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Long, true);
1929          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
1930        } catch (Throwable unexpected) {
1931          if (traceJNI) unexpected.printStackTrace(System.err);
1932          env.recordException(unexpected);
1933          return 0;
1934        }
1935      }
1936    
1937      /**
1938       * CallNonvirtualLongMethodV:  invoke a virtual method that returns a long value
1939       * @param env A JREF index for the JNI environment object
1940       * @param objJREF a JREF index for the object instance
1941       * @param classJREF a JREF index for the class object that declares this method
1942       * @param methodID id of a MethodReference
1943       * @param argAddress a raw address to a variable argument list, each element is
1944       *              1-word or 2-words of the appropriate type for the method invocation
1945       * @return the long value returned from the method invocation
1946       */
1947      private static long CallNonvirtualLongMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1948                                                    Address argAddress) throws Exception {
1949        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethodV  \n");
1950        RuntimeEntrypoints.checkJNICountDownToGC();
1951    
1952        try {
1953          Object obj = env.getJNIRef(objJREF);
1954          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Long, true);
1955          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
1956        } catch (Throwable unexpected) {
1957          if (traceJNI) unexpected.printStackTrace(System.err);
1958          env.recordException(unexpected);
1959          return 0;
1960        }
1961      }
1962    
1963      /**
1964       * CallNonvirtualLongMethodA:  invoke a virtual method that returns a long value
1965       * @param env A JREF index for the JNI environment object
1966       * @param objJREF a JREF index for the object instance
1967       * @param classJREF a JREF index for the class object that declares this method
1968       * @param methodID id of a MethodReference
1969       * @param argAddress a raw address to an array of unions in C, each element is 2-word
1970       *        and hold an argument of the appropriate type for the method invocation
1971       * @return the long value returned from the method invocation
1972       */
1973      private static long CallNonvirtualLongMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
1974                                                    Address argAddress) throws Exception {
1975        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualLongMethodA  \n");
1976        RuntimeEntrypoints.checkJNICountDownToGC();
1977    
1978        try {
1979          Object obj = env.getJNIRef(objJREF);
1980          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Long, true);
1981          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
1982        } catch (Throwable unexpected) {
1983          if (traceJNI) unexpected.printStackTrace(System.err);
1984          env.recordException(unexpected);
1985          return 0;
1986        }
1987      }
1988    
1989      /**
1990       * CallNonvirtualFloatMethod:  invoke a virtual method that returns a float value
1991       *                           arguments passed using the vararg ... style
1992       * NOTE:  the vararg's are not visible in the method signature here;
1993       *        they are saved in the caller frame and the glue frame
1994       * @param env A JREF index for the JNI environment object
1995       * @param objJREF a JREF index for the object instance
1996       * @param classJREF a JREF index for the class object that declares this method
1997       * @param methodID id of a MethodReference
1998       * @return the float value returned from the method invocation
1999       */
2000      private static float CallNonvirtualFloatMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
2001          throws Exception {
2002        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethod  \n");
2003        RuntimeEntrypoints.checkJNICountDownToGC();
2004    
2005        try {
2006          Object obj = env.getJNIRef(objJREF);
2007          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Float, true);
2008          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
2009        } catch (Throwable unexpected) {
2010          if (traceJNI) unexpected.printStackTrace(System.err);
2011          env.recordException(unexpected);
2012          return 0;
2013        }
2014      }
2015    
2016      /**
2017       * CallNonvirtualFloatMethodV:  invoke a virtual method that returns a float value
2018       * @param env A JREF index for the JNI environment object
2019       * @param objJREF a JREF index for the object instance
2020       * @param classJREF a JREF index for the class object that declares this method
2021       * @param methodID id of a MethodReference
2022       * @param argAddress a raw address to a variable argument list, each element is
2023       *              1-word or 2-words of the appropriate type for the method invocation
2024       * @return the float value returned from the method invocation
2025       */
2026      private static float CallNonvirtualFloatMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
2027                                                      Address argAddress) throws Exception {
2028        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethodV  \n");
2029        RuntimeEntrypoints.checkJNICountDownToGC();
2030    
2031        try {
2032          Object obj = env.getJNIRef(objJREF);
2033          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Float, true);
2034          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
2035        } catch (Throwable unexpected) {
2036          if (traceJNI) unexpected.printStackTrace(System.err);
2037          env.recordException(unexpected);
2038          return 0;
2039        }
2040      }
2041    
2042      /**
2043       * CallNonvirtualFloatMethodA:  invoke a virtual method that returns a float value
2044       * @param env A JREF index for the JNI environment object
2045       * @param objJREF a JREF index for the object instance
2046       * @param classJREF a JREF index for the class object that declares this method
2047       * @param methodID id of a MethodReference
2048       * @param argAddress a raw address to an array of unions in C, each element is 2-word
2049       *        and hold an argument of the appropriate type for the method invocation
2050       * @return the float value returned from the method invocation
2051       */
2052      private static float CallNonvirtualFloatMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
2053                                                      Address argAddress) throws Exception {
2054        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualFloatMethodA  \n");
2055        RuntimeEntrypoints.checkJNICountDownToGC();
2056    
2057        try {
2058          Object obj = env.getJNIRef(objJREF);
2059          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Float, true);
2060          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
2061        } catch (Throwable unexpected) {
2062          if (traceJNI) unexpected.printStackTrace(System.err);
2063          env.recordException(unexpected);
2064          return 0;
2065        }
2066      }
2067    
2068      /**
2069       * CallNonvirtualDoubleMethod:  invoke a virtual method that returns a double value
2070       *                           arguments passed using the vararg ... style
2071       * NOTE:  the vararg's are not visible in the method signature here;
2072       *        they are saved in the caller frame and the glue frame
2073       * @param env A JREF index for the JNI environment object
2074       * @param objJREF a JREF index for the object instance
2075       * @param classJREF a JREF index for the class object that declares this method
2076       * @param methodID id of a MethodReference
2077       * @return the double value returned from the method invocation
2078       */
2079      private static double CallNonvirtualDoubleMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
2080          throws Exception {
2081        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethod  \n");
2082        RuntimeEntrypoints.checkJNICountDownToGC();
2083    
2084        try {
2085          Object obj = env.getJNIRef(objJREF);
2086          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Double, true);
2087          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
2088        } catch (Throwable unexpected) {
2089          if (traceJNI) unexpected.printStackTrace(System.err);
2090          env.recordException(unexpected);
2091          return 0;
2092        }
2093      }
2094    
2095      /**
2096       * CallNonvirtualDoubleMethodV:  invoke a virtual method that returns a double value
2097       * @param env A JREF index for the JNI environment object
2098       * @param objJREF a JREF index for the object instance
2099       * @param classJREF a JREF index for the class object that declares this method
2100       * @param methodID id of a MethodReference
2101       * @param argAddress a raw address to a variable argument list, each element is
2102       *              1-word or 2-words of the appropriate type for the method invocation
2103       * @return the double value returned from the method invocation
2104       */
2105      private static double CallNonvirtualDoubleMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
2106                                                        Address argAddress) throws Exception {
2107        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethodV  \n");
2108        RuntimeEntrypoints.checkJNICountDownToGC();
2109    
2110        try {
2111          Object obj = env.getJNIRef(objJREF);
2112          Object returnObj = JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Double, true);
2113          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
2114        } catch (Throwable unexpected) {
2115          if (traceJNI) unexpected.printStackTrace(System.err);
2116          env.recordException(unexpected);
2117          return 0;
2118        }
2119      }
2120    
2121      /**
2122       * CallNonvirtualDoubleMethodA:  invoke a virtual method that returns a double value
2123       * @param env A JREF index for the JNI environment object
2124       * @param objJREF a JREF index for the object instance
2125       * @param classJREF a JREF index for the class object that declares this method
2126       * @param methodID id of a MethodReference
2127       * @param argAddress a raw address to an array of unions in C, each element is 2-word
2128       *        and hold an argument of the appropriate type for the method invocation
2129       * @return the double value returned from the method invocation
2130       */
2131      private static double CallNonvirtualDoubleMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
2132                                                        Address argAddress) throws Exception {
2133        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualDoubleMethodA  \n");
2134        RuntimeEntrypoints.checkJNICountDownToGC();
2135    
2136        try {
2137          Object obj = env.getJNIRef(objJREF);
2138          Object returnObj = JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Double, true);
2139          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
2140        } catch (Throwable unexpected) {
2141          if (traceJNI) unexpected.printStackTrace(System.err);
2142          env.recordException(unexpected);
2143          return 0;
2144        }
2145      }
2146    
2147      /**
2148       * CallNonvirtualVoidMethod:  invoke a virtual method that returns a void value
2149       *                           arguments passed using the vararg ... style
2150       * NOTE:  the vararg's are not visible in the method signature here;
2151       *        they are saved in the caller frame and the glue frame
2152       * @param env A JREF index for the JNI environment object
2153       * @param objJREF a JREF index for the object instance
2154       * @param classJREF a JREF index for the class object that declares this method
2155       * @param methodID id of a MethodReference
2156       */
2157      private static void CallNonvirtualVoidMethod(JNIEnvironment env, int objJREF, int classJREF, int methodID)
2158          throws Exception {
2159        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethod  \n");
2160        RuntimeEntrypoints.checkJNICountDownToGC();
2161    
2162        try {
2163          Object obj = env.getJNIRef(objJREF);
2164          JNIHelpers.invokeWithDotDotVarArg(obj, methodID, TypeReference.Void, true);
2165        } catch (Throwable unexpected) {
2166          if (traceJNI) unexpected.printStackTrace(System.err);
2167          env.recordException(unexpected);
2168        }
2169      }
2170    
2171      /**
2172       * CallNonvirtualVoidMethodV:  invoke a virtual method that returns void
2173       * @param env A JREF index for the JNI environment object
2174       * @param objJREF a JREF index for the object instance
2175       * @param classJREF a JREF index for the class object that declares this method
2176       * @param methodID id of a MethodReference
2177       * @param argAddress a raw address to a variable argument list, each element is
2178       *              1-word or 2-words of the appropriate type for the method invocation
2179       */
2180      private static void CallNonvirtualVoidMethodV(JNIEnvironment env, int objJREF, int classJREF, int methodID,
2181                                                    Address argAddress) throws Exception {
2182        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethodV  \n");
2183        RuntimeEntrypoints.checkJNICountDownToGC();
2184    
2185        try {
2186          Object obj = env.getJNIRef(objJREF);
2187          JNIHelpers.invokeWithVarArg(obj, methodID, argAddress, TypeReference.Void, true);
2188        } catch (Throwable unexpected) {
2189          if (traceJNI) unexpected.printStackTrace(System.err);
2190          env.recordException(unexpected);
2191        }
2192      }
2193    
2194      /**
2195       * CallNonvirtualVoidMethodA:  invoke a virtual method that returns void
2196       * @param env A JREF index for the JNI environment object
2197       * @param objJREF a JREF index for the object instance
2198       * @param classJREF a JREF index for the class object that declares this method
2199       * @param methodID id of a MethodReference
2200       * @param argAddress a raw address to an array of unions in C, each element is 2-word
2201       *        and hold an argument of the appropriate type for the method invocation
2202       */
2203      private static void CallNonvirtualVoidMethodA(JNIEnvironment env, int objJREF, int classJREF, int methodID,
2204                                                    Address argAddress) throws Exception {
2205        if (traceJNI) VM.sysWrite("JNI called: CallNonvirtualVoidMethodA  \n");
2206        RuntimeEntrypoints.checkJNICountDownToGC();
2207    
2208        try {
2209          Object obj = env.getJNIRef(objJREF);
2210          JNIHelpers.invokeWithJValue(obj, methodID, argAddress, TypeReference.Void, true);
2211        } catch (Throwable unexpected) {
2212          if (traceJNI) unexpected.printStackTrace(System.err);
2213          env.recordException(unexpected);
2214        }
2215      }
2216    
2217      /**
2218       * GetFieldID:  return a field id, which can be cached in native code and reused
2219       * @param env A JREF index for the JNI environment object
2220       * @param classJREF a JREF index for the RVMClass object
2221       * @param fieldNameAddress a raw address to a null-terminated string in C for the field name
2222       * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor
2223       * @return the fieldID of an instance field given the class, field name
2224       *         and type. Return 0 if the field is not found
2225       * @exception NoSuchFieldError if the specified field cannot be found
2226       * @exception ExceptionInInitializerError if the class initializer fails
2227       * @exception OutOfMemoryError if the system runs out of memory
2228       */
2229      private static int GetFieldID(JNIEnvironment env, int classJREF, Address fieldNameAddress,
2230                                    Address descriptorAddress) {
2231        if (traceJNI) VM.sysWrite("JNI called: GetFieldID  \n");
2232        RuntimeEntrypoints.checkJNICountDownToGC();
2233    
2234        try {
2235          if (traceJNI)
2236            VM.sysWriteln("called GetFieldID with classJREF = ",classJREF);
2237          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
2238          if (VM.VerifyAssertions) VM._assert(cls!=null);
2239          String fieldString = JNIHelpers.createStringFromC(fieldNameAddress);
2240          Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString);
2241    
2242          String descriptorString = JNIHelpers.createStringFromC(descriptorAddress);
2243          Atom descriptor = Atom.findOrCreateAsciiAtom(descriptorString);
2244    
2245          // list of all instance fields including superclasses.
2246          // Iterate in reverse order since if there are multiple instance
2247          // fields of the same name & descriptor we want to find the most derived one.
2248          RVMField[] fields = java.lang.JikesRVMSupport.getTypeForClass(cls).getInstanceFields();
2249          for (int i = fields.length-1; i>=0; i--) {
2250            RVMField f = fields[i];
2251            if (f.getName() == fieldName && f.getDescriptor() == descriptor) {
2252              return f.getId();
2253            }
2254          }
2255    
2256          // create exception and return 0 if not found
2257          env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls));
2258          return 0;
2259        } catch (Throwable unexpected) {
2260          if (traceJNI) unexpected.printStackTrace(System.err);
2261          env.recordException(unexpected);
2262          return 0;
2263        }
2264      }
2265    
2266      /**
2267       * GetObjectField: read a instance field of type Object
2268       * @param env A JREF index for the JNI environment object
2269       * @param objJREF a JREF index for the target object
2270       * @param fieldID the id for the RVMField that describes this field
2271       * @return the value of the Object field, converted to a JREF index
2272       *         or 0 if the fieldID is incorrect
2273       */
2274      private static int GetObjectField(JNIEnvironment env, int objJREF, int fieldID) {
2275        if (traceJNI) VM.sysWrite("JNI called: GetObjectField  \n");
2276        RuntimeEntrypoints.checkJNICountDownToGC();
2277    
2278        try {
2279          Object obj = env.getJNIRef(objJREF);
2280          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2281          Object objVal = field.getObjectUnchecked(obj);
2282          return env.pushJNIRef(objVal);
2283        } catch (Throwable unexpected) {
2284          if (traceJNI) unexpected.printStackTrace(System.err);
2285          env.recordException(unexpected);
2286          return 0;
2287        }
2288      }
2289    
2290      /**
2291       * GetBooleanField: read an instance field of type boolean
2292       * @param env A JREF index for the JNI environment object
2293       * @param objJREF a JREF index for the target object
2294       * @param fieldID the id for the RVMField that describes this field
2295       * @return the value of the boolean field, or 0 if the fieldID is incorrect
2296       */
2297      private static int GetBooleanField(JNIEnvironment env, int objJREF, int fieldID) {
2298        if (traceJNI) VM.sysWrite("JNI called: GetBooleanField  \n");
2299        RuntimeEntrypoints.checkJNICountDownToGC();
2300    
2301        try {
2302          Object obj = env.getJNIRef(objJREF);
2303          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2304          return field.getBooleanValueUnchecked(obj) ? 1 : 0;
2305        } catch (Throwable unexpected) {
2306          if (traceJNI) unexpected.printStackTrace(System.err);
2307          env.recordException(unexpected);
2308          return 0;
2309        }
2310      }
2311    
2312      /**
2313       * GetByteField:  read an instance field of type byte
2314       * @param env A JREF index for the JNI environment object
2315       * @param objJREF a JREF index for the target object
2316       * @param fieldID the id for the RVMField that describes this field
2317       * @return the value of the byte field, or 0 if the fieldID is incorrect
2318       */
2319      private static int GetByteField(JNIEnvironment env, int objJREF, int fieldID) {
2320        if (traceJNI) VM.sysWrite("JNI called: GetByteField  \n");
2321        RuntimeEntrypoints.checkJNICountDownToGC();
2322    
2323        try {
2324          Object obj = env.getJNIRef(objJREF);
2325          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2326          return field.getByteValueUnchecked(obj);
2327        } catch (Throwable unexpected) {
2328          if (traceJNI) unexpected.printStackTrace(System.err);
2329          env.recordException(unexpected);
2330          return 0;
2331        }
2332      }
2333    
2334      /**
2335       * GetCharField:  read an instance field of type character
2336       * @param env A JREF index for the JNI environment object
2337       * @param objJREF a JREF index for the target object
2338       * @param fieldID the id for the RVMField that describes this field
2339       * @return the value of the character field, or 0 if the fieldID is incorrect
2340       */
2341      private static int GetCharField(JNIEnvironment env, int objJREF, int fieldID) {
2342        if (traceJNI) VM.sysWrite("JNI called: GetCharField  \n");
2343        RuntimeEntrypoints.checkJNICountDownToGC();
2344    
2345        try {
2346          Object obj = env.getJNIRef(objJREF);
2347          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2348          return field.getCharValueUnchecked(obj);
2349        } catch (Throwable unexpected) {
2350          if (traceJNI) unexpected.printStackTrace(System.err);
2351          env.recordException(unexpected);
2352          return 0;
2353        }
2354      }
2355    
2356      /**
2357       * GetShortField:  read an instance field of type short
2358       * @param env A JREF index for the JNI environment object
2359       * @param objJREF a JREF index for the target object
2360       * @param fieldID the id for the RVMField that describes this field
2361       * @return the value of the short field, or 0 if the fieldID is incorrect
2362       */
2363      private static int GetShortField(JNIEnvironment env, int objJREF, int fieldID) {
2364        if (traceJNI) VM.sysWrite("JNI called: GetShortField  \n");
2365        RuntimeEntrypoints.checkJNICountDownToGC();
2366    
2367        try {
2368          Object obj = env.getJNIRef(objJREF);
2369          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2370          return field.getShortValueUnchecked(obj);
2371        } catch (Throwable unexpected) {
2372          if (traceJNI) unexpected.printStackTrace(System.err);
2373          env.recordException(unexpected);
2374          return 0;
2375        }
2376      }
2377    
2378      /**
2379       * GetIntField:  read an instance field of type integer
2380       * @param env A JREF index for the JNI environment object
2381       * @param objJREF a JREF index for the target object
2382       * @param fieldID the id for the RVMField that describes this field
2383       * @return the value of the integer field, or 0 if the fieldID is incorrect
2384       */
2385      private static int GetIntField(JNIEnvironment env, int objJREF, int fieldID) {
2386        if (traceJNI) VM.sysWrite("JNI called: GetIntField  \n");
2387        RuntimeEntrypoints.checkJNICountDownToGC();
2388    
2389        try {
2390          Object obj = env.getJNIRef(objJREF);
2391          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2392          return field.getIntValueUnchecked(obj);
2393        } catch (Throwable unexpected) {
2394          if (traceJNI) unexpected.printStackTrace(System.err);
2395          env.recordException(unexpected);
2396          return 0;
2397        }
2398      }
2399    
2400      /**
2401       * GetLongField:  read an instance field of type long
2402       * @param env A JREF index for the JNI environment object
2403       * @param objJREF a JREF index for the target object
2404       * @param fieldID the id for the RVMField that describes this field
2405       * @return the value of the long field or 0 if the fieldID is incorrect
2406       */
2407      private static long GetLongField(JNIEnvironment env, int objJREF, int fieldID) {
2408        if (traceJNI) VM.sysWrite("JNI called: GetLongField  \n");
2409        RuntimeEntrypoints.checkJNICountDownToGC();
2410    
2411        try {
2412          Object obj = env.getJNIRef(objJREF);
2413          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2414          return field.getLongValueUnchecked(obj);
2415        } catch (Throwable unexpected) {
2416          if (traceJNI) unexpected.printStackTrace(System.err);
2417          env.recordException(unexpected);
2418          return 0L;
2419        }
2420      }
2421    
2422      /**
2423       * GetFloatField:  read an instance field of type float
2424       * @param env A JREF index for the JNI environment object
2425       * @param objJREF a JREF index for the target object
2426       * @param fieldID the id for the RVMField that describes this field
2427       * @return the value of the float field or 0 if the fieldID is incorrect
2428       */
2429      private static float GetFloatField(JNIEnvironment env, int objJREF, int fieldID) {
2430        if (traceJNI) VM.sysWrite("JNI called: GetFloatField  \n");
2431        RuntimeEntrypoints.checkJNICountDownToGC();
2432    
2433        try {
2434          Object obj = env.getJNIRef(objJREF);
2435          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2436          return field.getFloatValueUnchecked(obj);
2437        } catch (Throwable unexpected) {
2438          if (traceJNI) unexpected.printStackTrace(System.err);
2439          env.recordException(unexpected);
2440          return 0f;
2441        }
2442      }
2443    
2444      /**
2445       * GetDoubleField:  read an instance field of type double
2446       * @param env A JREF index for the JNI environment object
2447       * @param objJREF a JREF index for the target object
2448       * @param fieldID the id for the RVMField that describes this field
2449       * @return the value of the double field or 0 if the fieldID is incorrect
2450       */
2451      private static double GetDoubleField(JNIEnvironment env, int objJREF, int fieldID) {
2452        if (traceJNI) VM.sysWrite("JNI called: GetDoubleField  \n");
2453        RuntimeEntrypoints.checkJNICountDownToGC();
2454    
2455        try {
2456          Object obj = env.getJNIRef(objJREF);
2457          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2458          return field.getDoubleValueUnchecked(obj);
2459        } catch (Throwable unexpected) {
2460          if (traceJNI) unexpected.printStackTrace(System.err);
2461          env.recordException(unexpected);
2462          return 0.0;
2463        }
2464      }
2465    
2466      /**
2467       * SetObjectField: set a instance field of type Object
2468       * @param env A JREF index for the JNI environment object
2469       * @param objJREF a JREF index for the target object
2470       * @param fieldID the id for the RVMField that describes this field
2471       * @param valueJREF a JREF index for the value to assign
2472       */
2473      private static void SetObjectField(JNIEnvironment env, int objJREF, int fieldID, int valueJREF) {
2474        if (traceJNI) VM.sysWrite("JNI called: SetObjectField  \n");
2475        RuntimeEntrypoints.checkJNICountDownToGC();
2476    
2477        try {
2478          Object obj = env.getJNIRef(objJREF);
2479          Object value = env.getJNIRef(valueJREF);
2480          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2481          field.setObjectValueUnchecked(obj, value);
2482        } catch (Throwable unexpected) {
2483          if (traceJNI) unexpected.printStackTrace(System.err);
2484          env.recordException(unexpected);
2485        }
2486      }
2487    
2488      /**
2489       * SetBooleanField: set an instance field of type boolean
2490       * @param env A JREF index for the JNI environment object
2491       * @param objJREF a JREF index for the target object
2492       * @param fieldID the id for the RVMField that describes this field
2493       * @param value   boolean value to assign
2494       */
2495      private static void SetBooleanField(JNIEnvironment env, int objJREF, int fieldID, boolean value) {
2496        if (traceJNI) VM.sysWrite("JNI called: SetBooleanField  \n");
2497        RuntimeEntrypoints.checkJNICountDownToGC();
2498    
2499        try {
2500          Object obj = env.getJNIRef(objJREF);
2501          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2502          field.setBooleanValueUnchecked(obj, value);
2503        } catch (Throwable unexpected) {
2504          if (traceJNI) unexpected.printStackTrace(System.err);
2505          env.recordException(unexpected);
2506        }
2507      }
2508    
2509      /**
2510       * SetByteField: set an instance field of type byte
2511       * @param env A JREF index for the JNI environment object
2512       * @param objJREF a JREF index for the target object
2513       * @param fieldID the id for the RVMField that describes this field
2514       * @param value   byte value to assign
2515       */
2516      private static void SetByteField(JNIEnvironment env, int objJREF, int fieldID, byte value) {
2517        if (traceJNI) VM.sysWrite("JNI called: SetByteField  \n");
2518        RuntimeEntrypoints.checkJNICountDownToGC();
2519    
2520        try {
2521          Object obj = env.getJNIRef(objJREF);
2522          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2523          field.setByteValueUnchecked(obj, value);
2524        } catch (Throwable unexpected) {
2525          if (traceJNI) unexpected.printStackTrace(System.err);
2526          env.recordException(unexpected);
2527        }
2528      }
2529    
2530      /**
2531       * SetCharField: set an instance field of type char
2532       * @param env A JREF index for the JNI environment object
2533       * @param objJREF a JREF index for the target object
2534       * @param fieldID the id for the RVMField that describes this field
2535       * @param value   char value to assign
2536       */
2537      private static void SetCharField(JNIEnvironment env, int objJREF, int fieldID, char value) {
2538        if (traceJNI) VM.sysWrite("JNI called: SetCharField  \n");
2539        RuntimeEntrypoints.checkJNICountDownToGC();
2540    
2541        try {
2542          Object obj = env.getJNIRef(objJREF);
2543          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2544          field.setCharValueUnchecked(obj, value);
2545        } catch (Throwable unexpected) {
2546          if (traceJNI) unexpected.printStackTrace(System.err);
2547          env.recordException(unexpected);
2548        }
2549      }
2550    
2551      /**
2552       * SetShortField: set an instance field of type short
2553       * @param env A JREF index for the JNI environment object
2554       * @param objJREF a JREF index for the target object
2555       * @param fieldID the id for the RVMField that describes this field
2556       * @param value   short value to assign
2557       */
2558      private static void SetShortField(JNIEnvironment env, int objJREF, int fieldID, short value) {
2559        if (traceJNI) VM.sysWrite("JNI called: SetShortField  \n");
2560        RuntimeEntrypoints.checkJNICountDownToGC();
2561    
2562        try {
2563          Object obj = env.getJNIRef(objJREF);
2564          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2565          field.setShortValueUnchecked(obj, value);
2566        } catch (Throwable unexpected) {
2567          if (traceJNI) unexpected.printStackTrace(System.err);
2568          env.recordException(unexpected);
2569        }
2570      }
2571    
2572      /**
2573       * SetIntField: set an instance field of type integer
2574       * @param env A JREF index for the JNI environment object
2575       * @param objJREF a JREF index for the target object
2576       * @param fieldID the id for the RVMField that describes this field
2577       * @param value   integer value to assign
2578       */
2579      private static void SetIntField(JNIEnvironment env, int objJREF, int fieldID, int value) {
2580        if (traceJNI) VM.sysWrite("JNI called: SetIntField  \n");
2581        RuntimeEntrypoints.checkJNICountDownToGC();
2582    
2583        try {
2584          Object obj = env.getJNIRef(objJREF);
2585          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2586          field.setIntValueUnchecked(obj, value);
2587        } catch (Throwable unexpected) {
2588          if (traceJNI) unexpected.printStackTrace(System.err);
2589          env.recordException(unexpected);
2590        }
2591      }
2592    
2593      /**
2594       * SetLongField: set an instance field of type long
2595       * @param env A JREF index for the JNI environment object
2596       * @param objJREF a JREF index for the target object
2597       * @param fieldID the id for the RVMField that describes this field
2598       * @param value   long value to assign
2599       */
2600      private static void SetLongField(JNIEnvironment env, int objJREF, int fieldID, long value) {
2601        if (traceJNI) VM.sysWrite("JNI called: SetLongField  \n");
2602        RuntimeEntrypoints.checkJNICountDownToGC();
2603    
2604        try {
2605          Object obj = env.getJNIRef(objJREF);
2606          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2607          field.setLongValueUnchecked(obj, value);
2608        } catch (Throwable unexpected) {
2609          if (traceJNI) unexpected.printStackTrace(System.err);
2610          env.recordException(unexpected);
2611        }
2612      }
2613    
2614      /**
2615       * SetFloatField: set an instance field of type float
2616       * @param env A JREF index for the JNI environment object
2617       * @param objJREF a JREF index for the target object
2618       * @param fieldID the id for the RVMField that describes this field
2619       * @param value   float value to assign
2620       */
2621      private static void SetFloatField(JNIEnvironment env, int objJREF, int fieldID, float value) {
2622        if (traceJNI) VM.sysWrite("JNI called: SetFloatField  \n");
2623        RuntimeEntrypoints.checkJNICountDownToGC();
2624    
2625        try {
2626          Object obj = env.getJNIRef(objJREF);
2627          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2628          field.setFloatValueUnchecked(obj, value);
2629        } catch (Throwable unexpected) {
2630          if (traceJNI) unexpected.printStackTrace(System.err);
2631          env.recordException(unexpected);
2632        }
2633      }
2634    
2635      /**
2636       * SetDoubleField: set an instance field of type double
2637       * @param env A JREF index for the JNI environment object
2638       * @param objJREF a JREF index for the target object
2639       * @param fieldID the id for the RVMField that describes this field
2640       * @param value   double value to assign
2641       */
2642      private static void SetDoubleField(JNIEnvironment env, int objJREF, int fieldID, double value) {
2643        if (traceJNI) VM.sysWrite("JNI called: SetDoubleField  \n");
2644        RuntimeEntrypoints.checkJNICountDownToGC();
2645    
2646        try {
2647          Object obj = env.getJNIRef(objJREF);
2648          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
2649          field.setDoubleValueUnchecked(obj, value);
2650        } catch (Throwable unexpected) {
2651          if (traceJNI) unexpected.printStackTrace(System.err);
2652          env.recordException(unexpected);
2653        }
2654      }
2655    
2656      /**
2657       * GetStaticMethodID:  return the method ID for invocation later
2658       * @param env A JREF index for the JNI environment object
2659       * @param classJREF a JREF index for the class object
2660       * @param methodNameAddress a raw address to a null-terminated string in C for the method name
2661       * @param methodSigAddress a raw address to a null-terminated string in C for <DOCUMENTME TODO>
2662       * @return a method ID or null if it fails
2663       * @exception NoSuchMethodError if the method is not found
2664       * @exception ExceptionInInitializerError if the initializer fails
2665       * @exception OutOfMemoryError if the system runs out of memory
2666       */
2667      private static int GetStaticMethodID(JNIEnvironment env, int classJREF, Address methodNameAddress,
2668                                           Address methodSigAddress) {
2669        if (traceJNI) VM.sysWrite("JNI called: GetStaticMethodID  \n");
2670        RuntimeEntrypoints.checkJNICountDownToGC();
2671    
2672        try {
2673          // obtain the names as String from the native space
2674          String methodString = JNIHelpers.createStringFromC(methodNameAddress);
2675          Atom methodName = Atom.findOrCreateAsciiAtom(methodString);
2676          String sigString = JNIHelpers.createStringFromC(methodSigAddress);
2677          Atom sigName = Atom.findOrCreateAsciiAtom(sigString);
2678    
2679          // get the target class
2680          Class<?> jcls = (Class<?>) env.getJNIRef(classJREF);
2681          RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls);
2682          if (!type.isClassType()) {
2683            env.recordException(new NoSuchMethodError());
2684            return 0;
2685          }
2686    
2687          RVMClass klass = type.asClass();
2688          if (!klass.isInitialized()) {
2689            RuntimeEntrypoints.initializeClassForDynamicLink(klass);
2690          }
2691    
2692          // Find the target method
2693          RVMMethod meth = klass.findStaticMethod(methodName, sigName);
2694          if (meth == null) {
2695            env.recordException(new NoSuchMethodError());
2696            return 0;
2697          }
2698    
2699          if (traceJNI) VM.sysWrite("got method " + meth + "\n");
2700          return meth.getId();
2701        } catch (Throwable unexpected) {
2702          if (traceJNI) unexpected.printStackTrace(System.err);
2703          env.recordException(unexpected);
2704          return 0;
2705        }
2706      }
2707    
2708      /**
2709       * CallStaticObjectMethod:  invoke a static method that returns an object value
2710       *                          arguments passed using the vararg ... style
2711       * NOTE:  the vararg's are not visible in the method signature here; they are saved
2712       *        in the caller frame and the glue frame
2713       * @param env A JREF index for the JNI environment object
2714       * @param classJREF a JREF index for the class object
2715       * @param methodID id of a MethodReference
2716       * @return the JREF index for the object returned from the method invocation
2717       */
2718      private static int CallStaticObjectMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
2719        if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethod  \n");
2720        RuntimeEntrypoints.checkJNICountDownToGC();
2721    
2722        try {
2723          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, null);
2724          return env.pushJNIRef(returnObj);
2725        } catch (Throwable unexpected) {
2726          if (traceJNI) unexpected.printStackTrace(System.err);
2727          env.recordException(unexpected);
2728          return 0;
2729        }
2730      }
2731    
2732      /**
2733       * CallStaticObjectMethodV:  invoke a static method that returns an object
2734       * @param env A JREF index for the JNI environment object
2735       * @param classJREF a JREF index for the class object
2736       * @param methodID id of a MethodReference
2737       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
2738       *                   of the appropriate type for the method invocation
2739       * @return the JREF index for the object returned from the method invocation
2740       */
2741      private static int CallStaticObjectMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
2742          throws Exception {
2743        if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethodV  \n");
2744        RuntimeEntrypoints.checkJNICountDownToGC();
2745    
2746        try {
2747          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, null);
2748          return env.pushJNIRef(returnObj);
2749        } catch (Throwable unexpected) {
2750          if (traceJNI) unexpected.printStackTrace(System.err);
2751          env.recordException(unexpected);
2752          return 0;
2753        }
2754      }
2755    
2756      /**
2757       * CallStaticObjectMethodA:  invoke a static method that returns an object
2758       * @param env A JREF index for the JNI environment object
2759       * @param classJREF a JREF index for the class object
2760       * @param methodID id of a MethodReference
2761       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
2762       *                   of the appropriate type for the method invocation
2763       * @return the JREF index for the object returned from the method invocation
2764       */
2765      private static int CallStaticObjectMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
2766          throws Exception {
2767        if (traceJNI) VM.sysWrite("JNI called: CallStaticObjectMethodA  \n");
2768        RuntimeEntrypoints.checkJNICountDownToGC();
2769    
2770        try {
2771          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, null);
2772          return env.pushJNIRef(returnObj);
2773        } catch (Throwable unexpected) {
2774          if (traceJNI) unexpected.printStackTrace(System.err);
2775          env.recordException(unexpected);
2776          return 0;
2777        }
2778      }
2779    
2780      /**
2781       * CallStaticBooleanMethod:  invoke a static method that returns a boolean value
2782       *                           arguments passed using the vararg ... style
2783       * NOTE:  the vararg's are not visible in the method signature here; they are saved
2784       *        in the caller frame and the glue frame
2785       * @param env A JREF index for the JNI environment object
2786       * @param classJREF a JREF index for the class object
2787       * @param methodID id of a MethodReference
2788       * @return the boolean value returned from the method invocation
2789       */
2790      private static boolean CallStaticBooleanMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
2791        if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethod  \n");
2792        RuntimeEntrypoints.checkJNICountDownToGC();
2793    
2794        try {
2795          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Boolean);
2796          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
2797        } catch (Throwable unexpected) {
2798          if (traceJNI) unexpected.printStackTrace(System.err);
2799          env.recordException(unexpected);
2800          return false;
2801        }
2802      }
2803    
2804      /**
2805       * CallStaticBooleanMethodV:  invoke a static method that returns a boolean value
2806       * @param env A JREF index for the JNI environment object
2807       * @param classJREF a JREF index for the class object
2808       * @param methodID id of a MethodReference
2809       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
2810       *                   of the appropriate type for the method invocation
2811       * @return the boolean value returned from the method invocation
2812       */
2813      private static boolean CallStaticBooleanMethodV(JNIEnvironment env, int classJREF, int methodID,
2814                                                      Address argAddress) throws Exception {
2815        if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethodV  \n");
2816        RuntimeEntrypoints.checkJNICountDownToGC();
2817    
2818        try {
2819          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Boolean);
2820          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
2821        } catch (Throwable unexpected) {
2822          if (traceJNI) unexpected.printStackTrace(System.err);
2823          env.recordException(unexpected);
2824          return false;
2825        }
2826      }
2827    
2828      /**
2829       * CallStaticBooleanMethodA:  invoke a static method that returns a boolean value
2830       * @param env A JREF index for the JNI environment object
2831       * @param classJREF a JREF index for the class object
2832       * @param methodID id of a MethodReference
2833       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
2834       *                   of the appropriate type for the method invocation
2835       * @return the boolean value returned from the method invocation
2836       */
2837      private static boolean CallStaticBooleanMethodA(JNIEnvironment env, int classJREF, int methodID,
2838                                                      Address argAddress) throws Exception {
2839        if (traceJNI) VM.sysWrite("JNI called: CallStaticBooleanMethodA  \n");
2840        RuntimeEntrypoints.checkJNICountDownToGC();
2841    
2842        try {
2843          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Boolean);
2844          return Reflection.unwrapBoolean(returnObj);     // should be a wrapper for a boolean value
2845        } catch (Throwable unexpected) {
2846          if (traceJNI) unexpected.printStackTrace(System.err);
2847          env.recordException(unexpected);
2848          return false;
2849        }
2850      }
2851    
2852      /**
2853       * CallStaticByteMethod:  invoke a static method that returns a byte value
2854       *                        arguments passed using the vararg ... style
2855       * NOTE:  the vararg's are not visible in the method signature here; they are saved
2856       *        in the caller frame and the glue frame
2857       * @param env A JREF index for the JNI environment object
2858       * @param classJREF a JREF index for the class object
2859       * @param methodID id of a MethodReference
2860       * @return the byte value returned from the method invocation
2861       */
2862      private static byte CallStaticByteMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
2863        if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethod  \n");
2864        RuntimeEntrypoints.checkJNICountDownToGC();
2865    
2866        try {
2867          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Byte);
2868          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
2869        } catch (Throwable unexpected) {
2870          if (traceJNI) unexpected.printStackTrace(System.err);
2871          env.recordException(unexpected);
2872          return 0;
2873        }
2874      }
2875    
2876      /**
2877       * CallStaticByteMethodV:  invoke a static method that returns a byte value
2878       * @param env A JREF index for the JNI environment object
2879       * @param classJREF a JREF index for the class object
2880       * @param methodID id of a MethodReference
2881       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
2882       *                   of the appropriate type for the method invocation
2883       * @return the byte value returned from the method invocation
2884       */
2885      private static byte CallStaticByteMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
2886          throws Exception {
2887        if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethodV  \n");
2888        RuntimeEntrypoints.checkJNICountDownToGC();
2889    
2890        try {
2891          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Byte);
2892          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
2893        } catch (Throwable unexpected) {
2894          if (traceJNI) unexpected.printStackTrace(System.err);
2895          env.recordException(unexpected);
2896          return 0;
2897        }
2898      }
2899    
2900      /**
2901       * CallStaticByteMethodA:  invoke a static method that returns a byte value
2902       * @param env A JREF index for the JNI environment object
2903       * @param classJREF a JREF index for the class object
2904       * @param methodID id of a MethodReference
2905       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
2906       *                   of the appropriate type for the method invocation
2907       * @return the byte value returned from the method invocation
2908       */
2909      private static byte CallStaticByteMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
2910          throws Exception {
2911        if (traceJNI) VM.sysWrite("JNI called: CallStaticByteMethodA  \n");
2912        RuntimeEntrypoints.checkJNICountDownToGC();
2913    
2914        try {
2915          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Byte);
2916          return Reflection.unwrapByte(returnObj);     // should be a wrapper for a byte value
2917        } catch (Throwable unexpected) {
2918          if (traceJNI) unexpected.printStackTrace(System.err);
2919          env.recordException(unexpected);
2920          return 0;
2921        }
2922      }
2923    
2924      /**
2925       * CallStaticCharMethod:  invoke a static method that returns a char value
2926       *                        arguments passed using the vararg ... style
2927       * NOTE:  the vararg's are not visible in the method signature here; they are saved
2928       *        in the caller frame and the glue frame
2929       * @param env A JREF index for the JNI environment object
2930       * @param classJREF a JREF index for the class object
2931       * @param methodID id of a MethodReference
2932       * @return the char value returned from the method invocation
2933       */
2934      private static char CallStaticCharMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
2935        if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethod  \n");
2936        RuntimeEntrypoints.checkJNICountDownToGC();
2937    
2938        try {
2939          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Char);
2940          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
2941        } catch (Throwable unexpected) {
2942          if (traceJNI) unexpected.printStackTrace(System.err);
2943          env.recordException(unexpected);
2944          return 0;
2945        }
2946      }
2947    
2948      /**
2949       * CallStaticCharMethodV:  invoke a static method that returns a char value
2950       * @param env A JREF index for the JNI environment object
2951       * @param classJREF a JREF index for the class object
2952       * @param methodID id of a MethodReference
2953       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
2954       *                   of the appropriate type for the method invocation
2955       * @return the char value returned from the method invocation
2956       */
2957      private static char CallStaticCharMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
2958          throws Exception {
2959        if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethodV  \n");
2960        RuntimeEntrypoints.checkJNICountDownToGC();
2961    
2962        try {
2963          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Char);
2964          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
2965        } catch (Throwable unexpected) {
2966          if (traceJNI) unexpected.printStackTrace(System.err);
2967          env.recordException(unexpected);
2968          return 0;
2969        }
2970      }
2971    
2972      /**
2973       * CallStaticCharMethodA:  invoke a static method that returns a char value
2974       * @param env A JREF index for the JNI environment object
2975       * @param classJREF a JREF index for the class object
2976       * @param methodID id of a MethodReference
2977       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
2978       *                   of the appropriate type for the method invocation
2979       * @return the char value returned from the method invocation
2980       */
2981      private static char CallStaticCharMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
2982          throws Exception {
2983        if (traceJNI) VM.sysWrite("JNI called: CallStaticCharMethodA  \n");
2984        RuntimeEntrypoints.checkJNICountDownToGC();
2985    
2986        try {
2987          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Char);
2988          return Reflection.unwrapChar(returnObj);     // should be a wrapper for a char value
2989        } catch (Throwable unexpected) {
2990          if (traceJNI) unexpected.printStackTrace(System.err);
2991          env.recordException(unexpected);
2992          return 0;
2993        }
2994      }
2995    
2996      /**
2997       * CallStaticShortMethod:  invoke a static method that returns a short value
2998       *                         arguments passed using the vararg ... style
2999       * NOTE:  the vararg's are not visible in the method signature here; they are saved
3000       *        in the caller frame and the glue frame
3001       * @param env A JREF index for the JNI environment object
3002       * @param classJREF a JREF index for the class object
3003       * @param methodID id of a MethodReference
3004       * @return the short value returned from the method invocation
3005       */
3006      private static short CallStaticShortMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
3007        if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethod  \n");
3008        RuntimeEntrypoints.checkJNICountDownToGC();
3009    
3010        try {
3011          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Short);
3012          return Reflection.unwrapShort(returnObj);     // should be a wrapper for an short value
3013        } catch (Throwable unexpected) {
3014          if (traceJNI) unexpected.printStackTrace(System.err);
3015          env.recordException(unexpected);
3016          return 0;
3017        }
3018      }
3019    
3020      /**
3021       * CallStaticShortMethodV:  invoke a static method that returns a short value
3022       * @param env A JREF index for the JNI environment object
3023       * @param classJREF a JREF index for the class object
3024       * @param methodID id of a MethodReference
3025       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
3026       *                   of the appropriate type for the method invocation
3027       * @return the short value returned from the method invocation
3028       */
3029      private static short CallStaticShortMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3030          throws Exception {
3031        if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethodV  \n");
3032        RuntimeEntrypoints.checkJNICountDownToGC();
3033    
3034        try {
3035          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Short);
3036          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
3037        } catch (Throwable unexpected) {
3038          if (traceJNI) unexpected.printStackTrace(System.err);
3039          env.recordException(unexpected);
3040          return 0;
3041        }
3042      }
3043    
3044      /**
3045       * CallStaticShortMethodA:  invoke a static method that returns a short value
3046       * @param env A JREF index for the JNI environment object
3047       * @param classJREF a JREF index for the class object
3048       * @param methodID id of a MethodReference
3049       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3050       *                   of the appropriate type for the method invocation
3051       * @return the short value returned from the method invocation
3052       */
3053      private static short CallStaticShortMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3054          throws Exception {
3055        if (traceJNI) VM.sysWrite("JNI called: CallStaticShortMethodA  \n");
3056        RuntimeEntrypoints.checkJNICountDownToGC();
3057    
3058        try {
3059          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Short);
3060          return Reflection.unwrapShort(returnObj);     // should be a wrapper for a short value
3061        } catch (Throwable unexpected) {
3062          if (traceJNI) unexpected.printStackTrace(System.err);
3063          env.recordException(unexpected);
3064          return 0;
3065        }
3066      }
3067    
3068      /**
3069       * CallStaticIntMethod:  invoke a static method that returns an integer value
3070       *                       arguments passed using the vararg ... style
3071       * NOTE:  the vararg's are not visible in the method signature here; they are saved
3072       *        in the caller frame and the glue frame
3073       * @param env A JREF index for the JNI environment object
3074       * @param classJREF a JREF index for the class object
3075       * @param methodID id of a MethodReference
3076       * @return the integer value returned from the method invocation
3077       */
3078      private static int CallStaticIntMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
3079        if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethod  \n");
3080        RuntimeEntrypoints.checkJNICountDownToGC();
3081    
3082        try {
3083          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Int);
3084          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
3085        } catch (Throwable unexpected) {
3086          if (traceJNI) unexpected.printStackTrace(System.err);
3087          env.recordException(unexpected);
3088          return 0;
3089        }
3090      }
3091    
3092      /**
3093       * CallStaticIntMethodV:  invoke a static method that returns an integer value
3094       * @param env A JREF index for the JNI environment object
3095       * @param classJREF a JREF index for the class object
3096       * @param methodID id of a MethodReference
3097       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
3098       *                   of the appropriate type for the method invocation
3099       * @return the integer value returned from the method invocation
3100       */
3101      private static int CallStaticIntMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3102          throws Exception {
3103        if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethodV  \n");
3104        RuntimeEntrypoints.checkJNICountDownToGC();
3105    
3106        try {
3107          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Int);
3108          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
3109        } catch (Throwable unexpected) {
3110          if (traceJNI) unexpected.printStackTrace(System.err);
3111          env.recordException(unexpected);
3112          return 0;
3113        }
3114      }
3115    
3116      /**
3117       * CallStaticIntMethodA:  invoke a static method that returns an integer value
3118       * @param env A JREF index for the JNI environment object
3119       * @param classJREF a JREF index for the class object
3120       * @param methodID id of a MethodReference
3121       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3122       *                   of the appropriate type for the method invocation
3123       * @return the integer value returned from the method invocation
3124       */
3125      private static int CallStaticIntMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3126          throws Exception {
3127        if (traceJNI) VM.sysWrite("JNI called: CallStaticIntMethodA  \n");
3128        RuntimeEntrypoints.checkJNICountDownToGC();
3129    
3130        try {
3131          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Int);
3132          return Reflection.unwrapInt(returnObj);     // should be a wrapper for an integer value
3133        } catch (Throwable unexpected) {
3134          if (traceJNI) unexpected.printStackTrace(System.err);
3135          env.recordException(unexpected);
3136          return 0;
3137        }
3138      }
3139    
3140      /**
3141       * CallStaticLongMethod:  invoke a static method that returns a long value
3142       *                        arguments passed using the vararg ... style
3143       * NOTE:  the vararg's are not visible in the method signature here; they are saved
3144       *        in the caller frame and the glue frame
3145       * @param env A JREF index for the JNI environment object
3146       * @param classJREF a JREF index for the class object
3147       * @param methodID id of a MethodReference
3148       * @return the long value returned from the method invocation
3149       */
3150      private static long CallStaticLongMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
3151        if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethod  \n");
3152        RuntimeEntrypoints.checkJNICountDownToGC();
3153    
3154        try {
3155          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Long);
3156          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
3157        } catch (Throwable unexpected) {
3158          if (traceJNI) unexpected.printStackTrace(System.err);
3159          env.recordException(unexpected);
3160          return 0L;
3161        }
3162      }
3163    
3164      /**
3165       * CallStaticLongMethodV:  invoke a static method that returns a long value
3166       * @param env A JREF index for the JNI environment object
3167       * @param classJREF a JREF index for the class object
3168       * @param methodID id of a MethodReference
3169       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
3170       *                   of the appropriate type for the method invocation
3171       * @return the long value returned from the method invocation
3172       */
3173      private static long CallStaticLongMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3174          throws Exception {
3175        if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethodV  \n");
3176        RuntimeEntrypoints.checkJNICountDownToGC();
3177    
3178        try {
3179          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Long);
3180          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
3181        } catch (Throwable unexpected) {
3182          if (traceJNI) unexpected.printStackTrace(System.err);
3183          env.recordException(unexpected);
3184          return 0L;
3185        }
3186      }
3187    
3188      /**
3189       * CallStaticLongMethodA:  invoke a static method that returns a long value
3190       * @param env A JREF index for the JNI environment object
3191       * @param classJREF a JREF index for the class object
3192       * @param methodID id of a MethodReference
3193       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3194       *                   of the appropriate type for the method invocation
3195       * @return the long value returned from the method invocation
3196       */
3197      private static long CallStaticLongMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3198          throws Exception {
3199        if (traceJNI) VM.sysWrite("JNI called: CallStaticLongMethodA  \n");
3200        RuntimeEntrypoints.checkJNICountDownToGC();
3201    
3202        try {
3203          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Long);
3204          return Reflection.unwrapLong(returnObj);     // should be a wrapper for a long value
3205        } catch (Throwable unexpected) {
3206          if (traceJNI) unexpected.printStackTrace(System.err);
3207          env.recordException(unexpected);
3208          return 0L;
3209        }
3210      }
3211    
3212      /**
3213       * CallStaticFloagMethod:  invoke a static method that returns a float value
3214       *                         arguments passed using the vararg ... style
3215       * NOTE:  the vararg's are not visible in the method signature here; they are saved
3216       *        in the caller frame and the glue frame
3217       * @param env A JREF index for the JNI environment object
3218       * @param classJREF a JREF index for the class object
3219       * @param methodID id of a MethodReference
3220       * @return the float value returned from the method invocation
3221       */
3222      private static float CallStaticFloatMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
3223        if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethod  \n");
3224        RuntimeEntrypoints.checkJNICountDownToGC();
3225    
3226        try {
3227          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Float);
3228          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
3229        } catch (Throwable unexpected) {
3230          if (traceJNI) unexpected.printStackTrace(System.err);
3231          env.recordException(unexpected);
3232          return 0f;
3233        }
3234      }
3235    
3236      /**
3237       * CallStaticFloatMethodV:  invoke a static method that returns a float value
3238       * @param env A JREF index for the JNI environment object
3239       * @param classJREF a JREF index for the class object
3240       * @param methodID id of a MethodReference
3241       * @param argAddress a raw address to a variable argument list, each element is 1-word or 2-words
3242       *                   of the appropriate type for the method invocation
3243       * @return the float value returned from the method invocation
3244       */
3245      private static float CallStaticFloatMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3246          throws Exception {
3247        if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethodV  \n");
3248        RuntimeEntrypoints.checkJNICountDownToGC();
3249    
3250        try {
3251          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Float);
3252          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
3253        } catch (Throwable unexpected) {
3254          if (traceJNI) unexpected.printStackTrace(System.err);
3255          env.recordException(unexpected);
3256          return 0f;
3257        }
3258      }
3259    
3260      /**
3261       * CallStaticFloatMethodA:  invoke a static method that returns a float value
3262       * @param env A JREF index for the JNI environment object
3263       * @param classJREF a JREF index for the class object
3264       * @param methodID id of a MethodReference
3265       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3266       *                   of the appropriate type for the method invocation
3267       * @return the float value returned from the method invocation
3268       */
3269      private static float CallStaticFloatMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3270          throws Exception {
3271        if (traceJNI) VM.sysWrite("JNI called: CallStaticFloatMethodA  \n");
3272        RuntimeEntrypoints.checkJNICountDownToGC();
3273    
3274        try {
3275          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Float);
3276          return Reflection.unwrapFloat(returnObj);     // should be a wrapper for a float value
3277        } catch (Throwable unexpected) {
3278          if (traceJNI) unexpected.printStackTrace(System.err);
3279          env.recordException(unexpected);
3280          return 0f;
3281        }
3282      }
3283    
3284      /**
3285       * CallStaticDoubleMethod:  invoke a static method that returns a double value
3286       *                          arguments passed using the vararg ... style
3287       * NOTE:  the vararg's are not visible in the method signature here; they are saved
3288       *        in the caller frame and the glue frame
3289       * @param env A JREF index for the JNI environment object
3290       * @param classJREF a JREF index for the class object
3291       * @param methodID an id of a MethodReference
3292       * @return the double value returned from the method invocation
3293       */
3294      private static double CallStaticDoubleMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
3295        if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethod  \n");
3296        RuntimeEntrypoints.checkJNICountDownToGC();
3297    
3298        try {
3299          Object returnObj = JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Double);
3300          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
3301        } catch (Throwable unexpected) {
3302          if (traceJNI) unexpected.printStackTrace(System.err);
3303          env.recordException(unexpected);
3304          return 0;
3305        }
3306      }
3307    
3308      /**
3309       * CallStaticDoubleMethodV:  invoke a static method that returns a double value
3310       * @param env A JREF index for the JNI environment object
3311       * @param classJREF a JREF index for the class object
3312       * @param methodID an id of a MethodReference
3313       * @param argAddress a raw address to a  variable argument list, each element is 1-word or 2-words
3314       *                   of the appropriate type for the method invocation
3315       * @return the double value returned from the method invocation
3316       */
3317      private static double CallStaticDoubleMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3318          throws Exception {
3319        if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethodV  \n");
3320        RuntimeEntrypoints.checkJNICountDownToGC();
3321    
3322        try {
3323          Object returnObj = JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Double);
3324          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
3325        } catch (Throwable unexpected) {
3326          if (traceJNI) unexpected.printStackTrace(System.err);
3327          env.recordException(unexpected);
3328          return 0;
3329        }
3330      }
3331    
3332      /**
3333       * CallStaticDoubleMethodA:  invoke a static method that returns a double value
3334       * @param env A JREF index for the JNI environment object
3335       * @param classJREF a JREF index for the class object
3336       * @param methodID id of a MethodReference
3337       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3338       *                   of the appropriate type for the method invocation
3339       * @return the double value returned from the method invocation
3340       */
3341      private static double CallStaticDoubleMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3342          throws Exception {
3343        if (traceJNI) VM.sysWrite("JNI called: CallStaticDoubleMethodA  \n");
3344        RuntimeEntrypoints.checkJNICountDownToGC();
3345    
3346        try {
3347          Object returnObj = JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Double);
3348          return Reflection.unwrapDouble(returnObj);     // should be a wrapper for a double value
3349        } catch (Throwable unexpected) {
3350          if (traceJNI) unexpected.printStackTrace(System.err);
3351          env.recordException(unexpected);
3352          return 0;
3353        }
3354      }
3355    
3356      /**
3357       * CallStaticVoidMethod:  invoke a static method that returns void
3358       *                       arguments passed using the vararg ... style
3359       * NOTE:  the vararg's are not visible in the method signature here; they are saved
3360       *        in the caller frame and the glue frame
3361       * @param env A JREF index for the JNI environment object
3362       * @param classJREF a JREF index for the class object
3363       * @param methodID id of a MethodReference
3364       */
3365      private static void CallStaticVoidMethod(JNIEnvironment env, int classJREF, int methodID) throws Exception {
3366        if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethod  \n");
3367        RuntimeEntrypoints.checkJNICountDownToGC();
3368    
3369        try {
3370          JNIHelpers.invokeWithDotDotVarArg(methodID, TypeReference.Void);
3371        } catch (Throwable unexpected) {
3372          if (traceJNI) unexpected.printStackTrace(System.err);
3373          env.recordException(unexpected);
3374        }
3375      }
3376    
3377      /**
3378       * CallStaticVoidMethodA:  invoke a static method that returns void
3379       * @param env A JREF index for the JNI environment object
3380       * @param classJREF a JREF index for the class object
3381       * @param methodID id of a MethodReference
3382       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3383       *                   of the appropriate type for the method invocation
3384       */
3385      private static void CallStaticVoidMethodV(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3386          throws Exception {
3387        if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethodV  \n");
3388        RuntimeEntrypoints.checkJNICountDownToGC();
3389    
3390        try {
3391          JNIHelpers.invokeWithVarArg(methodID, argAddress, TypeReference.Void);
3392        } catch (Throwable unexpected) {
3393          if (traceJNI) unexpected.printStackTrace(System.err);
3394          env.recordException(unexpected);
3395        }
3396      }
3397    
3398      /**
3399       * CallStaticVoidMethodA:  invoke a static method that returns void
3400       * @param env A JREF index for the JNI environment object
3401       * @param classJREF a JREF index for the class object
3402       * @param methodID id of a MethodReference
3403       * @param argAddress a raw address to an array of unions in C, each element is 2-word and hold an argument
3404       *                   of the appropriate type for the method invocation
3405       */
3406      private static void CallStaticVoidMethodA(JNIEnvironment env, int classJREF, int methodID, Address argAddress)
3407          throws Exception {
3408        if (traceJNI) VM.sysWrite("JNI called: CallStaticVoidMethodA  \n");
3409        RuntimeEntrypoints.checkJNICountDownToGC();
3410    
3411        try {
3412          JNIHelpers.invokeWithJValue(methodID, argAddress, TypeReference.Void);
3413        } catch (Throwable unexpected) {
3414          if (traceJNI) unexpected.printStackTrace(System.err);
3415          env.recordException(unexpected);
3416        }
3417      }
3418    
3419      /**
3420       * GetStaticFieldID:  return a field id which can be cached in native code and reused
3421       * @param env A JREF index for the JNI environment object
3422       * @param classJREF a JREF index for the RVMClass object
3423       * @param fieldNameAddress a raw address to a null-terminated string in C for the field name
3424       * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor
3425       * @return the offset of a static field given the class, field name
3426       *         and type. Return 0 if the field is not found
3427       * @exception NoSuchFieldError if the specified field cannot be found
3428       * @exception ExceptionInInitializerError if the class initializer fails
3429       * @exception OutOfMemoryError if the system runs out of memory
3430       */
3431      private static int GetStaticFieldID(JNIEnvironment env, int classJREF, Address fieldNameAddress,
3432                                          Address descriptorAddress) {
3433        if (traceJNI) VM.sysWrite("JNI called: GetStaticFieldID  \n");
3434        RuntimeEntrypoints.checkJNICountDownToGC();
3435    
3436        try {
3437          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
3438    
3439          String fieldString = JNIHelpers.createStringFromC(fieldNameAddress);
3440          Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString);
3441          String descriptorString = JNIHelpers.createStringFromC(descriptorAddress);
3442          Atom descriptor = Atom.findOrCreateAsciiAtom(descriptorString);
3443    
3444          RVMType rvmType = java.lang.JikesRVMSupport.getTypeForClass(cls);
3445          if (rvmType.isClassType()) {
3446            // First search for the fields in the class and its superclasses
3447            for (RVMClass curClass = rvmType.asClass(); curClass != null; curClass = curClass.getSuperClass()) {
3448              for (RVMField field : curClass.getStaticFields()) {
3449                if (field.getName() == fieldName && field.getDescriptor() == descriptor) {
3450                  return field.getId();
3451                }
3452              }
3453            }
3454            // Now search all implemented interfaces (includes inherited interfaces)
3455            for (RVMClass curClass : rvmType.asClass().getAllImplementedInterfaces()) {
3456              for (RVMField field : curClass.getStaticFields()) {
3457                if (field.getName() == fieldName && field.getDescriptor() == descriptor) {
3458                  return field.getId();
3459                }
3460              }
3461            }
3462          }
3463    
3464          env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls));
3465          return 0;
3466        } catch (Throwable unexpected) {
3467          if (traceJNI) unexpected.printStackTrace(System.err);
3468          env.recordException(unexpected);
3469          return 0;
3470        }
3471      }
3472    
3473      /**
3474       * GetStaticObjectField: read a static field of type Object
3475       * @param env A JREF index for the JNI environment object
3476       * @param classJREF a JREF index for the RVMClass object
3477       * @param fieldID the id for the RVMField that describes this field
3478       * @return the value of the Object field, converted to a JREF index
3479       *         or 0 if the fieldID is incorrect
3480       */
3481      private static int GetStaticObjectField(JNIEnvironment env, int classJREF, int fieldID) {
3482        if (traceJNI) VM.sysWrite("JNI called: GetStaticObjectField  \n");
3483        RuntimeEntrypoints.checkJNICountDownToGC();
3484    
3485        try {
3486          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3487          Object value = field.getObjectUnchecked(null);
3488          return env.pushJNIRef(value);
3489        } catch (Throwable unexpected) {
3490          if (traceJNI) unexpected.printStackTrace(System.err);
3491          env.recordException(unexpected);
3492          return 0;
3493        }
3494      }
3495    
3496      /**
3497       * GetStaticBooleanField: read a static field of type boolean
3498       * @param env A JREF index for the JNI environment object
3499       * @param classJREF a JREF index for the RVMClass object
3500       * @param fieldID the id for the RVMField that describes this field
3501       * @return the value of the boolean field, or 0 if the fieldID is incorrect
3502       */
3503      private static int GetStaticBooleanField(JNIEnvironment env, int classJREF, int fieldID) {
3504        if (traceJNI) VM.sysWrite("JNI called: GetStaticBooleanField  \n");
3505        RuntimeEntrypoints.checkJNICountDownToGC();
3506    
3507        try {
3508          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3509          return field.getBooleanValueUnchecked(null) ? 1 : 0;
3510        } catch (Throwable unexpected) {
3511          if (traceJNI) unexpected.printStackTrace(System.err);
3512          env.recordException(unexpected);
3513          return 0;
3514        }
3515      }
3516    
3517      /**
3518       * GetStaticByteField:  read a static field of type byte
3519       * @param env A JREF index for the JNI environment object
3520       * @param classJREF a JREF index for the RVMClass object
3521       * @param fieldID the id for the RVMField that describes this field
3522       * @return the value of the byte field, or 0 if the fieldID is incorrect
3523       */
3524      private static int GetStaticByteField(JNIEnvironment env, int classJREF, int fieldID) {
3525        if (traceJNI) VM.sysWrite("JNI called: GetStaticByteField  \n");
3526        RuntimeEntrypoints.checkJNICountDownToGC();
3527    
3528        try {
3529          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3530          return field.getByteValueUnchecked(null);
3531        } catch (Throwable unexpected) {
3532          if (traceJNI) unexpected.printStackTrace(System.err);
3533          env.recordException(unexpected);
3534          return 0;
3535        }
3536      }
3537    
3538      /**
3539       * GetStaticCharField:  read a static field of type character
3540       * @param env A JREF index for the JNI environment object
3541       * @param classJREF a JREF index for the RVMClass object
3542       * @param fieldID the id for the RVMField that describes this field
3543       * @return the value of the character field, or 0 if the fieldID is incorrect
3544       */
3545      private static int GetStaticCharField(JNIEnvironment env, int classJREF, int fieldID) {
3546        if (traceJNI) VM.sysWrite("JNI called: GetStaticCharField  \n");
3547        RuntimeEntrypoints.checkJNICountDownToGC();
3548    
3549        try {
3550          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3551          return field.getCharValueUnchecked(null);
3552        } catch (Throwable unexpected) {
3553          if (traceJNI) unexpected.printStackTrace(System.err);
3554          env.recordException(unexpected);
3555          return 0;
3556        }
3557      }
3558    
3559      /**
3560       * GetStaticShortField:  read a static field of type short
3561       * @param env A JREF index for the JNI environment object
3562       * @param classJREF a JREF index for the RVMClass object
3563       * @param fieldID the id for the RVMField that describes this field
3564       * @return the value of the short field, or 0 if the fieldID is incorrect
3565       */
3566      private static int GetStaticShortField(JNIEnvironment env, int classJREF, int fieldID) {
3567        if (traceJNI) VM.sysWrite("JNI called: GetStaticShortField  \n");
3568        RuntimeEntrypoints.checkJNICountDownToGC();
3569    
3570        try {
3571          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3572          return field.getShortValueUnchecked(null);
3573        } catch (Throwable unexpected) {
3574          if (traceJNI) unexpected.printStackTrace(System.err);
3575          env.recordException(unexpected);
3576          return 0;
3577        }
3578      }
3579    
3580      /**
3581       * GetStaticIntField:  read a static field of type integer
3582       * @param env A JREF index for the JNI environment object
3583       * @param classJREF a JREF index for the RVMClass object
3584       * @param fieldID the id for the RVMField that describes this field
3585       * @return the value of the integer field, or 0 if the fieldID is incorrect
3586       */
3587      private static int GetStaticIntField(JNIEnvironment env, int classJREF, int fieldID) {
3588        if (traceJNI) VM.sysWrite("JNI called: GetStaticIntField  \n");
3589        RuntimeEntrypoints.checkJNICountDownToGC();
3590    
3591        try {
3592          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3593          return field.getIntValueUnchecked(null);
3594        } catch (Throwable unexpected) {
3595          if (traceJNI) unexpected.printStackTrace(System.err);
3596          env.recordException(unexpected);
3597          return 0;
3598        }
3599      }
3600    
3601      /**
3602       * GetStaticLongField:  read a static field of type long
3603       * @param env A JREF index for the JNI environment object
3604       * @param classJREF a JREF index for the RVMClass object
3605       * @param fieldID the id for the RVMField that describes this field
3606       * @return the value of the long field or 0 if the fieldID is incorrect
3607       */
3608      private static long GetStaticLongField(JNIEnvironment env, int classJREF, int fieldID) {
3609        if (traceJNI) VM.sysWrite("JNI called: GetStaticLongField  \n");
3610        RuntimeEntrypoints.checkJNICountDownToGC();
3611    
3612        try {
3613          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3614          return field.getLongValueUnchecked(null);
3615        } catch (Throwable unexpected) {
3616          if (traceJNI) unexpected.printStackTrace(System.err);
3617          env.recordException(unexpected);
3618          return 0;
3619        }
3620      }
3621    
3622      /**
3623       * GetStaticFloatField:  read a static field of type float
3624       * @param env A JREF index for the JNI environment object
3625       * @param classJREF a JREF index for the RVMClass object
3626       * @param fieldID the id for the RVMField that describes this field
3627       * @return the value of the float field or 0 if the fieldID is incorrect
3628       */
3629      private static float GetStaticFloatField(JNIEnvironment env, int classJREF, int fieldID) {
3630        if (traceJNI) VM.sysWrite("JNI called: GetStaticFloatField  \n");
3631        RuntimeEntrypoints.checkJNICountDownToGC();
3632    
3633        try {
3634          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3635          return field.getFloatValueUnchecked(null);
3636        } catch (Throwable unexpected) {
3637          if (traceJNI) unexpected.printStackTrace(System.err);
3638          env.recordException(unexpected);
3639          return 0;
3640        }
3641      }
3642    
3643      /**
3644       * GetStaticDoubleField:  read a static field of type double
3645       * @param env A JREF index for the JNI environment object
3646       * @param classJREF a JREF index for the RVMClass object
3647       * @param fieldID the id for the RVMField that describes this field
3648       * @return the value of the double field or 0 if the fieldID is incorrect
3649       */
3650      private static double GetStaticDoubleField(JNIEnvironment env, int classJREF, int fieldID) {
3651        if (traceJNI) VM.sysWrite("JNI called: GetStaticDoubleField  \n");
3652        RuntimeEntrypoints.checkJNICountDownToGC();
3653    
3654        try {
3655          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3656          return field.getDoubleValueUnchecked(null);
3657        } catch (Throwable unexpected) {
3658          if (traceJNI) unexpected.printStackTrace(System.err);
3659          env.recordException(unexpected);
3660          return 0;
3661        }
3662      }
3663    
3664      /**
3665       * SetStaticObjectField:  set a static field of type Object
3666       * @param env         A JREF index for the JNI environment object
3667       * @param classJREF   A JREF index for the {@link RVMClass} object
3668       * @param fieldID     The id for the {@link RVMField} that describes this
3669       *                    field
3670       * @param objectJREF  A JREF index of the value to assign
3671       */
3672      private static void SetStaticObjectField(JNIEnvironment env, int classJREF, int fieldID, int objectJREF) {
3673        if (traceJNI) VM.sysWrite("JNI called: SetStaticObjectField  \n");
3674        RuntimeEntrypoints.checkJNICountDownToGC();
3675    
3676        try {
3677          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3678          Object ref = env.getJNIRef(objectJREF);
3679          field.setObjectValueUnchecked(null, ref);
3680        } catch (Throwable unexpected) {
3681          if (traceJNI) unexpected.printStackTrace(System.err);
3682          env.recordException(unexpected);
3683        }
3684      }
3685    
3686      /**
3687       * SetStaticBooleanField:  set a static field of type boolean
3688       * @param env A JREF index for the JNI environment object
3689       * @param classJREF A JREF index for the RVMClass object
3690       * @param fieldID the id for the RVMField that describes this field
3691       * @param fieldValue  The value to assign
3692       */
3693      private static void SetStaticBooleanField(JNIEnvironment env, int classJREF, int fieldID, boolean fieldValue) {
3694        if (traceJNI) VM.sysWrite("JNI called: SetStaticBooleanField  \n");
3695        RuntimeEntrypoints.checkJNICountDownToGC();
3696    
3697        try {
3698          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3699          field.setBooleanValueUnchecked(null, fieldValue);
3700        } catch (Throwable unexpected) {
3701          if (traceJNI) unexpected.printStackTrace(System.err);
3702          env.recordException(unexpected);
3703        }
3704      }
3705    
3706      /**
3707       * SetStaticByteField:  set a static field of type byte
3708       * @param env A JREF index for the JNI environment object
3709       * @param classJREF a JREF index for the RVMClass object
3710       * @param fieldID the id for the RVMField that describes this field
3711       * @param fieldValue the value to assign
3712       */
3713      private static void SetStaticByteField(JNIEnvironment env, int classJREF, int fieldID, byte fieldValue) {
3714        if (traceJNI) VM.sysWrite("JNI called: SetStaticByteField  \n");
3715        RuntimeEntrypoints.checkJNICountDownToGC();
3716    
3717        try {
3718          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3719          field.setByteValueUnchecked(null, fieldValue);
3720        } catch (Throwable unexpected) {
3721          if (traceJNI) unexpected.printStackTrace(System.err);
3722          env.recordException(unexpected);
3723        }
3724      }
3725    
3726      /**
3727       * SetStaticCharField:  set a static field of type char
3728       * @param env A JREF index for the JNI environment object
3729       * @param classJREF a JREF index for the RVMClass object
3730       * @param fieldID the id for the RVMField that describes this field
3731       * @param fieldValue  The value to assign
3732       */
3733      private static void SetStaticCharField(JNIEnvironment env, int classJREF, int fieldID, char fieldValue) {
3734        if (traceJNI) VM.sysWrite("JNI called: SetStaticCharField  \n");
3735        RuntimeEntrypoints.checkJNICountDownToGC();
3736    
3737        try {
3738          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3739          field.setCharValueUnchecked(null, fieldValue);
3740        } catch (Throwable unexpected) {
3741          if (traceJNI) unexpected.printStackTrace(System.err);
3742          env.recordException(unexpected);
3743        }
3744      }
3745    
3746      /**
3747       * SetStaticShortField:  set a static field of type short
3748       * @param env A JREF index for the JNI environment object
3749       * @param classJREF a JREF index for the RVMClass object
3750       * @param fieldID the id for the RVMField that describes this field
3751       * @param fieldValue  The value to assign
3752       */
3753      private static void SetStaticShortField(JNIEnvironment env, int classJREF, int fieldID, short fieldValue) {
3754        if (traceJNI) VM.sysWrite("JNI called: SetStaticShortField  \n");
3755        RuntimeEntrypoints.checkJNICountDownToGC();
3756    
3757        try {
3758          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3759          field.setShortValueUnchecked(null, fieldValue);
3760        } catch (Throwable unexpected) {
3761          if (traceJNI) unexpected.printStackTrace(System.err);
3762          env.recordException(unexpected);
3763        }
3764      }
3765    
3766      /**
3767       * SetStaticIntField:  set a static field of type integer
3768       * @param env A JREF index for the JNI environment object
3769       * @param classJREF a JREF index for the RVMClass object
3770       * @param fieldID the id for the RVMField that describes this field
3771       * @param fieldValue  The value to assign
3772       */
3773      private static void SetStaticIntField(JNIEnvironment env, int classJREF, int fieldID, int fieldValue) {
3774        if (traceJNI) VM.sysWrite("JNI called: SetStaticIntField  \n");
3775        RuntimeEntrypoints.checkJNICountDownToGC();
3776    
3777        try {
3778          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3779          field.setIntValueUnchecked(null, fieldValue);
3780        } catch (Throwable unexpected) {
3781          if (traceJNI) unexpected.printStackTrace(System.err);
3782          env.recordException(unexpected);
3783        }
3784      }
3785    
3786      /**
3787       * SetStaticLongField:  set a static field of type long
3788       * @param env A JREF index for the JNI environment object
3789       * @param classJREF a JREF index for the RVMClass object
3790       * @param fieldID the id for the RVMField that describes this field
3791       * @param fieldValue  The value to assign
3792       */
3793      private static void SetStaticLongField(JNIEnvironment env, int classJREF, int fieldID, long fieldValue) {
3794        if (traceJNI) VM.sysWrite("JNI called: SetStaticLongField  \n");
3795        RuntimeEntrypoints.checkJNICountDownToGC();
3796    
3797        try {
3798          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3799          field.setLongValueUnchecked(null, fieldValue);
3800        } catch (Throwable unexpected) {
3801          if (traceJNI) unexpected.printStackTrace(System.err);
3802          env.recordException(unexpected);
3803        }
3804      }
3805    
3806      /**
3807       * SetStaticFloatField:  set a static field of type float
3808       * @param env A JREF index for the JNI environment object
3809       * @param classJREF a JREF index for the RVMClass object
3810       * @param fieldID the id for the RVMField that describes this field
3811       * @param fieldValue  The value to assign
3812       */
3813      private static void SetStaticFloatField(JNIEnvironment env, int classJREF, int fieldID, float fieldValue) {
3814        if (traceJNI) VM.sysWrite("JNI called: SetStaticFloatField  \n");
3815        RuntimeEntrypoints.checkJNICountDownToGC();
3816    
3817        try {
3818          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3819          field.setFloatValueUnchecked(null, fieldValue);
3820        } catch (Throwable unexpected) {
3821          if (traceJNI) unexpected.printStackTrace(System.err);
3822          env.recordException(unexpected);
3823        }
3824      }
3825    
3826      /**
3827       * SetStaticDoubleField:  set a static field of type float
3828       * @param env A JREF index for the JNI environment object
3829       * @param classJREF a JREF index for the RVMClass object
3830       * @param fieldID the id for the RVMField that describes this field
3831       * @param fieldValue  The value to assign
3832       */
3833      private static void SetStaticDoubleField(JNIEnvironment env, int classJREF, int fieldID, double fieldValue) {
3834        if (traceJNI) VM.sysWrite("JNI called: SetStaticDoubleField  \n");
3835        RuntimeEntrypoints.checkJNICountDownToGC();
3836    
3837        try {
3838          RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
3839          field.setDoubleValueUnchecked(null, fieldValue);
3840        } catch (Throwable unexpected) {
3841          if (traceJNI) unexpected.printStackTrace(System.err);
3842          env.recordException(unexpected);
3843        }
3844      }
3845    
3846      /**
3847       * NewString: create a String Object from C array of unicode chars
3848       * @param env A JREF index for the JNI environment object
3849       * @param uchars address of C array of 16 bit unicode characters
3850       * @param len the number of chars in the C array
3851       * @return the allocated String Object, converted to a JREF index
3852       *         or 0 if an OutOfMemoryError Exception has been thrown
3853       * @exception OutOfMemoryError
3854       */
3855      private static int NewString(JNIEnvironment env, Address uchars, int len) {
3856        if (traceJNI) VM.sysWrite("JNI called: NewString  \n");
3857        RuntimeEntrypoints.checkJNICountDownToGC();
3858    
3859        try {
3860          final char[] contents = new char[len];
3861          Memory.memcopy(Magic.objectAsAddress(contents), uchars, len * 2);
3862          return env.pushJNIRef(java.lang.JikesRVMSupport.newStringWithoutCopy(contents, 0, len));
3863        } catch (Throwable unexpected) {
3864          if (traceJNI) unexpected.printStackTrace(System.err);
3865          env.recordException(unexpected);
3866          return 0;
3867        }
3868      }
3869    
3870      /**
3871       * GetStringLength:  return the length of a String
3872       * @param env A JREF index for the JNI environment object
3873       * @param objJREF a JREF index for the String object
3874       * @return the length of the String
3875       */
3876      private static int GetStringLength(JNIEnvironment env, int objJREF) {
3877        if (traceJNI) VM.sysWrite("JNI called: GetStringLength  \n");
3878        RuntimeEntrypoints.checkJNICountDownToGC();
3879    
3880        try {
3881          String str = (String) env.getJNIRef(objJREF);
3882          return str.length();
3883        } catch (Throwable unexpected) {
3884          if (traceJNI) unexpected.printStackTrace(System.err);
3885          env.recordException(unexpected);
3886          return 0;
3887        }
3888      }
3889    
3890      /**
3891       * GetStringChars:  return address of buffer containing contents of a String
3892       * @param env A JREF index for the JNI environment object
3893       * @param strJREF a JREF index for the String object
3894       * @param isCopyAddress address of isCopy jboolean (an int)
3895       * @return address of a copy of the String unicode characters
3896       *         and *isCopy is set to 1 (TRUE)
3897       * @exception OutOfMemoryError if the system runs out of memory
3898       */
3899      private static Address GetStringChars(JNIEnvironment env, int strJREF, Address isCopyAddress) {
3900        if (traceJNI) VM.sysWrite("JNI called: GetStringChars  \n");
3901        RuntimeEntrypoints.checkJNICountDownToGC();
3902    
3903        String str = (String) env.getJNIRef(strJREF);
3904        char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str);
3905        int strOffset = java.lang.JikesRVMSupport.getStringOffset(str);
3906        int len = java.lang.JikesRVMSupport.getStringLength(str);
3907    
3908        // alloc non moving buffer in C heap for a copy of string contents
3909        Address copyBuffer = sysCall.sysMalloc(len * 2);
3910        if (copyBuffer.isZero()) {
3911          env.recordException(new OutOfMemoryError());
3912          return Address.zero();
3913        }
3914        try {
3915          Address strBase = Magic.objectAsAddress(strChars);
3916          Address srcBase = strBase.plus(strOffset * 2);
3917          Memory.memcopy(copyBuffer, srcBase, len * 2);
3918    
3919          /* Set caller's isCopy boolean to true, if we got a valid (non-null)
3920             address */
3921          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
3922    
3923          return copyBuffer;
3924        } catch (Throwable unexpected) {
3925          if (traceJNI) unexpected.printStackTrace(System.err);
3926          env.recordException(unexpected);
3927          sysCall.sysFree(copyBuffer);
3928          return Address.zero();
3929        }
3930      }
3931    
3932      /**
3933       * ReleaseStringChars:  release buffer obtained via GetStringChars
3934       * @param env A JREF index for the JNI environment object
3935       * @param objJREF a JREF index for the String object
3936       * @param bufAddress address of buffer to release
3937       */
3938      private static void ReleaseStringChars(JNIEnvironment env, int objJREF, Address bufAddress) {
3939        if (traceJNI) VM.sysWrite("JNI called: ReleaseStringChars  \n");
3940        RuntimeEntrypoints.checkJNICountDownToGC();
3941    
3942        try {
3943          sysCall.sysFree(bufAddress);
3944        } catch (Throwable unexpected) {
3945          if (traceJNI) unexpected.printStackTrace(System.err);
3946          env.recordException(unexpected);
3947        }
3948      }
3949    
3950      /**
3951       * NewStringUTF: create a String Object from C array of utf8 bytes
3952       * @param env A JREF index for the JNI environment object
3953       * @param utf8bytes address of C array of 8 bit utf8 bytes
3954       * @return the allocated String Object, converted to a JREF index
3955       *         or 0 if an OutOfMemoryError Exception has been thrown
3956       * @exception OutOfMemoryError if the system runs out of memory
3957       */
3958      private static int NewStringUTF(JNIEnvironment env, Address utf8bytes) {
3959        if (traceJNI) VM.sysWrite("JNI called: NewStringUTF  \n");
3960        RuntimeEntrypoints.checkJNICountDownToGC();
3961    
3962        try {
3963          String returnString = JNIHelpers.createUTFStringFromC(utf8bytes);
3964          return env.pushJNIRef(returnString);
3965        } catch (Throwable unexpected) {
3966          if (traceJNI) unexpected.printStackTrace(System.err);
3967          env.recordException(unexpected);
3968          return 0;
3969        }
3970      }
3971    
3972      /**
3973       * GetStringUTFLength: return number of bytes to represent a String in UTF8 format
3974       * @param env A JREF index for the JNI environment object
3975       * @param objJREF a JREF index for the String object
3976       * @return number of bytes to represent in UTF8 format
3977       */
3978      private static int GetStringUTFLength(JNIEnvironment env, int objJREF) {
3979        if (traceJNI) VM.sysWrite("JNI called: GetStringUTFLength  \n");
3980        RuntimeEntrypoints.checkJNICountDownToGC();
3981    
3982        try {
3983          String str = (String) env.getJNIRef(objJREF);
3984          return UTF8Convert.utfLength(str);
3985        } catch (Throwable unexpected) {
3986          if (traceJNI) unexpected.printStackTrace(System.err);
3987          env.recordException(unexpected);
3988          return 0;
3989        }
3990      }
3991    
3992      /**
3993       * GetStringUTFChars:  return address of buffer containing contents of a String
3994       * @param env A JREF index for the JNI environment object
3995       * @param strJREF a JREF index for the String object
3996       * @param isCopyAddress address of isCopy jboolean (an int)
3997       * @return address of a copy of the String unicode characters
3998       *         and *isCopy is set to 1 (TRUE)
3999       * @exception OutOfMemoryError if the system runs out of memory
4000       */
4001      private static Address GetStringUTFChars(JNIEnvironment env, int strJREF, Address isCopyAddress) {
4002        if (traceJNI) VM.sysWrite("JNI called: GetStringUTFChars  \n");
4003        RuntimeEntrypoints.checkJNICountDownToGC();
4004    
4005        String str = (String) env.getJNIRef(strJREF);
4006    
4007        // Get length of C string
4008        int len = UTF8Convert.utfLength(str) + 1; // for terminating zero
4009    
4010        // alloc non moving buffer in C heap for string
4011        Address copyBuffer = sysCall.sysMalloc(len);
4012        if (copyBuffer.isZero()) {
4013          env.recordException(new OutOfMemoryError());
4014          return Address.zero();
4015        }
4016        try {
4017          JNIHelpers.createUTFForCFromString(str, copyBuffer, len);
4018          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4019          return copyBuffer;
4020        } catch (Throwable unexpected) {
4021          if (traceJNI) unexpected.printStackTrace(System.err);
4022          env.recordException(unexpected);
4023          return Address.zero();
4024        }
4025      }
4026    
4027      /**
4028       * ReleaseStringUTFChars:  release buffer obtained via GetStringUTFChars
4029       * @param env A JREF index for the JNI environment object
4030       * @param objJREF a JREF index for the String object
4031       * @param bufAddress address of buffer to release
4032       */
4033      private static void ReleaseStringUTFChars(JNIEnvironment env, int objJREF, Address bufAddress) {
4034        if (traceJNI) VM.sysWrite("JNI called: ReleaseStringUTFChars  \n");
4035        RuntimeEntrypoints.checkJNICountDownToGC();
4036    
4037        try {
4038          sysCall.sysFree(bufAddress);
4039        } catch (Throwable unexpected) {
4040          if (traceJNI) unexpected.printStackTrace(System.err);
4041          env.recordException(unexpected);
4042        }
4043      }
4044    
4045      /**
4046       * GetArrayLength: return array length
4047       * @param env A JREF index for the JNI environment object
4048       * @param arrayJREF a JREF index for the source array
4049       * @return the array length, or -1 if it's not an array
4050       */
4051      private static int GetArrayLength(JNIEnvironment env, int arrayJREF) {
4052        if (traceJNI) VM.sysWrite("JNI called: GetArrayLength  \n");
4053        RuntimeEntrypoints.checkJNICountDownToGC();
4054    
4055        try {
4056          Object theArray = env.getJNIRef(arrayJREF);
4057          RVMType arrayType = Magic.getObjectType(theArray);
4058          return arrayType.isArrayType() ? Magic.getArrayLength(theArray) : -1;
4059        } catch (Throwable unexpected) {
4060          if (traceJNI) unexpected.printStackTrace(System.err);
4061          env.recordException(unexpected);
4062          return -1;
4063        }
4064      }
4065    
4066      /**
4067       * NewObjectArray: create a new Object array
4068       * @param env A JREF index for the JNI environment object
4069       * @param length the size of the new array
4070       * @param classJREF a JREF index for the class of the element
4071       * @param initElementJREF a JREF index for the value to initialize the array elements
4072       * @return the new Object array initialized
4073       * @exception OutOfMemoryError if the system runs out of memory
4074       */
4075      private static int NewObjectArray(JNIEnvironment env, int length, int classJREF, int initElementJREF) {
4076        if (traceJNI) VM.sysWrite("JNI called: NewObjectArray  \n");
4077        RuntimeEntrypoints.checkJNICountDownToGC();
4078    
4079        try {
4080          Object initElement = env.getJNIRef(initElementJREF);
4081          Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
4082    
4083          if (cls == null) {
4084            throw new NullPointerException();
4085          }
4086          if (length < 0) {
4087            throw new NegativeArraySizeException();
4088          }
4089    
4090          RVMArray arrayType = java.lang.JikesRVMSupport.getTypeForClass(cls).getArrayTypeForElementType();
4091          if (!arrayType.isInitialized()) {
4092            arrayType.resolve();
4093            arrayType.instantiate();
4094            arrayType.initialize();
4095          }
4096          Object[] newArray = (Object[]) RuntimeEntrypoints.resolvedNewArray(length, arrayType);
4097    
4098          if (initElement != null) {
4099            for (int i = 0; i < length; i++) {
4100              newArray[i] = initElement;
4101            }
4102          }
4103    
4104          return env.pushJNIRef(newArray);
4105        } catch (Throwable unexpected) {
4106          if (traceJNI) unexpected.printStackTrace(System.err);
4107          env.recordException(unexpected);
4108          return 0;
4109        }
4110      }
4111    
4112      /**
4113       * GetObjectArrayElement: retrieve an object from an object array
4114       * @param env A JREF index for the JNI environment object
4115       * @param arrayJREF a JREF index for the source array
4116       * @param index the index for the targeted element
4117       * @return the object at the specified index
4118       * @exception ArrayIndexOutOfBoundsException if the index is out of range
4119       */
4120      private static int GetObjectArrayElement(JNIEnvironment env, int arrayJREF, int index) {
4121        if (traceJNI) VM.sysWrite("JNI called: GetObjectArrayElement  \n");
4122        RuntimeEntrypoints.checkJNICountDownToGC();
4123    
4124        try {
4125          Object[] sourceArray = (Object[]) env.getJNIRef(arrayJREF);
4126    
4127          if (sourceArray == null) {
4128            return 0;
4129          }
4130    
4131          RVMArray arrayType = Magic.getObjectType(sourceArray).asArray();
4132          RVMType elementType = arrayType.getElementType();
4133          if (elementType.isPrimitiveType() || elementType.isUnboxedType()) {
4134            return 0;
4135          }
4136    
4137          if (index >= Magic.getArrayLength(sourceArray)) {
4138            env.recordException(new ArrayIndexOutOfBoundsException());
4139            return 0;
4140          }
4141    
4142          return env.pushJNIRef(sourceArray[index]);
4143        } catch (Throwable unexpected) {
4144          if (traceJNI) unexpected.printStackTrace(System.err);
4145          env.recordException(unexpected);
4146          return 0;
4147        }
4148      }
4149    
4150      /**
4151       * SetObjectArrayElement: store an object into an object array
4152       * @param env A JREF index for the JNI environment object
4153       * @param arrayJREF a JREF index for the source array
4154       * @param index the index for the targeted element
4155       * @param objectJREF a JREF index for the object to store into the array
4156       * @exception ArrayStoreException if the element types do not match
4157       *            ArrayIndexOutOfBoundsException if the index is out of range
4158       */
4159      private static void SetObjectArrayElement(JNIEnvironment env, int arrayJREF, int index, int objectJREF) {
4160        if (traceJNI) VM.sysWrite("JNI called: SetObjectArrayElement  \n");
4161        RuntimeEntrypoints.checkJNICountDownToGC();
4162    
4163        try {
4164          Object[] sourceArray = (Object[]) env.getJNIRef(arrayJREF);
4165          Object elem = env.getJNIRef(objectJREF);
4166          sourceArray[index] = elem;
4167        } catch (Throwable e) {
4168          env.recordException(e);
4169        }
4170      }
4171    
4172      /**
4173       * NewBooleanArray: create a new boolean array
4174       * @param env A JREF index for the JNI environment object
4175       * @param length the size of the new array
4176       * @return the new boolean array
4177       * @exception OutOfMemoryError if the system runs out of memory
4178       */
4179      private static int NewBooleanArray(JNIEnvironment env, int length) {
4180        if (traceJNI) VM.sysWrite("JNI called: NewBooleanArray  \n");
4181        RuntimeEntrypoints.checkJNICountDownToGC();
4182    
4183        try {
4184          boolean[] newArray = new boolean[length];
4185          return env.pushJNIRef(newArray);
4186        } catch (Throwable unexpected) {
4187          if (traceJNI) unexpected.printStackTrace(System.err);
4188          env.recordException(unexpected);
4189          return 0;
4190        }
4191      }
4192    
4193      /**
4194       * NewByteArray: create a new byte array
4195       * @param env A JREF index for the JNI environment object
4196       * @param length the size of the new array
4197       * @return the new byte array
4198       * @exception OutOfMemoryError if the system runs out of memory
4199       */
4200      private static int NewByteArray(JNIEnvironment env, int length) {
4201        if (traceJNI) VM.sysWrite("JNI called: NewByteArray  \n");
4202        RuntimeEntrypoints.checkJNICountDownToGC();
4203    
4204        try {
4205          byte[] newArray = new byte[length];
4206          return env.pushJNIRef(newArray);
4207        } catch (Throwable unexpected) {
4208          if (traceJNI) unexpected.printStackTrace(System.err);
4209          env.recordException(unexpected);
4210          return 0;
4211        }
4212      }
4213    
4214      /**
4215       * NewCharArray: create a new char array
4216       * @param env A JREF index for the JNI environment object
4217       * @param length the size of the new array
4218       * @return the new char array
4219       * @exception OutOfMemoryError if the system runs out of memory
4220       */
4221      private static int NewCharArray(JNIEnvironment env, int length) {
4222        if (traceJNI) VM.sysWrite("JNI called: NewCharArray  \n");
4223        RuntimeEntrypoints.checkJNICountDownToGC();
4224    
4225        try {
4226          char[] newArray = new char[length];
4227          return env.pushJNIRef(newArray);
4228        } catch (Throwable unexpected) {
4229          if (traceJNI) unexpected.printStackTrace(System.err);
4230          env.recordException(unexpected);
4231          return 0;
4232        }
4233      }
4234    
4235      /**
4236       * NewShortArray: create a new short array
4237       * @param env A JREF index for the JNI environment object
4238       * @param length the size of the new array
4239       * @return the new short array
4240       * @exception OutOfMemoryError if the system runs out of memory
4241       */
4242      private static int NewShortArray(JNIEnvironment env, int length) {
4243        if (traceJNI) VM.sysWrite("JNI called: NewShortArray  \n");
4244        RuntimeEntrypoints.checkJNICountDownToGC();
4245    
4246        try {
4247          short[] newArray = new short[length];
4248          return env.pushJNIRef(newArray);
4249        } catch (Throwable unexpected) {
4250          if (traceJNI) unexpected.printStackTrace(System.err);
4251          env.recordException(unexpected);
4252          return 0;
4253        }
4254      }
4255    
4256      /**
4257       * NewIntArray: create a new integer array
4258       * @param env A JREF index for the JNI environment object
4259       * @param length the size of the new array
4260       * @return the new integer array
4261       * @exception OutOfMemoryError if the system runs out of memory
4262       */
4263      private static int NewIntArray(JNIEnvironment env, int length) {
4264        if (traceJNI) VM.sysWrite("JNI called: NewIntArray  \n");
4265        RuntimeEntrypoints.checkJNICountDownToGC();
4266    
4267        try {
4268          int[] newArray = new int[length];
4269          return env.pushJNIRef(newArray);
4270        } catch (Throwable unexpected) {
4271          if (traceJNI) unexpected.printStackTrace(System.err);
4272          env.recordException(unexpected);
4273          return 0;
4274        }
4275      }
4276    
4277      /**
4278       * NewLongArray: create a new long array
4279       * @param env A JREF index for the JNI environment object
4280       * @param length the size of the new array
4281       * @return the new long array
4282       * @exception OutOfMemoryError if the system runs out of memory
4283       */
4284      private static int NewLongArray(JNIEnvironment env, int length) {
4285        if (traceJNI) VM.sysWrite("JNI called: NewLongArray  \n");
4286        RuntimeEntrypoints.checkJNICountDownToGC();
4287    
4288        try {
4289          long[] newArray = new long[length];
4290          return env.pushJNIRef(newArray);
4291        } catch (Throwable unexpected) {
4292          if (traceJNI) unexpected.printStackTrace(System.err);
4293          env.recordException(unexpected);
4294          return 0;
4295        }
4296      }
4297    
4298      /**
4299       * NewFloatArray: create a new float array
4300       * @param env A JREF index for the JNI environment object
4301       * @param length the size of the new array
4302       * @return the new float array
4303       * @exception OutOfMemoryError if the system runs out of memory
4304       */
4305      private static int NewFloatArray(JNIEnvironment env, int length) {
4306        if (traceJNI) VM.sysWrite("JNI called: NewFloatArray  \n");
4307        RuntimeEntrypoints.checkJNICountDownToGC();
4308    
4309        try {
4310          float[] newArray = new float[length];
4311          return env.pushJNIRef(newArray);
4312        } catch (Throwable unexpected) {
4313          if (traceJNI) unexpected.printStackTrace(System.err);
4314          env.recordException(unexpected);
4315          return 0;
4316        }
4317      }
4318    
4319      /**
4320       * NewDoubleArray: create a new double array
4321       * @param env A JREF index for the JNI environment object
4322       * @param length the size of the new array
4323       * @return the new long array
4324       * @exception OutOfMemoryError if the system runs out of memory
4325       */
4326      private static int NewDoubleArray(JNIEnvironment env, int length) {
4327        if (traceJNI) VM.sysWrite("JNI called: NewDoubleArray  \n");
4328        RuntimeEntrypoints.checkJNICountDownToGC();
4329    
4330        try {
4331          double[] newArray = new double[length];
4332          return env.pushJNIRef(newArray);
4333        } catch (Throwable unexpected) {
4334          if (traceJNI) unexpected.printStackTrace(System.err);
4335          env.recordException(unexpected);
4336          return 0;
4337        }
4338      }
4339    
4340      /**
4341       * GetBooleanArrayElements: get all the elements of a boolean array
4342       * @param env A JREF index for the JNI environment object
4343       * @param arrayJREF a JREF index for the source array
4344       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4345       * @return A pointer to the boolean array and the isCopy flag is set to true if it's a copy
4346       *         or false if it's a direct pointer
4347       * @exception OutOfMemoryError if the system runs out of memory
4348       */
4349      private static Address GetBooleanArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4350        if (traceJNI) VM.sysWrite("JNI called: GetBooleanArrayElements  \n");
4351        RuntimeEntrypoints.checkJNICountDownToGC();
4352    
4353        try {
4354          boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF);
4355          int size = sourceArray.length;
4356    
4357          // alloc non moving buffer in C heap for a copy of string contents
4358          Address copyBuffer = sysCall.sysMalloc(size);
4359          if (copyBuffer.isZero()) {
4360            env.recordException(new OutOfMemoryError());
4361            return Address.zero();
4362          }
4363    
4364          Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size);
4365    
4366          /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4367             address */
4368          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4369    
4370          return copyBuffer;
4371        } catch (Throwable unexpected) {
4372          if (traceJNI) unexpected.printStackTrace(System.err);
4373          env.recordException(unexpected);
4374          return Address.zero();
4375        }
4376      }
4377    
4378      /**
4379       * GetByteArrayElements: get all the elements of a byte array
4380       * @param env A JREF index for the JNI environment object
4381       * @param arrayJREF a JREF index for the source array
4382       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4383       * @return A pointer to the byte array and the isCopy flag is set to true if it's a copy
4384       *         or false if it's a direct pointer
4385       * @exception OutOfMemoryError if the system runs out of memory
4386       */
4387      private static Address GetByteArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4388        if (traceJNI) VM.sysWrite("JNI called: GetByteArrayElements \n");
4389        RuntimeEntrypoints.checkJNICountDownToGC();
4390    
4391        try {
4392          byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF);
4393          int size = sourceArray.length;
4394    
4395          if (MemoryManager.willNeverMove(sourceArray)) {
4396            /* return a direct pointer */
4397            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4398            return Magic.objectAsAddress(sourceArray);
4399          } else {
4400            // alloc non moving buffer in C heap for a copy of string contents
4401            Address copyBuffer = sysCall.sysMalloc(size);
4402    
4403            if (copyBuffer.isZero()) {
4404              env.recordException(new OutOfMemoryError());
4405              return Address.zero();
4406            }
4407    
4408            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size);
4409    
4410            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4411               address */
4412            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4413    
4414            return copyBuffer;
4415          }
4416        } catch (Throwable unexpected) {
4417          if (traceJNI) unexpected.printStackTrace(System.err);
4418          env.recordException(unexpected);
4419          return Address.zero();
4420        }
4421      }
4422    
4423      /**
4424       * GetCharArrayElements: get all the elements of a char array
4425       * @param env A JREF index for the JNI environment object
4426       * @param arrayJREF a JREF index for the source array
4427       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4428       * @return A pointer to the char array and the isCopy flag is set to true if it's a copy
4429       *         or false if it's a direct pointer
4430       * @exception OutOfMemoryError if the system runs out of memory
4431       */
4432      private static Address GetCharArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4433        if (traceJNI) VM.sysWrite("JNI called: GetCharArrayElements  \n");
4434        RuntimeEntrypoints.checkJNICountDownToGC();
4435    
4436        try {
4437          char[] sourceArray = (char[]) env.getJNIRef(arrayJREF);
4438          int size = sourceArray.length;
4439    
4440          if (MemoryManager.willNeverMove(sourceArray)) {
4441            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4442            return Magic.objectAsAddress(sourceArray);
4443          } else {
4444            // alloc non moving buffer in C heap for a copy of string contents
4445            Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_CHAR);
4446            if (copyBuffer.isZero()) {
4447              env.recordException(new OutOfMemoryError());
4448              return Address.zero();
4449            }
4450    
4451            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size * BYTES_IN_CHAR);
4452    
4453            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4454             address */
4455            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4456    
4457            return copyBuffer;
4458          }
4459        } catch (Throwable unexpected) {
4460          if (traceJNI) unexpected.printStackTrace(System.err);
4461          env.recordException(unexpected);
4462          return Address.zero();
4463        }
4464      }
4465    
4466      /**
4467       * GetShortArrayElements: get all the elements of a short array
4468       * @param env A JREF index for the JNI environment object
4469       * @param arrayJREF a JREF index for the source array
4470       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4471       * @return A pointer to the short array and the isCopy flag is set to true if it's a copy
4472       *         or false if it's a direct pointer
4473       * @exception OutOfMemoryError if the system runs out of memory
4474       */
4475      private static Address GetShortArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4476        if (traceJNI) VM.sysWrite("JNI called: GetShortArrayElements  \n");
4477        RuntimeEntrypoints.checkJNICountDownToGC();
4478    
4479        try {
4480          short[] sourceArray = (short[]) env.getJNIRef(arrayJREF);
4481          int size = sourceArray.length;
4482    
4483          if (MemoryManager.willNeverMove(sourceArray)) {
4484            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4485            return Magic.objectAsAddress(sourceArray);
4486          } else {
4487            // alloc non moving buffer in C heap for a copy of string contents
4488            Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_SHORT);
4489            if (copyBuffer.isZero()) {
4490              env.recordException(new OutOfMemoryError());
4491              return Address.zero();
4492            }
4493    
4494            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size * BYTES_IN_SHORT);
4495    
4496            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4497             address */
4498            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4499    
4500            return copyBuffer;
4501          }
4502        } catch (Throwable unexpected) {
4503          if (traceJNI) unexpected.printStackTrace(System.err);
4504          env.recordException(unexpected);
4505          return Address.zero();
4506        }
4507      }
4508    
4509      /**
4510       * GetIntArrayElements: get all the elements of an integer array
4511       * @param env A JREF index for the JNI environment object
4512       * @param arrayJREF a JREF index for the source array
4513       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4514       * @return A pointer to the integer array and the isCopy flag is set to true if it's a copy
4515       *         or false if it's a direct pointer
4516       * @exception OutOfMemoryError if the system runs out of memory
4517       */
4518      private static Address GetIntArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4519        if (traceJNI) VM.sysWrite("JNI called: GetIntArrayElements  \n");
4520        RuntimeEntrypoints.checkJNICountDownToGC();
4521    
4522        try {
4523          int[] sourceArray = (int[]) env.getJNIRef(arrayJREF);
4524          int size = sourceArray.length;
4525    
4526          if (MemoryManager.willNeverMove(sourceArray)) {
4527            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4528            return Magic.objectAsAddress(sourceArray);
4529          } else {
4530            // alloc non moving buffer in C heap for a copy of array contents
4531            Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_INT);
4532            if (copyBuffer.isZero()) {
4533              env.recordException(new OutOfMemoryError());
4534              return Address.zero();
4535            }
4536            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_INT);
4537    
4538            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4539             address */
4540            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4541    
4542            return copyBuffer;
4543          }
4544        } catch (Throwable unexpected) {
4545          if (traceJNI) unexpected.printStackTrace(System.err);
4546          env.recordException(unexpected);
4547          return Address.zero();
4548        }
4549      }
4550    
4551      /**
4552       * GetLongArrayElements: get all the elements of a long array
4553       * @param env A JREF index for the JNI environment object
4554       * @param arrayJREF a JREF index for the source array
4555       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4556       * @return A pointer to the long array and the isCopy flag is set to true if it's a copy
4557       *         or false if it's a direct pointer
4558       * @exception OutOfMemoryError if the system runs out of memory
4559       */
4560      private static Address GetLongArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4561        if (traceJNI) VM.sysWrite("JNI called: GetLongArrayElements  \n");
4562        RuntimeEntrypoints.checkJNICountDownToGC();
4563    
4564        try {
4565          long[] sourceArray = (long[]) env.getJNIRef(arrayJREF);
4566          int size = sourceArray.length;
4567    
4568          if (MemoryManager.willNeverMove(sourceArray)) {
4569            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4570            return Magic.objectAsAddress(sourceArray);
4571          } else {
4572            // alloc non moving buffer in C heap for a copy of string contents
4573            Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_LONG);
4574            if (copyBuffer.isZero()) {
4575              env.recordException(new OutOfMemoryError());
4576              return Address.zero();
4577            }
4578            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_LONG);
4579    
4580            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4581             address */
4582            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4583    
4584            return copyBuffer;
4585          }
4586        } catch (Throwable unexpected) {
4587          if (traceJNI) unexpected.printStackTrace(System.err);
4588          env.recordException(unexpected);
4589          return Address.zero();
4590        }
4591      }
4592    
4593      /**
4594       * GetFloatArrayElements: get all the elements of a float array
4595       * @param env A JREF index for the JNI environment object
4596       * @param arrayJREF a JREF index for the source array
4597       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4598       * @return A pointer to the float array and the isCopy flag is set to true if it's a copy
4599       *         or false if it's a direct pointer
4600       * @exception OutOfMemoryError if the system runs out of memory
4601       */
4602      private static Address GetFloatArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4603        if (traceJNI) VM.sysWrite("JNI called: GetFloatArrayElements  \n");
4604        RuntimeEntrypoints.checkJNICountDownToGC();
4605    
4606        try {
4607          float[] sourceArray = (float[]) env.getJNIRef(arrayJREF);
4608          int size = sourceArray.length;
4609    
4610          if (MemoryManager.willNeverMove(sourceArray)) {
4611            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4612            return Magic.objectAsAddress(sourceArray);
4613          } else {
4614            // alloc non moving buffer in C heap for a copy of string contents
4615            Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_FLOAT);
4616            if (copyBuffer.isZero()) {
4617              env.recordException(new OutOfMemoryError());
4618              return Address.zero();
4619            }
4620    
4621            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_FLOAT);
4622    
4623            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4624             address */
4625            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4626    
4627            return copyBuffer;
4628          }
4629        } catch (Throwable unexpected) {
4630          if (traceJNI) unexpected.printStackTrace(System.err);
4631          env.recordException(unexpected);
4632          return Address.zero();
4633        }
4634      }
4635    
4636      /**
4637       * GetDoubleArrayElements: get all the elements of a double array
4638       * @param env A JREF index for the JNI environment object
4639       * @param arrayJREF a JREF index for the source array
4640       * @param isCopyAddress address of a flag to indicate whether the returned array is a copy or a direct pointer
4641       * @return A pointer to the double array and the isCopy flag is set to true if it's a copy
4642       *         or false if it's a direct pointer
4643       * @exception OutOfMemoryError if the system runs out of memory
4644       */
4645      private static Address GetDoubleArrayElements(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
4646        if (traceJNI) VM.sysWrite("JNI called: GetDoubleArrayElements  \n");
4647        RuntimeEntrypoints.checkJNICountDownToGC();
4648    
4649        try {
4650          double[] sourceArray = (double[]) env.getJNIRef(arrayJREF);
4651          int size = sourceArray.length;
4652    
4653          if (MemoryManager.willNeverMove(sourceArray)) {
4654            JNIGenericHelpers.setBoolStar(isCopyAddress, false);
4655            return Magic.objectAsAddress(sourceArray);
4656          } else {
4657            // alloc non moving buffer in C heap for a copy of string contents
4658            Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_DOUBLE);
4659            if (copyBuffer.isZero()) {
4660              env.recordException(new OutOfMemoryError());
4661              return Address.zero();
4662            }
4663            Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_DOUBLE);
4664    
4665            /* Set caller's isCopy boolean to true, if we got a valid (non-null)
4666             address */
4667            JNIGenericHelpers.setBoolStar(isCopyAddress, true);
4668    
4669            return copyBuffer;
4670          }
4671        } catch (Throwable unexpected) {
4672          if (traceJNI) unexpected.printStackTrace(System.err);
4673          env.recordException(unexpected);
4674          return Address.zero();
4675        }
4676      }
4677    
4678      /**
4679       * ReleaseBooleanArrayElements: free the native copy of the array, update changes to Java array as indicated
4680       * @param env A JREF index for the JNI environment object
4681       * @param arrayJREF a JREF index for the source array
4682       * @param copyBufferAddress the address of the copy of the array
4683       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4684       *    releaseMode 0:  copy back and free the buffer
4685       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4686       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4687       */
4688      private static void ReleaseBooleanArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4689                                                      int releaseMode) {
4690        if (traceJNI) VM.sysWrite("JNI called: ReleaseBooleanArrayElements  \n");
4691        RuntimeEntrypoints.checkJNICountDownToGC();
4692    
4693        try {
4694          boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF);
4695    
4696          // If a direct pointer was given to the user, no need to update or release
4697          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4698            int size = sourceArray.length;
4699    
4700            // mode 0 and mode 1:  copy back the buffer
4701            if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
4702              for (int i = 0; i < size; i += BYTES_IN_INT) {
4703                Address addr = copyBufferAddress.plus(i);
4704                int data = addr.loadInt();
4705                if (VM.LittleEndian) {
4706                  if (i < size) sourceArray[i] = ((data) & 0x000000ff) != 0;
4707                  if (i + 1 < size) sourceArray[i + 1] = ((data >>> BITS_IN_BYTE) & 0x000000ff) != 0;
4708                  if (i + 2 < size) sourceArray[i + 2] = ((data >>> (2 * BITS_IN_BYTE)) & 0x000000ff) != 0;
4709                  if (i + 3 < size) sourceArray[i + 3] = ((data >>> (3 * BITS_IN_BYTE)) & 0x000000ff) != 0;
4710                } else {
4711                  if (i < size) sourceArray[i] = ((data >>> (3 * BITS_IN_BYTE)) & 0x000000ff) != 0;
4712                  if (i + 1 < size) sourceArray[i + 1] = ((data >>> (2 * BITS_IN_BYTE)) & 0x000000ff) != 0;
4713                  if (i + 2 < size) sourceArray[i + 2] = ((data >>> BITS_IN_BYTE) & 0x000000ff) != 0;
4714                  if (i + 3 < size) sourceArray[i + 3] = ((data) & 0x000000ff) != 0;
4715                }
4716              }
4717            }
4718    
4719            // mode 0 and mode 2:  free the buffer
4720            if (releaseMode == 0 || releaseMode == 2) {
4721              sysCall.sysFree(copyBufferAddress);
4722            }
4723          }
4724        } catch (Throwable unexpected) {
4725          if (traceJNI) unexpected.printStackTrace(System.err);
4726          env.recordException(unexpected);
4727        }
4728      }
4729    
4730      /**
4731       * ReleaseByteArrayElements: free the native copy of the array, update changes to Java array as indicated
4732       * @param env A JREF index for the JNI environment object
4733       * @param arrayJREF a JREF index for the source array
4734       * @param copyBufferAddress the address of the copy of the array
4735       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4736       *    releaseMode 0:  copy back and free the buffer
4737       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4738       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4739       */
4740      private static void ReleaseByteArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4741                                                   int releaseMode) {
4742        if (traceJNI) VM.sysWrite("JNI called: ReleaseByteArrayElements  releaseMode=", releaseMode);
4743        RuntimeEntrypoints.checkJNICountDownToGC();
4744    
4745        try {
4746          byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF);
4747    
4748          // If a direct pointer was given to the user, no need to update or release
4749          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4750            int size = sourceArray.length;
4751            if (traceJNI) VM.sysWrite(" size=", size);
4752    
4753            // mode 0 and mode 1:  copy back the buffer
4754            if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
4755              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size);
4756            }
4757    
4758            // mode 0 and mode 2:  free the buffer
4759            if (releaseMode == 0 || releaseMode == 2) {
4760              sysCall.sysFree(copyBufferAddress);
4761            }
4762          } else {
4763            // Nothing to be done
4764          }
4765        } catch (Throwable unexpected) {
4766          if (traceJNI) unexpected.printStackTrace(System.err);
4767          env.recordException(unexpected);
4768        }
4769        if (traceJNI) VM.sysWrite("\n");
4770      }
4771    
4772      /**
4773       * ReleaseCharArrayElements: free the native copy of the array, update changes to Java array as indicated
4774       * @param env A JREF index for the JNI environment object
4775       * @param arrayJREF a JREF index for the source array
4776       * @param copyBufferAddress the address of the copy of the array
4777       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4778       *    releaseMode 0:  copy back and free the buffer
4779       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4780       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4781       */
4782      private static void ReleaseCharArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4783                                                   int releaseMode) {
4784        if (traceJNI) VM.sysWrite("JNI called: ReleaseCharArrayElements \n");
4785        RuntimeEntrypoints.checkJNICountDownToGC();
4786    
4787        try {
4788          char[] sourceArray = (char[]) env.getJNIRef(arrayJREF);
4789    
4790          // If a direct pointer was given to the user, no need to update or release
4791          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4792            int size = sourceArray.length;
4793    
4794            // mode 0 and mode 1:  copy back the buffer
4795            if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
4796              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_CHAR);
4797            }
4798    
4799            // mode 0 and mode 2:  free the buffer
4800            if (releaseMode == 0 || releaseMode == 2) {
4801              sysCall.sysFree(copyBufferAddress);
4802            }
4803          }
4804        } catch (Throwable unexpected) {
4805          if (traceJNI) unexpected.printStackTrace(System.err);
4806          env.recordException(unexpected);
4807        }
4808      }
4809    
4810      /**
4811       * ReleaseShortArrayElements: free the native copy of the array, update changes to Java array as indicated
4812       * @param env A JREF index for the JNI environment object
4813       * @param arrayJREF a JREF index for the source array
4814       * @param copyBufferAddress the address of the copy of the array
4815       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4816       *    releaseMode 0:  copy back and free the buffer
4817       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4818       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4819       */
4820      private static void ReleaseShortArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4821                                                    int releaseMode) {
4822        if (traceJNI) VM.sysWrite("JNI called: ReleaseShortArrayElements  \n");
4823        RuntimeEntrypoints.checkJNICountDownToGC();
4824    
4825        try {
4826          short[] sourceArray = (short[]) env.getJNIRef(arrayJREF);
4827    
4828          // If a direct pointer was given to the user, no need to update or release
4829          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4830            int size = sourceArray.length;
4831    
4832            // mode 0 and mode 1:  copy back the buffer
4833            if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
4834              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_SHORT);
4835            }
4836    
4837            // mode 0 and mode 2:  free the buffer
4838            if (releaseMode == 0 || releaseMode == 2) {
4839              sysCall.sysFree(copyBufferAddress);
4840            }
4841          }
4842        } catch (Throwable unexpected) {
4843          if (traceJNI) unexpected.printStackTrace(System.err);
4844          env.recordException(unexpected);
4845        }
4846      }
4847    
4848      /**
4849       * ReleaseIntArrayElements: free the native copy of the array, update changes to Java array as indicated
4850       * @param env A JREF index for the JNI environment object
4851       * @param arrayJREF a JREF index for the source array
4852       * @param copyBufferAddress the address of the copy of the array
4853       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4854       *    releaseMode 0:  copy back and free the buffer
4855       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4856       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4857       */
4858      private static void ReleaseIntArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4859                                                  int releaseMode) {
4860        if (traceJNI) VM.sysWrite("JNI called: ReleaseIntArrayElements  \n");
4861        RuntimeEntrypoints.checkJNICountDownToGC();
4862    
4863        try {
4864          int[] sourceArray = (int[]) env.getJNIRef(arrayJREF);
4865    
4866          // If a direct pointer was given to the user, no need to update or release
4867          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4868            int size = sourceArray.length;
4869    
4870            // mode 0 and mode 1:  copy back the buffer
4871            if (releaseMode == 0 || releaseMode == 1) {
4872              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_INT);
4873            }
4874    
4875            // mode 0 and mode 2:  free the buffer
4876            if (releaseMode == 0 || releaseMode == 2) {
4877              sysCall.sysFree(copyBufferAddress);
4878            }
4879          }
4880        } catch (Throwable unexpected) {
4881          if (traceJNI) unexpected.printStackTrace(System.err);
4882          env.recordException(unexpected);
4883        }
4884      }
4885    
4886      /**
4887       * ReleaseLongArrayElements: free the native copy of the array, update changes to Java array as indicated
4888       * @param env A JREF index for the JNI environment object
4889       * @param arrayJREF a JREF index for the source array
4890       * @param copyBufferAddress the address of the copy of the array
4891       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4892       *    releaseMode 0:  copy back and free the buffer
4893       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4894       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4895       */
4896      private static void ReleaseLongArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4897                                                   int releaseMode) {
4898        if (traceJNI) VM.sysWrite("JNI called: ReleaseLongArrayElements  \n");
4899        RuntimeEntrypoints.checkJNICountDownToGC();
4900    
4901        try {
4902          long[] sourceArray = (long[]) env.getJNIRef(arrayJREF);
4903    
4904          // If a direct pointer was given to the user, no need to update or release
4905          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4906            int size = sourceArray.length;
4907    
4908            // mode 0 and mode 1:  copy back the buffer
4909            if (releaseMode == 0 || releaseMode == 1) {
4910              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_LONG);
4911            }
4912    
4913            // mode 0 and mode 2:  free the buffer
4914            if (releaseMode == 0 || releaseMode == 2) {
4915              sysCall.sysFree(copyBufferAddress);
4916            }
4917          }
4918        } catch (Throwable unexpected) {
4919          if (traceJNI) unexpected.printStackTrace(System.err);
4920          env.recordException(unexpected);
4921        }
4922      }
4923    
4924      /**
4925       * ReleaseFloatArrayElements: free the native copy of the array, update changes to Java array as indicated
4926       * @param env A JREF index for the JNI environment object
4927       * @param arrayJREF a JREF index for the source array
4928       * @param copyBufferAddress the address of the copy of the array
4929       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4930       *    releaseMode 0:  copy back and free the buffer
4931       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4932       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4933       */
4934      private static void ReleaseFloatArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4935                                                    int releaseMode) {
4936        if (traceJNI) VM.sysWrite("JNI called: ReleaseFloatArrayElements  \n");
4937        RuntimeEntrypoints.checkJNICountDownToGC();
4938    
4939        try {
4940          float[] sourceArray = (float[]) env.getJNIRef(arrayJREF);
4941    
4942          // If a direct pointer was given to the user, no need to update or release
4943          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4944            int size = sourceArray.length;
4945    
4946            // mode 0 and mode 1:  copy back the buffer
4947            if (releaseMode == 0 || releaseMode == 1) {
4948              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_FLOAT);
4949            }
4950    
4951            // mode 0 and mode 2:  free the buffer
4952            if (releaseMode == 0 || releaseMode == 2) {
4953              sysCall.sysFree(copyBufferAddress);
4954            }
4955          }
4956        } catch (Throwable unexpected) {
4957          if (traceJNI) unexpected.printStackTrace(System.err);
4958          env.recordException(unexpected);
4959        }
4960      }
4961    
4962      /**
4963       * ReleaseDoubleArrayElements: free the native copy of the array, update changes to Java array as indicated
4964       * @param env A JREF index for the JNI environment object
4965       * @param arrayJREF a JREF index for the source array
4966       * @param copyBufferAddress the address of the copy of the array
4967       * @param releaseMode one of 3 codes to indicate whether to copy back or free the array:
4968       *    releaseMode 0:  copy back and free the buffer
4969       *    releaseMode 1:  JNI_COMMIT, copy back but do not free the buffer
4970       *    releaseMode 2:  JNI_ABORT, free the buffer with copying back
4971       */
4972      private static void ReleaseDoubleArrayElements(JNIEnvironment env, int arrayJREF, Address copyBufferAddress,
4973                                                     int releaseMode) {
4974        if (traceJNI) VM.sysWrite("JNI called: ReleaseDoubleArrayElements  \n");
4975        RuntimeEntrypoints.checkJNICountDownToGC();
4976    
4977        try {
4978          double[] sourceArray = (double[]) env.getJNIRef(arrayJREF);
4979    
4980          // If a direct pointer was given to the user, no need to update or release
4981          if (Magic.objectAsAddress(sourceArray).NE(copyBufferAddress)) {
4982            int size = sourceArray.length;
4983    
4984            // mode 0 and mode 1:  copy back the buffer
4985            if (releaseMode == 0 || releaseMode == 1) {
4986              Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_DOUBLE);
4987            }
4988    
4989            // mode 0 and mode 2:  free the buffer
4990            if (releaseMode == 0 || releaseMode == 2) {
4991              sysCall.sysFree(copyBufferAddress);
4992            }
4993          }
4994        } catch (Throwable unexpected) {
4995          if (traceJNI) unexpected.printStackTrace(System.err);
4996          env.recordException(unexpected);
4997        }
4998      }
4999    
5000      /**
5001       * GetBooleanArrayRegion: copy a region of the array into the native buffer
5002       * @param env A JREF index for the JNI environment object
5003       * @param arrayJREF a JREF index for the source array
5004       * @param startIndex the starting index to copy
5005       * @param length the number of elements to copy
5006       * @param bufAddress the destination address in native to copy to
5007       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5008       */
5009      private static void GetBooleanArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5010                                                Address bufAddress) {
5011        if (traceJNI) VM.sysWrite("JNI called: GetBooleanArrayRegion  \n");
5012        RuntimeEntrypoints.checkJNICountDownToGC();
5013    
5014        try {
5015          boolean[] sourceArray = (boolean[]) env.getJNIRef(arrayJREF);
5016    
5017          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5018            env.recordException(new ArrayIndexOutOfBoundsException());
5019            return;
5020          }
5021          Memory.memcopy(bufAddress, Magic.objectAsAddress(sourceArray).plus(startIndex), length);
5022        } catch (Throwable unexpected) {
5023          if (traceJNI) unexpected.printStackTrace(System.err);
5024          env.recordException(unexpected);
5025        }
5026      }
5027    
5028      /**
5029       * GetByteArrayRegion: copy a region of the array into the native buffer
5030       * @param env A JREF index for the JNI environment object
5031       * @param arrayJREF a JREF index for the source array
5032       * @param startIndex the starting index to copy
5033       * @param length the number of elements to copy
5034       * @param bufAddress the destination address in native to copy to
5035       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5036       */
5037      private static void GetByteArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5038                                             Address bufAddress) {
5039        if (traceJNI) VM.sysWrite("JNI called: GetByteArrayRegion  \n");
5040        RuntimeEntrypoints.checkJNICountDownToGC();
5041    
5042        try {
5043          byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF);
5044    
5045          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5046            env.recordException(new ArrayIndexOutOfBoundsException());
5047            return;
5048          }
5049    
5050          Memory.memcopy(bufAddress, Magic.objectAsAddress(sourceArray).plus(startIndex), length);
5051        } catch (Throwable unexpected) {
5052          if (traceJNI) unexpected.printStackTrace(System.err);
5053          env.recordException(unexpected);
5054        }
5055      }
5056    
5057      /**
5058       * GetCharArrayRegion: copy a region of the array into the native buffer
5059       * @param env A JREF index for the JNI environment object
5060       * @param arrayJREF a JREF index for the source array
5061       * @param startIndex the starting index to copy
5062       * @param length the number of elements to copy
5063       * @param bufAddress the destination address in native to copy to
5064       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5065       */
5066      private static void GetCharArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5067                                             Address bufAddress) {
5068        if (traceJNI) VM.sysWrite("JNI called: GetCharArrayRegion  \n");
5069        RuntimeEntrypoints.checkJNICountDownToGC();
5070    
5071        try {
5072          char[] sourceArray = (char[]) env.getJNIRef(arrayJREF);
5073    
5074          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5075            env.recordException(new ArrayIndexOutOfBoundsException());
5076            return;
5077          }
5078    
5079          Memory.memcopy(bufAddress,
5080                            Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_CHAR),
5081                            length << LOG_BYTES_IN_CHAR);
5082        } catch (Throwable unexpected) {
5083          if (traceJNI) unexpected.printStackTrace(System.err);
5084          env.recordException(unexpected);
5085        }
5086      }
5087    
5088      /**
5089       * GetShortArrayRegion: copy a region of the array into the native buffer
5090       * @param env A JREF index for the JNI environment object
5091       * @param arrayJREF a JREF index for the source array
5092       * @param startIndex the starting index to copy
5093       * @param length the number of elements to copy
5094       * @param bufAddress the destination address in native to copy to
5095       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5096       */
5097      private static void GetShortArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5098                                              Address bufAddress) {
5099        if (traceJNI) VM.sysWrite("JNI called: GetShortArrayRegion  \n");
5100        RuntimeEntrypoints.checkJNICountDownToGC();
5101    
5102        try {
5103          short[] sourceArray = (short[]) env.getJNIRef(arrayJREF);
5104    
5105          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5106            env.recordException(new ArrayIndexOutOfBoundsException());
5107            return;
5108          }
5109    
5110          Memory.memcopy(bufAddress,
5111                            Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_SHORT),
5112                            length << LOG_BYTES_IN_SHORT);
5113        } catch (Throwable unexpected) {
5114          if (traceJNI) unexpected.printStackTrace(System.err);
5115          env.recordException(unexpected);
5116        }
5117      }
5118    
5119      /**
5120       * GetIntArrayRegion: copy a region of the array into the native buffer
5121       * @param env A JREF index for the JNI environment object
5122       * @param arrayJREF a JREF index for the source array
5123       * @param startIndex the starting index to copy
5124       * @param length the number of elements to copy
5125       * @param bufAddress the destination address in native to copy to
5126       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5127       */
5128      private static void GetIntArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5129                                            Address bufAddress) {
5130        if (traceJNI) VM.sysWrite("JNI called: GetIntArrayRegion  \n");
5131        RuntimeEntrypoints.checkJNICountDownToGC();
5132    
5133        try {
5134          int[] sourceArray = (int[]) env.getJNIRef(arrayJREF);
5135    
5136          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5137            env.recordException(new ArrayIndexOutOfBoundsException());
5138            return;
5139          }
5140    
5141          Memory.memcopy(bufAddress,
5142                            Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_INT),
5143                            length << LOG_BYTES_IN_INT);
5144        } catch (Throwable unexpected) {
5145          if (traceJNI) unexpected.printStackTrace(System.err);
5146          env.recordException(unexpected);
5147        }
5148      }
5149    
5150      /**
5151       * GetLongArrayRegion: copy a region of the array into the native buffer
5152       * @param env A JREF index for the JNI environment object
5153       * @param arrayJREF a JREF index for the source array
5154       * @param startIndex the starting index to copy
5155       * @param length the number of elements to copy
5156       * @param bufAddress the destination address in native to copy to
5157       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5158       */
5159      private static void GetLongArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5160                                             Address bufAddress) {
5161        if (traceJNI) VM.sysWrite("JNI called: GetLongArrayRegion   \n");
5162        RuntimeEntrypoints.checkJNICountDownToGC();
5163    
5164        try {
5165          long[] sourceArray = (long[]) env.getJNIRef(arrayJREF);
5166    
5167          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5168            env.recordException(new ArrayIndexOutOfBoundsException());
5169            return;
5170          }
5171    
5172          Memory.memcopy(bufAddress,
5173                            Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_LONG),
5174                            length << LOG_BYTES_IN_LONG);
5175        } catch (Throwable unexpected) {
5176          if (traceJNI) unexpected.printStackTrace(System.err);
5177          env.recordException(unexpected);
5178        }
5179      }
5180    
5181      /**
5182       * GetFloatArrayRegion: copy a region of the array into the native buffer
5183       * @param env A JREF index for the JNI environment object
5184       * @param arrayJREF a JREF index for the source array
5185       * @param startIndex the starting index to copy
5186       * @param length the number of elements to copy
5187       * @param bufAddress the destination address in native to copy to
5188       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5189       */
5190      private static void GetFloatArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5191                                              Address bufAddress) {
5192        if (traceJNI) VM.sysWrite("JNI called: GetFloatArrayRegion    \n");
5193        RuntimeEntrypoints.checkJNICountDownToGC();
5194    
5195        try {
5196          float[] sourceArray = (float[]) env.getJNIRef(arrayJREF);
5197    
5198          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5199            env.recordException(new ArrayIndexOutOfBoundsException());
5200            return;
5201          }
5202    
5203          Memory.memcopy(bufAddress,
5204                            Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_FLOAT),
5205                            length << LOG_BYTES_IN_FLOAT);
5206        } catch (Throwable unexpected) {
5207          if (traceJNI) unexpected.printStackTrace(System.err);
5208          env.recordException(unexpected);
5209        }
5210      }
5211    
5212      /**
5213       * GetDoubleArrayRegion: copy a region of the array into the native buffer
5214       * @param env A JREF index for the JNI environment object
5215       * @param arrayJREF a JREF index for the source array
5216       * @param startIndex the starting index to copy
5217       * @param length the number of elements to copy
5218       * @param bufAddress the destination address in native to copy to
5219       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5220       */
5221      private static void GetDoubleArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5222                                               Address bufAddress) {
5223        if (traceJNI) VM.sysWrite("JNI called: GetDoubleArrayRegion   \n");
5224        RuntimeEntrypoints.checkJNICountDownToGC();
5225    
5226        try {
5227          double[] sourceArray = (double[]) env.getJNIRef(arrayJREF);
5228    
5229          if ((startIndex < 0) || (startIndex + length > sourceArray.length)) {
5230            env.recordException(new ArrayIndexOutOfBoundsException());
5231            return;
5232          }
5233    
5234          Memory.memcopy(bufAddress,
5235                            Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_DOUBLE),
5236                            length << LOG_BYTES_IN_DOUBLE);
5237        } catch (Throwable unexpected) {
5238          if (traceJNI) unexpected.printStackTrace(System.err);
5239          env.recordException(unexpected);
5240        }
5241      }
5242    
5243      /**
5244       * SetBooleanArrayRegion: copy a region of the native buffer into the array (1 byte element)
5245       * @param env A JREF index for the JNI environment object
5246       * @param arrayJREF a JREF index for the destination array
5247       * @param startIndex the starting index to copy
5248       * @param length the number of elements to copy
5249       * @param bufAddress the source address in native to copy from
5250       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5251       */
5252      private static void SetBooleanArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5253                                                Address bufAddress) {
5254        if (traceJNI) VM.sysWrite("JNI called: SetBooleanArrayRegion  \n");
5255        RuntimeEntrypoints.checkJNICountDownToGC();
5256    
5257        try {
5258          boolean[] destinationArray = (boolean[]) env.getJNIRef(arrayJREF);
5259    
5260          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5261            env.recordException(new ArrayIndexOutOfBoundsException());
5262            return;
5263          }
5264    
5265          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length);
5266        } catch (Throwable unexpected) {
5267          if (traceJNI) unexpected.printStackTrace(System.err);
5268          env.recordException(unexpected);
5269        }
5270      }
5271    
5272      /**
5273       * SetByteArrayRegion: copy a region of the native buffer into the array (1 byte element)
5274       * @param env A JREF index for the JNI environment object
5275       * @param arrayJREF a JREF index for the destination array
5276       * @param startIndex the starting index to copy
5277       * @param length the number of elements to copy
5278       * @param bufAddress the source address in native to copy from
5279       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5280       */
5281      private static void SetByteArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5282                                             Address bufAddress) {
5283        if (traceJNI) VM.sysWrite("JNI called: SetByteArrayRegion  \n");
5284        RuntimeEntrypoints.checkJNICountDownToGC();
5285    
5286        try {
5287          byte[] destinationArray = (byte[]) env.getJNIRef(arrayJREF);
5288    
5289          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5290            env.recordException(new ArrayIndexOutOfBoundsException());
5291            return;
5292          }
5293    
5294          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length);
5295        } catch (Throwable unexpected) {
5296          if (traceJNI) unexpected.printStackTrace(System.err);
5297          env.recordException(unexpected);
5298        }
5299      }
5300    
5301      /**
5302       * SetCharArrayRegion: copy a region of the native buffer into the array (2 byte element)
5303       * @param env A JREF index for the JNI environment object
5304       * @param arrayJREF a JREF index for the destination array
5305       * @param startIndex the starting index to copy
5306       * @param length the number of elements to copy
5307       * @param bufAddress the source address in native to copy from
5308       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5309       */
5310      private static void SetCharArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5311                                             Address bufAddress) {
5312        if (traceJNI) VM.sysWrite("JNI called: SetCharArrayRegion  \n");
5313        RuntimeEntrypoints.checkJNICountDownToGC();
5314    
5315        try {
5316          char[] destinationArray = (char[]) env.getJNIRef(arrayJREF);
5317    
5318          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5319            env.recordException(new ArrayIndexOutOfBoundsException());
5320            return;
5321          }
5322    
5323          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_CHAR),
5324                            bufAddress,
5325                            length << LOG_BYTES_IN_CHAR);
5326        } catch (Throwable unexpected) {
5327          if (traceJNI) unexpected.printStackTrace(System.err);
5328          env.recordException(unexpected);
5329        }
5330      }
5331    
5332      /**
5333       * SetShortArrayRegion: copy a region of the native buffer into the array (2 byte element)
5334       * @param env A JREF index for the JNI environment object
5335       * @param arrayJREF a JREF index for the destination array
5336       * @param startIndex the starting index to copy
5337       * @param length the number of elements to copy
5338       * @param bufAddress the source address in native to copy from
5339       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5340       */
5341      private static void SetShortArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5342                                              Address bufAddress) {
5343        if (traceJNI) VM.sysWrite("JNI called: SetShortArrayRegion  \n");
5344        RuntimeEntrypoints.checkJNICountDownToGC();
5345    
5346        try {
5347          short[] destinationArray = (short[]) env.getJNIRef(arrayJREF);
5348    
5349          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5350            env.recordException(new ArrayIndexOutOfBoundsException());
5351            return;
5352          }
5353    
5354          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_SHORT),
5355                            bufAddress,
5356                            length << LOG_BYTES_IN_SHORT);
5357        } catch (Throwable unexpected) {
5358          if (traceJNI) unexpected.printStackTrace(System.err);
5359          env.recordException(unexpected);
5360        }
5361      }
5362    
5363      /**
5364       * SetIntArrayRegion: copy a region of the native buffer into the array
5365       * @param env A JREF index for the JNI environment object
5366       * @param arrayJREF a JREF index for the destination array
5367       * @param startIndex the starting index to copy
5368       * @param length the number of elements to copy
5369       * @param bufAddress the source address in native to copy from
5370       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5371       */
5372      private static void SetIntArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5373                                            Address bufAddress) {
5374        if (traceJNI) VM.sysWrite("JNI called: SetIntArrayRegion  \n");
5375        RuntimeEntrypoints.checkJNICountDownToGC();
5376    
5377        try {
5378          int[] destinationArray = (int[]) env.getJNIRef(arrayJREF);
5379    
5380          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5381            env.recordException(new ArrayIndexOutOfBoundsException());
5382            return;
5383          }
5384    
5385          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_INT),
5386                            bufAddress,
5387                            length << LOG_BYTES_IN_INT);
5388        } catch (Throwable unexpected) {
5389          if (traceJNI) unexpected.printStackTrace(System.err);
5390          env.recordException(unexpected);
5391        }
5392      }
5393    
5394      /**
5395       * SetLongArrayRegion: copy a region of the native buffer into the array
5396       * @param env A JREF index for the JNI environment object
5397       * @param arrayJREF a JREF index for the destination array
5398       * @param startIndex the starting index to copy
5399       * @param length the number of elements to copy
5400       * @param bufAddress the source address in native to copy from
5401       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5402       */
5403      private static void SetLongArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5404                                             Address bufAddress) {
5405        if (traceJNI) VM.sysWrite("JNI called: SetLongArrayRegion  \n");
5406        RuntimeEntrypoints.checkJNICountDownToGC();
5407    
5408        try {
5409          long[] destinationArray = (long[]) env.getJNIRef(arrayJREF);
5410    
5411          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5412            env.recordException(new ArrayIndexOutOfBoundsException());
5413            return;
5414          }
5415    
5416          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_LONG),
5417                            bufAddress,
5418                            length << LOG_BYTES_IN_LONG);
5419        } catch (Throwable unexpected) {
5420          if (traceJNI) unexpected.printStackTrace(System.err);
5421          env.recordException(unexpected);
5422        }
5423      }
5424    
5425      /**
5426       * SetFloatArrayRegion: copy a region of the native buffer into the array
5427       * @param env A JREF index for the JNI environment object
5428       * @param arrayJREF a JREF index for the destination array
5429       * @param startIndex the starting index to copy
5430       * @param length the number of elements to copy
5431       * @param bufAddress the source address in native to copy from
5432       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5433       */
5434      private static void SetFloatArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5435                                              Address bufAddress) {
5436        if (traceJNI) VM.sysWrite("JNI called: SetFloatArrayRegion  \n");
5437        RuntimeEntrypoints.checkJNICountDownToGC();
5438    
5439        try {
5440          float[] destinationArray = (float[]) env.getJNIRef(arrayJREF);
5441    
5442          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5443            env.recordException(new ArrayIndexOutOfBoundsException());
5444            return;
5445          }
5446    
5447          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_FLOAT),
5448                            bufAddress,
5449                            length << LOG_BYTES_IN_FLOAT);
5450        } catch (Throwable unexpected) {
5451          if (traceJNI) unexpected.printStackTrace(System.err);
5452          env.recordException(unexpected);
5453        }
5454      }
5455    
5456      /**
5457       * SetDoubleArrayRegion: copy a region of the native buffer into the array
5458       * @param env A JREF index for the JNI environment object
5459       * @param arrayJREF a JREF index for the destination array
5460       * @param startIndex the starting index to copy
5461       * @param length the number of elements to copy
5462       * @param bufAddress the source address in native to copy from
5463       * @exception ArrayIndexOutOfBoundsException if one of the indices in the region is not valid
5464       */
5465      private static void SetDoubleArrayRegion(JNIEnvironment env, int arrayJREF, int startIndex, int length,
5466                                               Address bufAddress) {
5467        if (traceJNI) VM.sysWrite("JNI called: SetDoubleArrayRegion  \n");
5468        RuntimeEntrypoints.checkJNICountDownToGC();
5469    
5470        try {
5471          double[] destinationArray = (double[]) env.getJNIRef(arrayJREF);
5472    
5473          if ((startIndex < 0) || (startIndex + length > destinationArray.length)) {
5474            env.recordException(new ArrayIndexOutOfBoundsException());
5475            return;
5476          }
5477    
5478          Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_DOUBLE),
5479                            bufAddress,
5480                            length << LOG_BYTES_IN_DOUBLE);
5481        } catch (Throwable unexpected) {
5482          if (traceJNI) unexpected.printStackTrace(System.err);
5483          env.recordException(unexpected);
5484        }
5485      }
5486    
5487      /**
5488       * RegisterNatives: registers implementation of native methods
5489       * @param env A JREF index for the JNI environment object
5490       * @param classJREF a JREF index for the class to register native methods in
5491       * @param methodsAddress the address of an array of native methods to be registered
5492       * @param nmethods the number of native methods in the array
5493       * @return 0 is successful -1 if failed
5494       * @exception NoSuchMethodError if a specified method cannot be found or is not native
5495       */
5496      private static int RegisterNatives(JNIEnvironment env, int classJREF, Address methodsAddress, int nmethods) {
5497        if (traceJNI) VM.sysWrite("JNI called: RegisterNatives  \n");
5498        RuntimeEntrypoints.checkJNICountDownToGC();
5499    
5500        try {
5501          // get the target class
5502          Class<?> jcls = (Class<?>) env.getJNIRef(classJREF);
5503          RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls);
5504          if (!type.isClassType()) {
5505            env.recordException(new NoSuchMethodError());
5506            return 0;
5507          }
5508    
5509          RVMClass klass = type.asClass();
5510          if (!klass.isInitialized()) {
5511            RuntimeEntrypoints.initializeClassForDynamicLink(klass);
5512          }
5513    
5514          // Create list of methods and verify them to avoid partial success
5515          NativeMethod[] methods = new NativeMethod[nmethods];
5516          AddressArray symbols = AddressArray.create(nmethods);
5517    
5518          Address curMethod = methodsAddress;
5519          for (int i = 0; i < nmethods; i++) {
5520            String methodString = JNIHelpers.createStringFromC(curMethod.loadAddress());
5521            Atom methodName = Atom.findOrCreateAsciiAtom(methodString);
5522            String sigString =
5523                JNIHelpers.createStringFromC(curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS)));
5524            Atom sigName = Atom.findOrCreateAsciiAtom(sigString);
5525    
5526            // Find the target method
5527            RVMMethod meth = klass.findDeclaredMethod(methodName, sigName);
5528    
5529            if (meth == null || !meth.isNative()) {
5530              env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName));
5531              return -1;
5532            }
5533            methods[i] = (NativeMethod) meth;
5534            symbols.set(i, curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS * 2)));
5535            curMethod = curMethod.plus(3 * BYTES_IN_ADDRESS);
5536          }
5537    
5538          // Register methods
5539          for (int i = 0; i < nmethods; i++) {
5540            methods[i].registerNativeSymbol(symbols.get(i));
5541          }
5542    
5543          return 0;
5544        } catch (Throwable unexpected) {
5545          if (traceJNI) unexpected.printStackTrace(System.err);
5546          env.recordException(unexpected);
5547          return -1;
5548        }
5549      }
5550    
5551      /**
5552       * UnregisterNatives: unregisters native methods
5553       * @param env A JREF index for the JNI environment object
5554       * @param classJREF a JREF index for the class to register native methods in
5555       * @return 0 is successful -1 if failed
5556       */
5557      private static int UnregisterNatives(JNIEnvironment env, int classJREF) {
5558        if (traceJNI) VM.sysWrite("JNI called: UnregisterNatives  \n");
5559        RuntimeEntrypoints.checkJNICountDownToGC();
5560    
5561        try {
5562    
5563          // get the target class
5564          Class<?> jcls = (Class<?>) env.getJNIRef(classJREF);
5565          RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls);
5566          if (!type.isClassType()) {
5567            env.recordException(new NoClassDefFoundError());
5568            return -1;
5569          }
5570    
5571          RVMClass klass = type.asClass();
5572          if (!klass.isInitialized()) {
5573            return 0;
5574          }
5575    
5576          klass.unregisterNativeMethods();
5577          return 0;
5578        } catch (Throwable unexpected) {
5579          if (traceJNI) unexpected.printStackTrace(System.err);
5580          env.recordException(unexpected);
5581          return -1;
5582        }
5583      }
5584    
5585      /**
5586       * MonitorEnter
5587       * @param env A JREF index for the JNI environment object
5588       * @param objJREF a JREF index for the object to lock
5589       * @return 0 if the object is locked successfully, -1 if not
5590       */
5591      private static int MonitorEnter(JNIEnvironment env, int objJREF) {
5592        if (traceJNI) VM.sysWrite("JNI called: MonitorEnter  \n");
5593        RuntimeEntrypoints.checkJNICountDownToGC();
5594    
5595        try {
5596          Object obj = env.getJNIRef(objJREF);
5597          ObjectModel.genericLock(obj);
5598          return 0;
5599        } catch (Throwable unexpected) {
5600          if (traceJNI) unexpected.printStackTrace(System.err);
5601          return -1;
5602        }
5603      }
5604    
5605      /**
5606       * MonitorExit
5607       * @param env A JREF index for the JNI environment object
5608       * @param objJREF a JREF index for the object to unlock
5609       * @return 0 if the object is unlocked successfully, -1 if not
5610       */
5611      private static int MonitorExit(JNIEnvironment env, int objJREF) {
5612        if (traceJNI) VM.sysWrite("JNI called: MonitorExit  \n");
5613        RuntimeEntrypoints.checkJNICountDownToGC();
5614    
5615        try {
5616          Object obj = env.getJNIRef(objJREF);
5617          ObjectModel.genericUnlock(obj);
5618          return 0;
5619        } catch (Throwable unexpected) {
5620          if (traceJNI) unexpected.printStackTrace(System.err);
5621          return -1;
5622        }
5623      }
5624    
5625      private static int GetJavaVM(JNIEnvironment env, Address StarStarJavaVM) {
5626        if (traceJNI) VM.sysWrite("JNI called: GetJavaVM \n");
5627        RuntimeEntrypoints.checkJNICountDownToGC();
5628    
5629        try {
5630          if (traceJNI) VM.sysWriteln(StarStarJavaVM);
5631          Address JavaVM = BootRecord.the_boot_record.sysJavaVM;
5632          StarStarJavaVM.store(JavaVM);
5633    
5634          return 0;
5635        } catch (Throwable unexpected) {
5636          if (traceJNI) unexpected.printStackTrace(System.err);
5637          return -1;
5638        }
5639      }
5640    
5641      /*******************************************************************
5642       * These functions were added in Java 2  (JNI 1.2)
5643       */
5644    
5645      /**
5646       * FromReflectedMethod
5647       * @param env A JREF index for the JNI environment object
5648       * @param methodJREF a JREF index for the java.lang.reflect.Method or
5649       * java.lang.reflect.Constructor object.
5650       * @return the jmethodID corresponding to methodJREF
5651       */
5652      private static int FromReflectedMethod(JNIEnvironment env, int methodJREF) {
5653        if (traceJNI) VM.sysWrite("JNI called: FromReflectedMethod \n");
5654        RuntimeEntrypoints.checkJNICountDownToGC();
5655    
5656        Object methodObj = env.getJNIRef(methodJREF);
5657        RVMMethod meth;
5658        if (methodObj instanceof Constructor) {
5659          meth = java.lang.reflect.JikesRVMSupport.getMethodOf((Constructor<?>) methodObj);
5660        } else {
5661          meth = java.lang.reflect.JikesRVMSupport.getMethodOf((Method) methodObj);
5662        }
5663    
5664        if (traceJNI) VM.sysWrite("got method " + meth + "\n");
5665        return meth.getId();
5666      }
5667    
5668      /**
5669       * FromReflectedField
5670       * @param env A JREF index for the JNI environment object
5671       * @param fieldJREF a JREF index for a java.lang.reflect.Field methodID
5672       * @return the jfieldID corresponding to fieldJREF
5673       * */
5674      private static int FromReflectedField(JNIEnvironment env, int fieldJREF) {
5675        if (traceJNI) VM.sysWrite("JNI called: FromReflectedField \n");
5676        RuntimeEntrypoints.checkJNICountDownToGC();
5677    
5678        Field fieldObj = (Field) env.getJNIRef(fieldJREF);
5679        RVMField f = java.lang.reflect.JikesRVMSupport.getFieldOf(fieldObj);
5680        if (traceJNI) VM.sysWrite("got field " + f + "\n");
5681        return f.getId();
5682      }
5683    
5684      /**
5685       * ToReflectedMethod
5686       * @param env A JREF index for the JNI environment object
5687       * @param clsJREF The JREF index of the class from which methodID was
5688       * derived.
5689       * @param methodID a jmethodID to turn into a reflected method
5690       * @param isStatic argument that is not specified in Sun's JNI 1.2 spec,
5691       *            but IS present in the 1.4.2 JDK's implementation!  Our
5692       *            implementation will just ignore it, in any case.  This is a
5693       *            good example of why the same entity
5694       *            shouldn't get to write both the spec and the reference
5695       *            implementation.
5696       * @return a JREF index for the java.lang.reflect.Method or
5697       * java.lang.reflect.Constructor object associated with methodID.
5698       */
5699      private static int ToReflectedMethod(JNIEnvironment env, int clsJREF, int methodID, boolean isStatic) {
5700        if (traceJNI) VM.sysWrite("JNI called: ToReflectedMethod \n");
5701        RuntimeEntrypoints.checkJNICountDownToGC();
5702    
5703        RVMMethod targetMethod = MemberReference.getMemberRef(methodID).asMethodReference().resolve();
5704        Object ret;
5705        if (targetMethod.isObjectInitializer()) {
5706          ret = java.lang.reflect.JikesRVMSupport.createConstructor(targetMethod);
5707        } else {
5708          ret = java.lang.reflect.JikesRVMSupport.createMethod(targetMethod);
5709        }
5710        return env.pushJNIRef(ret);
5711      }
5712    
5713      /**
5714       * ToReflectedField
5715       * @param env A JREF index for the JNI environment object
5716       * @param clsJREF The JREF index of the class from which fieldID was
5717       * derived.
5718       * @param fieldID a jfieldID
5719       * @param isStatic argument that is not specified in Sun's JNI 1.2 spec,
5720       *            but IS present in the 1.4.2 JDK's implementation!  Our
5721       *            implementation will just ignore it, in any case.  This is a
5722       *            good example of why the same entity
5723       *            shouldn't get to write both the spec and the reference
5724       *            implementation.
5725       * @return a JREF index for the java.lang.reflect.Field object associated
5726       *         with fieldID.
5727       */
5728      private static int ToReflectedField(JNIEnvironment env, int clsJREF, int fieldID, boolean isStatic) {
5729        if (traceJNI) VM.sysWrite("JNI called: ToReflectedField \n");
5730        RuntimeEntrypoints.checkJNICountDownToGC();
5731    
5732        RVMField field = MemberReference.getMemberRef(fieldID).asFieldReference().resolve();
5733        return env.pushJNIRef(java.lang.reflect.JikesRVMSupport.createField(field));
5734      }
5735    
5736      /** Push a local frame for local references.
5737       * We could implement this more fancily, but it seems that we hardly need
5738       * to, since we allow an unlimited number of local refs.  One could force
5739       * running out of memory in a long-running loop in JNI, of course.
5740       */
5741      private static int PushLocalFrame(JNIEnvironment env, int capacity) {
5742        if (traceJNI) VM.sysWrite("JNI called: PushLocalFrame \n");
5743        RuntimeEntrypoints.checkJNICountDownToGC();
5744    
5745        return 0;                   // OK
5746      }
5747    
5748      /** Push a local frame for local references.
5749       * We could implement this more fancily, but it seems that we hardly need
5750       * to, since we allow an unlimited number of local refs.  One could force
5751       * running out of memory in a long-running loop in JNI, of course, and this
5752       * might save us from that.  Let's hold off until we need it.  TODO.
5753       *
5754       * @return a local reference in the old frame that refers to the same object
5755       *   as oldJREF.
5756       */
5757      private static int PopLocalFrame(JNIEnvironment env, int resultJREF) {
5758        if (traceJNI) VM.sysWrite("JNI called: PopLocalFrame \n");
5759        RuntimeEntrypoints.checkJNICountDownToGC();
5760    
5761        // do nothing.
5762        return resultJREF;
5763      }
5764    
5765      /**
5766       * NewLocalRef
5767       *
5768       * @param env A JREF index for the JNI environment object
5769       * @param oldJREF JREF index of an existing reference.
5770       * @return a new local reference that refers to the same object as oldJREF.
5771       *       C NULL pointer if the oldJREF refers to null.
5772       */
5773      private static int NewLocalRef(JNIEnvironment env, int oldJREF) {
5774        if (traceJNI) VM.sysWrite("JNI called: NewLocalRef \n");
5775        RuntimeEntrypoints.checkJNICountDownToGC();
5776    
5777        Object oldObj = env.getJNIRef(oldJREF);
5778        /* pushJNIRef automatically handles null refs properly. */
5779        return env.pushJNIRef(oldObj);
5780      }
5781    
5782      /**
5783       * EnsureLocalCapacity
5784       *
5785       * @param env A JREF index for the JNI environment object
5786       * @param capacity how many more local references do we want to ensure can
5787       * be created?
5788       * @return 0 on success.  The JNI spec says that on failure this throws
5789       * OutOfMemoryError and returns a negative number.  But we don't have to
5790       * worry about that at all.
5791       */
5792      private static int EnsureLocalCapacity(JNIEnvironment env, int capacity) {
5793        if (traceJNI) VM.sysWrite("JNI called: EnsureLocalCapacity \n");
5794        RuntimeEntrypoints.checkJNICountDownToGC();
5795    
5796        return 0;                   // success!
5797      }
5798    
5799      /** GetStringRegion:  Copy a region of Unicode characters from a string to
5800       *  the given buffer.
5801       *
5802       *  @param env A JREF index for the JNI environment object
5803       *  @param strJREF a JREF index for the String object
5804       *  @param start index to start reading characters from the string
5805       *  @param len how many characters to read
5806       *  @param buf the buffer to copy the region into
5807       *  @exception StringIndexOutOfBoundsException if asked for an out-of-range
5808       *        region of the string.
5809       */
5810      private static void GetStringRegion(JNIEnvironment env, int strJREF, int start, int len, Address buf) {
5811        if (traceJNI) VM.sysWrite("JNI called: GetStringRegion \n");
5812        RuntimeEntrypoints.checkJNICountDownToGC();
5813    
5814        try {
5815          String str = (String) env.getJNIRef(strJREF);
5816          char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str);
5817          int strOffset = java.lang.JikesRVMSupport.getStringOffset(str);
5818          int strLen = java.lang.JikesRVMSupport.getStringLength(str);
5819          if (strLen < start + len) {
5820            env.recordException(new StringIndexOutOfBoundsException());
5821            return;
5822          }
5823          Address strBase = Magic.objectAsAddress(strChars);
5824          Address srcBase = strBase.plus(strOffset * 2).plus(start * 2);
5825          Memory.memcopy(buf, srcBase, len * 2);
5826    
5827        } catch (Throwable unexpected) {
5828          if (traceJNI) unexpected.printStackTrace(System.err);
5829          env.recordException(unexpected);
5830        }
5831      }
5832    
5833      /** GetStringUTFRegion:  Copy a region of Unicode characters from a string to
5834       *  the given buffer, as UTF8 characters.
5835       *
5836       *  @param env A JREF index for the JNI environment object
5837       *  @param strJREF a JREF index for the String object
5838       *  @param start index to start reading characters from the string
5839       *  @param len how many characters to read from the string
5840       *  @param buf the buffer to copy the region into -- assume it's big enough
5841       *  @exception StringIndexOutOfBoundsException if asked for an out-of-range
5842       *        region of the string.
5843       */
5844      private static void GetStringUTFRegion(JNIEnvironment env, int strJREF, int start, int len, Address buf) {
5845        if (traceJNI) VM.sysWrite("JNI called: GetStringUTFRegion \n");
5846        RuntimeEntrypoints.checkJNICountDownToGC();
5847    
5848        try {
5849          String str = (String) env.getJNIRef(strJREF);
5850          String region = str.substring(start, start+len);
5851          // Get length of C string
5852          int utflen = UTF8Convert.utfLength(region) + 1; // for terminating zero
5853          JNIHelpers.createUTFForCFromString(region, buf, utflen);
5854        } catch (Throwable unexpected) {
5855          if (traceJNI) unexpected.printStackTrace(System.err);
5856          env.recordException(unexpected);
5857        }
5858      }
5859    
5860      /**
5861       * GetPrimitiveArrayCritical: return a direct pointer to the primitive array
5862       * and disable GC so that the array will not be moved.  This function
5863       * is intended to be paired with the ReleasePrimitiveArrayCritical function
5864       * within a short time so that GC will be reenabled
5865       *
5866       * @param env A JREF index for the JNI environment object
5867       * @param arrayJREF a JREF index for the primitive array in Java
5868       * @param isCopyAddress address of isCopy jboolean (an int)
5869       * @return The address of the primitive array, and the jboolean pointed to by isCopyAddress is set to false, indicating that this is not a copy.   Address zero (null) on error.
5870       * @exception OutOfMemoryError is specified but will not be thrown in this implementation
5871       *            since no copy will be made
5872       */
5873      private static Address GetPrimitiveArrayCritical(JNIEnvironment env, int arrayJREF, Address isCopyAddress) {
5874    
5875        if (traceJNI) VM.sysWrite("JNI called: GetPrimitiveArrayCritical \n");
5876        RuntimeEntrypoints.checkJNICountDownToGC();
5877    
5878        try {
5879          Object primitiveArray = env.getJNIRef(arrayJREF);
5880    
5881          // not an array, return null
5882          if (!primitiveArray.getClass().isArray()) {
5883            return Address.zero();
5884          }
5885    
5886          /* Set caller's isCopy boolean to false, if we got a valid (non-null)
5887             address */
5888          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
5889    
5890          // For array of primitive, return the object address, which is the array itself
5891          VM.disableGC(true);
5892          return Magic.objectAsAddress(primitiveArray);
5893        } catch (Throwable unexpected) {
5894          if (traceJNI) unexpected.printStackTrace(System.err);
5895          env.recordException(unexpected);
5896          return Address.zero();
5897        }
5898      }
5899    
5900      /**
5901       * ReleasePrimitiveArrayCritical: this function is intended to be paired
5902       * with the GetPrimitiveArrayCritical function.
5903       * Since the native code has direct access
5904       * to the array, no copyback update is necessary;  GC is simply reenabled.
5905       * @param env A JREF index for the JNI environment object
5906       * @param arrayJREF a JREF index for the primitive array in Java
5907       * @param arrayCopyAddress
5908       * @param mode a flag indicating whether to update the Java array with the
5909       *            copy and whether to free the copy. For this implementation,
5910       *            no copy was made so this flag has no effect.
5911       */
5912      private static void ReleasePrimitiveArrayCritical(JNIEnvironment env, int arrayJREF, Address arrayCopyAddress,
5913                                                        int mode) {
5914        if (traceJNI) VM.sysWrite("JNI called: ReleasePrimitiveArrayCritical \n");
5915        RuntimeEntrypoints.checkJNICountDownToGC();
5916    
5917        try {
5918          VM.enableGC(true);
5919        } catch (Throwable unexpected) {
5920          if (traceJNI) unexpected.printStackTrace(System.err);
5921          env.recordException(unexpected);
5922        }
5923      }
5924    
5925      /** GetStringCritical:
5926       * Like GetStringChars and ReleaseStringChars, but in some VM environments
5927       * the VM may be able to avoid making a copy.   Native code must not issue
5928       * arbitrary JNI calls and must not cause the current thread to block.
5929       *
5930       * @param env A JREF index for the JNI environment object
5931       * @param strJREF a JREF index for the string in Java
5932       * @param isCopyAddress address of isCopy jboolean (an int)
5933       * @return The address of the backing array; address zero (null) on error, and the jboolean pointed to by isCopyAddress is set to false, indicating that this is not a copy.
5934       */
5935      private static Address GetStringCritical(JNIEnvironment env, int strJREF, Address isCopyAddress) {
5936        if (traceJNI) VM.sysWrite("JNI called: GetStringCritical \n");
5937        RuntimeEntrypoints.checkJNICountDownToGC();
5938    
5939        String str = (String) env.getJNIRef(strJREF);
5940        char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str);
5941        int strOffset = java.lang.JikesRVMSupport.getStringOffset(str);
5942    
5943        /* Set caller's isCopy boolean to false, if we got a valid (non-null)
5944           address */
5945        JNIGenericHelpers.setBoolStar(isCopyAddress, false);
5946    
5947        VM.disableGC(true);
5948        Address strBase = Magic.objectAsAddress(strChars);
5949        return strBase.plus(strOffset * 2);
5950      }
5951    
5952      /**
5953       * ReleaseStringCritical: this function is intended to be paired with the
5954       * GetStringCritical function.  Since the native code has direct access
5955       * to the string's backing array of characters, no copyback update is
5956       * necessary;  GC is simply reenabled.
5957       *
5958       * @param env A JREF index for the JNI environment object
5959       * @param strJREF a JREF index for the string in Java (ignored)
5960       * @param carray the pointer returned by GetStringCritical (ignored)
5961       */
5962      private static void ReleaseStringCritical(JNIEnvironment env, int strJREF, Address carray) {
5963        if (traceJNI) VM.sysWrite("JNI called: ReleaseStringCritical \n");
5964        RuntimeEntrypoints.checkJNICountDownToGC();
5965    
5966        try {
5967          VM.enableGC(true);
5968        } catch (Throwable unexpected) {
5969          if (traceJNI) unexpected.printStackTrace(System.err);
5970          env.recordException(unexpected);
5971        }
5972      }
5973    
5974      private static int NewWeakGlobalRef(JNIEnvironment env, int objectJREF) {
5975        if (traceJNI) VM.sysWrite("JNI called: NewWeakGlobalRef \n");
5976        RuntimeEntrypoints.checkJNICountDownToGC();
5977    
5978        try {
5979          Object obj1 = env.getJNIRef(objectJREF);
5980          return JNIGlobalRefTable.newWeakRef(obj1);
5981        } catch (Throwable unexpected) {
5982          if (traceJNI) unexpected.printStackTrace(System.err);
5983          env.recordException(unexpected);
5984          return 0;
5985        }
5986      }
5987    
5988      private static void DeleteWeakGlobalRef(JNIEnvironment env, int refJREF) {
5989        if (traceJNI) VM.sysWrite("JNI called: DeleteWeakGlobalRef \n");
5990        RuntimeEntrypoints.checkJNICountDownToGC();
5991    
5992        try {
5993          JNIGlobalRefTable.deleteWeakRef(refJREF);
5994        } catch (Throwable unexpected) {
5995          if (traceJNI) unexpected.printStackTrace(System.err);
5996          env.recordException(unexpected);
5997        }
5998      }
5999    
6000      private static int ExceptionCheck(JNIEnvironment env) {
6001        if (traceJNI) VM.sysWrite("JNI called: ExceptionCheck \n");
6002        RuntimeEntrypoints.checkJNICountDownToGC();
6003    
6004        return env.getException() == null ? 0 : 1;
6005      }
6006    
6007      /*******************************************************************
6008       * These functions are in JNI 1.4
6009       */
6010    
6011      private static int NewDirectByteBuffer(JNIEnvironment env, Address address, long capacity) {
6012        if (traceJNI) VM.sysWrite("JNI called: NewDirectByteBuffer \n");
6013        RuntimeEntrypoints.checkJNICountDownToGC();
6014    
6015        try {
6016          Buffer buffer = java.nio.JikesRVMSupport.newDirectByteBuffer(address, capacity);
6017          return env.pushJNIRef(buffer);
6018        } catch (Throwable unexpected) {
6019          if (traceJNI) unexpected.printStackTrace(System.err);
6020          env.recordException(unexpected);
6021          return 0;
6022        }
6023      }
6024    
6025      private static Address GetDirectBufferAddress(JNIEnvironment env, int bufJREF) {
6026        if (traceJNI) VM.sysWrite("JNI called: GetDirectBufferAddress \n");
6027        RuntimeEntrypoints.checkJNICountDownToGC();
6028    
6029        try {
6030          Buffer buffer = (Buffer) env.getJNIRef(bufJREF);
6031          //if (buffer instanceof ByteBuffer) {
6032          //  VM.sysWrite("ByteBuffer, ");
6033          //  if (((ByteBuffer)buffer).isDirect())
6034          //    VM.sysWrite("Direct, ");
6035          //}
6036          //VM.sysWriteln("Direct buffer address = ",result);
6037          return java.nio.JikesRVMSupport.getDirectBufferAddress(buffer);
6038        } catch (Throwable unexpected) {
6039          if (traceJNI) unexpected.printStackTrace(System.err);
6040          env.recordException(unexpected);
6041          return Address.zero();
6042        }
6043      }
6044    
6045      private static long GetDirectBufferCapacity(JNIEnvironment env, int bufJREF) {
6046        if (traceJNI) VM.sysWrite("JNI called: GetDirectBufferCapacity \n");
6047        RuntimeEntrypoints.checkJNICountDownToGC();
6048    
6049        try {
6050          Buffer buffer = (Buffer) env.getJNIRef(bufJREF);
6051          return buffer.capacity();
6052        } catch (Throwable unexpected) {
6053          if (traceJNI) unexpected.printStackTrace(System.err);
6054          env.recordException(unexpected);
6055          return -1;
6056        }
6057      }
6058    
6059      /*******************************************************************
6060       * Empty Slots
6061       */
6062    
6063      private static int reserved0(JNIEnvironment env) {
6064        VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n");
6065        VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP);
6066        return -1;
6067      }
6068    
6069      private static int reserved1(JNIEnvironment env) {
6070        VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n");
6071        VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP);
6072        return -1;
6073      }
6074    
6075      private static int reserved2(JNIEnvironment env) {
6076        VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n");
6077        VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP);
6078        return -1;
6079      }
6080    
6081      private static int reserved3(JNIEnvironment env) {
6082        VM.sysWrite("JNI ERROR: reserved function slot not implemented, exiting ...\n");
6083        VM.sysExit(VM.EXIT_STATUS_UNSUPPORTED_INTERNAL_OP);
6084        return -1;
6085      }
6086    }