001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.jni;
014
015 import java.lang.ref.WeakReference;
016 import org.jikesrvm.VM;
017 import org.jikesrvm.runtime.Magic;
018 import org.jikesrvm.mm.mminterface.MemoryManager;
019 import org.vmmagic.pragma.Entrypoint;
020 import org.vmmagic.pragma.Uninterruptible;
021 import org.vmmagic.unboxed.ObjectReference;
022 import org.vmmagic.unboxed.AddressArray;
023 import org.vmmagic.unboxed.Address;
024
025 /**
026 * Weak Global References are global references (negative numbers), with the
027 * 2^30 bit UNset. Mask in the 2^30 bit to get the real index into the table.
028 */
029 public class JNIGlobalRefTable {
030
031 @Entrypoint
032 public static AddressArray JNIGlobalRefs = AddressArray.create(100);
033 private static int free = 1;
034
035 static int newGlobalRef(Object referent) {
036 if (VM.VerifyAssertions) VM._assert(MemoryManager.validRef(ObjectReference.fromObject(referent)));
037
038 if (free >= JNIGlobalRefs.length()) {
039 AddressArray newGlobalRefs = AddressArray.create(JNIGlobalRefs.length() * 2);
040 copyAndReplaceGlobalRefs(newGlobalRefs);
041 }
042
043 JNIGlobalRefs.set(free, Magic.objectAsAddress(referent));
044 return -free++;
045 }
046
047 @Uninterruptible
048 private static void copyAndReplaceGlobalRefs(AddressArray newGlobalRefs) {
049 for(int i=0; i < JNIGlobalRefs.length(); i++) {
050 newGlobalRefs.set(i, JNIGlobalRefs.get(i));
051 }
052 JNIGlobalRefs = newGlobalRefs;
053 }
054
055 /* Weak references are returned with the STRONG_REF_BIT bit UNset. */
056 public static final int STRONG_REF_BIT = 1 << 30;
057
058 static int newWeakRef(Object referent) {
059 int gref = newGlobalRef(new WeakReference<Object>(referent));
060 return gref & ~STRONG_REF_BIT;
061 }
062
063 static void deleteGlobalRef(int index) {
064 if (VM.VerifyAssertions) VM._assert(!isWeakRef(index));
065 JNIGlobalRefs.set(-index, Address.zero());
066 }
067
068 static void deleteWeakRef(int index) {
069 if (VM.VerifyAssertions) VM._assert(isWeakRef(index));
070 int gref = index | STRONG_REF_BIT;
071 deleteGlobalRef(gref);
072 }
073
074 @Uninterruptible
075 static Object globalRef(int index) {
076 if (VM.VerifyAssertions) VM._assert(!isWeakRef(index));
077
078 return Magic.addressAsObject(JNIGlobalRefs.get(-index));
079 }
080
081 @Uninterruptible
082 static Object weakRef(int index) {
083 if (VM.VerifyAssertions) VM._assert(isWeakRef(index));
084 @SuppressWarnings("unchecked") // yes, we're being bad.
085 WeakReference<Object> ref = (WeakReference<Object>) globalRef(index | STRONG_REF_BIT);
086 return java.lang.ref.JikesRVMSupport.uninterruptibleReferenceGet(ref);
087 }
088
089 @Uninterruptible
090 static Object ref(int index) {
091 if (isWeakRef(index)) {
092 return weakRef(index);
093 } else {
094 return globalRef(index);
095 }
096 }
097
098 @Uninterruptible
099 static boolean isWeakRef(int index) {
100 return (index & STRONG_REF_BIT) == 0;
101 }
102 }