From a7e86e6cd437e1360014111f0dfee8bea7c23b38 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 31 Mar 2014 15:23:42 -0600 Subject: [PATCH] implement Unsafe.{get|put}*Volatile --- classpath/sun/misc/Unsafe.java | 28 ++++++++- src/builtin.cpp | 106 +++++++++++++++++++++++++++++++++ test/UnsafeTest.java | 59 ++++++++++++++++++ 3 files changed, 191 insertions(+), 2 deletions(-) diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 9bae7e60c0..1b0a9c183d 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -46,15 +46,39 @@ public final class Unsafe { public native void putDouble(long address, double x); + public native boolean getBooleanVolatile(Object o, long offset); + + public native void putBooleanVolatile(Object o, long offset, boolean x); + + public native byte getByteVolatile(Object o, long offset); + + public native void putByteVolatile(Object o, long offset, byte x); + + public native short getShortVolatile(Object o, long offset); + + public native void putShortVolatile(Object o, long offset, short x); + + public native char getCharVolatile(Object o, long offset); + + public native void putCharVolatile(Object o, long offset, char x); + public native int getIntVolatile(Object o, long offset); public native void putIntVolatile(Object o, long offset, int x); + public native float getFloatVolatile(Object o, long offset); + + public native void putFloatVolatile(Object o, long offset, float x); + + public native double getDoubleVolatile(Object o, long offset); + + public native void putDoubleVolatile(Object o, long offset, double x); + public native long getLongVolatile(Object o, long offset); - public native long putLongVolatile(Object o, long offset, long x); + public native void putLongVolatile(Object o, long offset, long x); - public native long putOrderedLong(Object o, long offset, long x); + public native void putOrderedLong(Object o, long offset, long x); public native void putOrderedInt(Object o, long offset, int x); diff --git a/src/builtin.cpp b/src/builtin.cpp index 6bcc4f5e16..e70a5189ae 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -992,6 +992,112 @@ Avian_sun_misc_Unsafe_getIntVolatile return result; } +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putByteVolatile +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int8_t value = arguments[4]; + + storeStoreMemoryBarrier(); + fieldAtOffset(o, offset) = value; + storeLoadMemoryBarrier(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getByteVolatile +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + int8_t result = fieldAtOffset(o, offset); + loadMemoryBarrier(); + return result; +} + +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putBooleanVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putByteVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getBooleanVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getByteVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putShortVolatile +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int16_t value = arguments[4]; + + storeStoreMemoryBarrier(); + fieldAtOffset(o, offset) = value; + storeLoadMemoryBarrier(); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getShortVolatile +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + int16_t result = fieldAtOffset(o, offset); + loadMemoryBarrier(); + return result; +} + +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putCharVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putShortVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getCharVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getShortVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putFloatVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putIntVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getFloatVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getIntVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT void JNICALL +Avian_sun_misc_Unsafe_putDoubleVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putLongVolatile(t, method, arguments); +} + +extern "C" AVIAN_EXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getDoubleVolatile +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getLongVolatile(t, method, arguments); +} + extern "C" AVIAN_EXPORT void JNICALL Avian_sun_misc_Unsafe_throwException (Thread* t, object, uintptr_t* arguments) diff --git a/test/UnsafeTest.java b/test/UnsafeTest.java index 3cbc6733e7..a644641dda 100644 --- a/test/UnsafeTest.java +++ b/test/UnsafeTest.java @@ -76,10 +76,69 @@ public class UnsafeTest { } } + private static void unsafeArray(Unsafe u) { + final int offset = u.arrayBaseOffset(long[].class); + final int scale = u.arrayIndexScale(long[].class); + final int size = 64; + final long[] array = new long[size]; + + for (int i = 0; i < size; ++i) + u.putBooleanVolatile(array, offset + (i * scale), i % 2 == 0); + + for (int i = 0; i < size; ++i) + expect(u.getBooleanVolatile(array, offset + (i * scale)) + == (i % 2 == 0)); + + for (int i = 0; i < size; ++i) + u.putByteVolatile(array, offset + (i * scale), (byte) 42); + + for (int i = 0; i < size; ++i) + expect(u.getByteVolatile(array, offset + (i * scale)) == 42); + + for (int i = 0; i < size; ++i) + u.putShortVolatile(array, offset + (i * scale), (short) -12345); + + for (int i = 0; i < size; ++i) + expect(u.getShortVolatile(array, offset + (i * scale)) == -12345); + + for (int i = 0; i < size; ++i) + u.putCharVolatile(array, offset + (i * scale), (char) 23456); + + for (int i = 0; i < size; ++i) + expect(u.getCharVolatile(array, offset + (i * scale)) == 23456); + + for (int i = 0; i < size; ++i) + u.putIntVolatile(array, offset + (i * scale), 0x12345678); + + for (int i = 0; i < size; ++i) + expect(u.getIntVolatile(array, offset + (i * scale)) == 0x12345678); + + for (int i = 0; i < size; ++i) + u.putFloatVolatile(array, offset + (i * scale), 1.2345678F); + + for (int i = 0; i < size; ++i) + expect(u.getFloatVolatile(array, offset + (i * scale)) == 1.2345678F); + + for (int i = 0; i < size; ++i) + u.putLongVolatile(array, offset + (i * scale), 0x1234567890ABCDEFL); + + for (int i = 0; i < size; ++i) + expect(u.getLongVolatile(array, offset + (i * scale)) + == 0x1234567890ABCDEFL); + + for (int i = 0; i < size; ++i) + u.putDoubleVolatile(array, offset + (i * scale), 1.23456789012345D); + + for (int i = 0; i < size; ++i) + expect(u.getDoubleVolatile(array, offset + (i * scale)) + == 1.23456789012345D); + } + public static void main(String[] args) { Unsafe u = avian.Machine.getUnsafe(); unsafeCatch(u); unsafeMemory(u); + unsafeArray(u); } }