Author: mturk Date: Mon Jul 18 18:36:29 2011 New Revision: 1147999 URL: http://svn.apache.org/viewvc?rev=1147999&view=rev Log: Add more unsafe object put/get wrappers
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Unsafe.java commons/sandbox/runtime/trunk/src/main/native/shared/unsafe.c commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUnsafe.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Unsafe.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Unsafe.java?rev=1147999&r1=1147998&r2=1147999&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Unsafe.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Unsafe.java Mon Jul 18 18:36:29 2011 @@ -37,6 +37,9 @@ public final class Unsafe private static native int getOffset1(Field f); private static native int getBase0(Field f); private static native Object getObject0(Object o, int off); + private static native Object getObject1(Object o, int off); + private static native void putObject0(Object o, int off, Object v); + private static native void putObject1(Object o, int off, Object v); private static native int peek0(long ptr); private static native long peek1(long ptr); @@ -129,6 +132,59 @@ public final class Unsafe return getObject0(o, offset); } + /** + * Fetches a reference value from a given Java variable with volatile + * load semantics. + */ + public static Object getObjectVolatile(Object o, int offset) + throws UnsupportedOperationException, IllegalArgumentException + { + if (unsafe == null) + throw new UnsupportedOperationException(); + if (o == null || offset < 0) + throw new IllegalArgumentException(); + return getObject0(o, offset); + } + + /** + * Stores a reference value into a given Java variable. + * <p> + * Unless the reference {@code x} being stored is either null + * or matches the field type, the results are undefined. + * If the reference {@code o} is non-null, car marks or + * other store barriers for that object (if the VM requires them) + * are updated. + */ + public static void putObject(Object o, int offset, Object x) + throws UnsupportedOperationException, IllegalArgumentException + { + if (unsafe == null) + throw new UnsupportedOperationException(); + if (o == null || offset < 0) + throw new IllegalArgumentException(); + putObject0(o, offset, x); + } + + /** + * Stores a reference value into a given Java variable + * with a volatile sementics. + * <p> + * Unless the reference {@code x} being stored is either null + * or matches the field type, the results are undefined. + * If the reference {@code o} is non-null, car marks or + * other store barriers for that object (if the VM requires them) + * are updated. + */ + public static void putObjectVolatile(Object o, int offset, Object x) + throws UnsupportedOperationException, IllegalArgumentException + { + if (unsafe == null) + throw new UnsupportedOperationException(); + if (o == null || offset < 0) + throw new IllegalArgumentException(); + putObject0(o, offset, x); + } + private static native char[] getchr0(String str); /** * Get the {@code str} private character array. Modified: commons/sandbox/runtime/trunk/src/main/native/shared/unsafe.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/unsafe.c?rev=1147999&r1=1147998&r2=1147999&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/shared/unsafe.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/shared/unsafe.c Mon Jul 18 18:36:29 2011 @@ -43,29 +43,41 @@ J_DECLARE_M_ID(0000) = { J_DECLARE_M_ID(0001) = { 0, + "getObjectVolatile", + "(Ljava/lang/Object;J)Ljava/lang/Object;" +}; + +J_DECLARE_M_ID(0002) = { + 0, "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V" }; -J_DECLARE_M_ID(0002) = { +J_DECLARE_M_ID(0003) = { + 0, + "putObjectVolatile", + "(Ljava/lang/Object;JLjava/lang/Object;)V" +}; + + +J_DECLARE_M_ID(0004) = { 0, "objectFieldOffset", "(Ljava/lang/reflect/Field;)J" }; -J_DECLARE_M_ID(0003) = { +J_DECLARE_M_ID(0005) = { 0, "staticFieldBase", "(Ljava/lang/reflect/Field;)Ljava/lang/Object;" }; -J_DECLARE_M_ID(0004) = { +J_DECLARE_M_ID(0006) = { 0, "staticFieldOffset", "(Ljava/lang/reflect/Field;)J" }; - ACR_CLASS_CTOR(Unsafe) { if (AcrLoadClass(env, &_clazzn, 0) == JNI_FALSE) @@ -77,6 +89,8 @@ ACR_CLASS_CTOR(Unsafe) J_LOAD_METHOD(0002); J_LOAD_METHOD(0003); J_LOAD_METHOD(0004); + J_LOAD_METHOD(0005); + J_LOAD_METHOD(0006); _clazzn.u = 1; return JNI_TRUE; @@ -111,7 +125,7 @@ AcrUnsafeObjectFieldOffset(JNI_STDARGS) if (_get_unsafe(env) == 0) { return INVALID_FIELD_OFFSET; } - fo = CALL_METHOD1(Long, 0002, _unsafe_instance, obj); + fo = CALL_METHOD1(Long, 0004, _unsafe_instance, obj); if (fo > 0 && fo < INT_MAX) return (jint)fo; else @@ -126,7 +140,7 @@ AcrUnsafeStaticFieldBase(JNI_STDARGS) if (_get_unsafe(env) == 0) { return INVALID_FIELD_OFFSET; } - fo = CALL_METHOD1(Long, 0003, _unsafe_instance, obj); + fo = CALL_METHOD1(Long, 0005, _unsafe_instance, obj); if (fo > 0 && fo < INT_MAX) return (jint)fo; else @@ -141,7 +155,7 @@ AcrUnsafeStaticFieldOffset(JNI_STDARGS) if (_get_unsafe(env) == 0) { return INVALID_FIELD_OFFSET; } - fo = CALL_METHOD1(Long, 0004, _unsafe_instance, obj); + fo = CALL_METHOD1(Long, 0006, _unsafe_instance, obj); if (fo > 0 && fo < INT_MAX) return (jint)fo; else @@ -205,7 +219,27 @@ ACR_JNI_EXPORT(jobject, Unsafe, getObjec if (!CLAZZ_LOADED) return 0; else - return CALL_METHOD2(Object, 0000, _unsafe_instance, o, off); + return CALL_METHOD2(Object, 0000, _unsafe_instance, o, (jlong)off); +} + +ACR_JNI_EXPORT(jobject, Unsafe, getObject1)(JNI_STDARGS, jobject o, jint off) +{ + if (!CLAZZ_LOADED) + return 0; + else + return CALL_METHOD2(Object, 0001, _unsafe_instance, o, P2J(off)); +} + +ACR_JNI_EXPORT(void, Unsafe, putObject0)(JNI_STDARGS, jobject o, jint off, jobject v) +{ + if (CLAZZ_LOADED) + CALL_VMETHOD3(0002, _unsafe_instance, o, P2J(off), v); +} + +ACR_JNI_EXPORT(void, Unsafe, putObject1)(JNI_STDARGS, jobject o, jint off, jobject v) +{ + if (CLAZZ_LOADED) + CALL_VMETHOD3(0003, _unsafe_instance, o, P2J(off), v); } ACR_JNI_EXPORT(jint, Unsafe, peek0)(JNI_STDARGS, jlong ptr) Modified: commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUnsafe.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUnsafe.java?rev=1147999&r1=1147998&r2=1147999&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUnsafe.java (original) +++ commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestUnsafe.java Mon Jul 18 18:36:29 2011 @@ -26,6 +26,7 @@ public class TestUnsafe extends Assert { private int i = 12345; private String s = "hello world"; + private static String S = "hello world"; private static native int test0(Object o, int off); private static native Object test1(Object o, int off); @@ -63,6 +64,23 @@ public class TestUnsafe extends Assert } @Test(groups = { "private" }) + public void getDirectObjectVolatile() + throws Exception + { + int off = Unsafe.objectFieldOffset(TestUnsafe.class.getDeclaredField("s")); + assertEquals((String)Unsafe.getObjectVolatile(this, off), "hello world"); + } + + @Test(groups = { "private" }) + public void putDirectObject() + throws Exception + { + int off = Unsafe.objectFieldOffset(TestUnsafe.class.getDeclaredField("s")); + Unsafe.putObject(this, off, "HELLO WORLD"); + assertEquals(s, "HELLO WORLD"); + } + + @Test(groups = { "private" }) public void nativeFileDescriptor() throws Exception {