diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java index d6ddd16f25845c82fb8772eb3ca45bd1202f488e..67df0b447c1ddc39ff296046f11e96472a2a5925 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java @@ -96,6 +96,8 @@ public final class NativeDataAccess { private static final boolean TRACE_MIRROR_ALLOCATION_SITES = false; + private static final long EMPTY_DATA_ADDRESS = 0xDEADL; + public static boolean isNativeMirror(Object o) { return o instanceof NativeMirror; } @@ -132,9 +134,16 @@ public final class NativeDataAccess { @TruffleBoundary void allocateNative(Object source, int len, int elementBase, int elementSize) { assert dataAddress == 0; - dataAddress = UnsafeAdapter.UNSAFE.allocateMemory(len * elementSize); - UnsafeAdapter.UNSAFE.copyMemory(source, elementBase, null, dataAddress, len * elementSize); + if (len != 0) { + dataAddress = UnsafeAdapter.UNSAFE.allocateMemory(len * elementSize); + UnsafeAdapter.UNSAFE.copyMemory(source, elementBase, null, dataAddress, len * elementSize); + } else { + dataAddress = EMPTY_DATA_ADDRESS; + } this.length = len; + + // ensure that marker address is not used + assert this.length == 0 || dataAddress != EMPTY_DATA_ADDRESS; } @TruffleBoundary @@ -146,6 +155,9 @@ public final class NativeDataAccess { UnsafeAdapter.UNSAFE.putByte(dataAddress + bytes.length, (byte) 0); // C strings // terminator this.length = bytes.length + 1; + + // ensure that marker address is not used + assert this.length == 0 || dataAddress != EMPTY_DATA_ADDRESS; } @Override @@ -153,7 +165,9 @@ public final class NativeDataAccess { super.finalize(); nativeMirrors.remove(id); // System.out.println(String.format("gc'ing %16x", id)); - if (dataAddress != 0) { + if (dataAddress == EMPTY_DATA_ADDRESS) { + assert (dataAddress = 0xbadbad) != 0; + } else if (dataAddress != 0) { // System.out.println(String.format("freeing data at %16x", dataAddress)); UnsafeAdapter.UNSAFE.freeMemory(dataAddress); assert (dataAddress = 0xbadbad) != 0; @@ -493,7 +507,7 @@ public final class NativeDataAccess { } else { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); long address = mirror.dataAddress; - assert address != 0; + assert address != 0 || address == EMPTY_DATA_ADDRESS; int length = 0; while (length < mirror.length && UnsafeAdapter.UNSAFE.getByte(address + length) != 0) { length++; @@ -507,7 +521,7 @@ public final class NativeDataAccess { static long allocateNativeContents(RLogicalVector vector, byte[] data, int length) { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); assert mirror != null; - assert mirror.dataAddress == 0 ^ data == null; + assert mirror.dataAddress == 0 ^ (data == null || mirror.dataAddress == EMPTY_DATA_ADDRESS); if (mirror.dataAddress == 0) { int[] intArray = new int[data.length]; for (int i = 0; i < data.length; i++) { @@ -522,7 +536,7 @@ public final class NativeDataAccess { static long allocateNativeContents(RIntVector vector, int[] data, int length) { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); assert mirror != null; - assert mirror.dataAddress == 0 ^ data == null; + assert mirror.dataAddress == 0 ^ (data == null || mirror.dataAddress == EMPTY_DATA_ADDRESS); if (mirror.dataAddress == 0) { noIntNative.invalidate(); mirror.allocateNative(data, length, Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE); @@ -533,7 +547,7 @@ public final class NativeDataAccess { static long allocateNativeContents(RRawVector vector, byte[] data, int length) { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); assert mirror != null; - assert mirror.dataAddress == 0 ^ data == null; + assert mirror.dataAddress == 0 ^ (data == null || mirror.dataAddress == EMPTY_DATA_ADDRESS); if (mirror.dataAddress == 0) { noRawNative.invalidate(); mirror.allocateNative(data, length, Unsafe.ARRAY_BYTE_BASE_OFFSET, Unsafe.ARRAY_BYTE_INDEX_SCALE); @@ -544,7 +558,7 @@ public final class NativeDataAccess { static long allocateNativeContents(RDoubleVector vector, double[] data, int length) { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); assert mirror != null; - assert mirror.dataAddress == 0 ^ data == null; + assert mirror.dataAddress == 0 ^ (data == null || mirror.dataAddress == EMPTY_DATA_ADDRESS); if (mirror.dataAddress == 0) { noDoubleNative.invalidate(); mirror.allocateNative(data, length, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE); @@ -555,7 +569,7 @@ public final class NativeDataAccess { static long allocateNativeContents(RComplexVector vector, double[] data, int length) { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); assert mirror != null; - assert mirror.dataAddress == 0 ^ data == null; + assert mirror.dataAddress == 0 ^ (data == null || mirror.dataAddress == EMPTY_DATA_ADDRESS); if (mirror.dataAddress == 0) { noComplexNative.invalidate(); mirror.allocateNative(data, length, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE * 2); @@ -566,7 +580,7 @@ public final class NativeDataAccess { static long allocateNativeContents(CharSXPWrapper vector, String contents) { NativeMirror mirror = (NativeMirror) vector.getNativeMirror(); assert mirror != null; - assert mirror.dataAddress == 0 ^ contents == null; + assert mirror.dataAddress == 0 ^ (contents == null || mirror.dataAddress == EMPTY_DATA_ADDRESS); if (mirror.dataAddress == 0) { noCahrSXPNative.invalidate(); mirror.allocateNative(contents);