Skip to content

Commit

Permalink
[Truffle] Use a fixed Property for Mutex.
Browse files Browse the repository at this point in the history
* No need for a node to read or write.
* No need to write the field in initialize anymore!
  • Loading branch information
eregon committed Mar 23, 2015
1 parent da370fb commit edbffdb
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 53 deletions.
80 changes: 33 additions & 47 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/MutexNodes.java
Expand Up @@ -9,14 +9,21 @@
*/
package org.jruby.truffle.nodes.core;

import java.util.EnumSet;
import java.util.concurrent.locks.ReentrantLock;

import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObjectFactory;
import com.oracle.truffle.api.object.HiddenKey;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import com.oracle.truffle.api.object.LocationModifier;
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;

import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyThread;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;

Expand All @@ -28,48 +35,45 @@
public abstract class MutexNodes {

private static final HiddenKey LOCK_IDENTIFIER = new HiddenKey("lock");
private static final Property LOCK_PROPERTY;

@CoreMethod(names = "initialize")
public abstract static class InitializeNode extends UnaryCoreMethodNode {

@Child private WriteHeadObjectFieldNode writeLock;

public InitializeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
writeLock = new WriteHeadObjectFieldNode(LOCK_IDENTIFIER);
}
static {
Shape.Allocator allocator = RubyBasicObject.LAYOUT.createAllocator();
LOCK_PROPERTY = Property.create(LOCK_IDENTIFIER, allocator.locationForType(ReentrantLock.class, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull)), 0);
}

public InitializeNode(InitializeNode prev) {
super(prev);
writeLock = prev.writeLock;
}
public static Allocator createMutexAllocator(Shape emptyShape) {
Shape shape = emptyShape.addProperty(LOCK_PROPERTY);
final DynamicObjectFactory factory = shape.createFactory();

@Specialization
public RubyBasicObject lock(RubyBasicObject mutex) {
writeLock.execute(mutex, new ReentrantLock());
return mutex;
}
return new Allocator() {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBasicObject(rubyClass, factory.newInstance(new ReentrantLock()));
}
};
}

protected static ReentrantLock getLock(RubyBasicObject mutex) {
// mutex has the proper shape since Ruby disallow calling Mutex methods on non-Mutex instances.
assert mutex.getDynamicObject().getShape().hasProperty(LOCK_IDENTIFIER);
return (ReentrantLock) LOCK_PROPERTY.get(mutex.getDynamicObject(), true);
}

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

@Child private ReadHeadObjectFieldNode readLock;

public LockNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
}

public LockNode(LockNode prev) {
super(prev);
readLock = prev.readLock;
}

@Specialization
public RubyBasicObject lock(RubyBasicObject mutex) {
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
final ReentrantLock lock = getLock(mutex);

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

@Child private ReadHeadObjectFieldNode readLock;

public IsLockedNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
}

public IsLockedNode(IsLockedNode prev) {
super(prev);
readLock = prev.readLock;
}

@Specialization
public boolean isLocked(RubyBasicObject mutex) {
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
return lock.isLocked();
return getLock(mutex).isLocked();
}

}

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

@Child private ReadHeadObjectFieldNode readLock;

public IsOwnedNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
}

public IsOwnedNode(IsOwnedNode prev) {
super(prev);
readLock = prev.readLock;
}

@Specialization
public boolean isOwned(RubyBasicObject mutex) {
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
return lock.isHeldByCurrentThread();
return getLock(mutex).isHeldByCurrentThread();
}

}

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

@Child private ReadHeadObjectFieldNode readLock;

public TryLockNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
}

public TryLockNode(TryLockNode prev) {
super(prev);
readLock = prev.readLock;
}

@Specialization
public boolean tryLock(RubyBasicObject mutex) {
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
final ReentrantLock lock = getLock(mutex);

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

@Child private ReadHeadObjectFieldNode readLock;

public UnlockNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readLock = new ReadHeadObjectFieldNode(LOCK_IDENTIFIER);
}

public UnlockNode(UnlockNode prev) {
super(prev);
readLock = prev.readLock;
}

@Specialization
public RubyBasicObject unlock(RubyBasicObject mutex) {
final ReentrantLock lock = (ReentrantLock) readLock.execute(mutex);
final ReentrantLock lock = getLock(mutex);

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

Expand Down
Expand Up @@ -21,6 +21,7 @@
import org.jruby.runtime.load.LoadServiceResource;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ArrayNodes;
import org.jruby.truffle.nodes.core.MutexNodes;
import org.jruby.truffle.nodes.core.ProcessNodes;
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
import org.jruby.truffle.nodes.objects.Allocator;
Expand Down Expand Up @@ -272,7 +273,7 @@ public CoreLibrary(RubyContext context) {
hashClass = defineClass("Hash", new RubyHash.HashAllocator());
matchDataClass = defineClass("MatchData");
methodClass = defineClass("Method");
defineClass("Mutex");
defineClass("Mutex", MutexNodes.createMutexAllocator(context.getEmptyShape()));
nilClass = defineClass("NilClass");
procClass = defineClass("Proc", new RubyProc.ProcAllocator());
processModule = defineModule("Process");
Expand Down Expand Up @@ -1167,5 +1168,4 @@ public RubySymbol getMapBangSymbol() {
public RubySymbol getMapSymbol() {
return mapSymbol;
}

}
Expand Up @@ -49,11 +49,15 @@ public class RubyBasicObject {
@CompilationFinal protected RubyClass metaClass;

public RubyBasicObject(RubyClass rubyClass) {
this(rubyClass, rubyClass.getContext());
this(rubyClass, LAYOUT.newInstance(rubyClass.getContext().getEmptyShape()));
}

public RubyBasicObject(RubyClass rubyClass, RubyContext context) {
dynamicObject = LAYOUT.newInstance(context.getEmptyShape());
public RubyBasicObject(RubyClass rubyClass, DynamicObject dynamicObject) {
this(rubyClass.getContext(), rubyClass, dynamicObject);
}

public RubyBasicObject(RubyContext context, RubyClass rubyClass, DynamicObject dynamicObject) {
this.dynamicObject = dynamicObject;

if (rubyClass != null) {
unsafeSetLogicalClass(rubyClass);
Expand Down
Expand Up @@ -113,7 +113,7 @@ public RubyModule(RubyContext context, RubyModule lexicalParent, String name, No
}

protected RubyModule(RubyContext context, RubyClass selfClass, RubyModule lexicalParent, String name, Node currentNode) {
super(selfClass, context);
super(context, selfClass, LAYOUT.newInstance(context.getEmptyShape()));
this.context = context;

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

0 comments on commit edbffdb

Please sign in to comment.