13
13
import org .jruby .runtime .Visibility ;
14
14
import org .jruby .runtime .builtin .IRubyObject ;
15
15
import org .jruby .runtime .load .Library ;
16
- import org . jruby . util . unsafe . UnsafeHolder ;
16
+ import sun . misc . Unsafe ;
17
17
18
18
import java .io .IOException ;
19
+ import java .lang .reflect .Field ;
19
20
import java .lang .reflect .Method ;
20
21
21
22
public class SynchronizationLibrary implements Library {
22
23
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
+
23
56
private static final ObjectAllocator JRUBY_OBJECT_ALLOCATOR = new ObjectAllocator () {
24
57
public IRubyObject allocate (Ruby runtime , RubyClass klazz ) {
25
58
return new JRubyObject (runtime , klazz );
@@ -65,8 +98,13 @@ public void load(Ruby runtime, boolean wrap) throws IOException {
65
98
JRubyLockableObject .class , JRUBY_LOCKABLE_OBJECT_ALLOCATOR );
66
99
}
67
100
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 ) {
70
108
final RubyClass parentClass = namespace .getClass (parentName );
71
109
72
110
if (parentClass == null ) {
@@ -90,23 +128,6 @@ private RubyClass defineClass(Ruby runtime, RubyModule namespace, String parentN
90
128
// module JRubyAttrVolatile
91
129
public static class JRubyAttrVolatile {
92
130
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
-
110
131
// volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
111
132
// on volatile fields. any volatile field could have been used but using the thread context is an
112
133
// attempt to avoid code elimination.
@@ -122,37 +143,44 @@ public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject s
122
143
final ThreadContext oldContext = threadContext ;
123
144
threadContext = context ;
124
145
} else {
125
- UnsafeHolder . U .fullFence ();
146
+ UNSAFE .fullFence ();
126
147
}
127
148
return context .nil ;
128
149
}
129
150
130
151
@ 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 ) {
132
156
// Ensure we ses latest value with loadFence
133
157
if (!supportsFences ()) {
134
158
// piggybacking on volatile read, simulating loadFence
135
159
final ThreadContext oldContext = threadContext ;
136
- return ((RubyBasicObject )self ).instance_variable_get (context , name );
160
+ return ((RubyBasicObject ) self ).instance_variable_get (context , name );
137
161
} 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 );
140
164
}
141
165
}
142
166
143
167
@ 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 ) {
145
173
// Ensure we make last update visible
146
174
if (!supportsFences ()) {
147
175
// 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 );
149
177
threadContext = context ;
150
178
return result ;
151
179
} else {
152
180
// JRuby uses StampedVariableAccessor which calls fullFence
153
181
// so no additional steps needed.
154
182
// 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 );
156
184
}
157
185
}
158
186
}
0 commit comments