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