From 4138bd65770d6ab72500e49239262d14abd332e0 Mon Sep 17 00:00:00 2001 From: stepan <stepan.sindelar@oracle.com> Date: Fri, 26 May 2017 14:06:18 +0200 Subject: [PATCH] CachedExtractVector node evaluates promises extracted from environments. --- .../r/nodes/access/vector/CachedExtractVectorNode.java | 6 ++++++ .../oracle/truffle/r/nodes/builtin/InternalNode.java | 6 ++++++ .../com/oracle/truffle/r/test/ExpectedTestOutput.test | 10 +++++++++- .../truffle/r/test/library/base/TestEnvironments.java | 10 +++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java index 6a51aee479..7e8564b4ec 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java @@ -37,6 +37,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.profile.AlwaysOnBranchProfile; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.RError; @@ -49,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; @@ -86,6 +88,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { @Child private ExtractDimNamesNode extractDimNames; private final ConditionProfile resultHasDimensions = ConditionProfile.createBinaryProfile(); + private final ConditionProfile promiseInEnvironment = ConditionProfile.createBinaryProfile(); /** * Profile if any metadata was applied at any point in time. This is useful extract primitive @@ -254,6 +257,9 @@ final class CachedExtractVectorNode extends CachedVectorNode { String positionString = tryCastSingleString(positionsCheckNode, positions); if (positionString != null) { Object obj = env.get(positionString); + if (promiseInEnvironment.profile(obj instanceof RPromise)) { + obj = PromiseHelperNode.evaluateSlowPath(null, (RPromise) obj); + } return obj == null ? RNull.instance : obj; } throw error(RError.Message.WRONG_ARGS_SUBSET_ENV); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java index 7fceec433d..7b9821cf93 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java @@ -43,6 +43,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -245,6 +246,7 @@ public abstract class InternalNode extends OperatorNode { Object[] args = new Object[arguments.length]; for (int i = 0; i < args.length; i++) { args[i] = arguments[i].execute(frame); + assert !(args[i] instanceof RPromise); } return args; } @@ -273,6 +275,7 @@ public abstract class InternalNode extends OperatorNode { value = forcePromises(frame, (RArgsValuesAndNames) value); } args[i] = value; + assert !(args[i] instanceof RPromise); } return args; } @@ -281,6 +284,7 @@ public abstract class InternalNode extends OperatorNode { Object[] array = new Object[varArgs.getLength()]; for (int i = 0; i < array.length; i++) { array[i] = promiseHelper.checkEvaluate(frame, varArgs.getArgument(i)); + assert !(array[i] instanceof RPromise); } return new RArgsValuesAndNames(array, varArgs.getSignature()); } @@ -303,10 +307,12 @@ public abstract class InternalNode extends OperatorNode { for (int i = 0; i < args.length - 1; i++) { args[i] = arguments[i].execute(frame); + assert !(args[i] instanceof RPromise); } Object[] varArgs = new Object[arguments.length - (factory.getSignature().getLength() - 1)]; for (int i = 0; i < varArgs.length; i++) { varArgs[i] = arguments[args.length - 1 + i].execute(frame); + assert !(varArgs[i] instanceof RPromise); } args[args.length - 1] = new RArgsValuesAndNames(varArgs, ArgumentsSignature.empty(varArgs.length)); return args; diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 1ebb798330..78cd51bfc5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -78624,6 +78624,14 @@ Error in rm("foo", envir = baseenv()) : #{ x <- 1; lockBinding("x", globalenv()); x <- 1 } Error: cannot change value of locked binding for 'x' +##com.oracle.truffle.r.test.library.base.TestEnvironments.testFrameToEnv# +#{ makefun <- function(f) function(a) f(a); .Internal(islistfactor(environment(makefun(function(b) 2*b))$f, F)); } +[1] FALSE + +##com.oracle.truffle.r.test.library.base.TestEnvironments.testFrameToEnv# +#{ makefun <- function(f,s) function(a) f(a); s <- function() cat('side effect'); .Internal(islistfactor(environment(makefun(function(b) 2*b, s()))$f, F)); } +[1] FALSE + ##com.oracle.truffle.r.test.library.base.TestEnvironments.testFrames# #{ t1 <- function() { aa <- 1; t2 <- function() { cat("current frame is", sys.nframe(), "; "); cat("parents are frame numbers", sys.parents(), "; "); print(ls(envir = sys.frame(-1))) }; t2() }; t1() } current frame is 2 ; parents are frame numbers 0 1 ; [1] "aa" "t2" @@ -130695,7 +130703,7 @@ Error in attr(to, "a") <- "a" : external object cannot be attributed #if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in attr(to, which = "a") : external object cannot be attributed<<<NEWLINE>>>') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attr(to, which = 'a') } Error in attr(to, which = "a") : external object cannot be attributed -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#Ignored.ImplementationError# #if (length(grep("FastR", R.Version()$version.string)) != 1) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$classAsArg(tc) } [1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java index 44ac9c7cfa..31bbd86d48 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestEnvironments.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -285,4 +285,12 @@ public class TestEnvironments extends TestBase { assertEval("{ e <- new.env(); assign(\"x\", 1, e); attach(e, 2); x; detach(2); x }"); assertEval("{ detach(\"missing\"); x }"); } + + @Test + public void testFrameToEnv() { + // Note: islistfactor is internal and should fail if it gets promise directly + assertEval("{ makefun <- function(f) function(a) f(a); .Internal(islistfactor(environment(makefun(function(b) 2*b))$f, F)); }"); + // Turning frame into an environment should not evaluate all the promises: + assertEval("{ makefun <- function(f,s) function(a) f(a); s <- function() cat('side effect'); .Internal(islistfactor(environment(makefun(function(b) 2*b, s()))$f, F)); }"); + } } -- GitLab