diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index b7cc4812af454213b9f08f7492e38b9332378514..ee090e1c1ac7134433c540a1242dc2a56006ab89 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -77,6 +77,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; import com.oracle.truffle.r.runtime.ReturnException; +import com.oracle.truffle.r.runtime.RootWithBody; import com.oracle.truffle.r.runtime.SubstituteVirtualFrame; import com.oracle.truffle.r.runtime.ThreadTimings; import com.oracle.truffle.r.runtime.Utils; @@ -476,7 +477,7 @@ final class REngine implements Engine, Engine.Timings { * context of that frame. Note that passing only this one frame argument, strictly spoken, * violates the frame layout as set forth in {@link RArguments}. This is for internal use only. */ - private final class AnonymousRootNode extends RootNode { + private final class AnonymousRootNode extends RootNode implements RootWithBody { private final ValueProfile frameTypeProfile = ValueProfile.createClassProfile(); private final ConditionProfile isVirtualFrameProfile = ConditionProfile.createBinaryProfile(); @@ -566,6 +567,11 @@ final class REngine implements Engine, Engine.Timings { public boolean isCloningAllowed() { return false; } + + @Override + public RNode getBody() { + return body; + } } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b72e022b321a7d8fa76f41a506f474f6bd84ab90 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.nodes.test; + +import org.junit.Assert; +import org.junit.Test; + +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.nodes.access.WriteVariableSyntaxNode; +import com.oracle.truffle.r.nodes.control.BlockNode; +import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode; +import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.nodes.function.RCallSpecialNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.FastROptions; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RootWithBody; +import com.oracle.truffle.r.runtime.data.RExpression; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; + +public class SpecialCallTest extends TestBase { + private static final class CountCallsVisitor extends RSyntaxVisitor<Void> { + + public int normal; + public int special; + + CountCallsVisitor(RootCallTarget callTarget) { + accept(((RootWithBody) callTarget.getRootNode()).getBody().asRSyntaxNode()); + } + + @Override + protected Void visit(RSyntaxCall element) { + if (element instanceof RCallSpecialNode) { + special++; + } else if (element instanceof RCallNode) { + normal++; + } else { + assert element instanceof ReplacementDispatchNode || element instanceof WriteVariableSyntaxNode || element instanceof BlockNode : "unexpected node while testing"; + } + accept(element.getSyntaxLHS()); + for (RSyntaxElement arg : element.getSyntaxArguments()) { + accept(arg); + } + return null; + } + + @Override + protected Void visit(RSyntaxConstant element) { + return null; + } + + @Override + protected Void visit(RSyntaxLookup element) { + return null; + } + + @Override + protected Void visit(RSyntaxFunction element) { + for (RSyntaxElement arg : element.getSyntaxArgumentDefaults()) { + accept(arg); + } + accept(element.getSyntaxBody()); + return null; + } + } + + private static final class PrintCallsVisitor extends RSyntaxVisitor<Void> { + + private String indent = ""; + + void print(RootCallTarget callTarget) { + System.out.println(); + accept(((RootWithBody) callTarget.getRootNode()).getBody().asRSyntaxNode()); + } + + @Override + protected Void visit(RSyntaxCall element) { + System.out.println(indent + "call " + element.getClass().getSimpleName()); + indent += " "; + System.out.println(indent.substring(2) + "lhs:"); + accept(element.getSyntaxLHS()); + printArgs(element.getSyntaxSignature(), element.getSyntaxArguments()); + indent = indent.substring(4); + return null; + } + + @Override + protected Void visit(RSyntaxConstant element) { + System.out.println(indent + "constant " + element.getClass().getSimpleName() + " " + element.getValue().getClass().getSimpleName() + " " + element.getValue()); + return null; + } + + @Override + protected Void visit(RSyntaxLookup element) { + System.out.println(indent + "lookup " + element.getClass().getSimpleName() + " " + element.getIdentifier()); + return null; + } + + @Override + protected Void visit(RSyntaxFunction element) { + System.out.println(indent + "function " + element.getClass().getSimpleName()); + indent += " "; + printArgs(element.getSyntaxSignature(), element.getSyntaxArgumentDefaults()); + indent = indent.substring(4); + for (RSyntaxElement arg : element.getSyntaxArgumentDefaults()) { + accept(arg); + } + System.out.println(indent.substring(2) + "body:"); + accept(element.getSyntaxBody()); + return null; + } + + private void printArgs(ArgumentsSignature signature, RSyntaxElement[] arguments) { + for (int i = 0; i < arguments.length; i++) { + System.out.println(indent.substring(2) + "arg " + (signature.getName(i) == null ? "<unnamed>" : signature.getName(i))); + accept(arguments[i]); + } + } + } + + @Test + public void testBasic() { + // check a case with no calls + assertCallCounts("library(stats)", 0, 1, 0, 1); + } + + @Test + public void testArithmetic() { + assertCallCounts("1 + 1", 1, 0, 1, 0); + assertCallCounts("1 + 1 * 2 + 4", 3, 0, 3, 0); + + assertCallCounts("{ a <- 1; b <- 2; a + b }", 1, 0, 1, 0); + assertCallCounts("{ a <- 1; b <- 2; c <- 3; a + b * 2 * c}", 3, 0, 3, 0); + + assertCallCounts("{ a <- data.frame(a=1); b <- 2; c <- 3; a + b * 2 * c}", 3, 1, 2, 2); + assertCallCounts("{ a <- 1; b <- data.frame(a=1); c <- 3; a + b * 2 * c}", 3, 1, 0, 4); + + assertCallCounts("1 %*% 1", 0, 1, 0, 1); + } + + @Test + public void testSubset() { + assertCallCounts("{ a <- 1:10; a[1] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[2] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[4] }", 1, 1, 1, 1); + assertCallCounts("{ a <- list(c(1,2,3,4),2,3); a[1] }", 1, 2, 1, 2); + + assertCallCounts("{ a <- c(1,2,3,4); a[0.1] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[5] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[0] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[-1] }", 0, 3, 0, 3); // "-1" is a unary expression + assertCallCounts("{ a <- c(1,2,3,4); b <- -1; a[b] }", 1, 2, 0, 3); + assertCallCounts("{ a <- c(1,2,3,4); a[NA_integer_] }", 1, 1, 0, 2); + } + + @Test + public void testSubscript() { + assertCallCounts("{ a <- 1:10; a[[1]] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[[2]] }", 1, 1, 1, 1); + assertCallCounts("{ a <- c(1,2,3,4); a[[4]] }", 1, 1, 1, 1); + assertCallCounts("{ a <- list(c(1,2,3,4),2,3); a[[1]] }", 1, 2, 1, 2); + assertCallCounts("{ a <- list(a=c(1,2,3,4),2,3); a[[1]] }", 1, 2, 1, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[[0.1]] }", 1, 1, 1, 1); + + assertCallCounts("{ a <- c(1,2,3,4); a[[5]] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); a[[0]] }", 1, 1, 0, 2); + assertCallCounts("{ a <- c(1,2,3,4); b <- -1; a[[b]] }", 1, 2, 0, 3); + assertCallCounts("{ a <- c(1,2,3,4); a[[NA_integer_]] }", 1, 1, 0, 2); + } + + private static void assertCallCounts(String str, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) { + if (!FastROptions.UseSpecials.getBooleanValue()) { + return; + } + Source source = Source.newBuilder(str).mimeType(TruffleRLanguage.MIME).name("test").build(); + + RExpression expression = testVMContext.getThisEngine().parse(source); + assert expression.getLength() == 1; + RootCallTarget callTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) expression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test"); + + try { + CountCallsVisitor count1 = new CountCallsVisitor(callTarget); + Assert.assertEquals("initial special call count '" + str + "': ", initialSpecialCount, count1.special); + Assert.assertEquals("initial normal call count '" + str + "': ", initialNormalCount, count1.normal); + + try { + callTarget.call(REnvironment.globalEnv().getFrame()); + } catch (RError e) { + // ignore + } + + CountCallsVisitor count2 = new CountCallsVisitor(callTarget); + Assert.assertEquals("special call count after first call '" + str + "': ", finalSpecialCount, count2.special); + Assert.assertEquals("normal call count after first call '" + str + "': ", finalNormalCount, count2.normal); + + try { + callTarget.call(REnvironment.globalEnv().getFrame()); + } catch (RError e) { + // ignore + } + + CountCallsVisitor count3 = new CountCallsVisitor(callTarget); + Assert.assertEquals("special call count after second call '" + str + "': ", finalSpecialCount, count3.special); + Assert.assertEquals("normal call count after second call '" + str + "': ", finalNormalCount, count3.normal); + } catch (AssertionError e) { + new PrintCallsVisitor().print(callTarget); + throw e; + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java index 1e0d45dfc2e5aa3d9ca3f66eb0c9cb9367680a62..936e2babd89f1a40e0485779285835a07c622653 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java @@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.RCallSpecialNode; -import com.oracle.truffle.r.nodes.function.RCallSpecialNode.RecursiveSpecialBailout; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -241,10 +240,10 @@ abstract class ReplacementNode extends OperatorNode { RNode extractFunc = target; for (int i = calls.size() - 1; i >= 1; i--) { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); - ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(true); + ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); } this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create("*rhs*" + tempNamesStartIndex), calls.get(0), codeBuilderContext); - this.replaceCall.setPropagateFullCallNeededException(true); + this.replaceCall.setPropagateFullCallNeededException(); } @Override @@ -255,7 +254,7 @@ abstract class ReplacementNode extends OperatorNode { // shared, it could not be extracted from a shared container (list), so we should be // OK with not calling any other update function and just update the value directly. replaceCall.execute(frame); - } catch (FullCallNeededException | RecursiveSpecialBailout e) { + } catch (FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex)).executeReplacement(frame); } @@ -295,10 +294,10 @@ abstract class ReplacementNode extends OperatorNode { RNode extractFunc = target; for (int i = calls.size() - 1; i >= 1; i--) { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); - ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(true); + ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); } this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), rhs.asRSyntaxNode(), calls.get(0), codeBuilderContext); - this.replaceCall.setPropagateFullCallNeededException(true); + this.replaceCall.setPropagateFullCallNeededException(); } @Override @@ -316,17 +315,16 @@ abstract class ReplacementNode extends OperatorNode { // shared, it could not be extracted from a shared container (list), so we should be // OK with not calling any other update function and just update the value directly. replaceCall.execute(frame); - } catch (FullCallNeededException | RecursiveSpecialBailout e) { + } catch (FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); GenericReplacementNode replacement = replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex)); - Object rhsValue = e instanceof FullCallNeededException ? ((FullCallNeededException) e).rhsValue : ((RecursiveSpecialBailout) e).rhsValue; - if (rhsValue == null) { + if (e.rhsValue == null) { // we haven't queried the rhs value yet replacement.voidExecute(frame); } else { // rhs was already queried, so pass it along - replacement.voidExecuteWithRhs(frame, rhsValue); + replacement.voidExecuteWithRhs(frame, e.rhsValue); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java index 8259598aa45b9f78292eed86efc0d6672be9283c..830bf51331a185cf2cc207e1bc7c22577f1aace2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.Arrays; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.VirtualFrame; @@ -37,7 +35,6 @@ import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; -import com.oracle.truffle.r.runtime.builtins.RSpecialFactory.FullCallNeededException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RPromise; @@ -98,7 +95,6 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup { public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall { - private static final int NO_RECURSIVE_ARGUMENT_INDEX = -1; private static final boolean useSpecials = FastROptions.UseSpecials.getBooleanValue(); // currently cannot be RSourceSectionNode because of TruffleDSL restrictions @@ -129,12 +125,16 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode private final RFunction expectedFunction; /** - * If this instance is argument of another RCallSpecialNode (parent), then this will be the - * index into the parent arguments array, otherwise {@link #NO_RECURSIVE_ARGUMENT_INDEX}. + * If this is true, then any bailout should simply be forwarded by re-throwing the exception. */ - private int argumentIndex = NO_RECURSIVE_ARGUMENT_INDEX; private boolean propagateFullCallNeededException; + /** + * If this is non-null, then any bailout should lead to be forwarded by re-throwing the + * exception after replacing itself with a proper call node. + */ + private RCallSpecialNode callSpecialParent; + private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special) { this.sourceSectionR = sourceSection; this.expectedFunction = expectedFunction; @@ -206,7 +206,6 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode localArguments[i] = RContext.getASTBuilder().process(arguments[i]).asRNode(); } else { assert arguments[i] instanceof RCallSpecialNode; - ((RCallSpecialNode) arguments[i]).setArgumentIndex(i); localArguments[i] = arguments[i].asRNode(); } } @@ -219,7 +218,15 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode RFunction expectedFunction = RContext.lookupBuiltin(name); RInternalError.guarantee(expectedFunction != null); - return new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special); + RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special); + for (int i = 0; i < arguments.length; i++) { + if (!inReplace || !contains(ignoredArguments, i)) { + if (arguments[i] instanceof RCallSpecialNode) { + ((RCallSpecialNode) arguments[i]).setCallSpecialParent(callSpecial); + } + } + } + return callSpecial; } private static boolean contains(int[] ignoredArguments, int index) { @@ -239,45 +246,30 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode throw RSpecialFactory.throwFullCallNeeded(); } return special.execute(frame); - } catch (RecursiveSpecialBailout bailout) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - throwOnRecursiveSpecial(bailout.rhsValue); - return replace(getRCallNode(rewriteSpecialArgument(bailout))).execute(frame, function); } catch (RSpecialFactory.FullCallNeededException e) { CompilerDirectives.transferToInterpreterAndInvalidate(); - throwOnRecursiveSpecial(e.rhsValue); - return replace(getRCallNode()).execute(frame, function); - } - } - - private void throwOnRecursiveSpecial(Object rhsValue) { - if (isRecursiveSpecial()) { - throw new RecursiveSpecialBailout(argumentIndex, rhsValue); + if (propagateFullCallNeededException) { + throw e; + } + RCallNode callNode = getRCallNode(); + for (RSyntaxElement arg : arguments) { + if (arg instanceof RCallSpecialNode) { + ((RCallSpecialNode) arg).setCallSpecialParent(null); + } + } + if (callSpecialParent != null) { + RSyntaxNode[] args = callSpecialParent.arguments; + for (int i = 0; i < args.length; i++) { + if (args[i] == this) { + args[i] = callNode; + } + } + throw e; + } + return replace(callNode).execute(frame, function); } } - private RSyntaxNode[] rewriteSpecialArgument(RecursiveSpecialBailout bailout) { - // Note: other arguments that may be specials too, stay specials, their parent node will be - // changed in createRCallNode, but we are never going to use the original parent, which is - // the 'this.special' node that bailed out. - // Note 2: we have to make a copy of the array, because this node may have been shallow - // copied and the other copy will keep its copied parent, i.e. bailout exception from here - // will not reach the copied parent, but we would rewrite one of its arguments to full-blown - // RCallNode. It seems that bailing out happens less frequently than Node.copy, so we do the - // copying here. - RSyntaxNode[] newArguments = Arrays.copyOf(arguments, arguments.length); - RCallSpecialNode arg = (RCallSpecialNode) arguments[bailout.argumentIndex]; - newArguments[bailout.argumentIndex] = arg.getRCallNode(); - return newArguments; - } - - private boolean isRecursiveSpecial() { - // Note: we need to check the parent's parent, because it might have been rewritten by - // bailout of some of its other arguments. If parent is special node, then its parent must - // be RCallSpecialNode - return propagateFullCallNeededException || (argumentIndex != NO_RECURSIVE_ARGUMENT_INDEX && getParent() != null && getParent().getParent() instanceof RCallSpecialNode); - } - private RCallNode getRCallNode(RSyntaxNode[] newArguments) { return RCallNode.createCall(sourceSectionR, functionNode == null ? null : functionNode.getValueNode(), signature, newArguments); } @@ -286,16 +278,18 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode return getRCallNode(arguments); } - private void setArgumentIndex(int index) { - argumentIndex = index; + /** + * see {@link #propagateFullCallNeededException}. + */ + public void setPropagateFullCallNeededException() { + propagateFullCallNeededException = true; } /** - * If set to {@code true} the special call will raise {@link FullCallNeededException} even when - * the parent is a special call. + * see {@link #callSpecialParent}. */ - public void setPropagateFullCallNeededException(boolean flag) { - propagateFullCallNeededException = flag; + private void setCallSpecialParent(RCallSpecialNode call) { + callSpecialParent = call; } @Override @@ -318,20 +312,4 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode public RSyntaxElement[] getSyntaxArguments() { return arguments == null ? new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "...", false)} : arguments; } - - @SuppressWarnings("serial") - public static final class RecursiveSpecialBailout extends RuntimeException { - public final int argumentIndex; - public final Object rhsValue; - - RecursiveSpecialBailout(int argumentIndex, Object rhsValue) { - this.argumentIndex = argumentIndex; - this.rhsValue = rhsValue; - } - - @Override - public synchronized Throwable fillInStackTrace() { - return null; - } - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RootWithBody.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RootWithBody.java new file mode 100644 index 0000000000000000000000000000000000000000..b2736e10e5e517f3d2d9d73c1109e44cfdfdd3ba --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RootWithBody.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, 2016, 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; + +import com.oracle.truffle.r.runtime.nodes.RNode; + +/** + * Used for testing. + */ +public interface RootWithBody { + + RNode getBody(); +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java index 8c434b5af633b287c8aed8345d2e8fe4b6625689..94d1d71fb49c3ac82b4b3f74a69a2f5fa3e18356 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java @@ -31,8 +31,6 @@ public class RExpression extends RListBase implements RAbstractVector { private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Expression.getClazz()); - public String elementNamePrefix; - RExpression(Object[] data, int[] dims, RStringVector names) { super(data, dims, names); } 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 770ebe2b4ec977c8fd227b52fcf946edeb8a4417..e8978bb9d46e9afe5b8e564249e6a48f9f668c07 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 @@ -4039,7 +4039,7 @@ attr(,"match.length") [1] -1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_args.testArgs# +##com.oracle.truffle.r.test.builtins.TestBuiltin_args.testArgs#Output.IgnoreWhitespace# #{ f <- function(x=1, y) x + y; args(f); } function (x = 1, y) NULL @@ -6139,12 +6139,12 @@ Error in as.vector(x, "expression") : #argv <- structure(list(x = 1), .Names = 'x');do.call('as.expression', argv) expression(1) -##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#Output.IgnoreWhitespace# #as.function(c(alist(a=1+14, b=foo(x),c=), quote(a+foo(c)*b))) function (a = 1 + 14, b = foo(x), c) a + foo(c) * b -##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#Output.IgnoreWhitespace# #f <- function() a+foo(c)*b; as.function(c(alist(a=1+14, b=foo(x),c=), body(f))) function (a = 1 + 14, b = foo(x), c) a + foo(c) * b