Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 804dff38b3f5
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b272789ea242
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Mar 5, 2015

  1. [Truffle] Have a single dispath method for YieldDispatchNode.

    * Much less duplication and we already know default parameters in YieldDispatchHeadNode.
    eregon committed Mar 5, 2015
    Copy the full SHA
    0ded27e View commit details
  2. [Truffle] Make YieldDispatchNode rewriting thread-safe.

    * By re-reading under the lock the chain and checking if some other thread added
      a matching specilization. If that fails, we can rewrite safely rewrite.
    eregon committed Mar 5, 2015
    Copy the full SHA
    b272789 View commit details
Original file line number Diff line number Diff line change
@@ -47,30 +47,22 @@ public CachedYieldDispatchNode(RubyContext context, RubyProc block, YieldDispatc
}

@Override
public Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects) {
if (block.getCallTargetForBlocks() != callNode.getCallTarget()) {
return next.dispatch(frame, block, argumentsObjects);
}

return callNode.call(frame, RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope(), argumentsObjects));
protected boolean guard(RubyProc block) {
return block.getCallTargetForBlocks() == callNode.getCallTarget();
}

@Override
public Object dispatchWithModifiedBlock(VirtualFrame frame, RubyProc block, RubyProc modifiedBlock, Object[] argumentsObjects) {
if (block.getCallTargetForBlocks() != callNode.getCallTarget()) {
return next.dispatch(frame, block, argumentsObjects);
}

return callNode.call(frame, RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), block.getSelfCapturedInScope(), modifiedBlock, argumentsObjects));
protected YieldDispatchNode getNext() {
return next;
}

@Override
public Object dispatchWithModifiedSelf(VirtualFrame frame, RubyProc block, Object self, Object... argumentsObjects) {
if (block.getCallTargetForBlocks() != callNode.getCallTarget()) {
return next.dispatchWithModifiedSelf(frame, block, self, argumentsObjects);
public Object dispatchWithSelfAndBlock(VirtualFrame frame, RubyProc block, Object self, RubyProc modifiedBlock, Object... argumentsObjects) {
if (guard(block)) {
return callNode.call(frame, RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), self, modifiedBlock, argumentsObjects));
} else {
return next.dispatchWithSelfAndBlock(frame, block, self, modifiedBlock, argumentsObjects);
}

return callNode.call(frame, RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), self, block.getBlockCapturedInScope(), argumentsObjects));
}

@Override
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.NodeCost;
import com.oracle.truffle.api.nodes.NodeInfo;

import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyProc;
@@ -29,21 +30,14 @@ public GeneralYieldDispatchNode(RubyContext context) {
}

@Override
public Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects) {
return callNode.call(frame, block.getCallTargetForBlocks(),
RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), block.getSelfCapturedInScope(), block.getBlockCapturedInScope(), argumentsObjects));
}

@Override
public Object dispatchWithModifiedBlock(VirtualFrame frame, RubyProc block, RubyProc modifiedBlock, Object[] argumentsObjects) {
return callNode.call(frame, block.getCallTargetForBlocks(),
RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), block.getSelfCapturedInScope(), modifiedBlock, argumentsObjects));
protected boolean guard(RubyProc block) {
return true;
}

@Override
public Object dispatchWithModifiedSelf(VirtualFrame frame, RubyProc block, Object self, Object... argumentsObjects) {
public Object dispatchWithSelfAndBlock(VirtualFrame frame, RubyProc block, Object self, RubyProc modifiedBlock, Object... argumentsObjects) {
return callNode.call(frame, block.getCallTargetForBlocks(),
RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), self, block.getBlockCapturedInScope(), argumentsObjects));
RubyArguments.pack(block.getMethod(), block.getDeclarationFrame(), self, modifiedBlock, argumentsObjects));
}

}
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@
*/
package org.jruby.truffle.nodes.yield;

import java.util.concurrent.Callable;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeCost;
@@ -18,7 +20,6 @@
import org.jruby.truffle.nodes.dispatch.DispatchNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.util.cli.Options;

