diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index 5a101e6fdb9b732c4b04290468ad6523d956c214..a26281bc3111e1881a84dd7064563cbc3209d5e8 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.RContext.ConsoleHandler; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RPromise.Closure; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; import com.oracle.truffle.r.runtime.env.*; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; import com.oracle.truffle.r.runtime.ffi.*; @@ -427,8 +428,6 @@ public final class REngine implements RContext.Engine { return result; } - private static boolean traceMakeCallTarget; - /** * Wraps the Truffle AST in {@code node} in an anonymous function and returns a * {@link RootCallTarget} for it. We define the @@ -454,32 +453,12 @@ public final class REngine implements RContext.Engine { */ @SlowPath private static RootCallTarget doMakeCallTarget(RNode body, String funName) { - if (traceMakeCallTarget) { - doTraceMakeCallTarget(body); - } REnvironment.FunctionDefinition rootNodeEnvironment = new REnvironment.FunctionDefinition(REnvironment.emptyEnv()); FunctionDefinitionNode rootNode = new FunctionDefinitionNode(null, rootNodeEnvironment, body, FormalArguments.NO_ARGS, funName, true, true); RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); return callTarget; } - private static void doTraceMakeCallTarget(RNode body) { - String nodeClassName = body.getClass().getSimpleName(); - SourceSection ss = body.getSourceSection(); - String trace; - if (ss == null) { - if (body instanceof ConstantNode) { - trace = ((ConstantNode) body).getValue().toString(); - } else { - trace = "not constant/no source"; - } - } else { - trace = ss.toString(); - } - RContext.getInstance().getConsoleHandler().printf("makeCallTarget: node: %s, %s%n", nodeClassName, trace); - - } - /** * Execute {@code callTarget} in {@code frame}, optionally printing any result. N.B. * {@code callTarget.call} will create a new {@link VirtualFrame} called, say, {@code newFrame}, @@ -513,11 +492,13 @@ public final class REngine implements RContext.Engine { return result; } + private static final PromiseProfile globalPromiseProfile = new PromiseProfile(); + @SlowPath private static void printResult(Object result) { if (RContext.isVisible()) { // TODO cache this - Object resultValue = RPromise.checkEvaluate(null, result); + Object resultValue = RPromise.checkEvaluate(null, result, globalPromiseProfile); RFunction function = (RFunction) REnvironment.baseEnv().get("print"); function.getTarget().call(RArguments.create(function, null, new Object[]{resultValue, RMissing.instance})); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java index 12577371ac97a73c7036aa0f0ed059c3f8ae801f..2afa5567910fcc655244c33a4f46d53ea5965eb3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java @@ -33,6 +33,7 @@ import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.env.*; @@ -42,6 +43,8 @@ public abstract class DoCall extends RBuiltinNode { @Child private IndirectCallNode funCall = Truffle.getRuntime().createIndirectCallNode(); @Child private Get getNode; + private final PromiseProfile promiseProfile = new PromiseProfile(); + @Specialization(guards = "lengthOne") protected Object doDoCall(VirtualFrame frame, RAbstractStringVector fname, RList argsAsList, @SuppressWarnings("unused") REnvironment env) { RFunction func = RContext.getEngine().lookupBuiltin(fname.getDataAt(0)); @@ -56,7 +59,7 @@ public abstract class DoCall extends RBuiltinNode { Object n = argsAsList.getNames(); String[] argNames = n == RNull.instance ? null : ((RStringVector) n).getDataNonShared(); EvaluatedArguments evaledArgs = EvaluatedArguments.create(argValues, argNames); - EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(frame, func, evaledArgs, getEncapsulatingSourceSection()); + EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(frame, func, evaledArgs, getEncapsulatingSourceSection(), promiseProfile); Object[] callArgs = RArguments.create(func, funCall.getSourceSection(), reorderedArgs.getEvaluatedArgs(), reorderedArgs.getNames()); return funCall.call(frame, func.getTarget(), callArgs); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Force.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Force.java index 1f0079d04a44f69ae5d6d52d2dde6a34f223ebe7..a0d5e615c8a1bf6fe85f2b1f0db1521b0727b309 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Force.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Force.java @@ -30,16 +30,19 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; @RBuiltin(name = "force", kind = SUBSTITUTE, parameterNames = {"x"}) // TODO revert to R (promises) public abstract class Force extends RBuiltinNode { + private final PromiseProfile promiseProfile = new PromiseProfile(); + @Specialization protected Object force(VirtualFrame frame, Object arg) { if (arg instanceof RPromise) { RPromise promise = (RPromise) arg; - if (promise.isEvaluated()) { + if (promise.isEvaluated(promiseProfile)) { return promise.getValue(); } else { SourceSection callSrc = RArguments.getCallSourceSection(frame); 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 c47ada011af6093e43895b5587e17d7318b25653..2f4c7d542d9a5a2c186edf50127c0cf2cf607359 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 @@ -32,10 +32,13 @@ import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; @RBuiltin(name = "missing", kind = PRIMITIVE, parameterNames = {"x"}, nonEvalArgs = {0}) public abstract class Missing extends RBuiltinNode { + private final PromiseProfile promiseProfile = new PromiseProfile(); + @Specialization protected byte missing(VirtualFrame frame, RPromise promise) { controlVisibility(); @@ -54,13 +57,13 @@ public abstract class Missing extends RBuiltinNode { return RRuntime.asLogical(false); } - return RRuntime.asLogical(RMissingHelper.isMissing(obj)); + return RRuntime.asLogical(RMissingHelper.isMissing(obj, promiseProfile)); } @Specialization(guards = "!isPromise") protected byte missing(Object obj) { controlVisibility(); - return RRuntime.asLogical(RMissingHelper.isMissing(obj)); + return RRuntime.asLogical(RMissingHelper.isMissing(obj, promiseProfile)); } public boolean isPromise(Object obj) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java index 8dd8ca1aeb9f32f837d2789e68373a92627e1e9f..20b5681ace7487e18a22d2a1ea854a2d44f7cbba 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java @@ -35,6 +35,7 @@ import com.oracle.truffle.r.nodes.access.FrameSlotNode.InternalFrameSlot; import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; import com.oracle.truffle.r.runtime.ops.na.*; /** @@ -52,6 +53,8 @@ public abstract class OnExit extends RInvisibleBuiltinNode { private final ConditionProfile emptyPromiseProfile = ConditionProfile.createBinaryProfile(); private final NAProfile na = NAProfile.create(); + private final PromiseProfile promiseProfile = new PromiseProfile(); + @Override public RNode[] getParameterValues() { return new RNode[]{ConstantNode.create(RNull.instance), ConstantNode.create(false)}; @@ -66,10 +69,10 @@ public abstract class OnExit extends RInvisibleBuiltinNode { } // the empty (RNull.instance) expression is used to clear on.exit - boolean empty = emptyPromiseProfile.profile(expr.isDefaulted()); + boolean empty = emptyPromiseProfile.profile(expr.isDefault(promiseProfile)); assert !empty || expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise"; - assert empty || !expr.isEvaluated() : "promise cannot already be evaluated"; + assert empty || !expr.isEvaluated(promiseProfile) : "promise cannot already be evaluated"; ArrayList<Object> current; FrameSlot slot = onExitSlot.executeFrameSlot(frame); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TryFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TryFunctions.java index 80272716af56a0c1e857f876ee5bcd3b92dc999d..4bc79b72ac0a5ff84f146599adc898f24f0bde0e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TryFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TryFunctions.java @@ -31,6 +31,7 @@ import com.oracle.truffle.r.nodes.expressions.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; /** * Temporary substitutions that just evaluate the expression for package loading and assume no @@ -42,6 +43,8 @@ public class TryFunctions { @Child private ExpressionExecutorNode exprExecNode = ExpressionExecutorNode.create(); + private final PromiseProfile promiseProfile = new PromiseProfile(); + @Override public RNode[] getParameterValues() { return new RNode[]{ConstantNode.create(RMissing.instance), ConstantNode.create(RRuntime.LOGICAL_FALSE)}; @@ -50,7 +53,7 @@ public class TryFunctions { @Specialization protected Object doTry(VirtualFrame frame, RPromise expr, @SuppressWarnings("unused") byte silent) { controlVisibility(); - return PromiseHelper.evaluate(frame, exprExecNode, expr); + return PromiseHelper.evaluate(frame, exprExecNode, expr, promiseProfile); } } @@ -60,6 +63,8 @@ public class TryFunctions { @Child private ExpressionExecutorNode exprExecNode = ExpressionExecutorNode.create(); + private final PromiseProfile promiseProfile = new PromiseProfile(); + @Override public RNode[] getParameterValues() { return new RNode[]{ConstantNode.create(RMissing.instance), ConstantNode.create(EMPTY_OBJECT_ARRAY)}; @@ -74,7 +79,7 @@ public class TryFunctions { @Specialization protected Object doTryCatch(VirtualFrame frame, RPromise expr, Object[] args) { controlVisibility(); - return PromiseHelper.evaluate(frame, exprExecNode, expr); + return PromiseHelper.evaluate(frame, exprExecNode, expr, promiseProfile); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java index ea8de547b96b899e5f470184884dc308a8576495..dc2afb7fbf7a5cce07af04b5024a4947ccebcc3e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java @@ -22,6 +22,7 @@ import com.oracle.truffle.r.nodes.control.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; @RBuiltin(name = "UseMethod", kind = PRIMITIVE, parameterNames = {"generic", "object"}) public abstract class UseMethod extends RBuiltinNode { @@ -54,6 +55,8 @@ public abstract class UseMethod extends RBuiltinNode { @Child protected ClassHierarchyNode classHierarchyNode = ClassHierarchyNodeFactory.create(null); protected final String[] suppliedArgsNames; + private final PromiseProfile promiseProfile = new PromiseProfile(); + public UseMethodNode(String[] suppliedArgsNames) { this.suppliedArgsNames = suppliedArgsNames; } @@ -79,7 +82,7 @@ public abstract class UseMethod extends RBuiltinNode { enclosingArg = varArgs.getValues()[0]; } - enclosingArg = RPromise.checkEvaluate(frame, enclosingArg); + enclosingArg = RPromise.checkEvaluate(frame, enclosingArg, promiseProfile); return enclosingArg; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSetField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSetField.java deleted file mode 100644 index d37fc8b273845bde73d7876f10fe6b9496f4b092..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSetField.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.r.nodes.builtin.fastr; - -import java.lang.reflect.*; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.r.nodes.builtin.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.RError.Message; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.data.model.*; - -@RBuiltin(name = "fastr.setfield", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"field", "value"}) -public abstract class FastRSetField extends RInvisibleBuiltinNode { - - @Specialization - protected RNull setField(RAbstractStringVector vec, Object value) { - controlVisibility(); - String qualFieldName = vec.getDataAt(0); - int lx = qualFieldName.lastIndexOf('.'); - String simpleName = qualFieldName.substring(lx + 1); - String className = qualFieldName.substring(0, lx); - if (!className.startsWith("com")) { - className = "com.oracle.truffle.r." + className; - } - try { - Class<?> klass = Class.forName(className); - Field field = klass.getDeclaredField(simpleName); - field.setAccessible(true); - Class<?> fieldType = field.getType(); - switch (fieldType.getSimpleName()) { - case "boolean": - if (value instanceof Byte) { - field.setBoolean(null, RRuntime.fromLogical((byte) value)); - } else { - error(qualFieldName); - } - } - } catch (Exception ex) { - throw RError.error(Message.GENERIC, ex.getMessage()); - } - return RNull.instance; - } - - private static void error(String fieldName) throws RError { - throw RError.error(Message.GENERIC, "value is wrong type for %s", fieldName); - } - -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java index 86abf3a2635c2d40742801560ff628be2d09c6ed..a329deb1ce0fb75b9834e8783d35f84e4cf61145 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java @@ -31,8 +31,7 @@ import com.oracle.truffle.r.nodes.expressions.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.data.RPromise.EvalPolicy; -import com.oracle.truffle.r.runtime.data.RPromise.PromiseType; +import com.oracle.truffle.r.runtime.data.RPromise.*; import com.oracle.truffle.r.runtime.env.*; /** @@ -73,6 +72,7 @@ public abstract class AccessArgumentNode extends RNode { private final BranchProfile needsCalleeFrame = new BranchProfile(); private final BranchProfile strictEvaluation = new BranchProfile(); + private final PromiseProfile promiseProfile = new PromiseProfile(); /** * @param index {@link #getIndex()} @@ -114,23 +114,24 @@ public abstract class AccessArgumentNode extends RNode { } private Object handlePromise(VirtualFrame frame, RPromise promise, EnvProvider envProvider, boolean useExprExecNode) { - assert promise.getType() != PromiseType.NO_ARG; + assert !promise.isNonArgument(); + CompilerAsserts.compilationConstant(useExprExecNode); // Check whether it is necessary to create a callee REnvironment for the promise - if (promise.needsCalleeFrame()) { + if (promise.needsCalleeFrame(promiseProfile)) { needsCalleeFrame.enter(); // In this case the promise might lack the proper REnvironment, as it was created before // the environment was - promise.updateEnv(envProvider.getREnvironmentFor(frame)); + promise.updateEnv(envProvider.getREnvironmentFor(frame), promiseProfile); } // Now force evaluation for INLINED (might be the case for arguments by S3MethodDispatch) - if (promise.getEvalPolicy() == EvalPolicy.INLINED) { - if (CompilerAsserts.compilationConstant(useExprExecNode)) { - return PromiseHelper.evaluate(frame, exprExecNode, promise); + if (promise.isInlined(promiseProfile)) { + if (useExprExecNode) { + return PromiseHelper.evaluate(frame, exprExecNode, promise, promiseProfile); } else { strictEvaluation.enter(); - return promise.evaluate(frame); + return promise.evaluate(frame, promiseProfile); } } return promise; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java index 17b0c0a81c51669f085d03c754f05cc844b29975..70f5564b368bc8dc95ce0f082be9d6c5905474fc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariableNode.java @@ -30,7 +30,6 @@ import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.ReadVariableNodeFactory.BuiltinFunctionVariableNodeFactory; import com.oracle.truffle.r.nodes.access.ReadVariableNodeFactory.ReadAndCopySuperVariableNodeFactory; @@ -42,10 +41,13 @@ import com.oracle.truffle.r.nodes.expressions.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; import com.oracle.truffle.r.runtime.data.model.*; public abstract class ReadVariableNode extends RNode implements VisibilityController { + protected final PromiseProfile promiseProfile = new PromiseProfile(); + public abstract Object execute(VirtualFrame frame, MaterializedFrame enclosingFrame); /** @@ -152,13 +154,13 @@ public abstract class ReadVariableNode extends RNode implements VisibilityContro } if (obj instanceof RPromise) { RPromise promise = (RPromise) obj; - if (!promise.isEvaluated()) { + if (!promise.isEvaluated(promiseProfile)) { if (!forcePromise) { // since we do not know what type the evaluates to, it may match. // we recover from a wrong type later return true; } else { - obj = promise.evaluate(frame); + obj = promise.evaluate(frame, promiseProfile); } } else { obj = promise.getValue(); @@ -189,16 +191,12 @@ public abstract class ReadVariableNode extends RNode implements VisibilityContro @Child private ExpressionExecutorNode exprExecNode = ExpressionExecutorNode.create(); - private final BranchProfile directlyEvaluatedProfile = new BranchProfile(); - @Specialization public Object doValue(VirtualFrame frame, RPromise promise) { - if (!promise.isEvaluated() && promise.isInOriginFrame(frame)) { - directlyEvaluatedProfile.enter(); - - return PromiseHelper.evaluate(frame, exprExecNode, promise); + if (!promise.isEvaluated(promiseProfile) && promise.isInOriginFrame(frame, promiseProfile)) { + return PromiseHelper.evaluate(frame, exprExecNode, promise, promiseProfile); } - return promise.evaluate(frame); + return promise.evaluate(frame, promiseProfile); } @Specialization diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java index bda792a0fdc575037f181d10916a11acae081dec..8a5296ec23edec3a0cccff747f0238fc3512111f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java @@ -28,6 +28,7 @@ import com.oracle.truffle.r.nodes.expressions.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; /** * An {@link RNode} that handles accesses to components of the variadic argument (..1, ..2, etc.). @@ -39,6 +40,8 @@ public class ReadVariadicComponentNode extends RNode { private final int index; + private final PromiseProfile promiseProfile = new PromiseProfile(); + public ReadVariadicComponentNode(int index) { this.index = index; } @@ -64,7 +67,7 @@ public class ReadVariadicComponentNode extends RNode { if (ret instanceof RPromise) { // This might be the case, as lookup only checks for "..." to be a promise and forces it // eventually, NOT (all) of its content - ret = PromiseHelper.evaluate(frame, exprExecNode, (RPromise) ret); + ret = PromiseHelper.evaluate(frame, exprExecNode, (RPromise) ret, promiseProfile); } return ret == null ? RMissing.instance : ret; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java index 228fa37233c3afe4403cdda9f361404df00525ab..cb1486f4e4b210c8613102773b773b5274e67ad0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java @@ -36,6 +36,7 @@ import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RPromise.EvalPolicy; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; import com.oracle.truffle.r.runtime.data.RPromise.PromiseType; import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; @@ -46,8 +47,8 @@ import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; * {@link #matchArguments(VirtualFrame, RFunction, UnmatchedArguments, SourceSection, SourceSection)} * . The other match functions are used for special cases, where builtins make it necessary to * re-match parameters, e.g.: - * {@link #matchArgumentsEvaluated(VirtualFrame, RFunction, EvaluatedArguments, SourceSection)} for - * 'UseMethod' and + * {@link #matchArgumentsEvaluated(VirtualFrame, RFunction, EvaluatedArguments, SourceSection, PromiseProfile)} + * for 'UseMethod' and * {@link #matchArgumentsInlined(VirtualFrame, RFunction, UnmatchedArguments, SourceSection, SourceSection)} * for builtins which are implemented in Java ( @see {@link RBuiltinNode#inline(InlinedArguments)} * </p> @@ -186,7 +187,7 @@ public class ArgumentMatcher { * @return A Fresh {@link EvaluatedArguments} containing the arguments rearranged and stuffed * with default values (in the form of {@link RPromise}s where needed) */ - public static EvaluatedArguments matchArgumentsEvaluated(VirtualFrame frame, RFunction function, EvaluatedArguments evaluatedArgs, SourceSection callSrc) { + public static EvaluatedArguments matchArgumentsEvaluated(VirtualFrame frame, RFunction function, EvaluatedArguments evaluatedArgs, SourceSection callSrc, PromiseProfile promiseProfile) { RRootNode rootNode = (RRootNode) function.getTarget().getRootNode(); FormalArguments formals = rootNode.getFormalArguments(); Object[] evaledArgs = permuteArguments(function, evaluatedArgs.getEvaluatedArgs(), evaluatedArgs.getNames(), formals, new VarArgsAsObjectArrayFactory(), new ObjectArrayFactory(), callSrc, @@ -211,7 +212,7 @@ public class ArgumentMatcher { } } else if (function.isBuiltin() && evaledArg instanceof RPromise) { RPromise promise = (RPromise) evaledArg; - evaledArgs[i] = promise.evaluate(frame); + evaledArgs[i] = promise.evaluate(frame, promiseProfile); } } return new EvaluatedArguments(evaledArgs, formals.getNames()); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java index c81a8a215c4aea86fd3102ebca1ab36ad192c8dc..f3f1a671d2ed92b3214ef8cedf58f43c8be2bb0e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java @@ -22,6 +22,7 @@ import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; import com.oracle.truffle.r.runtime.data.model.*; import edu.umd.cs.findbugs.annotations.*; @@ -177,6 +178,8 @@ public class GroupDispatchNode extends S3DispatchNode { return null; } + private final PromiseProfile promiseProfile = new PromiseProfile(); + @SlowPath private void initFunCall(VirtualFrame frame, RFunction func) { // avoid re-evaluating arguments. @@ -189,11 +192,11 @@ public class GroupDispatchNode extends S3DispatchNode { if (evaluatedArgs[i] instanceof RArgsValuesAndNames) { RArgsValuesAndNames argsValuesAndNames = (RArgsValuesAndNames) evaluatedArgs[i]; if (argsValuesAndNames.length() == 1) { - argArray[index++] = ConstantNode.create(RPromise.checkEvaluate(frame, argsValuesAndNames.getValues()[0])); + argArray[index++] = ConstantNode.create(RPromise.checkEvaluate(frame, argsValuesAndNames.getValues()[0], promiseProfile)); } else { argArray = new RNode[argArray.length + argsValuesAndNames.length() - 1]; for (int j = 0; j < argsValuesAndNames.length(); j++) { - argArray[index++] = ConstantNode.create(RPromise.checkEvaluate(frame, argsValuesAndNames.getValues()[j])); + argArray[index++] = ConstantNode.create(RPromise.checkEvaluate(frame, argsValuesAndNames.getValues()[j], promiseProfile)); } } } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelper.java index 0054c1651f96ae2a5549fbab9494e6255d036315..0fa19b65e870eaec0aad4d040896c2ee867693ff 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelper.java @@ -28,6 +28,7 @@ import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.expressions.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; /** * Holds {@link RPromise}-related functionality that cannot be implemented in @@ -35,17 +36,18 @@ import com.oracle.truffle.r.runtime.data.*; */ public class PromiseHelper { /** - * Guarded by {@link RPromise#isInOriginFrame(VirtualFrame)}. + * Guarded by {@link RPromise#isInOriginFrame(VirtualFrame,PromiseProfile)}. * * @param frame The current {@link VirtualFrame} * @param exprExecNode The {@link ExpressionExecutorNode} * @param promise The {@link RPromise} to evaluate + * @param profile the profile for the site that operates on the promise * @return Evaluates the given {@link RPromise} in the given frame using the * {@link ExpressionExecutorNode} */ - public static Object evaluate(VirtualFrame frame, ExpressionExecutorNode exprExecNode, RPromise promise) { - if (promise.isEvaluated() || !promise.isInOriginFrame(frame)) { - return promise.evaluate(frame); + public static Object evaluate(VirtualFrame frame, ExpressionExecutorNode exprExecNode, RPromise promise, PromiseProfile profile) { + if (promise.isEvaluated(profile) || !promise.isInOriginFrame(frame, profile)) { + return promise.evaluate(frame, profile); } // Check for dependency cycle diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java index 3bd056722a7160bf4771f6b565a626922614cb9b..84b9afed9766fb4ad8a67503347ac3e6307eb02a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java @@ -34,6 +34,7 @@ import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RPromise.EvalPolicy; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; import com.oracle.truffle.r.runtime.data.RPromise.PromiseType; import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; import com.oracle.truffle.r.runtime.env.*; @@ -57,6 +58,8 @@ public class PromiseNode extends RNode { */ protected final EnvProvider envProvider; + protected final PromiseProfile promiseProfile = new PromiseProfile(); + /** * @param factory {@link #factory} * @param envProvider {@link #envProvider} @@ -142,11 +145,11 @@ public class PromiseNode extends RNode { return RMissing.instance; } RPromise promise = factory.createPromiseDefault(); - return PromiseHelper.evaluate(frame, exprExecNode, promise); + return PromiseHelper.evaluate(frame, exprExecNode, promise, promiseProfile); } else if (obj instanceof RArgsValuesAndNames) { - return ((RArgsValuesAndNames) obj).evaluate(frame); + return ((RArgsValuesAndNames) obj).evaluate(frame, promiseProfile); } else { - return RPromise.checkEvaluate(frame, obj); + return RPromise.checkEvaluate(frame, obj, promiseProfile); } } } @@ -182,6 +185,8 @@ public class PromiseNode extends RNode { private final RPromise promise; @CompilationFinal private boolean isEvaluated = false; + private final PromiseProfile promiseProfile = new PromiseProfile(); + private VarArgPromiseNode(RPromise promise) { this.promise = promise; } @@ -192,8 +197,8 @@ public class PromiseNode extends RNode { // the correct frame anyway if (!isEvaluated) { CompilerDirectives.transferToInterpreterAndInvalidate(); - Object result = promise.evaluate(frame); - isEvaluated = promise.isEvaluated(); + Object result = promise.evaluate(frame, promiseProfile); + isEvaluated = promise.isEvaluated(promiseProfile); return result; } @@ -273,6 +278,8 @@ public class PromiseNode extends RNode { @Children private final RNode[] varargs; protected final String[] names; + private final PromiseProfile promiseProfile = new PromiseProfile(); + public InlineVarArgsPromiseNode(RNode[] nodes, String[] names) { this.varargs = nodes; this.names = names; @@ -302,12 +309,12 @@ public class PromiseNode extends RNode { evaluatedNames = Utils.resizeArray(evaluatedNames, newLength); Object[] varargValues = argsValuesAndNames.getValues(); for (int j = 0; j < argsValuesAndNames.length(); j++) { - evaluatedArgs[index] = RPromise.checkEvaluate(frame, varargValues[j]); + evaluatedArgs[index] = RPromise.checkEvaluate(frame, varargValues[j], promiseProfile); evaluatedNames[index] = argsValuesAndNames.getNames()[j]; index++; } } else { - evaluatedArgs[index++] = RPromise.checkEvaluate(frame, argValue); + evaluatedArgs[index++] = RPromise.checkEvaluate(frame, argValue, promiseProfile); } } return new RArgsValuesAndNames(evaluatedArgs, evaluatedNames); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java index e81cf4bb82beb67f8a0c62fbffffff5458bb6ede..8bce1f373c46f5c3f91c065c1a8690749eae4a34 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java @@ -27,6 +27,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; /** * This class implements the behavior for {@link RMissing} which is needed inside this module, as it @@ -43,7 +44,7 @@ public class RMissingHelper { * @param value The value that should be examined * @return <code>true</code> iff this value is 'missing' in the definition of R */ - public static boolean isMissing(Object value) { + public static boolean isMissing(Object value, PromiseProfile promiseProfile) { if (value == RMissing.instance) { return true; } @@ -51,7 +52,7 @@ public class RMissingHelper { // This might be a promise... if (value instanceof RPromise) { RPromise promise = (RPromise) value; - if (promise.isDefaulted() || isMissingSymbol(promise)) { + if (promise.isDefault(promiseProfile) || isMissingSymbol(promise)) { return true; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java index 9b2521f596272fc440cd6949e78b197c7e871157..afdc7cdbcdd58790ce6dd1edc841de6522092707 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java @@ -19,9 +19,12 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RPromise.*; public class UseMethodDispatchNode extends S3DispatchNode { + private final PromiseProfile promiseProfile = new PromiseProfile(); + UseMethodDispatchNode(final String generic, final RStringVector type) { this.genericName = generic; this.type = type; @@ -108,7 +111,7 @@ public class UseMethodDispatchNode extends S3DispatchNode { // ...and use them as 'supplied' arguments... EvaluatedArguments evaledArgs = EvaluatedArguments.create(argValues, argNames); // ...to match them against the chosen function's formal arguments - EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(frame, targetFunction, evaledArgs, getEncapsulatingSourceSection()); + EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(frame, targetFunction, evaledArgs, getEncapsulatingSourceSection(), promiseProfile); return executeHelper2(callerFrame, reorderedArgs.getEvaluatedArgs(), reorderedArgs.getNames()); } @@ -137,7 +140,7 @@ public class UseMethodDispatchNode extends S3DispatchNode { // ...and use them as 'supplied' arguments... EvaluatedArguments evaledArgs = EvaluatedArguments.create(argValues, null); // ...to match them against the chosen function's formal arguments - EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(callerFrame, targetFunction, evaledArgs, getEncapsulatingSourceSection()); + EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(callerFrame, targetFunction, evaledArgs, getEncapsulatingSourceSection(), promiseProfile); return executeHelper2(callerFrame, reorderedArgs.getEvaluatedArgs(), reorderedArgs.getNames()); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java index 1b6402cc82e76b843b2cfd3e88e236c08d091d92..8326f1810e8d826ea75453c4561f6f0c10d9b29e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java @@ -83,12 +83,21 @@ public class REnvVars { } } + private static String rHome; + public static String rHome() { // This can be called before initialize, "R RHOME" - String rHome = getEnvVars().get("R_HOME"); if (rHome == null) { - // Should only happen in a unit test run - rHome = System.getProperty("user.dir"); + rHome = getEnvVars().get("R_HOME"); + if (rHome == null) { + // Should only happen in a unit test run, but can differ whether + // run from within IDE or from command line. + File file = new File(System.getProperty("user.dir")); + if (file.getName().endsWith("r.test")) { + file = file.getParentFile(); + } + rHome = file.getAbsolutePath(); + } } return rHome; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java index f18091e63800e28c6f79fb5ed518fb3e7554f6b5..7789ec888fa3f094d084139deceae8193134b20a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.runtime.data; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseProfile; /** * A simple wrapper class for passing the ... argument through RArguments @@ -49,10 +50,10 @@ public class RArgsValuesAndNames { } } - public RArgsValuesAndNames evaluate(VirtualFrame frame) { + public RArgsValuesAndNames evaluate(VirtualFrame frame, PromiseProfile promiseProfile) { Object[] newValues = new Object[values.length]; for (int i = 0; i < values.length; i++) { - newValues[i] = RPromise.checkEvaluate(frame, values[i]); + newValues[i] = RPromise.checkEvaluate(frame, values[i], promiseProfile); } return new RArgsValuesAndNames(newValues, names); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java index dab6ab839a852085d08d32c2934e9317b9f94e12..240ee7f5e91662cff9ac9568dcba13a678f712bb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java @@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.env.*; @@ -148,6 +149,46 @@ public final class RPromise extends RLanguageRep { return new RPromise(evalPolicy, type, env, closure); } + /** + * This class contains a profile of a specific promise evaluation site, i.e., a specific point + * in the AST where promises are inspected. + * + * This is useful to keep the amount of code included in Truffle compilation for each promise + * operation to a minimum. + */ + public static final class PromiseProfile { + private final ConditionProfile isEvaluatedProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile underEvaluationProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isNullEnvProfile = ConditionProfile.createBinaryProfile(); + + private final ConditionProfile isInlinedProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isDefaultProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isFrameForEnvProfile = ConditionProfile.createBinaryProfile(); + } + + public boolean isInlined(PromiseProfile profile) { + return profile.isInlinedProfile.profile(evalPolicy == EvalPolicy.INLINED); + } + + /** + * @return Whether this promise is of {@link #type} {@link PromiseType#ARG_DEFAULT}. + */ + public boolean isDefault(PromiseProfile profile) { + return profile.isDefaultProfile.profile(type == PromiseType.ARG_DEFAULT); + } + + public boolean isNonArgument() { + return type == PromiseType.NO_ARG; + } + + public boolean isNullEnv(PromiseProfile profile) { + return profile.isNullEnvProfile.profile(env == null); + } + + public boolean isEvaluated(PromiseProfile profile) { + return profile.isEvaluatedProfile.profile(isEvaluated); + } + /** * Evaluates this promise. If it has already been evaluated ({@link #isEvaluated()}), * {@link #getValue()} is returned. @@ -155,13 +196,14 @@ public final class RPromise extends RLanguageRep { * @param frame The {@link VirtualFrame} in which the evaluation of this promise is forced * @return The value this promise resolves to */ - public Object evaluate(VirtualFrame frame) { - if (isEvaluated) { + public Object evaluate(VirtualFrame frame, PromiseProfile profile) { + CompilerAsserts.compilationConstant(profile); + if (isEvaluated(profile)) { return value; } // Check for dependency cycle - if (underEvaluation) { + if (profile.underEvaluationProfile.profile(underEvaluation)) { SourceSection callSrc = RArguments.getCallSourceSection(frame); throw RError.error(callSrc, RError.Message.PROMISE_CYCLE); } @@ -170,13 +212,13 @@ public final class RPromise extends RLanguageRep { try { underEvaluation = true; - // Evaluate this promises value! + // Evaluate this promise's value! // Performance: We can use frame directly - if (env != null && !isInOriginFrame(frame)) { + if (!isNullEnv(profile) && !isInOriginFrame(frame, profile)) { SourceSection callSrc = frame != null ? RArguments.getCallSourceSection(frame) : null; newValue = doEvalArgument(callSrc); } else { - assert isInOriginFrame(frame); + assert isInOriginFrame(frame, profile); newValue = doEvalArgument(frame); } @@ -228,73 +270,59 @@ public final class RPromise extends RLanguageRep { * call, but the callee frame and environment get created _after_ the call happened. This update * has to take place in AccessArgumentNode, just before arguments get stuffed into the fresh * environment for the function. Whether a {@link RPromise} needs one is determined by - * {@link #needsCalleeFrame()}! + * {@link #needsCalleeFrame(PromiseProfile)}! * * @param newEnv The REnvironment this promise is to be evaluated in */ - public void updateEnv(REnvironment newEnv) { + public void updateEnv(REnvironment newEnv, PromiseProfile profile) { assert type == PromiseType.ARG_DEFAULT; - if (env == null && !isEvaluated) { + if (isNullEnv(profile) && !isEvaluated(profile)) { env = newEnv; } } /** * @param obj + * @param profile * @return If obj is a {@link RPromise}, it is evaluated and its result returned */ - public static Object checkEvaluate(VirtualFrame frame, Object obj) { + public static Object checkEvaluate(VirtualFrame frame, Object obj, PromiseProfile profile) { if (obj instanceof RPromise) { - return ((RPromise) obj).evaluate(frame); + return ((RPromise) obj).evaluate(frame, profile); } return obj; } /** * Only to be called from AccessArgumentNode, and in combination with - * {@link #updateEnv(REnvironment)}! + * {@link #updateEnv(REnvironment,PromiseProfile)}! * * @return Whether this promise needs a callee environment set (see - * {@link #updateEnv(REnvironment)}) + * {@link #updateEnv(REnvironment,PromiseProfile)}) */ - public boolean needsCalleeFrame() { - return evalPolicy == EvalPolicy.PROMISED && type == PromiseType.ARG_DEFAULT && env == null && !isEvaluated; + public boolean needsCalleeFrame(PromiseProfile profile) { + return !isInlined(profile) && isDefault(profile) && isNullEnv(profile) && !isEvaluated(profile); } /** * @param frame + * @param profile * @return Whether the given {@link RPromise} is in its origin context and thus can be resolved * directly inside the AST. */ - public boolean isInOriginFrame(VirtualFrame frame) { - if (evalPolicy == EvalPolicy.INLINED) { + public boolean isInOriginFrame(VirtualFrame frame, PromiseProfile profile) { + if (isInlined(profile)) { return true; } - assert evalPolicy == EvalPolicy.PROMISED; - if (type == PromiseType.ARG_DEFAULT && env == null) { + if (isDefault(profile) && isNullEnv(profile)) { return true; } - assert env != null; if (frame == null) { return false; } - return REnvironment.isFrameForEnv(frame, env); - } - - /** - * @return {@link #evalPolicy} - */ - public EvalPolicy getEvalPolicy() { - return evalPolicy; - } - - /** - * @return {@link #type} - */ - public PromiseType getType() { - return type; + return profile.isFrameForEnvProfile.profile(REnvironment.isFrameForEnv(frame, env)); } /** @@ -313,13 +341,6 @@ public final class RPromise extends RLanguageRep { return closure; } - /** - * @return Whether this promise is of {@link #type} {@link PromiseType#ARG_DEFAULT}. - */ - public boolean isDefaulted() { - return type == PromiseType.ARG_DEFAULT; - } - /** * @return {@link #env} */ diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java index 018202432b9c451812b301eacc5c0508d7a90155..0598baed349c0e5f2af520c44557d7fe160a35aa 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java @@ -159,6 +159,7 @@ public class TestBase { } else { try { expectedOutputManager = new ExpectedTestOutputManager(new File(expectedTestOutputURL.getPath()), false, false, false); + fastROutputManager = new FastRTestOutputManager(null); } catch (IOException ex) { Assert.fail("error reading: " + expectedTestOutputURL.getPath() + ": " + ex); }