diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index 39d41c413493129185eccdefefcc773adf41516b..7d0999d6da905a374068760941ef99bbc8b9be45 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -442,6 +442,12 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { ((RBaseNode) node).serialize(state); } + @Override + public void serializeFunctionDefinitionNode(RSerialize.State state, RFunction fn) { + FunctionDefinitionNode fdn = (FunctionDefinitionNode) fn.getRootNode(); + fdn.serializeImpl(state); + } + @Override public ArgumentsSignature getArgumentsSignature(RFunction f) { return ((RRootNode) f.getRootNode()).getSignature(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java index 1af8e0ba9aa15ae52e70af657e5b4e8f90e20ea0..a185e05d9c6da216f8ae526be748986133e9fc36 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java @@ -39,6 +39,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; @@ -107,7 +108,9 @@ public abstract class Assign extends RBuiltinNode { */ @Specialization protected Object assign(RAbstractStringVector xVec, Object value, REnvironment envir, byte inherits, // - @Cached("createBinaryProfile()") ConditionProfile inheritsProfile) { + @Cached("createBinaryProfile()") ConditionProfile inheritsProfile, + @Cached("createBinaryProfile()") ConditionProfile isShareableProfile, + @Cached("createBinaryProfile()") ConditionProfile isRefCountUpdateable) { String x = checkVariable(xVec); REnvironment env = envir; if (inheritsProfile.profile(RRuntime.fromLogical(inherits))) { @@ -129,6 +132,12 @@ public abstract class Assign extends RBuiltinNode { throw RError.error(errorContext(), RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV); } } + if (isShareableProfile.profile(value instanceof RShareable)) { + RShareable shareable = (RShareable) value; + if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) { + shareable.incRefCount(); + } + } try { env.put(x, value); } catch (PutException ex) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java index aa454c0002d8a29000c90055b468fb1ee87c8f77..eac4155fc6ef9de92adcbeb290f9d4c86f671876 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java @@ -37,6 +37,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; @@ -44,6 +45,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.CombineNodeGen.CombineInputCastNodeGen; import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; @@ -55,7 +57,6 @@ import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.nodes.unary.CastRawNodeGen; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.nodes.unary.CastToVectorNode; -import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; import com.oracle.truffle.r.nodes.unary.PrecedenceNode; import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -86,10 +87,19 @@ public abstract class Combine extends RBuiltinNode { protected static final int COMBINE_CACHED_LIMIT = PrecedenceNode.NUMBER_OF_PRECEDENCES; + private static final int MAX_PROFILES = 4; + @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); @Child private CombineInputCast inputCast = CombineInputCastNodeGen.create(null); @Child private CastToVectorNode castVector; + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final BranchProfile naBranch = BranchProfile.create(); + private final NACheck naCheck = NACheck.create(); + private final ConditionProfile fastNamesMerge = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isAbstractVectorProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile hasNewNamesProfile = ConditionProfile.createBinaryProfile(); + @CompilationFinal private final ValueProfile[] argProfiles = new ValueProfile[MAX_PROFILES]; public abstract Object executeCombine(Object value); @@ -107,9 +117,7 @@ public abstract class Combine extends RBuiltinNode { @Cached("args.getSignature()") ArgumentsSignature cachedSignature, // @Cached("precedence( args, cachedSignature.getLength())") int cachedPrecedence, // @Cached("createCast(cachedPrecedence)") CastNode cast, // - @Cached("create()") BranchProfile naBranch, // @Cached("create()") BranchProfile naNameBranch, // - @Cached("create()") NACheck naCheck, // @Cached("create()") NACheck naNameCheck, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { CompilerAsserts.partialEvaluationConstant(cachedSignature); @@ -121,13 +129,15 @@ public abstract class Combine extends RBuiltinNode { // perform all the casts Object[] elements = new Object[cachedSignature.getLength()]; - int size = prepareElements(args.getArguments(), cachedSignature, cast, cachedPrecedence, elements); + int size = prepareElements(args.getArguments(), cast, cachedPrecedence, elements); // prepare the names (if there are any) - RStringVector namesVector = hasNamesProfile.profile(hasNames(elements)) ? foldNames(naNameBranch, naNameCheck, elements, size) : null; + boolean signatureHasNames = signatureHasNames(cachedSignature); + CompilerAsserts.partialEvaluationConstant(signatureHasNames); + RStringVector namesVector = hasNamesProfile.profile(signatureHasNames || hasNames(elements)) ? foldNames(naNameBranch, naNameCheck, elements, size, cachedSignature) : null; // get the actual contents of the result - RVector result = foldContents(cachedPrecedence, naBranch, naCheck, elements, size, namesVector); + RVector result = foldContents(cachedPrecedence, elements, size, namesVector); RNode.reportWork(this, size); @@ -139,13 +149,17 @@ public abstract class Combine extends RBuiltinNode { } @ExplodeLoop - private int prepareElements(Object[] args, ArgumentsSignature signature, CastNode cast, int precedence, Object[] elements) { - boolean signatureHasNames = signatureHasNames(signature); - CompilerAsserts.partialEvaluationConstant(signatureHasNames); - + private int prepareElements(Object[] args, CastNode cast, int precedence, Object[] elements) { int size = 0; for (int i = 0; i < elements.length; i++) { - Object element = readAndCast(cast, args, signature, i, precedence, signatureHasNames); + Object element = readAndCast(cast, args[i], precedence); + if (i < argProfiles.length) { + if (argProfiles[i] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argProfiles[i] = ValueProfile.createClassProfile(); + } + element = argProfiles[i].profile(element); + } elements[i] = element; size += getElementSize(element); } @@ -165,7 +179,11 @@ public abstract class Combine extends RBuiltinNode { @ExplodeLoop private boolean hasNames(Object[] elements) { - for (Object element : elements) { + for (int i = 0; i < elements.length; i++) { + Object element = elements[i]; + if (i < argProfiles.length) { + element = argProfiles[i].profile(element); + } if (element instanceof RAbstractVector) { RAbstractVector vector = (RAbstractVector) element; if (vector.getNames(attrProfiles) != null) { @@ -177,22 +195,36 @@ public abstract class Combine extends RBuiltinNode { } @ExplodeLoop - private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size) { + private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size, ArgumentsSignature signature) { RStringVector result = RDataFactory.createStringVector(new String[size], true); result.incRefCount(); int pos = 0; - for (Object element : elements) { - pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element); + for (int i = 0; i < elements.length; i++) { + Object element = elements[i]; + if (i < argProfiles.length) { + element = argProfiles[i].profile(element); + } + pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element, i, signature); } return result; } - private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element) { + private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element, int index, ArgumentsSignature signature) { + String signatureName = signature.getName(index); if (element instanceof RAbstractVector) { RAbstractVector v = (RAbstractVector) element; + int length = v.getLength(); + RStringVector newNames = v.getNames(attrProfiles); - if (newNames != null) { - for (int i1 = 0; i1 < newNames.getLength(); i1++) { + if (signatureName != null && length > 0) { + if (fastNamesMerge.profile(length == 1 && newNames == null)) { + newNames = RDataFactory.createStringVector(new String[]{signatureName}, true); + } else { + newNames = RDataFactory.createStringVector(mergeNamesSlow(length, signatureName, newNames), true); + } + } + if (hasNewNamesProfile.profile(newNames != null)) { + for (int i1 = 0; i1 < length; i1++) { result.transferElementSameType(pos + i1, newNames, i1); } if (!newNames.isComplete()) { @@ -200,7 +232,7 @@ public abstract class Combine extends RBuiltinNode { result.setComplete(false); } } else { - for (int i1 = 0; i1 < v.getLength(); i1++) { + for (int i1 = 0; i1 < length; i1++) { result.updateDataAt(pos + i1, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck); } } @@ -209,23 +241,24 @@ public abstract class Combine extends RBuiltinNode { // nothing to do - NULL elements are skipped return 0; } else { - result.updateDataAt(pos, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck); + String name = signatureName != null ? signatureName : RRuntime.NAMES_ATTR_EMPTY_VALUE; + result.updateDataAt(pos, name, naNameCheck); return 1; } } @ExplodeLoop - private static RVector foldContents(int cachedPrecedence, BranchProfile naBranch, NACheck naCheck, Object[] elements, int size, RStringVector namesVector) { + private RVector foldContents(int cachedPrecedence, Object[] elements, int size, RStringVector namesVector) { RVector result = createResultVector(cachedPrecedence, size, namesVector); int pos = 0; for (Object element : elements) { - pos += processContentElement(naBranch, naCheck, result, pos, element); + pos += processContentElement(result, pos, element); } return result; } - private static int processContentElement(BranchProfile naBranch, NACheck naCheck, RVector result, int pos, Object element) { - if (element instanceof RAbstractVector) { + private int processContentElement(RVector result, int pos, Object element) { + if (isAbstractVectorProfile.profile(element instanceof RAbstractVector)) { RAbstractVector v = (RAbstractVector) element; for (int i = 0; i < v.getLength(); i++) { result.transferElementSameType(pos + i, v, i); @@ -254,12 +287,10 @@ public abstract class Combine extends RBuiltinNode { protected Object combine(RArgsValuesAndNames args, // @Cached("precedence(args, args.getLength())") int cachedPrecedence, // @Cached("createCast(cachedPrecedence)") CastNode cast, // - @Cached("create()") BranchProfile naBranch, // @Cached("create()") BranchProfile naNameBranch, // - @Cached("create()") NACheck naCheck, // @Cached("create()") NACheck naNameCheck, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { - return combineCached(args, args.getSignature(), cachedPrecedence, cast, naBranch, naNameBranch, naCheck, naNameCheck, hasNamesProfile); + return combineCached(args, args.getSignature(), cachedPrecedence, cast, naNameBranch, naNameCheck, hasNamesProfile); } @Specialization(guards = "!isArguments(args)") @@ -267,39 +298,11 @@ public abstract class Combine extends RBuiltinNode { return combine.executeCombine(new RArgsValuesAndNames(new Object[]{args}, EMPTY_SIGNATURE)); } - private Object readAndCast(CastNode castNode, Object[] values, ArgumentsSignature signature, int index, int precedence, boolean hasNames) { - Object value = inputCast.execute(values[index]); - if (hasNames) { - value = namesMerge(castVector(value), signature.getName(index)); - } + private Object readAndCast(CastNode castNode, Object arg, int precedence) { + Object value = inputCast.execute(arg); return (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : castNode.execute(value); } - private RAbstractVector namesMerge(RAbstractVector vector, String name) { - RStringVector orgNamesObject = vector.getNames(attrProfiles); - if (name == null) { - return vector; - } - if (vector.getLength() == 0) { - return vector; - } - return mergeNamesSlow(vector, name, orgNamesObject); - } - - private RAbstractVector castVector(Object value) { - if (castVector == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castVector = insert(CastToVectorNodeGen.create(false)); - } - RVector resultVector = ((RAbstractVector) castVector.execute(value)).materialize(); - // need to copy if vector is shared in case the same variable is used in combine, e.g. : - // x <- 1:2 ; names(x) <- c("A",NA) ; c(x,test=x) - if (resultVector.isShared()) { - resultVector = resultVector.copy(); - } - return resultVector; - } - protected int precedence(RArgsValuesAndNames args) { int precedence = NO_PRECEDENCE; Object[] array = args.getArguments(); @@ -376,37 +379,30 @@ public abstract class Combine extends RBuiltinNode { } @TruffleBoundary - private static RAbstractVector mergeNamesSlow(RAbstractVector vector, String name, RStringVector orgNames) { - /* - * TODO (chumer) we should reuse some node for this to concat a RStringVector with a String. - */ - RVector v = vector.materialize(); - RStringVector newNames; + private static String[] mergeNamesSlow(int length, String name, RStringVector orgNames) { + String[] names = new String[length]; if (orgNames == null) { assert (name != null); assert (!name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)); - if (v.getLength() == 1) { + if (length == 1) { // single value - just use the name - newNames = RDataFactory.createStringVector(new String[]{name}, true); + names[0] = name; } else { // multiple values - prepend name to the index of a given value - String[] names = new String[v.getLength()]; for (int i = 0; i < names.length; i++) { names[i] = name + (i + 1); } - newNames = RDataFactory.createStringVector(names, true); + return names; } } else { - if (vector.getLength() == 1) { - // single value - // prepend name to the original name + if (length == 1) { + // single value - prepend name to the original name assert (!name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)); String orgName = orgNames.getDataAt(0); - newNames = RDataFactory.createStringVector(new String[]{orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name : name + "." + orgName}, true); + names[0] = orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name : name + "." + orgName; } else { // multiple values - prepend name to the index of a given value or to the original // name - String[] names = new String[v.getLength()]; for (int i = 0; i < names.length; i++) { if (name == null) { names[i] = orgNames.getDataAt(i); @@ -416,11 +412,9 @@ public abstract class Combine extends RBuiltinNode { names[i] = orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name + (i + 1) : name + "." + orgName; } } - newNames = RDataFactory.createStringVector(names, true); } } - v.setNames(newNames); - return v; + return names; } @NodeChild diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java index e5e14eebc3563ef6b13e184a9e06a5cc0a02d9dd..5bf1d9ac7265203e81e5ecf582c584a5c72d04de 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java @@ -22,8 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -43,13 +43,13 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.ops.na.NACheck; +import com.oracle.truffle.r.runtime.ops.na.NAProfile; public class LogFunctions { @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) public abstract static class Log extends RBuiltinNode { - private final NACheck naCheck = NACheck.create(); + private final NAProfile naProfile = NAProfile.create(); private final BranchProfile nanProfile = BranchProfile.create(); @Override @@ -79,7 +79,7 @@ public class LogFunctions { for (int i = 0; i < vector.getLength(); i++) { int inputValue = vector.getDataAt(i); double result = RRuntime.DOUBLE_NA; - if (!RRuntime.isNA(inputValue)) { + if (!naProfile.isNA(inputValue)) { result = logb(inputValue, base); } resultVector[i] = result; @@ -101,8 +101,7 @@ public class LogFunctions { } private double logb(double x, double base) { - naCheck.enable(true); - if (naCheck.check(base)) { + if (naProfile.isNA(base)) { return RRuntime.DOUBLE_NA; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java index ba423dae3cbafc423b481033a8fb9b51cba8348a..fc26c8e3365e813b31cdb70fa6f5e27f2844690e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java @@ -22,7 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -30,9 +32,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.util.Arrays; import java.util.function.Function; +import com.oracle.truffle.api.dsl.Cached; 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.InitAttributesNode; +import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -142,39 +147,44 @@ public abstract class Repeat extends RBuiltinNode { } @Specialization(guards = {"each > 1", "hasNames(x)"}) - protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) { + protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames) { if (times.getLength() > 1) { errorBranch.enter(); throw invalidTimes(); } RAbstractVector input = handleEach(x, each); RStringVector names = (RStringVector) handleEach(x.getNames(attrProfiles), each); + RVector r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { names = (RStringVector) handleLengthOut(names, lengthOut, false); - RVector r = handleLengthOut(input, lengthOut, false); - r.setNames(names); - return r; + r = handleLengthOut(input, lengthOut, false); } else { names = (RStringVector) handleTimes(names, times, false); - RVector r = handleTimes(input, times, false); - r.setNames(names); - return r; + r = handleTimes(input, times, false); } + putNames.execute(initAttributes.execute(r), names); + r.setInternalNames(names); + return r; } @Specialization(guards = {"each <= 1", "hasNames(x)"}) - protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { + protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames) { + RStringVector names; + RVector r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - RStringVector names = (RStringVector) handleLengthOut(x.getNames(attrProfiles), lengthOut, true); - RVector r = handleLengthOut(x, lengthOut, true); - r.setNames(names); - return r; + names = (RStringVector) handleLengthOut(x.getNames(attrProfiles), lengthOut, true); + r = handleLengthOut(x, lengthOut, true); } else { - RStringVector names = (RStringVector) handleTimes(x.getNames(attrProfiles), times, true); - RVector r = handleTimes(x, times, true); - r.setNames(names); - return r; + names = (RStringVector) handleTimes(x.getNames(attrProfiles), times, true); + r = handleTimes(x, times, true); } + putNames.execute(initAttributes.execute(r), names); + r.setInternalNames(names); + return r; } /** diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java index 0cac8ae1caf25989e975c4cf4876315e0741de98..c2d61bfb227fca501542427026c13c971b3838d3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java @@ -31,12 +31,14 @@ import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RSrcref; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.ConsoleHandler; +import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; @@ -77,7 +79,6 @@ public abstract class BrowserInteractNode extends RNode { ConsoleHandler ch = RContext.getInstance().getConsoleHandler(); BrowserState browserState = RContext.getInstance().stateInstrumentation.getBrowserState(); String savedPrompt = ch.getPrompt(); - ch.setPrompt(browserPrompt(RArguments.getDepth(frame))); RFunction callerFunction = RArguments.getFunction(frame); // we may be at top level where there is not caller boolean callerIsDebugged = callerFunction == null ? false : DebugHandling.isDebugged(callerFunction); @@ -90,6 +91,7 @@ public abstract class BrowserInteractNode extends RNode { try { browserState.setInBrowser(browserCaller); LW: while (true) { + ch.setPrompt(browserPrompt(RArguments.getDepth(frame))); String input = ch.readLine(); if (input != null) { input = input.trim(); @@ -144,15 +146,27 @@ public abstract class BrowserInteractNode extends RNode { } default: - try { - RContext.getEngine().parseAndEval(RSource.fromTextInternal(input, RSource.Internal.BROWSER_INPUT), mFrame, true); - } catch (ReturnException e) { - exitMode = NEXT; - break LW; - } catch (ParseException e) { - throw e.throwAsRError(); + StringBuffer sb = new StringBuffer(input); + while (true) { + try { + RContext.getEngine().parseAndEval(RSource.fromTextInternal(sb.toString(), RSource.Internal.BROWSER_INPUT), mFrame, true); + } catch (IncompleteSourceException e) { + // read another line of input + ch.setPrompt("+ "); + sb.append(ch.readLine()); + // The only continuation in the while loop + continue; + } catch (ParseException e) { + e.report(ch); + continue LW; + } catch (RError e) { + continue LW; + } catch (ReturnException e) { + exitMode = NEXT; + break LW; + } + continue LW; } - break; } } } finally { 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 02dbbaf855144c918ced61076866063bb38648c5..15d687d6799438879e7d85a67c0a1d1ff06a3f96 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 @@ -138,10 +138,7 @@ public final class AccessArgumentNode extends RNode { private Object doArgument(VirtualFrame frame, Object arg) { if (hasDefaultArg) { - if (isMissingProfile.profile(arg == RMissing.instance)) { - return doArgumentInternal(frame); - } - if (isEmptyProfile.profile(arg == REmpty.instance)) { + if (isMissingProfile.profile(arg == RMissing.instance) || isEmptyProfile.profile(arg == REmpty.instance)) { return doArgumentInternal(frame); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java index b880d98d8649d7eb23de404bc596058810cec6e5..98ed65cc09722ad911098ba83ea80dae38fd6c05 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java @@ -48,10 +48,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode; */ abstract class BaseWriteVariableNode extends WriteVariableNode { + private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isCurrentProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isShareableProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isSharedProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isSharedPermanent = ConditionProfile.createBinaryProfile(); private final BranchProfile initialSetKindProfile = BranchProfile.create(); @@ -89,18 +90,18 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { // this comparison does not work consistently for boxing objects, so it's important // to do the RShareable check first. - if (isCurrentProfile.profile(isCurrentValue(frame, frameSlot, value))) { + if (isCurrentValue(frame, frameSlot, value)) { return value; } RShareable rShareable = (RShareable) shareableProfile.profile(value); if (mode == Mode.COPY) { return rShareable.copy(); } else { - if (isRefCountUpdateable.profile(!rShareable.isSharedPermanent())) { + if (!isSharedPermanent.profile(rShareable.isSharedPermanent())) { if (isSuper) { // if non-local assignment, increment conservatively rShareable.incRefCount(); - } else if (isSharedProfile.profile(!rShareable.isShared())) { + } else if (!isSharedProfile.profile(rShareable.isShared())) { // don't increment if already shared - will not get "unshared" until // this function exits anyway rShareable.incRefCount(); @@ -112,9 +113,9 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { return value; } - private static boolean isCurrentValue(Frame frame, FrameSlot frameSlot, Object value) { + private boolean isCurrentValue(Frame frame, FrameSlot frameSlot, Object value) { try { - return frame.isObject(frameSlot) && frame.getObject(frameSlot) == value; + return isObjectProfile.profile(frame.isObject(frameSlot)) && isCurrentProfile.profile(frame.getObject(frameSlot) == value); } catch (FrameSlotTypeException ex) { throw RInternalError.shouldNotReachHere(); } 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 6a304222baf4f22bbbf5296aebfe8f0c4d54ef28..8fc53aa127bc467060511104f8de4db53746de28 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 @@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.access.vector.CachedExtractVectorNodeFactory.SetNamesNodeGen; @@ -274,6 +273,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { private final ConditionProfile dimNamesNull = ConditionProfile.createBinaryProfile(); private final ValueProfile foundDimNamesProfile = ValueProfile.createClassProfile(); private final ConditionProfile selectPositionsProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile originalDimNamesPRofile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile foundNamesProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop private void applyDimensions(RAbstractContainer originalTarget, RVector extractedTarget, int extractedTargetLength, PositionProfile[] positionProfile, Object[] positions) { @@ -311,9 +312,9 @@ final class CachedExtractVectorNode extends CachedVectorNode { if (newDimNames != null) { extractedTarget.setDimNames(RDataFactory.createList(newDimNames)); } - } else if (newDimNames != null && originalDimNames.getLength() > 0) { + } else if (newDimNames != null && originalDimNamesPRofile.profile(originalDimNames.getLength() > 0)) { RAbstractStringVector foundNames = translateDimNamesToNames(positionProfile, originalDimNames, extractedTargetLength, positions); - if (foundNames != null) { + if (foundNamesProfile.profile(foundNames != null)) { foundNames = foundDimNamesProfile.profile(foundNames); if (foundNames.getLength() > 0) { metadataApplied.enter(); @@ -323,7 +324,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } - private final BranchProfile droppedDimensionProfile = BranchProfile.create(); + private final ConditionProfile droppedDimensionProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop private int countDimensions(PositionProfile[] boundsProfile) { @@ -331,8 +332,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { int dimCount = numberOfDimensions; for (int i = 0; i < numberOfDimensions; i++) { int selectedPositionsCount = boundsProfile[i].selectedPositionsCount; - if (selectedPositionsCount == 1) { - droppedDimensionProfile.enter(); + if (droppedDimensionProfile.profile(selectedPositionsCount == 1)) { dimCount--; } } @@ -342,6 +342,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } + private final ConditionProfile srcNamesProfile = ConditionProfile.createBinaryProfile(); + private final ValueProfile srcNamesValueProfile = ValueProfile.createClassProfile(); private final ConditionProfile newNamesProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop @@ -353,8 +355,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { continue; } - Object srcNames = originalDimNames.getDataAt(currentDimIndex); - if (srcNames != RNull.instance) { + Object srcNames = srcNamesValueProfile.profile(originalDimNames.getDataAt(currentDimIndex)); + if (srcNamesProfile.profile(srcNames != RNull.instance)) { Object position = positions[currentDimIndex]; Object newNames = extractNames((RAbstractStringVector) RRuntime.asAbstractVector(srcNames), new Object[]{position}, new PositionProfile[]{profile}, currentDimIndex, diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java index 3a292f4988bbddeb41e4e53d532c29db1c538625..15e5733176ca6cb894f83abed38731c4bff57c76 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java @@ -23,10 +23,10 @@ package com.oracle.truffle.r.nodes.access.vector; 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.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.access.vector.ExtractListElementNodeGen.UpdateStateOfListElementNodeGen; import com.oracle.truffle.r.runtime.data.RListBase; import com.oracle.truffle.r.runtime.data.RShareable; @@ -84,10 +84,12 @@ public abstract class ExtractListElement extends Node { } @Specialization - protected void doShareableValues(RListBase owner, RShareable value, // - @Cached("createBinaryProfile()") ConditionProfile sharedValue, // + protected void doShareableValues(RListBase owner, RShareable value, + @Cached("createClassProfile()") ValueProfile valueProfile, + @Cached("createBinaryProfile()") ConditionProfile sharedValue, @Cached("createBinaryProfile()") ConditionProfile temporaryOwner) { - if (sharedValue.profile(value.isShared())) { + RShareable profiledValue = valueProfile.profile(value); + if (sharedValue.profile(profiledValue.isShared())) { // it is already shared, not need to do anything return; } @@ -99,21 +101,25 @@ public abstract class ExtractListElement extends Node { return; } - if (value.isTemporary()) { + if (profiledValue.isTemporary()) { // make it at least non-shared (parent list must be also at least non-shared) - value.incRefCount(); + profiledValue.incRefCount(); } if (owner.isShared()) { // owner is shared, make the value shared too - value.incRefCount(); + profiledValue.incRefCount(); } } - @Fallback + @Specialization(guards = "isFallback(owner, value)") protected void doFallback(Object owner, Object value) { assert !(value instanceof RShareable && owner instanceof RAbstractVector && !(owner instanceof RListBase)) : "RShareables can only live inside lists and no other vectors."; // nop: either value is not RShareable, or the owner is "list" like structure with // reference semantics (e.g. REnvironment) } + + protected final boolean isFallback(Object owner, Object value) { + return !(value instanceof RShareable) || !(owner instanceof RListBase); + } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java index c83e56efcc76dd8284a1139f085bf9acf6bece68..3ab96e71be61213a05440038eba694b6d25bac6b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java @@ -44,6 +44,7 @@ final class PositionsCheckNode extends Node { private final VectorLengthProfile selectedPositionsCountProfile = VectorLengthProfile.create(); private final VectorLengthProfile maxOutOfBoundsProfile = VectorLengthProfile.create(); private final ConditionProfile containsNAProfile = ConditionProfile.createBinaryProfile(); + private final BranchProfile unsupportedProfile = BranchProfile.create(); private final boolean replace; private final int positionsLength; @@ -64,10 +65,12 @@ final class PositionsCheckNode extends Node { @ExplodeLoop public boolean isSupported(Object[] positions) { if (positionsCheck.length != positions.length) { + unsupportedProfile.enter(); return false; } for (int i = 0; i < positionsCheck.length; i++) { if (!positionsCheck[i].isSupported(positions[i])) { + unsupportedProfile.enter(); return false; } } 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 bfca64f94be16909d1fb4165563a0acb693e9a32..79c34d928574bbcfd5679d9990cc84cbb7e5746c 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 @@ -107,19 +107,20 @@ public abstract class CopyAttributesNode extends RBaseNode { @Specialization(guards = {"leftLength == rightLength", "containsMetadata(left, attrLeftProfiles) || containsMetadata(right, attrRightProfiles)"}) protected RAbstractVector copySameLength(RAbstractVector target, RAbstractVector left, @SuppressWarnings("unused") int leftLength, RAbstractVector right, - @SuppressWarnings("unused") int rightLength, // - @Cached("create()") CopyOfRegAttributesNode copyOfRegLeft, // - @Cached("create()") CopyOfRegAttributesNode copyOfRegRight, // - @Cached("createDim()") RemoveAttributeNode removeDim, // - @Cached("createDimNames()") RemoveAttributeNode removeDimNames, // - @Cached("create()") InitAttributesNode initAttributes, // - @Cached("createNames()") PutAttributeNode putNames, // - @Cached("createDim()") PutAttributeNode putDim, // - @Cached("create()") BranchProfile leftHasDimensions, // - @Cached("create()") BranchProfile rightHasDimensions, // - @Cached("create()") BranchProfile noDimensions, // - @Cached("createBinaryProfile()") ConditionProfile hasNamesLeft, // - @Cached("createBinaryProfile()") ConditionProfile hasNamesRight, // + @SuppressWarnings("unused") int rightLength, + @Cached("create()") CopyOfRegAttributesNode copyOfRegLeft, + @Cached("create()") CopyOfRegAttributesNode copyOfRegRight, + @Cached("createBinaryProfile()") ConditionProfile hasAttributes, + @Cached("createDim()") RemoveAttributeNode removeDim, + @Cached("createDimNames()") RemoveAttributeNode removeDimNames, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames, + @Cached("createDim()") PutAttributeNode putDim, + @Cached("create()") BranchProfile leftHasDimensions, + @Cached("create()") BranchProfile rightHasDimensions, + @Cached("create()") BranchProfile noDimensions, + @Cached("createBinaryProfile()") ConditionProfile hasNamesLeft, + @Cached("createBinaryProfile()") ConditionProfile hasNamesRight, @Cached("createBinaryProfile()") ConditionProfile hasDimNames) { if (LOG) { log("copyAttributes: =="); @@ -141,7 +142,7 @@ public abstract class CopyAttributesNode extends RBaseNode { if (newDimensions == null) { noDimensions.enter(); RAttributes attributes = result.getAttributes(); - if (attributes != null) { + if (hasAttributes.profile(attributes != null)) { removeDim.execute(attributes); removeDimNames.execute(attributes); result.setInternalDimNames(null); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java index b066be22af2ab3675b97b82ef6d48ff6029d2223..de60064a28a74110e61b45178f375df86982aeb0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.attributes; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; @@ -37,6 +38,8 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ public abstract class CopyOfRegAttributesNode extends RBaseNode { + private final ConditionProfile sizeOneProfile = ConditionProfile.createBinaryProfile(); + public abstract void execute(RAbstractVector source, RVector target); public static CopyOfRegAttributesNode create() { @@ -60,9 +63,9 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { // nothing to do } - protected static final boolean onlyDimAttribute(RAbstractVector source) { + protected final boolean onlyDimAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.DIM_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.DIM_ATTR_KEY; } @SuppressWarnings("unused") @@ -71,9 +74,9 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { // nothing to do } - protected static final boolean onlyNamesAttribute(RAbstractVector source) { + protected final boolean onlyNamesAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.NAMES_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.NAMES_ATTR_KEY; } @SuppressWarnings("unused") @@ -82,9 +85,9 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { // nothing to do } - protected static final boolean onlyClassAttribute(RAbstractVector source) { + protected final boolean onlyClassAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.CLASS_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.CLASS_ATTR_KEY; } @Specialization(guards = "onlyClassAttribute(source)") diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index ee4d814f981084f26fe209474fdbb1a721e4da9b..b26a5aca8397d77862132affd87663c5c274bbe6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -839,7 +839,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS FormalArguments formals = root.getFormalArguments(); if (root instanceof RBuiltinRootNode) { RBuiltinRootNode builtinRoot = (RBuiltinRootNode) root; - return new BuiltinCallNode(RBuiltinNode.inline(builtinRoot.getBuiltin(), null), builtinRoot.getBuiltin(), formals, originalCall); + return new BuiltinCallNode(RBuiltinNode.inline(builtinRoot.getBuiltin(), null), builtinRoot.getBuiltin(), formals, originalCall, explicitArgs); } else { return new DispatchedCallNode(cachedTarget, originalCall); } @@ -928,36 +928,54 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS private static final class BuiltinCallNode extends LeafCallNode { @Child private RBuiltinNode builtin; - @Child private PromiseCheckHelperNode promiseHelper; + @Child private PromiseCheckHelperNode varArgsPromiseHelper; + @Children private final PromiseHelperNode[] promiseHelpers; @Children private final CastNode[] casts; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); - private final BranchProfile emptyProfile = BranchProfile.create(); - private final BranchProfile varArgsProfile = BranchProfile.create(); - private final ConditionProfile wrapProfile = ConditionProfile.createBinaryProfile(); + // not using profiles to save overhead + @CompilationFinal private final boolean[] argEmptySeen; + @CompilationFinal private final boolean[] varArgSeen; + @CompilationFinal private final boolean[] nonWrapSeen; + @CompilationFinal private final boolean[] wrapSeen; + private final FormalArguments formals; private final RBuiltinDescriptor builtinDescriptor; + private final boolean explicitArgs; - BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall) { + BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall, boolean explicitArgs) { super(originalCall); this.builtin = builtin; this.builtinDescriptor = builtinDescriptor; + this.explicitArgs = explicitArgs; this.casts = builtin.getCasts(); this.formals = formalArguments; + promiseHelpers = new PromiseHelperNode[formals.getLength()]; + argEmptySeen = new boolean[formals.getLength()]; + varArgSeen = new boolean[formals.getLength()]; + nonWrapSeen = new boolean[formals.getLength()]; + wrapSeen = new boolean[formals.getLength()]; } @ExplodeLoop public Object[] castArguments(VirtualFrame frame, Object[] args) { int argCount = formals.getLength(); + int varArgIndex = formals.getSignature().getVarArgIndex(); Object[] result = new Object[argCount]; for (int i = 0; i < argCount; i++) { Object arg = args[i]; - if (arg == REmpty.instance) { - emptyProfile.enter(); + if (explicitArgs && arg == REmpty.instance) { + if (!argEmptySeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argEmptySeen[i] = true; + } arg = formals.getInternalDefaultArgumentAt(i); } - if (arg instanceof RArgsValuesAndNames) { - varArgsProfile.enter(); + if (varArgIndex == i && arg instanceof RArgsValuesAndNames) { + if (!varArgSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + varArgSeen[i] = true; + } RArgsValuesAndNames varArgs = (RArgsValuesAndNames) arg; if (builtinDescriptor.evaluatesArg(i)) { forcePromises(frame, varArgs); @@ -967,12 +985,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } else { if (builtinDescriptor.evaluatesArg(i)) { if (arg instanceof RPromise) { - if (promiseHelper == null) { + if (promiseHelpers[i] == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseCheckHelperNode()); + promiseHelpers[i] = insert(new PromiseHelperNode()); } - arg = promiseHelper.checkEvaluate(frame, arg); - + arg = promiseHelpers[i].evaluate(frame, (RPromise) arg); } if (i < casts.length && casts[i] != null) { assert builtinDescriptor.evaluatesArg(i); @@ -980,7 +997,16 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } } else { assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments"; - if (wrapProfile.profile(!(arg instanceof RPromise || arg instanceof RMissing))) { + if (arg instanceof RPromise || arg instanceof RMissing) { + if (!nonWrapSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + nonWrapSeen[i] = true; + } + } else { + if (!wrapSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + wrapSeen[i] = true; + } arg = createPromise(arg); } } @@ -993,11 +1019,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS private void forcePromises(VirtualFrame frame, RArgsValuesAndNames varArgs) { Object[] array = varArgs.getArguments(); for (int i = 0; i < array.length; i++) { - if (promiseHelper == null) { + if (varArgsPromiseHelper == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseCheckHelperNode()); + varArgsPromiseHelper = insert(new PromiseCheckHelperNode()); } - array[i] = promiseHelper.checkEvaluate(frame, array[i]); + array[i] = varArgsPromiseHelper.checkEvaluate(frame, array[i]); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java index 9cb4f0d2939053290bf23227eea5ed16281774fb..90437a0a43800871bbf1f9b5a22fe67c73bbe10d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.primitive; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; @@ -73,7 +74,7 @@ public final class BinaryMapNode extends RBaseNode { private final ConditionProfile maxLengthProfile; private final ConditionProfile leftIsNAProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile rightIsNAProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile seenEmpty = BranchProfile.create(); + private final ConditionProfile seenEmpty = ConditionProfile.createBinaryProfile(); private final ConditionProfile shareLeft; private final ConditionProfile shareRight; private final RType argumentType; @@ -229,16 +230,16 @@ public final class BinaryMapNode extends RBaseNode { private Object applyVectorized(RAbstractVector left, RAbstractVector leftCast, int leftLength, RAbstractVector right, RAbstractVector rightCast, int rightLength) { if (mayContainMetadata && (dimensionsProfile.profile(left.hasDimensions() && right.hasDimensions()))) { if (differentDimensions(left, right)) { + CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.NON_CONFORMABLE_ARRAYS); } } - if (leftLength == 0 || rightLength == 0) { + if (seenEmpty.profile(leftLength == 0 || rightLength == 0)) { /* * It is safe to skip attribute handling here as they are never copied if length is 0 of * either side. Note that dimension check still needs to be performed. */ - seenEmpty.enter(); return resultType.getEmpty(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java index 1c779089684ab3f4405a4289a2279be02d557295..98bfef344407cdf0d8a635dadf0742f77f547966 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java @@ -175,8 +175,12 @@ public final class UnaryMapNode extends RBaseNode { return result; } + private final ConditionProfile hasDimensionsProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile hasNamesProfile = ConditionProfile.createBinaryProfile(); + private boolean containsMetadata(RAbstractVector vector) { - return vector instanceof RVector && (vector.hasDimensions() || vector.getAttributes() != null || vector.getNames(attrProfiles) != null || vector.getDimNames(attrProfiles) != null); + return vector instanceof RVector && (hasDimensionsProfile.profile(vector.hasDimensions()) || vector.getAttributes() != null || hasNamesProfile.profile(vector.getNames(attrProfiles) != null) || + vector.getDimNames(attrProfiles) != null); } @TruffleBoundary diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java index 9132ef16228f3fa65e5b00ad550e40a32032a94e..7c3def09aa07d436b25b8cdbfdc7a4c5f13bff1a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java @@ -46,8 +46,6 @@ public final class ArgumentsSignature implements Iterable<String> { public static final String VARARG_NAME = "..."; public static final int NO_VARARG = -1; - private static final String VARARG_GETTER_PREFIX = ".."; - @CompilationFinal private static final ArgumentsSignature[] EMPTY_SIGNATURES = new ArgumentsSignature[32]; public static final ArgumentsSignature INVALID_SIGNATURE = new ArgumentsSignature(new String[]{"<<invalid>>"}); @@ -78,7 +76,7 @@ public final class ArgumentsSignature implements Iterable<String> { @CompilationFinal private final String[] names; @CompilationFinal private final int[] varArgIndexes; @CompilationFinal private final boolean[] isVarArg; - @CompilationFinal private final boolean[] isVarArgGetter; + private final int varArgIndex; private final int nonNullCount; private ArgumentsSignature(String[] names) { @@ -88,7 +86,6 @@ public final class ArgumentsSignature implements Iterable<String> { int index = NO_VARARG; int count = 0; this.isVarArg = new boolean[names.length]; - this.isVarArgGetter = new boolean[names.length]; for (int i = 0; i < names.length; i++) { String name = names[i]; if (name != null) { @@ -98,8 +95,6 @@ public final class ArgumentsSignature implements Iterable<String> { if (index != NO_VARARG) { index = i; } - } else if (name.startsWith(VARARG_GETTER_PREFIX)) { - this.isVarArgGetter[i] = true; } } } @@ -110,6 +105,7 @@ public final class ArgumentsSignature implements Iterable<String> { varArgIndexes[pos++] = i; } } + this.varArgIndex = varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0]; } public boolean isEmpty() { @@ -126,7 +122,7 @@ public final class ArgumentsSignature implements Iterable<String> { public int getVarArgIndex() { assert varArgIndexes.length <= 1 : "cannot ask for _the_ vararg index if there are multiple varargs"; - return varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0]; + return varArgIndex; } public int getVarArgCount() { @@ -207,7 +203,7 @@ public final class ArgumentsSignature implements Iterable<String> { * methods {@link #isVarArgsIndex(long)}, {@link #extractVarArgsArgumentIndex(long)} and * {@link #extractVarArgsArgumentIndex(long)} to access the data packed in the {@code long} * value. This method also removes arguments that are marked as 'unmatched' in the signature. - * + * * @param argListSize length of the result -- sum of lengths of all varargs contained within * varArgSignatures minus any unmatched arguments. */ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java index e73a6cd2d823f5592126a3502995b7364b1069a9..0fec763e0e56036ee7fb48ae964ffcfafebab476 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java @@ -29,6 +29,7 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Semaphore; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.RContext; @@ -42,12 +43,13 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RUnboundValue; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; /** * Implementation of a channel abstraction used for communication between parallel contexts in @@ -202,7 +204,7 @@ public class RChannel { private static class TransmitterCommon extends RSerialize.RefCounter { protected static class SerializedRef { - private int index; + private final int index; public SerializedRef(int index) { this.index = index; @@ -215,7 +217,7 @@ public class RChannel { protected static class SerializedList { - private RList list; + private final RList list; SerializedList(RList list) { this.list = list; @@ -229,8 +231,8 @@ public class RChannel { protected static class SerializedEnv { public static class Bindings { - private String[] names; - private Object[] values; + private final String[] names; + private final Object[] values; Bindings(String[] names, Object[] values) { this.names = names; @@ -268,9 +270,9 @@ public class RChannel { protected static class SerializedPromise { - private Object env; - private Object value; - private byte[] serializedExpr; + private final Object env; + private final Object value; + private final byte[] serializedExpr; public SerializedPromise(Object env, Object value, byte[] serializedExpr) { this.env = env; @@ -292,10 +294,34 @@ public class RChannel { } + protected static class SerializedFunction { + private final RAttributes attributes; + private final Object env; + private final byte[] serializedDef; + + public SerializedFunction(RAttributes attributes, Object env, byte[] serializedDef) { + this.attributes = attributes; + this.env = env; + this.serializedDef = serializedDef; + } + + public RAttributes getAttributes() { + return attributes; + } + + public Object getEnv() { + return env; + } + + public byte[] getSerializedDef() { + return serializedDef; + } + } + protected static class SerializedAttributable { - private RAttributes attributes; - private byte[] serializedAttributable; + private final RAttributes attributes; + private final byte[] serializedAttributable; public SerializedAttributable(RAttributes attributes, byte[] serializedAttributable) { this.attributes = attributes; @@ -401,6 +427,14 @@ public class RChannel { } + private SerializedFunction convertPrivateFunction(Object msg) throws IOException { + RFunction fn = (RFunction) msg; + byte[] serializedFunctionDef = RSerialize.serializeFunctionNonEnv(fn); + Object env = convertPrivate(REnvironment.frameToEnvironment(fn.getEnclosingFrame())); + RAttributes attributes = fn.getAttributes(); + return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, serializedFunctionDef); + } + private Object convertPrivateAttributable(Object msg) throws IOException { // do full serialization but handle attributes separately (no reason to serialize them // unconditionally) @@ -435,7 +469,7 @@ public class RChannel { } private static boolean serializeObject(Object o) { - return o instanceof RFunction || o instanceof REnvironment || o instanceof RConnection || o instanceof RLanguage; + return o instanceof REnvironment || o instanceof RConnection || o instanceof RLanguage; } private Object convertPrivate(Object o) throws IOException { @@ -445,6 +479,8 @@ public class RChannel { return convertPrivateEnv(o); } else if (o instanceof RPromise) { return convertPrivatePromise(o); + } else if (o instanceof RFunction) { + return convertPrivateFunction(o); } else if (!serializeObject(o)) { // we need to make internal values (permanently) shared to avoid updates to ref // count by different threads @@ -524,51 +560,11 @@ public class RChannel { } public Object processOutgoingMessage(Object data) { - Object msg = data; - if (msg instanceof RList) { - try { - msg = convertPrivateList(msg); - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating shareable list"); - } - } else if (shareableEnv(msg)) { - try { - msg = convertPrivateEnv(msg); - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating shareable environment"); - } - } else if (msg instanceof RPromise) { - try { - msg = convertPrivatePromise(msg); - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating shareable promise"); - } - } else if (!serializeObject(msg)) { - // make sure that what's passed through the channel will be copied on the first - // update - makeShared(msg); - try { - if (msg instanceof RAttributable && ((RAttributable) msg).getAttributes() != null) { - Object newMsg = convertObjectAttributesToPrivate(msg); - if (newMsg == msg) { - makeShared(msg); - } // otherwise a copy has been created to store new attributes - return newMsg; - } else { - return makeShared(msg); - } - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating channel message"); - } - } else { - assert msg instanceof RAttributable; - try { - msg = convertPrivateAttributable(msg); - } catch (IOException x) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error creating shareable attributable"); - } + try { + return convertPrivate(data); + } catch (IOException x) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error serializing message for channel transmission"); } - return msg; } } @@ -588,6 +584,8 @@ public class RChannel { ret = unserializeEnv((SerializedEnv) el); } else if (el instanceof SerializedPromise) { ret = unserializePromise((SerializedPromise) el); + } else if (el instanceof SerializedFunction) { + ret = unserializeFunction((SerializedFunction) el); } else if (el instanceof SerializedAttributable) { ret = unserializeAttributable((SerializedAttributable) el); } @@ -642,6 +640,25 @@ public class RChannel { return RSerialize.unserializePromise(expr, env, p.getValue()); } + @TruffleBoundary + private RFunction unserializeFunction(SerializedFunction f) throws IOException { + Map<String, Object> constants = new HashMap<>(); + RPairList l = (RPairList) RSerialize.unserialize(f.getSerializedDef(), null, null, null); + // seems like the best (only) way to make deparser see a correct pair list type here + RPairList closxpList = RDataFactory.createPairList(l.car(), l.cdr(), RNull.instance, SEXPTYPE.CLOSXP); + String deparse = RDeparse.deparseDeserialize(constants, closxpList); + REnvironment env = (REnvironment) unserializeObject(f.getEnv()); + MaterializedFrame enclosingFrame = env.getFrame(); + RFunction fn = RContext.getEngine().parseFunction(constants, null, RSource.fromTextInternal(deparse, RSource.Internal.PAIRLIST_DEPARSE), enclosingFrame); + RAttributes attributes = f.getAttributes(); + if (attributes != null) { + assert fn.getAttributes() == null; + // attributes unserialized in caller methods + fn.initAttributes(attributes); + } + return fn; + } + @TruffleBoundary private static RAttributable unserializeAttributable(SerializedAttributable a) throws IOException { RAttributes attributes = a.getAttributes(); @@ -668,9 +685,11 @@ public class RChannel { if (newVal != val) { // class attribute is a string vector which should be always shared assert !a.getName().equals(RRuntime.CLASS_ATTR_KEY); - // TODO: this is a bit brittle as it relies on the iterator to work correctly in + // TODO: this is a bit brittle as it relies on the iterator to work + // correctly in // the - // face of updates (which it does under current implementation of attributes) + // face of updates (which it does under current implementation of + // attributes) attributable.setAttr(a.getName(), newVal); } } @@ -678,24 +697,7 @@ public class RChannel { public Object processedReceivedMessage(Object msg) { try { - Object ret = msg; - if (msg instanceof SerializedList) { - RList list = ((SerializedList) msg).getList(); - // list and attributes are already private (shallow copies - do the appropriate - // changes in place) - unserializeList(list); - ret = list; - } else if (msg instanceof SerializedEnv) { - ret = unserializeEnv((SerializedEnv) msg); - } else if (msg instanceof SerializedPromise) { - ret = unserializePromise((SerializedPromise) msg); - } else if (msg instanceof SerializedAttributable) { - ret = unserializeAttributable((SerializedAttributable) msg); - } - if (ret instanceof RAttributable && ((RAttributable) ret).getAttributes() != null) { - unserializeAttributes((RAttributable) ret); - } - return ret; + return unserializeObject(msg); } catch (IOException x) { throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error unserializing msg from the channel"); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java index a4c2666b45d703bbe24068e2ddda4450b4d9c57d..0827b88505e7236f32f1e265b16d5a62fe59968c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java @@ -94,6 +94,11 @@ public interface RRuntimeASTAccess { */ void serializeNode(RSerialize.State state, Object node); + /** + * Helper function for {@code serialize} working around cyclic dependency. + */ + void serializeFunctionDefinitionNode(RSerialize.State state, RFunction fn); + /** * Returns the real caller associated with {@code rl}, by locating the {@code RSyntaxNode} * associated with the node stored with {@code rl}. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index cf63c459a0801639fa0e09200f7ce1938970d867..0f70a3f2a23cbfe9e1e33e7396581cc08f6f3c44 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -2262,6 +2262,24 @@ public class RSerialize { } } + @TruffleBoundary + public static byte[] serializeFunctionNonEnv(RFunction fn) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + Output output = new Output(out, XDR, DEFAULT_VERSION, null); + State state = new PLState(output); + state.openPairList(SEXPTYPE.CLOSXP); + RContext.getRRuntimeASTAccess().serializeFunctionDefinitionNode(state, fn); + Object res = state.closePairList(); + // CLOSXP-type ensures that the list is not shrunk + state.convertUnboundValues((RPairList) res); + output.serialize(state, res); + return out.toByteArray(); + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); + } + } + @TruffleBoundary public static void serialize(RConnection conn, Object obj, int type, int version, Object refhook) throws IOException { Output output = new Output(conn, type, version, (CallHook) refhook); 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 f14f81f0e2490e343fce14310a77e725cd894dc4..55b970ddc97b6a285dda59fc42380e4b08aca143 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 @@ -7011,6 +7011,16 @@ raw(0) #argv <- list(list());as.raw(argv[[1]]); raw(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_assign.testassign +#x <- c(1,2,4); e <- new.env(); assign('foo', x, e); x[[1]] <- 5; x; get('foo', e) +[1] 5 2 4 +[1] 1 2 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_assign.testassign +#x <- c(1,2,4); e <- new.env(); assign('foo', x, e, inherits=0); x[[1]] <- 5; x; get('foo', e) +[1] 5 2 4 +[1] 1 2 4 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_assign.testassign1 #argv <- structure(list(x = '`', value = TRUE), .Names = c('x', 'value'));do.call('assign', argv) @@ -108830,6 +108840,10 @@ a b c d e #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels16.R") } [1] 7 7 +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels17.R") } +[1] 42 7 + ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels2.R") } [[1]] diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java index 5f58a4207b4a06023d731072559ddc46e703c28b..56b2634e7bd148379b854990670f847e107d8261 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_assign.java @@ -22,4 +22,10 @@ public class TestBuiltin_assign extends TestBase { public void testassign1() { assertEval("argv <- structure(list(x = '`', value = TRUE), .Names = c('x', 'value'));do.call('assign', argv)"); } + + @Test + public void testassign() { + assertEval("x <- c(1,2,4); e <- new.env(); assign('foo', x, e); x[[1]] <- 5; x; get('foo', e)"); + assertEval("x <- c(1,2,4); e <- new.env(); assign('foo', x, e, inherits=0); x[[1]] <- 5; x; get('foo', e)"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R new file mode 100644 index 0000000000000000000000000000000000000000..68cc2c1f8467af241a592f689a0420c43fe56fc8 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R @@ -0,0 +1,18 @@ +# test passing a function (environment must stay private) + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch <- .fastr.channel.create(1L) + code <- "ch <- .fastr.channel.get(1L); f<-.fastr.channel.receive(ch); env <- environment(f); env[['x']] <- 7; .fastr.channel.send(ch, env[['x']])" + cx <- .fastr.context.spawn(code) + env <- new.env() + env[["x"]] <- 42 + f <- function() 42 + environment(f) <- env + .fastr.channel.send(ch, f) + y <- .fastr.channel.receive(ch) + .fastr.context.join(cx) + .fastr.channel.close(ch) + print(c(env[["x"]], y)) +} else { + print(c(42, 7)) +}