@NodeInfo(cost = NodeCost.UNINITIALIZED)
public class UninitializedYieldDispatchNode extends YieldDispatchNode {
@@ -30,57 +31,44 @@ public UninitializedYieldDispatchNode(RubyContext context) {
}

@Override
public Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects) {
CompilerDirectives.transferToInterpreterAndInvalidate();

depth++;

if (depth == DispatchNode.DISPATCH_POLYMORPHIC_MAX) {
final YieldDispatchHeadNode dispatchHead = (YieldDispatchHeadNode) NodeUtil.getNthParent(this, depth);
final GeneralYieldDispatchNode newGeneralYield = new GeneralYieldDispatchNode(getContext());
dispatchHead.getDispatch().replace(newGeneralYield);
return newGeneralYield.dispatch(frame, block, argumentsObjects);
}

final CachedYieldDispatchNode dispatch = new CachedYieldDispatchNode(getContext(), block, this);
replace(dispatch);
return dispatch.dispatch(frame, block, argumentsObjects);
protected boolean guard(RubyProc block) {
return false;
}

@Override
public Object dispatchWithModifiedBlock(VirtualFrame frame, RubyProc block, RubyProc modifiedBlock, Object[] argumentsObjects) {
public Object dispatchWithSelfAndBlock(VirtualFrame frame, final RubyProc block, Object self, RubyProc modifiedBlock, Object... argumentsObjects) {
CompilerDirectives.transferToInterpreterAndInvalidate();

depth++;

if (depth == DispatchNode.DISPATCH_POLYMORPHIC_MAX) {
final YieldDispatchHeadNode dispatchHead = (YieldDispatchHeadNode) NodeUtil.getNthParent(this, depth);
final GeneralYieldDispatchNode newGeneralYield = new GeneralYieldDispatchNode(getContext());
dispatchHead.getDispatch().replace(newGeneralYield);
return newGeneralYield.dispatch(frame, block, argumentsObjects);
}

final CachedYieldDispatchNode dispatch = new CachedYieldDispatchNode(getContext(), block, this);
replace(dispatch);
return dispatch.dispatchWithModifiedBlock(frame, block, modifiedBlock, argumentsObjects);
}

@Override
public Object dispatchWithModifiedSelf(VirtualFrame frame, RubyProc block, Object self, Object... argumentsObjects) {
CompilerDirectives.transferToInterpreterAndInvalidate();

depth++;

if (depth == DispatchNode.DISPATCH_POLYMORPHIC_MAX) {
final YieldDispatchHeadNode dispatchHead = (YieldDispatchHeadNode) NodeUtil.getNthParent(this, depth);
final GeneralYieldDispatchNode newGeneralYield = new GeneralYieldDispatchNode(getContext());
dispatchHead.getDispatch().replace(newGeneralYield);
return newGeneralYield.dispatchWithModifiedSelf(frame, block, self, argumentsObjects);
}

final CachedYieldDispatchNode dispatch = new CachedYieldDispatchNode(getContext(), block, this);
replace(dispatch);
return dispatch.dispatchWithModifiedSelf(frame, block, self, argumentsObjects);
final UninitializedYieldDispatchNode currentNode = this;

final YieldDispatchNode dispatch = atomic(new Callable<YieldDispatchNode>() {
@Override
public YieldDispatchNode call() {
// First try to see if we did not a miss a specialization added by another thread.
final YieldDispatchHeadNode dispatchHead = (YieldDispatchHeadNode) NodeUtil.getNthParent(currentNode, depth + 1);

YieldDispatchNode lookupDispatch = dispatchHead.getDispatch();
while (lookupDispatch != null) {
if (lookupDispatch.guard(block)) {
// This one worked, no need to rewrite anything.
return lookupDispatch;
}
lookupDispatch = lookupDispatch.getNext();
}

depth++;
if (depth < DispatchNode.DISPATCH_POLYMORPHIC_MAX) {
CachedYieldDispatchNode cachedDispatch = new CachedYieldDispatchNode(getContext(), block, currentNode);
replace(cachedDispatch);
return cachedDispatch;
} else {
GeneralYieldDispatchNode newGeneralYield = new GeneralYieldDispatchNode(getContext());
dispatchHead.getDispatch().replace(newGeneralYield);
return newGeneralYield;
}
}
});

return dispatch.dispatchWithSelfAndBlock(frame, block, self, modifiedBlock, argumentsObjects);
}

}
Original file line number Diff line number Diff line change
@@ -31,11 +31,11 @@ public YieldDispatchHeadNode(RubyContext context) {
}

public Object dispatch(VirtualFrame frame, RubyProc block, Object... argumentsObjects) {
return dispatch.dispatch(frame, block, argumentsObjects);
return dispatch.dispatchWithSelfAndBlock(frame, block, block.getSelfCapturedInScope(), block.getBlockCapturedInScope(), argumentsObjects);
}

public Object dispatchWithModifiedBlock(VirtualFrame frame, RubyProc block, RubyProc modifiedBlock, Object... argumentsObjects) {
return dispatch.dispatchWithModifiedBlock(frame, block, modifiedBlock, argumentsObjects);
return dispatch.dispatchWithSelfAndBlock(frame, block, block.getSelfCapturedInScope(), modifiedBlock, argumentsObjects);
}

public Object dispatchWithModifiedSelf(VirtualFrame currentFrame, RubyProc block, Object self, Object... argumentsObjects) {
@@ -48,7 +48,7 @@ public Object dispatchWithModifiedSelf(VirtualFrame currentFrame, RubyProc block
try {
frame.setObject(slot, Visibility.PUBLIC);

return dispatch.dispatchWithModifiedSelf(currentFrame, block, self, argumentsObjects);
return dispatch.dispatchWithSelfAndBlock(currentFrame, block, self, block.getBlockCapturedInScope(), argumentsObjects);
} finally {
frame.setObject(slot, oldVisibility);
}
Original file line number Diff line number Diff line change
@@ -23,11 +23,13 @@ public YieldDispatchNode(RubyContext context) {
this.context = context;
}

public abstract Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects);
protected YieldDispatchNode getNext() {
return null;
}

public abstract Object dispatchWithModifiedBlock(VirtualFrame frame, RubyProc block, RubyProc modifiedBlock, Object[] argumentsObjects);
protected abstract boolean guard(RubyProc block);

public abstract Object dispatchWithModifiedSelf(VirtualFrame frame, RubyProc block, Object self, Object... argumentsObjects);
public abstract Object dispatchWithSelfAndBlock(VirtualFrame frame, RubyProc block, Object self, RubyProc modifiedBlock, Object... argumentsObjects);

public RubyContext getContext() {
return context;