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: 45108cc4e1ef
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4457905e7c0d
Choose a head ref
  • 2 commits
  • 13 files changed
  • 1 contributor

Commits on Nov 1, 2014

  1. Copy the full SHA
    bce4398 View commit details
  2. Copy the full SHA
    4457905 View commit details
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ public RubyCallNode(RubyContext context, SourceSection section, String methodNam
this.arguments = arguments;
this.isSplatted = isSplatted;

dispatchHead = new DispatchHeadNode(context, ignoreVisibility, rubiniusPrimitive, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
dispatchHead = new DispatchHeadNode(context, ignoreVisibility, false, rubiniusPrimitive, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
respondToMissing = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.RETURN_MISSING);
respondToMissingCast = BooleanCastNodeFactory.create(context, section, null);

Original file line number Diff line number Diff line change
@@ -16,11 +16,13 @@
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.VirtualFrame;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.dispatch.Dispatch;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.yield.YieldDispatchHeadNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.*;
import org.jruby.util.cli.Options;

@CoreClass(name = "BasicObject")
public abstract class BasicObjectNodes {
@@ -227,7 +229,12 @@ public abstract static class SendNode extends CoreMethodNode {

public SendNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
dispatchNode = DispatchHeadNode.onSelf(context);

dispatchNode = new DispatchHeadNode(context, true, Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_INDIRECT.load(), false, Dispatch.MissingBehavior.CALL_METHOD_MISSING);

if (Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED.load()) {
dispatchNode.forceUncached();
}
}

public SendNode(SendNode prev) {
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyHash;
import org.jruby.truffle.runtime.methods.RubyMethod;
import org.jruby.util.cli.Options;

@CoreClass(name = "Kernel")
public abstract class KernelNodes {
@@ -1443,8 +1444,14 @@ public abstract static class RespondToNode extends CoreMethodNode {

public RespondToNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);

dispatch = new DispatchHeadNode(context, false, Dispatch.MissingBehavior.CALL_METHOD_MISSING);
dispatchIgnoreVisibility = new DispatchHeadNode(context, true, Dispatch.MissingBehavior.CALL_METHOD_MISSING);

if (Options.TRUFFLE_DISPATCH_METAPROGRAMMING_ALWAYS_UNCACHED.load()) {
dispatch.forceUncached();
dispatchIgnoreVisibility.forceUncached();
}
}

public RespondToNode(RespondToNode prev) {
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;
import com.oracle.truffle.api.utilities.BranchProfile;
import org.jruby.truffle.runtime.LexicalScope;
@@ -33,31 +34,36 @@ public abstract class CachedBooleanDispatchNode extends CachedDispatchNode {
private final BranchProfile falseProfile = new BranchProfile();

private final Object falseValue;
@Child protected DirectCallNode falseCall;
@Child protected DirectCallNode falseCallDirect;

private final Assumption trueUnmodifiedAssumption;
private final RubyMethod trueMethod;
private final BranchProfile trueProfile = new BranchProfile();

private final Object trueValue;
@Child protected DirectCallNode trueCall;
@Child protected DirectCallNode trueCallDirect;

@Child protected IndirectCallNode indirectCallNode;

public CachedBooleanDispatchNode(
RubyContext context, Object cachedName, DispatchNode next,
Assumption falseUnmodifiedAssumption, Object falseValue, RubyMethod falseMethod,
Assumption trueUnmodifiedAssumption, Object trueValue, RubyMethod trueMethod) {
super(context, cachedName, next);
Assumption trueUnmodifiedAssumption, Object trueValue, RubyMethod trueMethod,
boolean indirect) {
super(context, cachedName, next, indirect);

this.falseUnmodifiedAssumption = falseUnmodifiedAssumption;
this.falseMethod = falseMethod;
this.falseValue = falseValue;

if (falseMethod != null) {
falseCall = Truffle.getRuntime().createDirectCallNode(falseMethod.getCallTarget());
if (!indirect) {
falseCallDirect = Truffle.getRuntime().createDirectCallNode(falseMethod.getCallTarget());

if (falseCall.isSplittable() && falseMethod.getSharedMethodInfo().shouldAlwaysSplit()) {
insert(falseCall);
falseCall.split();
if (falseCallDirect.isSplittable() && falseMethod.getSharedMethodInfo().shouldAlwaysSplit()) {
insert(falseCallDirect);
falseCallDirect.split();
}
}
}

@@ -66,25 +72,32 @@ public CachedBooleanDispatchNode(
this.trueValue = trueValue;

if (trueMethod != null) {
trueCall = Truffle.getRuntime().createDirectCallNode(trueMethod.getCallTarget());
if (!indirect) {
trueCallDirect = Truffle.getRuntime().createDirectCallNode(trueMethod.getCallTarget());

if (trueCall.isSplittable() && trueMethod.getSharedMethodInfo().shouldAlwaysSplit()) {
insert(trueCall);
trueCall.split();
if (trueCallDirect.isSplittable() && trueMethod.getSharedMethodInfo().shouldAlwaysSplit()) {
insert(trueCallDirect);
trueCallDirect.split();
}
}
}

if (indirect) {
indirectCallNode = Truffle.getRuntime().createIndirectCallNode();
}
}

public CachedBooleanDispatchNode(CachedBooleanDispatchNode prev) {
super(prev);
falseUnmodifiedAssumption = prev.falseUnmodifiedAssumption;
falseMethod = prev.falseMethod;
falseValue = prev.falseValue;
falseCall = prev.falseCall;
falseCallDirect = prev.falseCallDirect;
trueUnmodifiedAssumption = prev.trueUnmodifiedAssumption;
trueValue = prev.trueValue;
trueMethod = prev.trueMethod;
trueCall = prev.trueCall;
trueCallDirect = prev.trueCallDirect;
indirectCallNode = prev.indirectCallNode;
}

@Specialization(guards = "guardName")
@@ -118,14 +131,26 @@ public Object dispatch(
}

if (dispatchAction == Dispatch.DispatchAction.CALL_METHOD) {
return trueCall.call(
frame,
RubyArguments.pack(
trueMethod,
trueMethod.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
if (isIndirect()) {
return indirectCallNode.call(
frame,
trueMethod.getCallTarget(),
RubyArguments.pack(
trueMethod,
trueMethod.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
} else {
return trueCallDirect.call(
frame,
RubyArguments.pack(
trueMethod,
trueMethod.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
}
} else if (dispatchAction == Dispatch.DispatchAction.RESPOND_TO_METHOD) {
return true;
} else if (dispatchAction == Dispatch.DispatchAction.READ_CONSTANT) {
@@ -152,14 +177,26 @@ public Object dispatch(
}

if (dispatchAction == Dispatch.DispatchAction.CALL_METHOD) {
return falseCall.call(
frame,
RubyArguments.pack(
falseMethod,
falseMethod.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
if (isIndirect()) {
return indirectCallNode.call(
frame,
falseMethod.getCallTarget(),
RubyArguments.pack(
falseMethod,
falseMethod.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
} else {
return falseCallDirect.call(
frame,
RubyArguments.pack(
falseMethod,
falseMethod.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
}
} else if (dispatchAction == Dispatch.DispatchAction.RESPOND_TO_METHOD) {
return true;
} else if (dispatchAction == Dispatch.DispatchAction.READ_CONSTANT) {
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;
import org.jruby.truffle.runtime.DebugOperations;
import org.jruby.truffle.runtime.LexicalScope;
@@ -37,19 +38,21 @@ public abstract class CachedBoxedDispatchNode extends CachedDispatchNode {

private final RubyMethod method;
@Child protected DirectCallNode callNode;
@Child protected IndirectCallNode indirectCallNode;

public CachedBoxedDispatchNode(RubyContext context, Object cachedName, DispatchNode next,
RubyClass expectedClass, Object value, RubyMethod method) {
this(context, cachedName, next, expectedClass, expectedClass.getUnmodifiedAssumption(), value, method);
RubyClass expectedClass, Object value, RubyMethod method,
boolean indirect) {
this(context, cachedName, next, expectedClass, expectedClass.getUnmodifiedAssumption(), value, method, indirect);
}

/**
* Allows to give the assumption, which is different than the expectedClass assumption for constant lookup.
*/
public CachedBoxedDispatchNode(RubyContext context, Object cachedName, DispatchNode next,
RubyClass expectedClass, Assumption unmodifiedAssumption,
Object value, RubyMethod method) {
super(context, cachedName, next);
Object value, RubyMethod method, boolean indirect) {
super(context, cachedName, next, indirect);

this.expectedClass = expectedClass;
this.unmodifiedAssumption = unmodifiedAssumption;
@@ -58,11 +61,15 @@ public CachedBoxedDispatchNode(RubyContext context, Object cachedName, DispatchN
this.method = method;

if (method != null) {
callNode = Truffle.getRuntime().createDirectCallNode(method.getCallTarget());

if (callNode.isSplittable() && method.getSharedMethodInfo().shouldAlwaysSplit()) {
insert(callNode);
callNode.split();
if (indirect) {
indirectCallNode = Truffle.getRuntime().createIndirectCallNode();
} else {
callNode = Truffle.getRuntime().createDirectCallNode(method.getCallTarget());

if (callNode.isSplittable() && method.getSharedMethodInfo().shouldAlwaysSplit()) {
insert(callNode);
callNode.split();
}
}
}
}
@@ -74,6 +81,7 @@ public CachedBoxedDispatchNode(CachedBoxedDispatchNode prev) {
value = prev.value;
method = prev.method;
callNode = prev.callNode;
indirectCallNode = prev.indirectCallNode;
}

@Specialization(guards = "guardName")
@@ -120,14 +128,26 @@ public Object dispatch(
}

if (dispatchAction == Dispatch.DispatchAction.CALL_METHOD) {
return callNode.call(
frame,
RubyArguments.pack(
method,
method.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
if (isIndirect()) {
return indirectCallNode.call(
frame,
method.getCallTarget(),
RubyArguments.pack(
method,
method.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
} else {
return callNode.call(
frame,
RubyArguments.pack(
method,
method.getDeclarationFrame(),
receiverObject,
CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
}
} else if (dispatchAction == Dispatch.DispatchAction.RESPOND_TO_METHOD) {
return true;
} else if (dispatchAction == Dispatch.DispatchAction.READ_CONSTANT) {
Loading