diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java index fb71c60e5ea88f609c93cbbde820c487e3d28a60..3fe5fcddda088bd95264832c0d49bd6603cb7c7a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java @@ -29,6 +29,9 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.nodes.RBaseNode; +/** + * Implements a fast-path version of {@code UpdateShareableChildValue}. + */ public abstract class UpdateShareableChildValueNode extends RBaseNode { public abstract void execute(Object owner, Object attrValue); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java new file mode 100644 index 0000000000000000000000000000000000000000..c08e0b7a43d9932f8277adc99da06508dcd69cd7 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, 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.runtime.data; + +public final class UpdateShareableChildValue { + private UpdateShareableChildValue() { + } + + // slow-path implementation of the same algorithm as in UpdateShareableChildValueNode + public static <T> T update(Object originalOwner, T originalVal) { + if (!(originalVal instanceof RSharingAttributeStorage) || !(originalOwner instanceof RSharingAttributeStorage)) { + RSharingAttributeStorage.verify(originalOwner); + RSharingAttributeStorage.verify(originalVal); + return originalVal; + } + + RSharingAttributeStorage val = (RSharingAttributeStorage) originalVal; + if (val.isShared()) { + return originalVal; + } + + RSharingAttributeStorage owner = (RSharingAttributeStorage) originalOwner; + if (owner.isTemporary()) { + return originalVal; + } + + if (val.isTemporary()) { + val.incRefCount(); + } + if (owner.isShared()) { + val.incRefCount(); + } + return originalVal; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java index 323b86b02bd282999713e69982814423b34bb4e9..dcb01ee548ac70950daf8f94469abd7aa8adf2c2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java @@ -50,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.UpdateShareableChildValue; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.NSBaseMaterializedFrame; import com.oracle.truffle.r.runtime.env.frame.REnvEmptyFrameAccess; @@ -666,7 +667,7 @@ public abstract class REnvironment extends RAttributeStorage { RStringVector names = list.getNames(); for (int i = 0; i < list.getLength(); i++) { try { - result.put(names.getDataAt(i), list.getDataAt(i)); + result.put(names.getDataAt(i), UpdateShareableChildValue.update(list, list.getDataAt(i))); } catch (PutException ex) { throw RError.error(RError.SHOW_CALLER2, ex); } 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 894ba059c4f6f3a33d501b2b69f62e786ca2f02c..6b712139c6b884e064e37d404d081ac413c82680 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 @@ -23441,6 +23441,18 @@ Error in eval(expr, envir, enclos) : object 'a' not found Error in eval(quote(x + y), c(-1, -2)) : numeric 'envir' arg not of length one +##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testWithEnvirAndEnclose# +#{ df <- list(a=c(1,2,3), b=c(3,4,5)); df$c <- with(df, a^2); df; } +$a +[1] 1 2 3 + +$b +[1] 3 4 5 + +$c +[1] 1 4 9 + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_exists.testexists1# #argv <- structure(list(x = '.Device'), .Names = 'x');do.call('exists', argv) [1] TRUE diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java index 81e890a9283abba172a357a621f78f3fff91c658..90624c90873ac5ec3374d09205b4ed43b13e6315 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java @@ -59,6 +59,9 @@ public class TestBuiltin_eval extends TestBase { assertEval("a <- 1; lang <- quote(list(a)); eval(lang, NULL, NULL)"); assertEval("a <- 1; lang <- quote(list(a)); eval(lang, new.env(), new.env())"); assertEval(Output.IgnoreErrorMessage, "y <- 2; x <- 2 ; eval(quote(x+y), c(-1, -2))"); + + // note: 'with' is a oneliner builtin calling into eval + assertEval("{ df <- list(a=c(1,2,3), b=c(3,4,5)); df$c <- with(df, a^2); df; }"); } @Test