66import org .jruby .RubyClass ;
77import org .jruby .RubyModule ;
88import org .jruby .RubyObject ;
9+ import org .jruby .RubyBasicObject ;
910import org .jruby .anno .JRubyClass ;
1011import org .jruby .anno .JRubyMethod ;
1112import org .jruby .runtime .ObjectAllocator ;
@@ -47,6 +48,9 @@ public void load(Ruby runtime, boolean wrap) throws IOException {
4748 defineModule ("Concurrent" ).
4849 defineModuleUnder ("Synchronization" );
4950
51+ RubyModule jrubyAttrVolatileModule = synchronizationModule .defineModuleUnder ("JRubyAttrVolatile" );
52+ jrubyAttrVolatileModule .defineAnnotatedMethods (JRubyAttrVolatile .class );
53+
5054 defineClass (runtime , synchronizationModule , "AbstractObject" , "JRubyObject" ,
5155 JRubyObject .class , JRUBY_OBJECT_ALLOCATOR );
5256
@@ -81,21 +85,16 @@ private RubyClass defineClass(Ruby runtime, RubyModule namespace, String parentN
8185 // SynchronizedVariableAccessor wraps with synchronized block, StampedVariableAccessor uses fullFence or
8286 // volatilePut
8387
84- @ JRubyClass (name = "JRubyObject" , parent = "AbstractObject" )
85- public static class JRubyObject extends RubyObject {
86- private static volatile ThreadContext threadContext = null ;
87-
88- public JRubyObject (Ruby runtime , RubyClass metaClass ) {
89- super (runtime , metaClass );
90- }
88+ // module JRubyAttrVolatile
89+ public static class JRubyAttrVolatile {
9190
92- @ JRubyMethod
93- public IRubyObject initialize ( ThreadContext context ) {
94- return this ;
95- }
91+ // volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
92+ // on volatile fields. any volatile field could have been used but using the thread context is an
93+ // attempt to avoid code elimination.
94+ private static volatile ThreadContext threadContext = null ;
9695
9796 @ JRubyMethod (name = "full_memory_barrier" , visibility = Visibility .PRIVATE )
98- public IRubyObject fullMemoryBarrier (ThreadContext context ) {
97+ public static IRubyObject fullMemoryBarrier (ThreadContext context , IRubyObject self ) {
9998 // Prevent reordering of ivar writes with publication of this instance
10099 if (UnsafeHolder .U == null || !UnsafeHolder .SUPPORTS_FENCES ) {
101100 // Assuming that following volatile read and write is not eliminated it simulates fullFence.
@@ -109,35 +108,43 @@ public IRubyObject fullMemoryBarrier(ThreadContext context) {
109108 }
110109
111110 @ JRubyMethod (name = "instance_variable_get_volatile" , visibility = Visibility .PROTECTED )
112- public IRubyObject instanceVariableGetVolatile (ThreadContext context , IRubyObject name ) {
111+ public static IRubyObject instanceVariableGetVolatile (ThreadContext context , IRubyObject self , IRubyObject name ) {
113112 // Ensure we ses latest value with loadFence
114113 if (UnsafeHolder .U == null || !UnsafeHolder .SUPPORTS_FENCES ) {
115114 // piggybacking on volatile read, simulating loadFence
116115 final ThreadContext oldContext = threadContext ;
117- return instance_variable_get (context , name );
116+ return (( RubyBasicObject ) self ). instance_variable_get (context , name );
118117 } else {
119118 UnsafeHolder .loadFence ();
120- return instance_variable_get (context , name );
119+ return (( RubyBasicObject ) self ). instance_variable_get (context , name );
121120 }
122121 }
123122
124123 @ JRubyMethod (name = "instance_variable_set_volatile" , visibility = Visibility .PROTECTED )
125- public IRubyObject InstanceVariableSetVolatile (ThreadContext context , IRubyObject name , IRubyObject value ) {
124+ public static IRubyObject InstanceVariableSetVolatile (ThreadContext context , IRubyObject self , IRubyObject name , IRubyObject value ) {
126125 // Ensure we make last update visible
127126 if (UnsafeHolder .U == null || !UnsafeHolder .SUPPORTS_FENCES ) {
128127 // piggybacking on volatile write, simulating storeFence
129- final IRubyObject result = instance_variable_set (name , value );
128+ final IRubyObject result = (( RubyBasicObject ) self ). instance_variable_set (name , value );
130129 threadContext = context ;
131130 return result ;
132131 } else {
133132 // JRuby uses StampedVariableAccessor which calls fullFence
134133 // so no additional steps needed.
135134 // See https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/runtime/ivars/StampedVariableAccessor.java#L151-L159
136- return instance_variable_set (name , value );
135+ return (( RubyBasicObject ) self ). instance_variable_set (name , value );
137136 }
138137 }
139138 }
140139
140+ @ JRubyClass (name = "JRubyObject" , parent = "AbstractObject" )
141+ public static class JRubyObject extends RubyObject {
142+
143+ public JRubyObject (Ruby runtime , RubyClass metaClass ) {
144+ super (runtime , metaClass );
145+ }
146+ }
147+
141148 @ JRubyClass (name = "Object" , parent = "JRubyObject" )
142149 public static class Object extends JRubyObject {
143150
0 commit comments