1313import org .jruby .runtime .Visibility ;
1414import org .jruby .runtime .builtin .IRubyObject ;
1515import org .jruby .runtime .load .Library ;
16- import org . jruby . util . unsafe . UnsafeHolder ;
16+ import sun . misc . Unsafe ;
1717
1818import java .io .IOException ;
19+ import java .lang .reflect .Field ;
1920import java .lang .reflect .Method ;
2021
2122public class SynchronizationLibrary implements Library {
2223
24+ private static final Unsafe UNSAFE = loadUnsafe ();
25+
26+ private static Unsafe loadUnsafe () {
27+ try {
28+ Class ncdfe = Class .forName ("sun.misc.Unsafe" );
29+ Field f = ncdfe .getDeclaredField ("theUnsafe" );
30+ f .setAccessible (true );
31+ return (Unsafe ) f .get ((java .lang .Object ) null );
32+ } catch (Exception var2 ) {
33+ return null ;
34+ } catch (NoClassDefFoundError var3 ) {
35+ return null ;
36+ }
37+ }
38+
39+ private static boolean supportsFences () {
40+ if (UNSAFE == null ) {
41+ return false ;
42+ } else {
43+ try {
44+ Method m = UNSAFE .getClass ().getDeclaredMethod ("fullFence" , new Class [0 ]);
45+ if (m != null ) {
46+ return true ;
47+ }
48+ } catch (Exception var1 ) {
49+ // nothing
50+ }
51+
52+ return false ;
53+ }
54+ }
55+
2356 private static final ObjectAllocator JRUBY_OBJECT_ALLOCATOR = new ObjectAllocator () {
2457 public IRubyObject allocate (Ruby runtime , RubyClass klazz ) {
2558 return new JRubyObject (runtime , klazz );
@@ -65,8 +98,13 @@ public void load(Ruby runtime, boolean wrap) throws IOException {
6598 JRubyLockableObject .class , JRUBY_LOCKABLE_OBJECT_ALLOCATOR );
6699 }
67100
68- private RubyClass defineClass (Ruby runtime , RubyModule namespace , String parentName , String name ,
69- Class javaImplementation , ObjectAllocator allocator ) {
101+ private RubyClass defineClass (
102+ Ruby runtime ,
103+ RubyModule namespace ,
104+ String parentName ,
105+ String name ,
106+ Class javaImplementation ,
107+ ObjectAllocator allocator ) {
70108 final RubyClass parentClass = namespace .getClass (parentName );
71109
72110 if (parentClass == null ) {
@@ -90,23 +128,6 @@ private RubyClass defineClass(Ruby runtime, RubyModule namespace, String parentN
90128 // module JRubyAttrVolatile
91129 public static class JRubyAttrVolatile {
92130
93- private static boolean supportsFences () {
94- if (UnsafeHolder .U == null ) {
95- return false ;
96- } else {
97- try {
98- Method m = UnsafeHolder .U .getClass ().getDeclaredMethod ("fullFence" , new Class [0 ]);
99- if (m != null ) {
100- return true ;
101- }
102- } catch (Exception var1 ) {
103- // nothing
104- }
105-
106- return false ;
107- }
108- }
109-
110131 // volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
111132 // on volatile fields. any volatile field could have been used but using the thread context is an
112133 // attempt to avoid code elimination.
@@ -122,37 +143,44 @@ public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject s
122143 final ThreadContext oldContext = threadContext ;
123144 threadContext = context ;
124145 } else {
125- UnsafeHolder . U .fullFence ();
146+ UNSAFE .fullFence ();
126147 }
127148 return context .nil ;
128149 }
129150
130151 @ JRubyMethod (name = "instance_variable_get_volatile" , visibility = Visibility .PUBLIC )
131- public static IRubyObject instanceVariableGetVolatile (ThreadContext context , IRubyObject self , IRubyObject name ) {
152+ public static IRubyObject instanceVariableGetVolatile (
153+ ThreadContext context ,
154+ IRubyObject self ,
155+ IRubyObject name ) {
132156 // Ensure we ses latest value with loadFence
133157 if (!supportsFences ()) {
134158 // piggybacking on volatile read, simulating loadFence
135159 final ThreadContext oldContext = threadContext ;
136- return ((RubyBasicObject )self ).instance_variable_get (context , name );
160+ return ((RubyBasicObject ) self ).instance_variable_get (context , name );
137161 } else {
138- UnsafeHolder . U .loadFence ();
139- return ((RubyBasicObject )self ).instance_variable_get (context , name );
162+ UNSAFE .loadFence ();
163+ return ((RubyBasicObject ) self ).instance_variable_get (context , name );
140164 }
141165 }
142166
143167 @ JRubyMethod (name = "instance_variable_set_volatile" , visibility = Visibility .PUBLIC )
144- public static IRubyObject InstanceVariableSetVolatile (ThreadContext context , IRubyObject self , IRubyObject name , IRubyObject value ) {
168+ public static IRubyObject InstanceVariableSetVolatile (
169+ ThreadContext context ,
170+ IRubyObject self ,
171+ IRubyObject name ,
172+ IRubyObject value ) {
145173 // Ensure we make last update visible
146174 if (!supportsFences ()) {
147175 // piggybacking on volatile write, simulating storeFence
148- final IRubyObject result = ((RubyBasicObject )self ).instance_variable_set (name , value );
176+ final IRubyObject result = ((RubyBasicObject ) self ).instance_variable_set (name , value );
149177 threadContext = context ;
150178 return result ;
151179 } else {
152180 // JRuby uses StampedVariableAccessor which calls fullFence
153181 // so no additional steps needed.
154182 // See https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/runtime/ivars/StampedVariableAccessor.java#L151-L159
155- return ((RubyBasicObject )self ).instance_variable_set (name , value );
183+ return ((RubyBasicObject ) self ).instance_variable_set (name , value );
156184 }
157185 }
158186 }
0 commit comments