Skip to content

Commit edbffdb

Browse files
committed
[Truffle] Use a fixed Property for Mutex.
* No need for a node to read or write. * No need to write the field in initialize anymore!
1 parent da370fb commit edbffdb

File tree

4 files changed

+43
-53
lines changed

4 files changed

+43
-53
lines changed

truffle/src/main/java/org/jruby/truffle/nodes/core/MutexNodes.java

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@
99
*/
1010
package org.jruby.truffle.nodes.core;
1111

12+
import java.util.EnumSet;
1213
import java.util.concurrent.locks.ReentrantLock;
1314

15+
import com.oracle.truffle.api.nodes.Node;
16+
import com.oracle.truffle.api.object.DynamicObjectFactory;
1417
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;
1723
import org.jruby.truffle.runtime.RubyContext;
1824
import org.jruby.truffle.runtime.control.RaiseException;
1925
import org.jruby.truffle.runtime.core.RubyBasicObject;
26+
import org.jruby.truffle.runtime.core.RubyClass;
2027
import org.jruby.truffle.runtime.core.RubyThread;
2128
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;
2229

@@ -28,48 +35,45 @@
2835
public abstract class MutexNodes {
2936

3037
private static final HiddenKey LOCK_IDENTIFIER = new HiddenKey("lock");
38+
private static final Property LOCK_PROPERTY;
3139

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+
}
4144

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();
4648

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+
}
5256

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);
5361
}
5462

