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 }