Skip to content
Snippets Groups Projects
Commit 112a839d authored by Lukas Stadler's avatar Lukas Stadler
Browse files

simplify AccessArgumentNode

parent b379fa4d
Branches
No related tags found
No related merge requests found
...@@ -26,9 +26,9 @@ import static com.oracle.truffle.r.nodes.function.opt.EagerEvalHelper.*; ...@@ -26,9 +26,9 @@ import static com.oracle.truffle.r.nodes.function.opt.EagerEvalHelper.*;
import com.oracle.truffle.api.*; import com.oracle.truffle.api.*;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.*;
import com.oracle.truffle.api.utilities.*;
import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.*;
import com.oracle.truffle.r.nodes.access.variables.*; import com.oracle.truffle.r.nodes.access.variables.*;
import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.nodes.builtin.*;
...@@ -42,12 +42,13 @@ import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; ...@@ -42,12 +42,13 @@ import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
import com.oracle.truffle.r.runtime.env.*; import com.oracle.truffle.r.runtime.env.*;
/** /**
* This {@link RNode} returns a function's argument specified by its formal index ( * This {@link RNode} returns a function's argument specified by its formal index. It is used to
* {@link #getIndex()}). It is used to populate a function's new frame right after the actual * populate a function's new frame right after the actual function call and before the function's
* function call and before the function's actual body is executed. * actual body is executed.
*/ */
@NodeChild(value = "readArgNode", type = ReadArgumentNode.class) public final class AccessArgumentNode extends RNode {
public abstract class AccessArgumentNode extends RNode {
@Child private ReadArgumentNode readArgNode;
@Child private PromiseHelperNode promiseHelper; @Child private PromiseHelperNode promiseHelper;
...@@ -56,7 +57,9 @@ public abstract class AccessArgumentNode extends RNode { ...@@ -56,7 +57,9 @@ public abstract class AccessArgumentNode extends RNode {
*/ */
private final int index; private final int index;
public abstract ReadArgumentNode getReadArgNode(); public ReadArgumentNode getReadArgNode() {
return readArgNode;
}
/** /**
* Used to cache {@link RPromise} evaluations. * Used to cache {@link RPromise} evaluations.
...@@ -68,23 +71,22 @@ public abstract class AccessArgumentNode extends RNode { ...@@ -68,23 +71,22 @@ public abstract class AccessArgumentNode extends RNode {
@CompilationFinal private boolean deoptimized; @CompilationFinal private boolean deoptimized;
@CompilationFinal private boolean defaultArgCanBeOptimized = EagerEvalHelper.optConsts() || EagerEvalHelper.optDefault() || EagerEvalHelper.optExprs(); @CompilationFinal private boolean defaultArgCanBeOptimized = EagerEvalHelper.optConsts() || EagerEvalHelper.optDefault() || EagerEvalHelper.optExprs();
private final ConditionProfile isMissingProfile = ConditionProfile.createBinaryProfile();
protected AccessArgumentNode(int index) { protected AccessArgumentNode(int index) {
this.index = index; this.index = index;
this.readArgNode = new ReadArgumentNode(index);
} }
public void setFormals(FormalArguments formals) { public void setFormals(FormalArguments formals) {
CompilerAsserts.neverPartOfCompilation(); CompilerAsserts.neverPartOfCompilation();
assert this.formals == null; assert this.formals == null;
this.formals = formals; this.formals = formals;
hasDefaultArg = formals.hasDefaultArgumentAt(getIndex()); hasDefaultArg = formals.hasDefaultArgumentAt(index);
} }
/**
* @param index {@link #getIndex()}
* @return A fresh {@link AccessArgumentNode} for the given index
*/
public static AccessArgumentNode create(int index) { public static AccessArgumentNode create(int index) {
return AccessArgumentNodeGen.create(index, new ReadArgumentNode(index)); return new AccessArgumentNode(index);
} }
@Override @Override
...@@ -92,34 +94,44 @@ public abstract class AccessArgumentNode extends RNode { ...@@ -92,34 +94,44 @@ public abstract class AccessArgumentNode extends RNode {
return this; return this;
} }
@Specialization(guards = {"hasDefaultArg()"}) @Override
protected Object doArgumentDefaultArg(VirtualFrame frame, @SuppressWarnings("unused") RMissing argMissing) { public Object execute(VirtualFrame frame) {
assert !(getRootNode() instanceof RBuiltinRootNode) : getRootNode(); return doArgument(frame, readArgNode.execute(frame));
Object result; }
if (canBeOptimized()) {
@Override
public NodeCost getCost() {
return hasDefaultArg ? NodeCost.MONOMORPHIC : NodeCost.NONE;
}
protected Object doArgument(VirtualFrame frame, Object arg) {
if (hasDefaultArg && isMissingProfile.profile(arg == RMissing.instance)) {
assert !(getRootNode() instanceof RBuiltinRootNode) : getRootNode();
// Insert default value // Insert default value
checkPromiseFactory(); checkPromiseFactory();
if (checkInsertOptDefaultArg()) { Object result;
result = optDefaultArgNode.execute(frame); if (canBeOptimized()) {
// Update RArguments for S3 dispatch to work if (checkInsertOptDefaultArg()) {
RArguments.setArgument(frame, index, result); result = optDefaultArgNode.execute(frame);
return result; // Update RArguments for S3 dispatch to work
} else { RArguments.setArgument(frame, index, result);
// Default arg cannot be optimized: Rewrite to default and assure that we don't take return result;
// this path again } else {
CompilerDirectives.transferToInterpreterAndInvalidate(); /*
defaultArgCanBeOptimized = false; * Default arg cannot be optimized: Rewrite to default and assure that we don't
* take this path again
*/
CompilerDirectives.transferToInterpreterAndInvalidate();
defaultArgCanBeOptimized = false;
}
} }
// Insert default value
result = factory.createPromise(frame.materialize());
// Update RArguments for S3 dispatch to work
RArguments.setArgument(frame, index, result);
return result;
} }
// Insert default value return arg;
checkPromiseFactory();
result = factory.createPromise(frame.materialize());
RArguments.setArgument(frame, index, result); // Update RArguments for S3 dispatch to work
return result;
}
protected boolean hasDefaultArg() {
return hasDefaultArg;
} }
private boolean canBeOptimized() { private boolean canBeOptimized() {
...@@ -129,14 +141,14 @@ public abstract class AccessArgumentNode extends RNode { ...@@ -129,14 +141,14 @@ public abstract class AccessArgumentNode extends RNode {
private void checkPromiseFactory() { private void checkPromiseFactory() {
if (factory == null) { if (factory == null) {
CompilerDirectives.transferToInterpreterAndInvalidate(); CompilerDirectives.transferToInterpreterAndInvalidate();
Closure defaultClosure = formals.getOrCreateClosure(formals.getDefaultArgumentAt(getIndex())); Closure defaultClosure = formals.getOrCreateClosure(formals.getDefaultArgumentAt(index));
factory = RPromiseFactory.create(PromiseType.ARG_DEFAULT, defaultClosure); factory = RPromiseFactory.create(PromiseType.ARG_DEFAULT, defaultClosure);
} }
} }
private boolean checkInsertOptDefaultArg() { private boolean checkInsertOptDefaultArg() {
if (optDefaultArgNode == null) { if (optDefaultArgNode == null) {
RNode defaultArg = formals.getDefaultArgumentAt(getIndex()); RNode defaultArg = formals.getDefaultArgumentAt(index);
RNode arg = EagerEvalHelper.unfold(defaultArg); RNode arg = EagerEvalHelper.unfold(defaultArg);
CompilerDirectives.transferToInterpreterAndInvalidate(); CompilerDirectives.transferToInterpreterAndInvalidate();
...@@ -157,15 +169,6 @@ public abstract class AccessArgumentNode extends RNode { ...@@ -157,15 +169,6 @@ public abstract class AccessArgumentNode extends RNode {
return true; return true;
} }
@Fallback
protected Object doArgument(Object obj) {
return obj;
}
public int getIndex() {
return index;
}
protected final class OptVariableDefaultPromiseNode extends OptVariablePromiseBaseNode { protected final class OptVariableDefaultPromiseNode extends OptVariablePromiseBaseNode {
public OptVariableDefaultPromiseNode(RPromiseFactory factory, ReadVariableNode rvn) { public OptVariableDefaultPromiseNode(RPromiseFactory factory, ReadVariableNode rvn) {
...@@ -187,12 +190,12 @@ public abstract class AccessArgumentNode extends RNode { ...@@ -187,12 +190,12 @@ public abstract class AccessArgumentNode extends RNode {
protected Object rewriteToAndExecuteFallback(VirtualFrame frame) { protected Object rewriteToAndExecuteFallback(VirtualFrame frame) {
CompilerDirectives.transferToInterpreterAndInvalidate(); CompilerDirectives.transferToInterpreterAndInvalidate();
deoptimized = true; deoptimized = true;
return doArgumentDefaultArg(frame, RMissing.instance); return doArgument(frame, RMissing.instance);
} }
@Override @Override
protected Object executeFallback(VirtualFrame frame) { protected Object executeFallback(VirtualFrame frame) {
return doArgumentDefaultArg(frame, RMissing.instance); return doArgument(frame, RMissing.instance);
} }
@Override @Override
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment