@Uninterruptible private static void copyAndReplaceGlobalRefs(AddressArray newGlobalRefs) { for (int i = 0; i < JNIGlobalRefs.length(); i++) { newGlobalRefs.set(i, JNIGlobalRefs.get(i)); } JNIGlobalRefs = newGlobalRefs; }
static int newGlobalRef(Object referent) { if (VM.VerifyAssertions) VM._assert(MemoryManager.validRef(ObjectReference.fromObject(referent))); if (free >= JNIGlobalRefs.length()) { AddressArray newGlobalRefs = AddressArray.create(JNIGlobalRefs.length() * 2); copyAndReplaceGlobalRefs(newGlobalRefs); } JNIGlobalRefs.set(free, Magic.objectAsAddress(referent)); return -free++; }
// return (address of) next ref in the current "frame" on the // threads JNIEnvironment stack of refs // When at the end of the current frame, update register locations to point // to the non-volatile registers saved in the JNI transition frame. // public Address getNextReferenceAddress() { // first report jni refs in the current frame in the jniRef side stack // until all in the frame are reported // if (jniNextRef > jniFramePtr) { Address ref_address = Magic.objectAsAddress(jniRefs).plus(jniNextRef); jniNextRef -= BYTES_IN_ADDRESS; return ref_address; } // no more refs to report, before returning 0, setup for processing // the next jni frame, if any // jniNextRef -> savedFramePtr for another "frame" of refs for another // sequence of Native C frames lower in the stack, or to 0 if this is the // last jni frame in the JNIRefs stack. If more frames, initialize for a // later scan of those refs. // if (jniFramePtr > 0) { jniFramePtr = jniRefs.get(jniFramePtr >> LOG_BYTES_IN_ADDRESS).toInt(); jniNextRef = jniNextRef - BYTES_IN_ADDRESS; } // set register locations for non-volatiles to point to registers saved in // the JNI transition frame at a fixed negative offset from the callers FP. // the save non-volatiles are EBX EBP and EDI. // registerLocations.set(EDI.value(), framePtr.plus(JNICompiler.EDI_SAVE_OFFSET)); registerLocations.set(EBX.value(), framePtr.plus(JNICompiler.EBX_SAVE_OFFSET)); registerLocations.set(EBP.value(), framePtr.plus(JNICompiler.EBP_SAVE_OFFSET)); return Address.zero(); // no more refs to report }
@Uninterruptible static Object globalRef(int index) { if (VM.VerifyAssertions) VM._assert(!isWeakRef(index)); return Magic.addressAsObject(JNIGlobalRefs.get(-index)); }
static void deleteGlobalRef(int index) { if (VM.VerifyAssertions) VM._assert(!isWeakRef(index)); JNIGlobalRefs.set(-index, Address.zero()); }
/** * Weak Global References are global references (negative numbers), with the 2^30 bit UNset. Mask in * the 2^30 bit to get the real index into the table. */ public class JNIGlobalRefTable { @Entrypoint public static AddressArray JNIGlobalRefs = AddressArray.create(100); private static int free = 1; static int newGlobalRef(Object referent) { if (VM.VerifyAssertions) VM._assert(MemoryManager.validRef(ObjectReference.fromObject(referent))); if (free >= JNIGlobalRefs.length()) { AddressArray newGlobalRefs = AddressArray.create(JNIGlobalRefs.length() * 2); copyAndReplaceGlobalRefs(newGlobalRefs); } JNIGlobalRefs.set(free, Magic.objectAsAddress(referent)); return -free++; } @Uninterruptible private static void copyAndReplaceGlobalRefs(AddressArray newGlobalRefs) { for (int i = 0; i < JNIGlobalRefs.length(); i++) { newGlobalRefs.set(i, JNIGlobalRefs.get(i)); } JNIGlobalRefs = newGlobalRefs; } /* Weak references are returned with the STRONG_REF_BIT bit UNset. */ public static final int STRONG_REF_BIT = 1 << 30; static int newWeakRef(Object referent) { int gref = newGlobalRef(new WeakReference<Object>(referent)); return gref & ~STRONG_REF_BIT; } static void deleteGlobalRef(int index) { if (VM.VerifyAssertions) VM._assert(!isWeakRef(index)); JNIGlobalRefs.set(-index, Address.zero()); } static void deleteWeakRef(int index) { if (VM.VerifyAssertions) VM._assert(isWeakRef(index)); int gref = index | STRONG_REF_BIT; deleteGlobalRef(gref); } @Uninterruptible static Object globalRef(int index) { if (VM.VerifyAssertions) VM._assert(!isWeakRef(index)); return Magic.addressAsObject(JNIGlobalRefs.get(-index)); } @Uninterruptible static Object weakRef(int index) { if (VM.VerifyAssertions) VM._assert(isWeakRef(index)); @SuppressWarnings("unchecked") // yes, we're being bad. WeakReference<Object> ref = (WeakReference<Object>) globalRef(index | STRONG_REF_BIT); return java.lang.ref.JikesRVMSupport.uninterruptibleReferenceGet(ref); } @Uninterruptible static Object ref(int index) { if (isWeakRef(index)) { return weakRef(index); } else { return globalRef(index); } } @Uninterruptible static boolean isWeakRef(int index) { return (index & STRONG_REF_BIT) == 0; } }