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

refactor Missing to not use the generic inline cache node

parent ef439641
Branches
No related tags found
No related merge requests found
......@@ -24,20 +24,18 @@ package com.oracle.truffle.r.nodes.builtin.base;
import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE;
import java.util.function.BiFunction;
import java.util.function.Function;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.nodes.InlineCacheNode;
import com.oracle.truffle.r.nodes.access.ConstantNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.base.MissingNodeGen.MissingCheckCacheNodeGen;
import com.oracle.truffle.r.nodes.function.GetMissingValueNode;
import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
import com.oracle.truffle.r.nodes.function.RMissingHelper;
......@@ -51,27 +49,43 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
@RBuiltin(name = "missing", kind = PRIMITIVE, parameterNames = {"x"}, nonEvalArgs = 0)
public abstract class Missing extends RBuiltinNode {
@Child private InlineCacheNode repCache;
public abstract static class MissingCheckCache extends Node {
private final ConditionProfile isSymbolNullProfile = ConditionProfile.createBinaryProfile();
protected static final int CACHE_LIMIT = 3;
private static InlineCacheNode createRepCache(int level) {
Function<String, RNode> reify = symbol -> createNodeForRep(symbol, level);
BiFunction<Frame, String, Object> generic = (frame, symbol) -> RRuntime.asLogical(RMissingHelper.isMissingArgument(frame, symbol));
return InlineCacheNode.createCache(3, reify, generic);
}
private final int level;
protected MissingCheckCache(int level) {
this.level = level;
}
public static MissingCheckCache create(int level) {
return MissingCheckCacheNodeGen.create(level);
}
public abstract boolean execute(Frame frame, String symbol);
protected MissingCheckLevel createNodeForRep(String symbol) {
return new MissingCheckLevel(symbol, level);
}
private static RNode createNodeForRep(String symbol, int level) {
if (symbol == null) {
return ConstantNode.create(RRuntime.LOGICAL_FALSE);
@Specialization(limit = "CACHE_LIMIT", guards = "cachedSymbol == symbol")
public static boolean checkCached(Frame frame, @SuppressWarnings("unused") String symbol, //
@SuppressWarnings("unused") @Cached("symbol") String cachedSymbol, //
@Cached("createNodeForRep(symbol)") MissingCheckLevel node) {
return node.execute(frame);
}
@Specialization(contains = "checkCached")
public static boolean check(Frame frame, String symbol) {
return RMissingHelper.isMissingArgument(frame, symbol);
}
return new MissingCheckLevel(symbol, level);
}
private static class MissingCheckLevel extends RNode {
protected static class MissingCheckLevel extends Node {
@Child private GetMissingValueNode getMissingValue;
@Child private InlineCacheNode recursive;
@Child private MissingCheckCache recursive;
@Child private PromiseHelperNode promiseHelper;
@CompilationFinal private FrameDescriptor recursiveDesc;
......@@ -87,18 +101,17 @@ public abstract class Missing extends RBuiltinNode {
this.getMissingValue = GetMissingValueNode.create(symbol);
}
@Override
public Object execute(VirtualFrame frame) {
public boolean execute(Frame frame) {
// Read symbols value directly
Object value = getMissingValue.execute(frame);
if (isNullProfile.profile(value == null)) {
// In case we are not able to read the symbol in current frame: This is not an
// argument and thus return false
return RRuntime.LOGICAL_FALSE;
return false;
}
if (isMissingProfile.profile(RMissingHelper.isMissing(value))) {
return RRuntime.LOGICAL_TRUE;
return true;
}
// This might be a promise...
......@@ -110,30 +123,30 @@ public abstract class Missing extends RBuiltinNode {
recursiveDesc = !promise.isEvaluated() && promise.getFrame() != null ? promise.getFrame().getFrameDescriptor() : null;
}
if (level == 0 && promiseHelper.isDefaultArgument(promise)) {
return RRuntime.LOGICAL_TRUE;
return true;
}
if (promiseHelper.isEvaluated(promise)) {
if (level > 0) {
return RRuntime.LOGICAL_FALSE;
return false;
}
} else {
// Check: If there is a cycle, return true. (This is done like in GNU R)
if (promiseHelper.isUnderEvaluation(promise)) {
return RRuntime.LOGICAL_TRUE;
return true;
}
}
String symbol = RMissingHelper.unwrapName((RNode) promise.getRep());
if (isSymbolNullProfile.profile(symbol == null)) {
return RRuntime.LOGICAL_FALSE;
return false;
} else {
if (recursiveDesc != null) {
promiseHelper.materialize(promise); // Ensure that promise holds a frame
}
if (recursiveDesc == null || recursiveDesc != promise.getFrame().getFrameDescriptor()) {
if (promiseHelper.isEvaluated(promise)) {
return RRuntime.LOGICAL_FALSE;
return false;
} else {
return RRuntime.asLogical(RMissingHelper.isMissingName(promise));
return RMissingHelper.isMissingName(promise);
}
} else {
if (recursiveDesc == null) {
......@@ -144,7 +157,7 @@ public abstract class Missing extends RBuiltinNode {
promise.setState(PromiseState.UnderEvaluation);
if (recursive == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
recursive = insert(createRepCache(level + 1));
recursive = insert(MissingCheckCache.create(level + 1));
}
return recursive.execute(promise.getFrame(), symbol);
} finally {
......@@ -153,18 +166,16 @@ public abstract class Missing extends RBuiltinNode {
}
}
}
return RRuntime.LOGICAL_FALSE;
return false;
}
}
@Specialization
protected byte missing(VirtualFrame frame, RPromise promise) {
if (repCache == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
repCache = insert(createRepCache(0));
}
protected byte missing(VirtualFrame frame, RPromise promise, //
@Cached("create(0)") MissingCheckCache cache, //
@Cached("createBinaryProfile()") ConditionProfile isNullSymbol) {
String symbol = RMissingHelper.unwrapName((RNode) promise.getRep());
return isSymbolNullProfile.profile(symbol == null) ? RRuntime.LOGICAL_FALSE : (byte) repCache.execute(frame, symbol);
return RRuntime.asLogical(isNullSymbol.profile(symbol == null) ? false : cache.execute(frame, symbol));
}
@Specialization
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment