diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java index 2d1259aef13953bb8228849bb260462a68d0ccc5..8f577b5e6ecba01b82b38d0b25895b0dc1f17976 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java @@ -39,7 +39,6 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."}) -// TODO define alias in R public abstract class AsDouble extends RBuiltinNode { @Child private CastDoubleNode castDoubleNode; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java index bbecfeff67beae84e463616580632205d8616725..dc7f08b5a6b1d9c739d075192346568b16b2ccff 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java @@ -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 diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java index 3ee3407d913bb8b50740ce2c3ed1f473af9be59e..8d8c040afce1aafde176e50acc39673a9ba32e3c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java @@ -14,18 +14,20 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RBuiltinKind.SUBSTITUTE; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode; +import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNodeGen; +import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; +import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; +import com.oracle.truffle.r.nodes.attributes.PutAttributeNodeGen; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -39,6 +41,12 @@ public abstract class Transpose extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final BranchProfile hasDimNamesProfile = BranchProfile.create(); + private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile(); + + @Child private CopyOfRegAttributesNode copyRegAttributes = CopyOfRegAttributesNodeGen.create(); + @Child private InitAttributesNode initAttributes = InitAttributesNode.create(); + @Child private PutAttributeNode putDimensions = PutAttributeNodeGen.createDim(); + @Child private PutAttributeNode putDimNames = PutAttributeNodeGen.createDimNames(); public abstract Object execute(Object o); @@ -63,100 +71,96 @@ public abstract class Transpose extends RBuiltinNode { } @Specialization(guards = "isEmpty2D(vector)") - @TruffleBoundary protected RAbstractVector transpose(RAbstractVector vector) { int[] dim = vector.getDimensions(); return vector.copyWithNewDimensions(new int[]{dim[1], dim[0]}); } - @Specialization(guards = "!isEmpty2D(vector)") - @TruffleBoundary - protected RIntVector transpose(RAbstractIntVector vector) { - return performAbstractIntVector(vector, vector.isMatrix() ? vector.getDimensions() : new int[]{vector.getLength(), 1}); + @FunctionalInterface + private interface InnerLoop<T extends RAbstractVector> { + RVector apply(T vector, int firstDim); } - private RIntVector performAbstractIntVector(RAbstractIntVector vector, int[] dim) { - int firstDim = dim[0]; // rows - int secondDim = dim[1]; + protected <T extends RAbstractVector> RVector transposeInternal(T vector, InnerLoop<T> innerLoop) { + int firstDim; + int secondDim; + if (isMatrixProfile.profile(vector.isMatrix())) { + firstDim = vector.getDimensions()[0]; + secondDim = vector.getDimensions()[1]; + } else { + firstDim = vector.getLength(); + secondDim = 1; + } + RNode.reportWork(this, vector.getLength()); + + RVector r = innerLoop.apply(vector, firstDim); + // copy attributes + copyRegAttributes.execute(vector, r); + // set new dimensions + int[] newDim = new int[]{secondDim, firstDim}; + r.setInternalDimensions(newDim); + putDimensions.execute(initAttributes.execute(r), RDataFactory.createIntVector(newDim, RDataFactory.COMPLETE_VECTOR)); + // set new dim names + RList dimNames = vector.getDimNames(attrProfiles); + if (dimNames != null) { + hasDimNamesProfile.enter(); + assert dimNames.getLength() == 2; + RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)}); + r.setInternalDimNames(newDimNames); + putDimNames.execute(r.getAttributes(), newDimNames); + } + return r; + } + + private static RVector innerLoopInt(RAbstractIntVector vector, int firstDim) { int[] result = new int[vector.getLength()]; int j = 0; - - RNode.reportWork(this, vector.getLength()); for (int i = 0; i < result.length; i++, j += firstDim) { if (j > (result.length - 1)) { j -= (result.length - 1); } result[i] = vector.getDataAt(j); } - int[] newDim = new int[]{secondDim, firstDim}; - RIntVector r = RDataFactory.createIntVector(result, vector.isComplete()); - r.copyAttributesFrom(attrProfiles, vector); - r.setDimensions(newDim); - setDimNames(r, vector); - return r; + return RDataFactory.createIntVector(result, vector.isComplete()); } - @Specialization(guards = "!isEmpty2D(vector)") - @TruffleBoundary - protected RDoubleVector transpose(RAbstractDoubleVector vector) { - return performAbstractDoubleVector(vector, vector.isMatrix() ? vector.getDimensions() : new int[]{vector.getLength(), 1}); - } - - private RDoubleVector performAbstractDoubleVector(RAbstractDoubleVector vector, int[] dim) { - int firstDim = dim[0]; - int secondDim = dim[1]; + private static RVector innerLoopDouble(RAbstractDoubleVector vector, int firstDim) { double[] result = new double[vector.getLength()]; int j = 0; - - RNode.reportWork(this, vector.getLength()); for (int i = 0; i < result.length; i++, j += firstDim) { if (j > (result.length - 1)) { j -= (result.length - 1); } result[i] = vector.getDataAt(j); } - int[] newDim = new int[]{secondDim, firstDim}; - RDoubleVector r = RDataFactory.createDoubleVector(result, vector.isComplete()); - r.copyAttributesFrom(attrProfiles, vector); - r.setDimensions(newDim); - setDimNames(r, vector); - return r; - } - - @Specialization(guards = "!isEmpty2D(vector)") - @TruffleBoundary - protected RStringVector transpose(RAbstractStringVector vector) { - return performAbstractStringVector(vector, vector.isMatrix() ? vector.getDimensions() : new int[]{vector.getLength(), 1}); + return RDataFactory.createDoubleVector(result, vector.isComplete()); } - private RStringVector performAbstractStringVector(RAbstractStringVector vector, int[] dim) { - int firstDim = dim[0]; - int secondDim = dim[1]; + private static RVector innerLoopString(RAbstractStringVector vector, int firstDim) { String[] result = new String[vector.getLength()]; int j = 0; - - RNode.reportWork(this, vector.getLength()); for (int i = 0; i < result.length; i++, j += firstDim) { if (j > (result.length - 1)) { j -= (result.length - 1); } result[i] = vector.getDataAt(j); } - int[] newDim = new int[]{secondDim, firstDim}; - RStringVector r = RDataFactory.createStringVector(result, vector.isComplete()); - r.copyAttributesFrom(attrProfiles, vector); - r.setDimensions(newDim); - setDimNames(r, vector); - return r; + return RDataFactory.createStringVector(result, vector.isComplete()); } - private void setDimNames(RVector newVector, RAbstractVector oldVector) { - RList dimNames = oldVector.getDimNames(attrProfiles); - if (dimNames != null) { - hasDimNamesProfile.enter(); - assert dimNames.getLength() == 2; - newVector.setDimNames(RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)})); - } + @Specialization(guards = "!isEmpty2D(vector)") + protected RVector transpose(RAbstractIntVector vector) { + return transposeInternal(vector, Transpose::innerLoopInt); + } + + @Specialization(guards = "!isEmpty2D(vector)") + protected RVector transpose(RAbstractDoubleVector vector) { + return transposeInternal(vector, Transpose::innerLoopDouble); + } + + @Specialization(guards = "!isEmpty2D(vector)") + protected RVector transpose(RAbstractStringVector vector) { + return transposeInternal(vector, Transpose::innerLoopString); } protected static boolean isEmpty2D(RAbstractVector vector) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java index 08725a78035513e5e75de37be68dae9a527edc79..82921e78731444b752b7bd5743d4d549345376a4 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java @@ -118,8 +118,15 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { @Override protected RSyntaxNode visit(RSyntaxFunction element) { + String assignedFrom = null; + if (element instanceof FunctionExpressionNode) { + FunctionExpressionNode function = (FunctionExpressionNode) element; + if (function.getParent() instanceof WriteVariableNode) { + assignedFrom = ((WriteVariableNode) function.getParent()).getName().toString(); + } + } ArrayList<Argument<RSyntaxNode>> params = createArguments(element.getSyntaxSignature(), element.getSyntaxArgumentDefaults()); - return function(element.getSourceSection(), params, accept(element.getSyntaxBody()), null); + return function(element.getSourceSection(), params, accept(element.getSyntaxBody()), assignedFrom); } }.accept(original); } @@ -210,8 +217,10 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { return signature; } - private static String getFunctionDescription(SourceSection source, RSyntaxNode assignedTo) { - if (assignedTo instanceof RSyntaxLookup) { + private static String getFunctionDescription(SourceSection source, Object assignedTo) { + if (assignedTo instanceof String) { + return (String) assignedTo; + } else if (assignedTo instanceof RSyntaxLookup) { return ((RSyntaxLookup) assignedTo).getIdentifier(); } else { String functionBody = source.getCode(); @@ -382,7 +391,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { } @Override - public RSyntaxNode function(SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, RSyntaxNode assignedTo) { + public RSyntaxNode function(SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, Object assignedTo) { String description = getFunctionDescription(source, assignedTo); RootCallTarget callTarget = rootFunction(source, params, body, description); return FunctionExpressionNode.create(source, callTarget); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java index 831e6a87db91e4521a947a2fd01e0bd54827913b..d9b138b73d4819b1379e3579944ad9ed6c3f6fd2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java @@ -554,10 +554,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta evalPromiseSlowPathWithName(frame, (RPromise) lookup.getValue()); } if (lookup != null) { - if (lookup.getValue() == null) { - return new LookupLevel(lookup); - } - if (checkTypeSlowPath(frame, lookup.getValue())) { + if (lookup.getValue() == null || checkTypeSlowPath(frame, lookup.getValue())) { return new LookupLevel(lookup); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java index 0f8a5f888010121e101d2a298c43f0f22ac3efcf..4f1a2ccad84568f50712f5df925f673209602a78 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java @@ -52,6 +52,10 @@ public abstract class CopyAttributesNode extends RBaseNode { this.copyAllAttributes = copyAllAttributes; } + public static CopyAttributesNode createCopyAllAttributes() { + return CopyAttributesNodeGen.create(true); + } + public abstract RAbstractVector execute(RAbstractVector target, RAbstractVector left, int leftLength, RAbstractVector right, int rightLength); protected boolean containsMetadata(RAbstractVector vector, RAttributeProfiles attrProfiles) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java index 8645729bf27bc87c31bad5baa917fce21685d3ac..2d23acf57927a512e833f6c78ae86a06588a0af7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/PutAttributeNode.java @@ -55,6 +55,10 @@ public abstract class PutAttributeNode extends RBaseNode { return PutAttributeNodeGen.create(RRuntime.DIM_ATTR_KEY); } + public static PutAttributeNode createDimNames() { + return PutAttributeNodeGen.create(RRuntime.DIMNAMES_ATTR_KEY); + } + public abstract void execute(RAttributes attr, Object value); protected boolean nameMatches(RAttributes attr, int index) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java index f027b716164a47b23766b3abfbf56e57ade0c3cf..a45022312ca4653b6c161b8c0734e45354ef3108 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java @@ -24,27 +24,24 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; 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.access.WriteLocalFrameVariableNode; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.nodes.RNode; /** * A {@link ArgumentStatePush} is used to bump up state transition for function arguments. */ -@NodeChild(value = "op") -public abstract class ArgumentStatePush extends RNode { +public abstract class ArgumentStatePush extends Node { - public abstract Object executeObject(VirtualFrame frame, Object shareable); + public abstract void executeObject(VirtualFrame frame, Object shareable); private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); @@ -64,7 +61,8 @@ public abstract class ArgumentStatePush extends RNode { return mask > 0; } - private void transitionStateExp(VirtualFrame frame, RShareable shareable) { + @Specialization + public void transitionState(VirtualFrame frame, RShareable shareable) { if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) { shareable.incRefCount(); } @@ -114,14 +112,8 @@ public abstract class ArgumentStatePush extends RNode { } } - @Specialization - public RNull transitionState(VirtualFrame frame, RShareable shareable) { - transitionStateExp(frame, shareable); - return RNull.instance; - } - @Specialization(guards = "!isShareable(o)") - public RNull transitionStateNonShareable(VirtualFrame frame, @SuppressWarnings("unused") Object o) { + public void transitionStateNonShareable(VirtualFrame frame, @SuppressWarnings("unused") Object o) { if (mask > 0) { // this argument used to be reference counted but is no longer CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -133,7 +125,6 @@ public abstract class ArgumentStatePush extends RNode { fdn.getArgPostProcess().transArgsBitSet = transArgsBitSet & (~mask); mask = -1; } - return RNull.instance; } protected boolean isShareable(Object o) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java index c5fc1a9e8e732796256db437b4a8d74aa3b32f65..309d854b53d85b61c9bbadbd3b89ddadd8b54c95 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PreProcessArgumentsNode.java @@ -52,7 +52,7 @@ final class PreProcessArgumentsNode extends RNode { static PreProcessArgumentsNode create(int length) { ArgumentStatePush[] argStatePushNodes = new ArgumentStatePush[length]; for (int i = 0; i < length; i++) { - argStatePushNodes[i] = ArgumentStatePushNodeGen.create(i, null); + argStatePushNodes[i] = ArgumentStatePushNodeGen.create(i); } return new PreProcessArgumentsNode(argStatePushNodes); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java index 51f811371e9c8bf5a3ffe2bc8f0cc7cc1a070403..12bc4b29ef23ec8e9c9bcd3c9b1ab3716c431ac6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java @@ -127,7 +127,6 @@ public class PromiseHelperNode extends RBaseNode { } } - @Child private InlineCacheNode expressionInlineCache; @Child private InlineCacheNode promiseClosureCache; @Child private PromiseHelperNode nextNode = null; @@ -176,26 +175,20 @@ public class PromiseHelperNode extends RBaseNode { throw RError.error(RError.SHOW_CALLER, RError.Message.PROMISE_CYCLE); } try { + if (promiseClosureCache == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseClosureCache = insert(InlineCacheNode.createPromise(FastROptions.PromiseCacheSize.getNonNegativeIntValue())); + } if (isInOriginFrame(frame, promise)) { // state change must happen inside of conditional as isInOriginalFrame checks the // state promise.setState(PromiseState.UnderEvaluation); - if (expressionInlineCache == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - expressionInlineCache = insert(InlineCacheNode.createExpression(FastROptions.PromiseCacheSize.getNonNegativeIntValue())); - } - return expressionInlineCache.execute(frame, promise.getRep()); + return promiseClosureCache.execute(frame, promise.getClosure()); } else { promise.setState(PromiseState.UnderEvaluation); Frame promiseFrame = promiseFrameProfile.profile(promise.getFrame()); assert promiseFrame != null; - - if (promiseClosureCache == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseClosureCache = insert(InlineCacheNode.createPromise(FastROptions.PromiseCacheSize.getNonNegativeIntValue())); - } - promiseFrame = wrapPromiseFrame(frame, promiseFrame); - return promiseClosureCache.execute(promiseFrame, promise.getClosure()); + return promiseClosureCache.execute(wrapPromiseFrame(frame, promiseFrame), promise.getClosure()); } } finally { promise.setState(state); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java index c6d3ff6620beb0ee4e1d2fe9ef1ef6e7a0d82448..7ed844a144758904c56d2f9e9463f19e2c1d3673 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java @@ -50,7 +50,7 @@ public final class WrapArgumentNode extends WrapArgumentBaseNode { super(operand, modeChange); this.modeChange = modeChange; this.index = index; - this.argPushStateNode = modeChange ? ArgumentStatePushNodeGen.create(index, null) : null; + this.argPushStateNode = modeChange ? ArgumentStatePushNodeGen.create(index) : null; } public boolean modeChange() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java index 903438fdc7430a941b14ef5c90f1102f4639d2be..0d9c02ebf52ab89c5fbf33243e42107d19b7c81b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapDefaultArgumentNode.java @@ -45,22 +45,16 @@ public final class WrapDefaultArgumentNode extends WrapArgumentBaseNode { @Override public Object execute(VirtualFrame frame) { Object result = operand.execute(frame); - return execute(result); - } - - public Object execute(Object o) { - Object result = o; RShareable rShareable = getShareable(result); if (rShareable != null) { shareable.enter(); if (isShared.profile(rShareable.isShared())) { - result = ((RShareable) o).copy(); + return ((RShareable) result).copy(); } else { - ((RShareable) o).incRefCount(); + ((RShareable) result).incRefCount(); } } return result; - } public static RNode create(RNode operand) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java index 7d19a9c479e82585435958ebdba4051a6da8f45e..c616637b9d65a548a3bbbaa1c7305a4c1e277e08 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java @@ -46,6 +46,7 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.StableValue; +import com.oracle.truffle.r.runtime.data.RPromise; /** * This class maintains information about the current hierarchy of environments in the system. This @@ -84,6 +85,7 @@ public final class FrameSlotChangeMonitor { private static final class StableValueLookupResult extends LookupResult { private final StableValue<Object> value; + @CompilationFinal private Object unwrappedValue; private StableValueLookupResult(String identifier, StableValue<Object> value) { super(identifier); @@ -100,7 +102,20 @@ public final class FrameSlotChangeMonitor { assumption.check(); StableValue<Object> result = value; result.getAssumption().check(); - return result.getValue(); + if (unwrappedValue == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + Object resultValue = result.getValue(); + if (resultValue instanceof RPromise) { + if (((RPromise) resultValue).isEvaluated()) { + unwrappedValue = ((RPromise) resultValue).getValue(); + } else { + return resultValue; + } + } else { + unwrappedValue = resultValue; + } + } + return unwrappedValue; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java index dd1c9b2d6aa24ee5d21844f0044432f5f296f481..70a1f36cce9b345a234bab65335174a81b962505 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java @@ -89,7 +89,7 @@ public interface RCodeBuilder<T> { * names - if it is non-null, it represents the left hand side that this function is assigned * to. */ - T function(SourceSection source, List<Argument<T>> arguments, T body, T assignedTo); + T function(SourceSection source, List<Argument<T>> arguments, T body, Object assignedTo); /** * Creates a new call target from a given function expression literal. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java index b134d915c22729215a4a9a839cb06b9844196dc2..12918a1ed0ee2629f5a3919fd483bbc2c5dc28b7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java @@ -16,7 +16,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG.RandomNumberGenerator; public abstract class RNGInitAdapter implements RandomNumberGenerator { // TODO: it seems like GNU R this is shared between the generators (does it matter?) - protected int[] iSeed = new int[625]; + protected final int[] iSeed = new int[625]; @Override public void setISeed(int[] seeds) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java index 606bb90664f1d783f592afcafd5ecdd520929404..ddc4d8a7d864fc4e840ee814dcbaaea072e56167 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java @@ -170,18 +170,26 @@ public final class MersenneTwister extends RNGInitAdapter { RInternalError.guarantee(localMti != N + 1); int pos = 0; - while (pos < count && localMti < N) { - int y = getMt(localMti++); - /* Tempering */ - y ^= (y >>> 11); - y ^= (y << 7) & TEMPERING_MASK_B; - y ^= (y << 15) & TEMPERING_MASK_C; - y ^= (y >>> 18); - result[pos] = RRNG.fixup((y & 0xffffffffL) * RRNG.I2_32M1); - pos++; - } + while (true) { + int loopCount = Math.min(count - pos, N - localMti); + for (int i = 0; i < loopCount; i++) { + int y = getMt(localMti + i); + /* Tempering */ + y ^= (y >>> 11); + y ^= (y << 7) & TEMPERING_MASK_B; + y ^= (y << 15) & TEMPERING_MASK_C; + y ^= (y >>> 18); + result[pos + i] = ((y + Integer.MIN_VALUE) - (double) Integer.MIN_VALUE) * RRNG.I2_32M1; + } + for (int i = 0; i < loopCount; i++) { + result[pos + i] = RRNG.fixup(result[pos + i]); + } + localMti += loopCount; + pos += loopCount; - while (pos < count) { + if (pos == count) { + break; + } /* generate N words at one time */ int kk; for (kk = 0; kk < N - M; kk++) { @@ -196,17 +204,6 @@ public final class MersenneTwister extends RNGInitAdapter { setMt(N - 1, getMt(M - 1) ^ (y2y >>> 1) ^ mag01(y2y & 0x1)); localMti = 0; - - while (pos < count && localMti < N) { - int y = getMt(localMti++); - /* Tempering */ - y ^= (y >>> 11); - y ^= (y << 7) & TEMPERING_MASK_B; - y ^= (y << 15) & TEMPERING_MASK_C; - y ^= (y >>> 18); - result[pos] = RRNG.fixup((y & 0xffffffffL) * RRNG.I2_32M1); - pos++; - } } localDummy0 = localMti; mti = localMti;