5563
@CoreMethod(names = "lock")
5664
public abstract static class LockNode extends UnaryCoreMethodNode {
5765

58-
@Child private ReadHeadObjectFieldNode readLock;
59-
6066
public LockNode(RubyContext context, SourceSection sourceSection) {
6167
super(context, sourceSection);
62-
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
6368
}
6469

6570
public LockNode(LockNode prev) {
6671
super(prev);
67-
readLock = prev.readLock;
6872
}
6973

7074
@Specialization
7175
public RubyBasicObject lock(RubyBasicObject mutex) {
72-
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
76+
final ReentrantLock lock = getLock(mutex);
7377

7478
if (lock.isHeldByCurrentThread()) {
7579
CompilerDirectives.transferToInterpreter();
@@ -95,67 +99,53 @@ public Boolean block() throws InterruptedException {
9599
@CoreMethod(names = "locked?")
96100
public abstract static class IsLockedNode extends UnaryCoreMethodNode {
97101

98-
@Child private ReadHeadObjectFieldNode readLock;
99-
100102
public IsLockedNode(RubyContext context, SourceSection sourceSection) {
101103
super(context, sourceSection);
102-
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
103104
}
104105

105106
public IsLockedNode(IsLockedNode prev) {
106107
super(prev);
107-
readLock = prev.readLock;
108108
}
109109

110110
@Specialization
111111
public boolean isLocked(RubyBasicObject mutex) {
112-
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
113-
return lock.isLocked();
112+
return getLock(mutex).isLocked();
114113
}
115114

116115
}
117116

118117
@CoreMethod(names = "owned?")
119118
public abstract static class IsOwnedNode extends UnaryCoreMethodNode {
120119

121-
@Child private ReadHeadObjectFieldNode readLock;
122-
123120
public IsOwnedNode(RubyContext context, SourceSection sourceSection) {
124121
super(context, sourceSection);
125-
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
126122
}
127123

128124
public IsOwnedNode(IsOwnedNode prev) {
129125
super(prev);
130-
readLock = prev.readLock;
131126
}
132127

133128
@Specialization
134129
public boolean isOwned(RubyBasicObject mutex) {
135-
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
136-
return lock.isHeldByCurrentThread();
130+
return getLock(mutex).isHeldByCurrentThread();
137131
}
138132

139133
}
140134

141135
@CoreMethod(names = "try_lock")
142136
public abstract static class TryLockNode extends UnaryCoreMethodNode {
143137

144-
@Child private ReadHeadObjectFieldNode readLock;
145-
146138
public TryLockNode(RubyContext context, SourceSection sourceSection) {
147139
super(context, sourceSection);
148-
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
149140
}
150141

151142
public TryLockNode(TryLockNode prev) {
152143
super(prev);
153-
readLock = prev.readLock;
154144
}
155145

156146
@Specialization
157147
public boolean tryLock(RubyBasicObject mutex) {
158-
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
148+
final ReentrantLock lock = getLock(mutex);
159149

160150
if (lock.isHeldByCurrentThread()) {
161151
return false;
@@ -175,21 +165,17 @@ public boolean tryLock(RubyBasicObject mutex) {
175165
@CoreMethod(names = "unlock")
176166
public abstract static class UnlockNode extends UnaryCoreMethodNode {
177167

178-
@Child private ReadHeadObjectFieldNode readLock;
179-
180168
public UnlockNode(RubyContext context, SourceSection sourceSection) {
181169
super(context, sourceSection);
182-
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
183170
}
184171

185172
public UnlockNode(UnlockNode prev) {
186173
super(prev);
187-
readLock = prev.readLock;
188174
}
189175

190176
@Specialization
191177
public RubyBasicObject unlock(RubyBasicObject mutex) {
192-
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
178+
final ReentrantLock lock = getLock(mutex);
193179

194180
final RubyThread thread = getContext().getThreadManager().getCurrentThread();
195181

truffle/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.jruby.runtime.load.LoadServiceResource;
2222
import org.jruby.truffle.nodes.RubyNode;
2323
import org.jruby.truffle.nodes.core.ArrayNodes;
24+
import org.jruby.truffle.nodes.core.MutexNodes;
2425
import org.jruby.truffle.nodes.core.ProcessNodes;
2526
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
2627
import org.jruby.truffle.nodes.objects.Allocator;
@@ -272,7 +273,7 @@ public CoreLibrary(RubyContext context) {
272273
hashClass = defineClass("Hash", new RubyHash.HashAllocator());
273274
matchDataClass = defineClass("MatchData");
274275
methodClass = defineClass("Method");
275-
defineClass("Mutex");
276+
defineClass("Mutex", MutexNodes.createMutexAllocator(context.getEmptyShape()));
276277
nilClass = defineClass("NilClass");
277278
procClass = defineClass("Proc", new RubyProc.ProcAllocator());
278279
processModule = defineModule("Process");
@@ -1167,5 +1168,4 @@ public RubySymbol getMapBangSymbol() {
11671168
public RubySymbol getMapSymbol() {
11681169
return mapSymbol;
11691170
}
1170-
11711171
}

truffle/src/main/java/org/jruby/truffle/runtime/core/RubyBasicObject.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,15 @@ public class RubyBasicObject {
4949
@CompilationFinal protected RubyClass metaClass;
5050

5151
public RubyBasicObject(RubyClass rubyClass) {
52-
this(rubyClass, rubyClass.getContext());
52+
this(rubyClass, LAYOUT.newInstance(rubyClass.getContext().getEmptyShape()));
5353
}
5454

55-
public RubyBasicObject(RubyClass rubyClass, RubyContext context) {
56-
dynamicObject = LAYOUT.newInstance(context.getEmptyShape());
55+
public RubyBasicObject(RubyClass rubyClass, DynamicObject dynamicObject) {
56+
this(rubyClass.getContext(), rubyClass, dynamicObject);
57+
}
58+
59+
public RubyBasicObject(RubyContext context, RubyClass rubyClass, DynamicObject dynamicObject) {
60+
this.dynamicObject = dynamicObject;
5761

5862
if (rubyClass != null) {
5963
unsafeSetLogicalClass(rubyClass);

truffle/src/main/java/org/jruby/truffle/runtime/core/RubyModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public RubyModule(RubyContext context, RubyModule lexicalParent, String name, No
113113
}
114114

115115
protected RubyModule(RubyContext context, RubyClass selfClass, RubyModule lexicalParent, String name, Node currentNode) {
116-
super(selfClass, context);
116+
super(context, selfClass, LAYOUT.newInstance(context.getEmptyShape()));
117117
this.context = context;
118118

119119
unmodifiedAssumption = new CyclicAssumption(name + " is unmodified");

0 commit comments

Comments
 (0)