From 54f74cba3fe324e0a89be8f0fda57c966864d942 Mon Sep 17 00:00:00 2001 From: stepan <stepan.sindelar@oracle.com> Date: Tue, 15 Aug 2017 13:37:11 +0200 Subject: [PATCH] Conversion from RList to Env in Eval handles ref-counting. --- .../opt/UpdateShareableChildValueNode.java | 3 + .../data/UpdateShareableChildValue.java | 55 +++++++++++++++++++ .../truffle/r/runtime/env/REnvironment.java | 3 +- .../truffle/r/test/ExpectedTestOutput.test | 12 ++++ .../r/test/builtins/TestBuiltin_eval.java | 3 + 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java 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 fb71c60e5e..3fe5fcddda 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 0000000000..c08e0b7a43 --- /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 323b86b02b..dcb01ee548 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 894ba059c4..6b712139c6 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 81e890a928..90624c9087 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 -- GitLab