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 java.lang.ref.WeakReference; 016import org.jikesrvm.VM; 017import org.jikesrvm.runtime.Magic; 018import org.jikesrvm.mm.mminterface.MemoryManager; 019import org.vmmagic.pragma.Entrypoint; 020import org.vmmagic.pragma.Uninterruptible; 021import org.vmmagic.unboxed.ObjectReference; 022import org.vmmagic.unboxed.AddressArray; 023import 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 */ 029public 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}