Permalink
Browse files

Double alignment on ARM

On ARM 32 bit platforms, such as ARM71, double access needs to be
aligned to 8-byte coundaries. These changes ensure that happens.
This is intended to be a patch commit that can be used to create
custom builds of Spark for the ARM 32-bit platforms.

Signed-off-by: Michael Kamprath <michael@claireware.com>
  • Loading branch information...
michaelkamprath committed Dec 25, 2016
1 parent cd0a083 commit 6079efbbab1a9640e9b8ce9d0b51c2c952e59659
@@ -84,11 +84,13 @@ public static void putFloat(Object object, long offset, float value) {
}
public static double getDouble(Object object, long offset) {
- return _UNSAFE.getDouble(object, offset);
+ // Using Long buffer for platforms requiring double byte alignment
+ return Double.longBitsToDouble(_UNSAFE.getLong(object, offset));
}
public static void putDouble(Object object, long offset, double value) {
- _UNSAFE.putDouble(object, offset, value);
+ // Using Long buffer for platforms requiring double byte alignment
+ _UNSAFE.putLong(object, offset, Double.doubleToRawLongBits(value));
}
public static Object getObjectVolatile(Object object, long offset) {
@@ -22,10 +22,14 @@
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import sun.misc.Cleaner;
import sun.misc.Unsafe;
public final class Platform {
+ private static final Logger logger = LoggerFactory.getLogger(Platform.class);
private static final Unsafe _UNSAFE;
@@ -44,6 +48,7 @@
public static final int DOUBLE_ARRAY_OFFSET;
private static final boolean unaligned;
+
static {
boolean _unaligned;
// use reflection to access unaligned field
@@ -119,11 +124,11 @@ public static void putFloat(Object object, long offset, float value) {
}
public static double getDouble(Object object, long offset) {
- return _UNSAFE.getDouble(object, offset);
+ return Double.longBitsToDouble(_UNSAFE.getLong(object, offset));
}
public static void putDouble(Object object, long offset, double value) {
- _UNSAFE.putDouble(object, offset, value);
+ _UNSAFE.putLong(object, offset, Double.doubleToRawLongBits(value));
}
public static Object getObjectVolatile(Object object, long offset) {
@@ -17,12 +17,12 @@
package org.apache.spark.unsafe;
-import org.apache.spark.unsafe.memory.MemoryAllocator;
-import org.apache.spark.unsafe.memory.MemoryBlock;
-
import org.junit.Assert;
import org.junit.Test;
+import org.apache.spark.unsafe.memory.MemoryBlock;
+import org.apache.spark.unsafe.memory.MemoryAllocator;
+
public class PlatformUtilSuite {
@Test
@@ -74,4 +74,27 @@ public void memoryDebugFillEnabledInTest() {
Platform.getByte(offheap.getBaseObject(), offheap.getBaseOffset()),
MemoryAllocator.MEMORY_DEBUG_FILL_CLEAN_VALUE);
}
+
+ /**
+ * This test ensures that double access is handled correctly for the host platform.
+ * On platforms that require double access to be aligned to 8-byte boundaries, this
+ * test should pass and not cause the JVM to segfault.
+ */
+ @Test
+ public void unalignedDoublePutAndGet() {
+ MemoryBlock testBuffer = MemoryBlock.fromLongArray(new long[20]);
+
+ // write a double to an unaligned location
+ long unalignedOffset = testBuffer.getBaseOffset() + 3;
+ // double check unalignment just to be sure:
+ if (unalignedOffset % 8 == 0) {
+ unalignedOffset++;
+ }
+
+ Platform.putDouble(testBuffer.getBaseObject(), unalignedOffset, 3.14159);
+
+ double foundDouble = Platform.getDouble(testBuffer.getBaseObject(), unalignedOffset);
+
+ Assert.assertEquals(3.14159, foundDouble, 0.000001);
+ }
}

0 comments on commit 6079efb

Please sign in to comment.