9
9
*/
10
10
package org .jruby .truffle .nodes .core ;
11
11
12
+ import java .util .EnumSet ;
12
13
import java .util .concurrent .locks .ReentrantLock ;
13
14
15
+ import com .oracle .truffle .api .nodes .Node ;
16
+ import com .oracle .truffle .api .object .DynamicObjectFactory ;
14
17
import com .oracle .truffle .api .object .HiddenKey ;
15
- import org .jruby .truffle .nodes .objectstorage .ReadHeadObjectFieldNode ;
16
- import org .jruby .truffle .nodes .objectstorage .WriteHeadObjectFieldNode ;
18
+ import com .oracle .truffle .api .object .LocationModifier ;
19
+ import com .oracle .truffle .api .object .Property ;
20
+ import com .oracle .truffle .api .object .Shape ;
21
+
22
+ import org .jruby .truffle .nodes .objects .Allocator ;
17
23
import org .jruby .truffle .runtime .RubyContext ;
18
24
import org .jruby .truffle .runtime .control .RaiseException ;
19
25
import org .jruby .truffle .runtime .core .RubyBasicObject ;
26
+ import org .jruby .truffle .runtime .core .RubyClass ;
20
27
import org .jruby .truffle .runtime .core .RubyThread ;
21
28
import org .jruby .truffle .runtime .subsystems .ThreadManager .BlockingActionWithoutGlobalLock ;
22
29
28
35
public abstract class MutexNodes {
29
36
30
37
private static final HiddenKey LOCK_IDENTIFIER = new HiddenKey ("lock" );
38
+ private static final Property LOCK_PROPERTY ;
31
39
32
- @ CoreMethod (names = "initialize" )
33
- public abstract static class InitializeNode extends UnaryCoreMethodNode {
34
-
35
- @ Child private WriteHeadObjectFieldNode writeLock ;
36
-
37
- public InitializeNode (RubyContext context , SourceSection sourceSection ) {
38
- super (context , sourceSection );
39
- writeLock = new WriteHeadObjectFieldNode (LOCK_IDENTIFIER );
40
- }
40
+ static {
41
+ Shape .Allocator allocator = RubyBasicObject .LAYOUT .createAllocator ();
42
+ LOCK_PROPERTY = Property .create (LOCK_IDENTIFIER , allocator .locationForType (ReentrantLock .class , EnumSet .of (LocationModifier .Final , LocationModifier .NonNull )), 0 );
43
+ }
41
44
42
- public InitializeNode (InitializeNode prev ) {
43
- super (prev );
44
- writeLock = prev .writeLock ;
45
- }
45
+ public static Allocator createMutexAllocator (Shape emptyShape ) {
46
+ Shape shape = emptyShape .addProperty (LOCK_PROPERTY );
47
+ final DynamicObjectFactory factory = shape .createFactory ();
46
48
47
- @ Specialization
48
- public RubyBasicObject lock (RubyBasicObject mutex ) {
49
- writeLock .execute (mutex , new ReentrantLock ());
50
- return mutex ;
51
- }
49
+ return new Allocator () {
50
+ @ Override
51
+ public RubyBasicObject allocate (RubyContext context , RubyClass rubyClass , Node currentNode ) {
52
+ return new RubyBasicObject (rubyClass , factory .newInstance (new ReentrantLock ()));
53
+ }
54
+ };
55
+ }
52
56
57
+ protected static ReentrantLock getLock (RubyBasicObject mutex ) {
58
+ // mutex has the proper shape since Ruby disallow calling Mutex methods on non-Mutex instances.
59
+ assert mutex .getDynamicObject ().getShape ().hasProperty (LOCK_IDENTIFIER );
60
+ return (ReentrantLock ) LOCK_PROPERTY .get (mutex .getDynamicObject (), true );
53
61
}
54
62
55
63
@ CoreMethod (names = "lock" )
56
64
public abstract static class LockNode extends UnaryCoreMethodNode {
57
65
58
- @ Child private ReadHeadObjectFieldNode readLock ;
59
-
60
66
public LockNode (RubyContext context , SourceSection sourceSection ) {
61
67
super (context , sourceSection );
62
- readLock = new ReadHeadObjectFieldNode (LOCK_IDENTIFIER );
63
68
}
64
69
65
70
public LockNode (LockNode prev ) {
66
71
super (prev );
67
- readLock = prev .readLock ;
68
72
}
69
73
70
74
@ Specialization
71
75
public RubyBasicObject lock (RubyBasicObject mutex ) {
72
- final ReentrantLock lock = ( ReentrantLock ) readLock . execute (mutex );
76
+ final ReentrantLock lock = getLock (mutex );
73
77
74
78
if (lock .isHeldByCurrentThread ()) {
75
79
CompilerDirectives .transferToInterpreter ();
@@ -95,67 +99,53 @@ public Boolean block() throws InterruptedException {
95
99
@ CoreMethod (names = "locked?" )
96
100
public abstract static class IsLockedNode extends UnaryCoreMethodNode {
97
101
98
- @ Child private ReadHeadObjectFieldNode readLock ;
99
-
100
102
public IsLockedNode (RubyContext context , SourceSection sourceSection ) {
101
103
super (context , sourceSection );
102
- readLock = new ReadHeadObjectFieldNode (LOCK_IDENTIFIER );
103
104
}
104
105
105
106
public IsLockedNode (IsLockedNode prev ) {
106
107
super (prev );
107
- readLock = prev .readLock ;
108
108
}
109
109
110
110
@ Specialization
111
111
public boolean isLocked (RubyBasicObject mutex ) {
112
- final ReentrantLock lock = (ReentrantLock ) readLock .execute (mutex );
113
- return lock .isLocked ();
112
+ return getLock (mutex ).isLocked ();
114
113
}
115
114
116
115
}
117
116
118
117
@ CoreMethod (names = "owned?" )
119
118
public abstract static class IsOwnedNode extends UnaryCoreMethodNode {
120
119
121
- @ Child private ReadHeadObjectFieldNode readLock ;
122
-
123
120
public IsOwnedNode (RubyContext context , SourceSection sourceSection ) {
124
121
super (context , sourceSection );
125
- readLock = new ReadHeadObjectFieldNode (LOCK_IDENTIFIER );
126
122
}
127
123
128
124
public IsOwnedNode (IsOwnedNode prev ) {
129
125
super (prev );
130
- readLock = prev .readLock ;
131
126
}
132
127
133
128
@ Specialization
134
129
public boolean isOwned (RubyBasicObject mutex ) {
135
- final ReentrantLock lock = (ReentrantLock ) readLock .execute (mutex );
136
- return lock .isHeldByCurrentThread ();
130
+ return getLock (mutex ).isHeldByCurrentThread ();
137
131
}
138
132
139
133
}
140
134
141
135
@ CoreMethod (names = "try_lock" )
142
136
public abstract static class TryLockNode extends UnaryCoreMethodNode {
143
137
144
- @ Child private ReadHeadObjectFieldNode readLock ;
145
-
146
138
public TryLockNode (RubyContext context , SourceSection sourceSection ) {
147
139
super (context , sourceSection );
148
- readLock = new ReadHeadObjectFieldNode (LOCK_IDENTIFIER );
149
140
}
150
141
151
142
public TryLockNode (TryLockNode prev ) {
152
143
super (prev );
153
- readLock = prev .readLock ;
154
144
}
155
145
156
146
@ Specialization
157
147
public boolean tryLock (RubyBasicObject mutex ) {
158
- final ReentrantLock lock = ( ReentrantLock ) readLock . execute (mutex );
148
+ final ReentrantLock lock = getLock (mutex );
159
149
160
150
if (lock .isHeldByCurrentThread ()) {
161
151
return false ;
@@ -175,21 +165,17 @@ public boolean tryLock(RubyBasicObject mutex) {
175
165
@ CoreMethod (names = "unlock" )
176
166
public abstract static class UnlockNode extends UnaryCoreMethodNode {
177
167
178
- @ Child private ReadHeadObjectFieldNode readLock ;
179
-
180
168
public UnlockNode (RubyContext context , SourceSection sourceSection ) {
181
169
super (context , sourceSection );
182
- readLock = new ReadHeadObjectFieldNode (LOCK_IDENTIFIER );
183
170
}
184
171
185
172
public UnlockNode (UnlockNode prev ) {
186
173
super (prev );
187
- readLock = prev .readLock ;
188
174
}
189
175
190
176
@ Specialization
191
177
public RubyBasicObject unlock (RubyBasicObject mutex ) {
192
- final ReentrantLock lock = ( ReentrantLock ) readLock . execute (mutex );
178
+ final ReentrantLock lock = getLock (mutex );
193
179
194
180
final RubyThread thread = getContext ().getThreadManager ().getCurrentThread ();
195
181
0 commit comments