From 289847100f618fc977e9848669b44de2e9b97b8d Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 4 Oct 2017 16:54:23 +0200
Subject: [PATCH] Refined assertion in 'NativeDataAccess' and introduced empty
 array marker address.

---
 .../r/runtime/data/NativeDataAccess.java      | 34 +++++++++++++------
 1 file changed, 24 insertions(+), 10 deletions(-)

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 d6ddd16f25..67df0b447c 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);
-- 
GitLab