@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++;
  }
Пример #3
0
  // 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;
  }
}