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