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 94ed95a323a79511e84ffc81b2a865a7a16a9db0..8548fd442c15ecd31ca37bedcb274c3f4eeb39d7 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 @@ -64,7 +64,6 @@ import com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; import com.oracle.truffle.r.runtime.RParserFactory; import com.oracle.truffle.r.runtime.RProfile; import com.oracle.truffle.r.runtime.RRuntime; @@ -209,7 +208,7 @@ final class REngine implements Engine, Engine.Timings { } // Should this print the result? try { - parseAndEval(RSource.fromText(call, RInternalSourceDescriptions.STARTUP_SHUTDOWN), globalFrame, false); + parseAndEval(RSource.fromTextInternal(call, RSource.Internal.STARTUP_SHUTDOWN), globalFrame, false); } catch (ParseException e) { throw new RInternalError(e, "error while parsing startup function"); } @@ -242,7 +241,7 @@ final class REngine implements Engine, Engine.Timings { try { Object lastValue = RNull.instance; for (RSyntaxNode node : list) { - RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), RInternalSourceDescriptions.REPL_WRAPPER, printResult, true); + RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), RSource.Internal.REPL_WRAPPER.string, printResult, true); lastValue = callTarget.call(frame); } return lastValue; @@ -300,7 +299,7 @@ final class REngine implements Engine, Engine.Timings { @SuppressWarnings("unchecked") @Child private FindContextNode<RContext> findContext = (FindContextNode<RContext>) TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); PolyglotEngineRootNode(List<RSyntaxNode> statements) { - super(TruffleRLanguage.class, SourceSection.createUnavailable("repl", RInternalSourceDescriptions.REPL_WRAPPER), new FrameDescriptor()); + super(TruffleRLanguage.class, SourceSection.createUnavailable("repl", RSource.Internal.REPL_WRAPPER.string), new FrameDescriptor()); this.statements = statements; } @@ -317,7 +316,7 @@ final class REngine implements Engine, Engine.Timings { try { Object lastValue = RNull.instance; for (RSyntaxNode node : statements) { - RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), RInternalSourceDescriptions.REPL_WRAPPER, true, true); + RootCallTarget callTarget = doMakeCallTarget(node.asRNode(), RSource.Internal.REPL_WRAPPER.string, true, true); lastValue = callTarget.call(newContext.stateREnvironment.getGlobalFrame()); } return lastValue; @@ -376,7 +375,7 @@ final class REngine implements Engine, Engine.Timings { if (n instanceof ConstantNode) { return ((ConstantNode) n).getValue(); } - RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME, false, false); + RootCallTarget callTarget = doMakeCallTarget(n, RSource.Internal.EVAL_WRAPPER.string, false, false); return callTarget.call(frame); } @@ -402,7 +401,7 @@ final class REngine implements Engine, Engine.Timings { // we need to copy the node, otherwise it (and its children) will specialized to a specific // frame descriptor and will fail on subsequent re-executions RSyntaxNode n = RContext.getASTBuilder().process(exprRep); - RootCallTarget callTarget = doMakeCallTarget(n.asRNode(), EVAL_FUNCTION_NAME, false, false); + RootCallTarget callTarget = doMakeCallTarget(n.asRNode(), RSource.Internal.EVAL_WRAPPER.string, false, false); return evalTarget(callTarget, caller, envir); } 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 f530a95f4a555018d359fb57490f8f1daef8c891..1cc9f5502c982708473f2bfa859f3c34486382a9 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 @@ -447,7 +447,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { @Override public void setFunctionName(RootNode node, String name) { - ((FunctionDefinitionNode) node).setDescription(name); + ((FunctionDefinitionNode) node).setName(name); } @Override diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java index 3dca9591b06ab35ffaa1a8af64fc0bf1e73f400f..0c5cdcd86f9305b26df4fac1ccff5bb2c7ba34c0 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java @@ -27,7 +27,7 @@ import java.io.IOException; import java.io.PrintWriter; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; +import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.RContext; @@ -115,7 +115,7 @@ class JLineConsoleHandler implements ConsoleHandler { @Override public String getInputDescription() { - return RInternalSourceDescriptions.SHELL_INPUT; + return RSource.Internal.SHELL_INPUT.string; } @Override diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java index 318e42ae6647257c8346cf2e7db592a8ea043f49..3911f4468da9e666304337ef8daead8ddaa8ec5c 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java @@ -52,7 +52,6 @@ import com.oracle.truffle.r.nodes.builtin.base.Quit; import com.oracle.truffle.r.runtime.BrowserQuitException; import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.Utils; @@ -139,7 +138,7 @@ public class RCommand { if (!options.getBoolean(SLAVE)) { options.setValue(NO_SAVE, true); } - consoleHandler = new StringConsoleHandler(exprs, System.out, RInternalSourceDescriptions.EXPRESSION_INPUT); + consoleHandler = new StringConsoleHandler(exprs, System.out, RSource.Internal.EXPRESSION_INPUT.string); } else { /* * GnuR behavior differs from the manual entry for {@code interactive} in that {@code @@ -172,8 +171,8 @@ public class RCommand { return ContextInfo.create(options, ContextKind.SHARE_NOTHING, null, consoleHandler); } - private static final Source GET_ECHO = RSource.fromText("invisible(getOption('echo'))", RInternalSourceDescriptions.GET_ECHO); - private static final Source QUIT_EOF = RSource.fromText("quit(\"default\", 0L, TRUE)", RInternalSourceDescriptions.QUIT_EOF); + private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO); + private static final Source QUIT_EOF = RSource.fromTextInternal("quit(\"default\", 0L, TRUE)", RSource.Internal.QUIT_EOF); /** * The read-eval-print loop, which can take input from a console, command line expression or a @@ -187,7 +186,7 @@ public class RCommand { * exiting. So,in either case, we never return. */ static void readEvalPrint(ContextInfo info) { - PolyglotEngine vm = info.apply(PolyglotEngine.newBuilder()).build(); + PolyglotEngine vm = info.createVM(); ConsoleHandler consoleHandler = info.getConsoleHandler(); try { // console.println("initialize time: " + (System.currentTimeMillis() - start)); @@ -207,7 +206,7 @@ public class RCommand { String continuePrompt = getContinuePrompt(); StringBuffer sb = new StringBuffer(input); - Source source = RSource.fromText(sb.toString(), RInternalSourceDescriptions.SHELL_INPUT); + Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT); while (true) { /* * N.B. As of Truffle rev 371045b1312d412bafa29882e6c3f7bfe6c0f8f1, only @@ -225,7 +224,7 @@ public class RCommand { throw new EOFException(); } sb.append(additionalInput); - source = RSource.fromText(sb.toString(), RInternalSourceDescriptions.SHELL_INPUT); + source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT); // The only continuation in the while loop continue; } catch (ParseException e) { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java new file mode 100644 index 0000000000000000000000000000000000000000..d03f663b1151eaae9a39bdecede4f62e9996a80e --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2016, 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.library.utils; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.function.Function; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; +import com.oracle.truffle.api.instrumentation.EventContext; +import com.oracle.truffle.api.instrumentation.ExecutionEventListener; +import com.oracle.truffle.api.instrumentation.SourceSectionFilter; +import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; +import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; +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.Utils; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState.RprofState; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; + +public abstract class Rprof extends RExternalBuiltinNode.Arg8 { + + @SuppressWarnings("unused") + @Specialization + public Object doRprof(RAbstractStringVector filenameVec, byte appendL, double intervalD, byte memProfilingL, + byte gcProfilingL, byte lineProfilingL, int numFiles, int bufSize) { + if (!RContext.getInstance().isInitial()) { + throw RError.error(this, RError.Message.GENERIC, "profiling not supported in created contexts"); + } + RprofState profState = RContext.getInstance().stateInstrumentation.getRprof(); + String filename = filenameVec.getDataAt(0); + if (filename.length() == 0) { + // disable + endProfiling(); + } else { + // enable + if (profState.out() != null) { + endProfiling(); + } + boolean append = RRuntime.fromLogical(appendL); + boolean memProfiling = RRuntime.fromLogical(memProfilingL); + boolean gcProfiling = RRuntime.fromLogical(gcProfilingL); + try { + PrintWriter out = new PrintWriter(new FileWriter(filename, append)); + if (memProfiling) { + RError.warning(this, RError.Message.GENERIC, "Rprof: memory profiling not supported"); + } + if (gcProfiling) { + RError.warning(this, RError.Message.GENERIC, "Rprof: gc profiling not supported"); + } + // interval is in seconds, we convert to millis + long intervalInMillis = (long) (1E3 * intervalD); + StatementListener statementListener = new StatementListener(); + ProfileThread profileThread = new ProfileThread(intervalInMillis, statementListener); + profileThread.setDaemon(true); + profState.initialize(out, profileThread, statementListener, intervalInMillis, RRuntime.fromLogical(lineProfilingL)); + profileThread.start(); + } catch (IOException ex) { + throw RError.error(this, RError.Message.GENERIC, String.format("Rprof: cannot open profile file '%s'", filename)); + } + } + return RNull.instance; + } + + private static void endProfiling() { + RprofState profState = RContext.getInstance().stateInstrumentation.getRprof(); + ProfileThread profileThread = (ProfileThread) profState.profileThread(); + profileThread.running = false; + HashMap<String, Integer> fileMap = null; + PrintWriter out = profState.out(); + StatementListener statementListener = (StatementListener) profState.statementListener(); + if (profState.lineProfiling()) { + out.print("line profiling: "); + } + out.printf("sample.interval=%d\n", profState.intervalInMillis() * 1000); + if (profState.lineProfiling()) { + // scan stacks to find files + fileMap = new HashMap<>(); + int fileIndex = 0; + for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { + for (RSyntaxNode node : intervalStack) { + String path = getPath(node); + if (path != null && fileMap.get(path) == null) { + fileMap.put(path, ++fileIndex); + out.printf("#File %d: %s\n", fileIndex, path); + } + } + } + } + for (ArrayList<RSyntaxNode> intervalStack : statementListener.intervalStacks) { + for (RSyntaxNode node : intervalStack) { + RootNode rootNode = node.asRNode().getRootNode(); + if (rootNode instanceof FunctionDefinitionNode) { + String name = rootNode.getName(); + if (profState.lineProfiling()) { + Integer fileIndex = fileMap.get(getPath(node)); + if (fileIndex != null) { + out.printf("%d#%d ", fileIndex, node.getSourceSection().getStartLine()); + } + } + out.printf("\"%s\" ", name); + } + } + out.println(); + } + out.close(); + } + + private static String getPath(RSyntaxNode node) { + Source source = node.getSourceSection().getSource(); + String path = RSource.getPath(source); + return path; + } + + private static final class ProfileThread extends Thread { + private final long interval; + private final StatementListener statementListener; + private volatile boolean running = true; + + private ProfileThread(long interval, StatementListener statementListener) { + this.interval = interval; + this.statementListener = statementListener; + } + + @Override + public void run() { + while (running) { + try { + Thread.sleep(interval); + statementListener.intervalElapsed(); + } catch (InterruptedException ex) { + + } + } + } + + } + + /** + * Emulates a sampling timer by checking when the sample interval rolls over and at that point + * collects the stack of functions. + */ + private static final class StatementListener implements ExecutionEventListener { + private ArrayList<ArrayList<RSyntaxNode>> intervalStacks = new ArrayList<>(); + private volatile boolean newInterval; + + private StatementListener() { + SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder(); + builder.tagIs(StandardTags.StatementTag.class); + SourceSectionFilter filter = builder.build(); + RInstrumentation.getInstrumenter().attachListener(filter, this); + } + + private void intervalElapsed() { + newInterval = true; + } + + @Override + public void onEnter(EventContext context, VirtualFrame frame) { + if (newInterval) { + /* context tells here we are now, frame provides callers. */ + final ArrayList<RSyntaxNode> stack = new ArrayList<>(); + stack.add((RSyntaxNode) context.getInstrumentedNode()); + collectStack(stack); + intervalStacks.add(stack); + newInterval = false; + } + } + + @TruffleBoundary + private static void collectStack(final ArrayList<RSyntaxNode> stack) { + Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { + + @Override + public Object apply(Frame f) { + RCaller call = RArguments.getCall(f); + if (call != null && call.isValidCaller()) { + while (call.isPromise()) { + call = call.getParent(); + } + RSyntaxNode syntaxNode = call.getSyntaxNode(); + stack.add(syntaxNode); + } + return null; + } + + }); + } + + @Override + public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { + } + + @Override + public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { + } + + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index fad9160130ca1186ab100605899d2220ea87fe66..d0e3a8c0b290f4475b190a19221974a6ec1ebd32 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -44,14 +44,12 @@ import com.oracle.truffle.r.nodes.builtin.base.foreign.DotC; import com.oracle.truffle.r.nodes.builtin.base.foreign.DotCNodeGen; import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctions; import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctionsFactory; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRCallCounting; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRCallCountingFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRContext; import com.oracle.truffle.r.nodes.builtin.fastr.FastRContextFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebug; import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebugNodeGen; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRFunctionTimer; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRFunctionTimerFactory; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRFunctionProfiler; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRFunctionProfilerFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentity; import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentityNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspect; @@ -277,8 +275,6 @@ public class BasePackage extends RBuiltinPackage { add(WithVisible.class, WithVisibleNodeGen::create); add(Exists.class, ExistsNodeGen::create); add(Expression.class, ExpressionNodeGen::create); - add(FastRCallCounting.CreateCallCounter.class, FastRCallCountingFactory.CreateCallCounterNodeGen::create); - add(FastRCallCounting.GetCallCounter.class, FastRCallCountingFactory.GetCallCounterNodeGen::create); add(FastRContext.CloseChannel.class, FastRContextFactory.CloseChannelNodeGen::create); add(FastRContext.Create.class, FastRContextFactory.CreateNodeGen::create); add(FastRContext.CreateChannel.class, FastRContextFactory.CreateChannelNodeGen::create); @@ -293,8 +289,10 @@ public class BasePackage extends RBuiltinPackage { add(FastRContext.Join.class, FastRContextFactory.JoinNodeGen::create); add(FastrDqrls.class, FastrDqrlsNodeGen::create); add(FastRDebug.class, FastRDebugNodeGen::create); - add(FastRFunctionTimer.CreateFunctionTimer.class, FastRFunctionTimerFactory.CreateFunctionTimerNodeGen::create); - add(FastRFunctionTimer.GetFunctionTimer.class, FastRFunctionTimerFactory.GetFunctionTimerNodeGen::create); + add(FastRFunctionProfiler.Create.class, FastRFunctionProfilerFactory.CreateNodeGen::create); + add(FastRFunctionProfiler.Get.class, FastRFunctionProfilerFactory.GetNodeGen::create); + add(FastRFunctionProfiler.Reset.class, FastRFunctionProfilerFactory.ResetNodeGen::create); + add(FastRFunctionProfiler.Clear.class, FastRFunctionProfilerFactory.ClearNodeGen::create); add(FastRIdentity.class, FastRIdentityNodeGen::create); add(FastRInspect.class, FastRInspectNodeGen::create); add(FastRInterop.Eval.class, FastRInteropFactory.EvalNodeGen::create); @@ -526,6 +524,7 @@ public class BasePackage extends RBuiltinPackage { add(Row.class, RowNodeGen::create); add(RowMeans.class, RowMeansNodeGen::create); add(RowSums.class, RowSumsNodeGen::create); + add(RowsumFunctions.Rowsum.class, RowsumFunctionsFactory.RowsumNodeGen::create); add(S3DispatchFunctions.NextMethod.class, S3DispatchFunctionsFactory.NextMethodNodeGen::create); add(S3DispatchFunctions.UseMethod.class, S3DispatchFunctionsFactory.UseMethodNodeGen::create); add(Sample.class, SampleNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java index 4bb4174be7632353f08c124180ef9ed97e6c638a..3c8f0d6b5588e442fa9d75712ccfb47e63032a3e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java @@ -62,7 +62,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @RBuiltin(name = "lapply", kind = INTERNAL, parameterNames = {"X", "FUN"}, splitCaller = true) public abstract class Lapply extends RBuiltinNode { - private static final Source CALL_SOURCE = RSource.fromText("FUN(X[[i]], ...)", "lapply"); + private static final Source CALL_SOURCE = RSource.fromTextInternal("FUN(X[[i]], ...)", RSource.Internal.LAPPLY); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java new file mode 100644 index 0000000000000000000000000000000000000000..f4d26ee3a7562e968f577cd5fdd594e879ac1cdb --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java @@ -0,0 +1,144 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (c) 1997-2015, The R Core Team + * Copyright (c) 2016, Oracle and/or its affiliates + * + * All rights reserved. + */ + +package com.oracle.truffle.r.nodes.builtin.base; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; + +import java.util.HashMap; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RBuiltinKind; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.ops.na.NACheck; + +// Translated from main/unique.c + +// TODO rowsum_df +public class RowsumFunctions { + + @RBuiltin(name = "rowsum_matrix", kind = RBuiltinKind.INTERNAL, parameterNames = {"x", "g", "uniqueg", "snarm", "rn"}) + public abstract static class Rowsum extends RBuiltinNode { + + private final ConditionProfile typeProfile = ConditionProfile.createBinaryProfile(); + private final NACheck na = NACheck.create(); + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(integerValue().or(doubleValue()), RError.Message.ROWSUM_NON_NUMERIC); + + casts.arg("g").asVector(); + + casts.arg("uniqueg").asVector(); + + casts.arg("snarm").asLogicalVector().findFirst().notNA(RError.Message.INVALID_LOGICAL).map(toBoolean()); + + casts.arg("rn").mustBe(stringValue(), RError.Message.ROWSUM_NAMES_NOT_CHAR).asStringVector(); + } + + @Specialization + @TruffleBoundary + protected Object rowsum(RAbstractVector xv, RAbstractVector g, RAbstractVector uniqueg, boolean narm, RAbstractStringVector rn) { + int p = xv.isMatrix() ? xv.getDimensions()[1] : 1; + int n = g.getLength(); + int ng = uniqueg.getLength(); + HashMap<Object, Integer> table = new HashMap<>(); + for (int i = 0; i < ng; i++) { + // uniqueg has no duplicates (by definition) + table.put(uniqueg.getDataAtAsObject(i), i); + } + int[] matches = new int[n]; + for (int i = 0; i < n; i++) { + Integer hi = table.get(g.getDataAtAsObject(i)); + matches[i] = xv == null ? 0 : hi + 1; + } + int offset = 0; + int offsetg = 0; + + boolean isInt = xv instanceof RIntVector; + RVector result; + na.enable(xv); + boolean complete = xv.isComplete(); + + if (typeProfile.profile(isInt)) { + RIntVector xi = (RIntVector) xv; + int[] ansi = new int[ng * p]; + for (int i = 0; i < p; i++) { + for (int j = 0; j < n; j++) { + int midx = matches[j] - 1 + offsetg; + int itmp = ansi[midx]; + if (na.check(xi.getDataAt(j + offset))) { + if (!narm) { + ansi[midx] = RRuntime.INT_NA; + complete = RDataFactory.INCOMPLETE_VECTOR; + } + } else if (!na.check(itmp)) { + long dtmp = itmp; + int jtmp = xi.getDataAt(j + offset); + dtmp += jtmp; + if (dtmp < Integer.MIN_VALUE || dtmp > Integer.MAX_VALUE) { + itmp = RRuntime.INT_NA; + complete = RDataFactory.INCOMPLETE_VECTOR; + } else { + itmp += jtmp; + } + ansi[midx] = itmp; + } + } + offset += n; + offsetg += ng; + } + result = RDataFactory.createIntVector(ansi, complete, new int[]{ng, p}); + } else { + RDoubleVector xd = (RDoubleVector) xv; + double[] ansd = new double[ng * p]; + for (int i = 0; i < p; i++) { + for (int j = 0; j < n; j++) { + int midx = matches[j] - 1 + offsetg; + double dtmp = xd.getDataAt(j + offset); + if (!narm || !Double.isNaN(dtmp)) { + ansd[midx] += dtmp; + } + } + offset += n; + offsetg += ng; + } + result = RDataFactory.createDoubleVector(ansd, complete, new int[]{ng, p}); + } + Object[] dimNamesData = new Object[2]; + dimNamesData[0] = rn; + RList dn2 = xv.materialize().getDimNames(); + if (dn2 != null && dn2.getLength() >= 2 && dn2.getDataAt(1) != RNull.instance) { + dimNamesData[1] = dn2.getDataAt(1); + } + RList dimNames = RDataFactory.createList(dimNamesData); + result.setDimNames(dimNames); + return result; + } + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java index 45ded5c9169373e32d0615ac29f2fa4c9e7c9df0..341a599ab3100966d00a8cae5e0d361e6d1cf630 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java @@ -97,10 +97,10 @@ public class TraceFunctions { @Specialization @TruffleBoundary protected byte traceOnOff(byte state) { - boolean prevState = RContext.getInstance().stateTraceHandling.getTracingState(); + boolean prevState = RContext.getInstance().stateInstrumentation.getTracingState(); boolean newState = RRuntime.fromLogical(state); if (newState != prevState) { - RContext.getInstance().stateTraceHandling.setTracingState(newState); + RContext.getInstance().stateInstrumentation.setTracingState(newState); } return RRuntime.asLogical(prevState); } @@ -108,7 +108,7 @@ public class TraceFunctions { @Specialization @TruffleBoundary protected byte traceOnOff(@SuppressWarnings("unused") RNull state) { - return RRuntime.asLogical(RContext.getInstance().stateTraceHandling.getTracingState()); + return RRuntime.asLogical(RContext.getInstance().stateInstrumentation.getTracingState()); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java index 63d2a6dc06af300cad8e5583b7514ddf202b7619..c0ec1fa2a2ba4fc2c375c0cb89e8c5648c292a52 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java @@ -60,6 +60,7 @@ import com.oracle.truffle.r.library.utils.CountFields; import com.oracle.truffle.r.library.utils.Crc64NodeGen; import com.oracle.truffle.r.library.utils.Download; import com.oracle.truffle.r.library.utils.MenuNodeGen; +import com.oracle.truffle.r.library.utils.RprofNodeGen; import com.oracle.truffle.r.library.utils.TypeConvertNodeGen; import com.oracle.truffle.r.library.utils.WriteTable; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; @@ -568,8 +569,9 @@ public class ForeignFunctions { return new Download(); case "termsform": return getExternalModelBuiltinNode("termsform"); - case "unzip": case "Rprof": + return RprofNodeGen.create(); + case "unzip": case "Rprofmem": case "addhistory": case "loadhistory": diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRCallCounting.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRCallCounting.java deleted file mode 100644 index 4039faa429afd3aafb46e1409bba4c31c8469d4f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRCallCounting.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2014, 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.builtin.fastr; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.instrumentation.REntryCounters; -import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.RBuiltinKind; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RVisibility; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RNull; - -public class FastRCallCounting { - - @RBuiltin(name = ".fastr.createcc", visibility = RVisibility.OFF, kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func"}) - public abstract static class CreateCallCounter extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected RNull createCallCounter(RFunction function) { - if (!function.isBuiltin()) { - REntryCounters.FunctionListener.installCounter(function); - } - return RNull.instance; - } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "func"); - } - } - - @RBuiltin(name = ".fastr.getcc", visibility = RVisibility.OFF, kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func"}) - public abstract static class GetCallCounter extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected Object getCallCount(RFunction function) { - if (!function.isBuiltin()) { - int entryCount = REntryCounters.FunctionListener.findCounter(function).getEnterCount(); - if (entryCount < 0) { - throw RError.error(this, RError.Message.GENERIC, "no associated counter"); - } else { - return entryCount; - } - } - return RNull.instance; - } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "func"); - } - } -} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index 78ba86e8c541e7816d4d5a8d5dff8179932eb958..b267e8713b6998709e7626fa3859e821d76bde3a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -38,7 +38,6 @@ import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RVisibility; @@ -123,7 +122,7 @@ public class FastRContext { RContext.EvalThread[] threads = new RContext.EvalThread[contexts.getLength()]; for (int i = 0; i < threads.length; i++) { ContextInfo info = checkContext(contexts.getDataAt(i), this); - threads[i] = new RContext.EvalThread(info, RSource.fromText(exprs.getDataAt(i % threads.length), RInternalSourceDescriptions.CONTEXT_EVAL)); + threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % threads.length), RSource.Internal.CONTEXT_EVAL)); } for (int i = 0; i < threads.length; i++) { threads[i].start(); @@ -187,7 +186,7 @@ public class FastRContext { RContext.EvalThread[] threads = new RContext.EvalThread[contexts.getLength()]; for (int i = 0; i < threads.length; i++) { ContextInfo info = checkContext(contexts.getDataAt(i), this); - threads[i] = new RContext.EvalThread(info, RSource.fromText(exprs.getDataAt(i % threads.length), RInternalSourceDescriptions.CONTEXT_EVAL)); + threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % threads.length), RSource.Internal.CONTEXT_EVAL)); } for (int i = 0; i < threads.length; i++) { threads[i].start(); @@ -203,9 +202,9 @@ public class FastRContext { } else { for (int i = 0; i < contexts.getLength(); i++) { ContextInfo info = checkContext(contexts.getDataAt(i), this); - PolyglotEngine vm = info.apply(PolyglotEngine.newBuilder()).build(); + PolyglotEngine vm = info.createVM(); try { - Source source = RSource.fromText(exprs.getDataAt(i % exprs.getLength()), RInternalSourceDescriptions.CONTEXT_EVAL); + Source source = RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL); PolyglotEngine.Value resultValue = vm.eval(source); results[i] = RContext.EvalThread.createEvalResult(resultValue); } catch (ParseException e) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionProfiler.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionProfiler.java new file mode 100644 index 0000000000000000000000000000000000000000..977de8fc70a5c51aefd9b21f23c0ab68316a6c81 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionProfiler.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2014, 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.builtin.fastr; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; + +import java.util.ArrayList; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.instrumentation.RFunctionProfiler; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RBuiltinKind; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RVisibility; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.tools.Profiler; + +public class FastRFunctionProfiler { + + @RBuiltin(name = ".fastr.profiler.create", visibility = RVisibility.OFF, kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func", "mode"}) + public abstract static class Create extends RBuiltinNode { + private static final int COUNTING = 1; + private static final int TIMING = 2; + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, "counting"}; + } + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("func").mustBe(instanceOf(RFunction.class).or(missingValue())); + + casts.arg("mode").mustBe(stringValue()).asStringVector(); + } + + private int checkMode(RAbstractStringVector modeVec) { + int result = 0; + for (int i = 0; i < modeVec.getLength(); i++) { + String mode = modeVec.getDataAt(i); + switch (mode) { + case "counting": + result |= COUNTING; + break; + case "timing": + result |= TIMING; + break; + default: + throw RError.error(this, RError.Message.GENERIC, "invalid 'mode', one of 'count, timning' expected"); + } + } + return result; + } + + @Specialization + @TruffleBoundary + protected RNull createFunctionProfiler(RFunction function, RAbstractStringVector modeVec) { + int mode = checkMode(modeVec); + if (!function.isBuiltin()) { + RFunctionProfiler.installTimer(function, (mode & COUNTING) != 0, (mode & TIMING) != 0); + } else { + throw RError.error(this, RError.Message.GENERIC, "cannot profile builtin functions"); + } + return RNull.instance; + } + + @Specialization + @TruffleBoundary + protected RNull createFunctionProfiler(@SuppressWarnings("unused") RMissing value, RAbstractStringVector modeVec) { + int mode = checkMode(modeVec); + RFunctionProfiler.installTimer(null, (mode & COUNTING) != 0, (mode & TIMING) != 0); + return RNull.instance; + } + + } + + @RBuiltin(name = ".fastr.profiler.get", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func", "threshold", "scale"}) + public abstract static class Get extends RBuiltinNode { + + private static final RStringVector COLNAMES = RDataFactory.createStringVector(new String[]{"Invocations", "TotalTime", "SelfTime"}, RDataFactory.COMPLETE_VECTOR); + private static final RStringVector ROWNAMES = RDataFactory.createStringVector(new String[]{"Combined", "Interpreted", "Compiled"}, RDataFactory.COMPLETE_VECTOR); + private static final int NCOLS = 3; + private static final int NROWS = 3; + + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("func").mustBe(instanceOf(RFunction.class).or(missingValue())); + + casts.arg("threshold").mustBe(integerValue().or(doubleValue())).asDoubleVector(); + + casts.arg("scale").mustBe(stringValue()).asStringVector(); + } + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, 0.0, "nanos"}; + } + + private void checkScale(String s) throws RError { + if (!(s.equals("nanos") || s.equals("millis") || s.equals("micros") || s.equals("secs"))) { + throw RError.error(this, RError.Message.GENERIC, "invalid scale: one of 'nanos, micros, millis, secs' expected"); + } + } + + @Specialization + @TruffleBoundary + protected Object get(@SuppressWarnings("unused") RMissing value, RAbstractDoubleVector thresholdVec, RAbstractStringVector scaleVec) { + String scale = scaleVec.getDataAt(0); + checkScale(scale); + double threshold = thresholdVec.getDataAt(0); + Profiler.Counter[] counters = RFunctionProfiler.getCounters(); + if (counters == null) { + throw RError.error(this, RError.Message.GENERIC, "profiling not enabled"); + } + ArrayList<RDoubleVector> dataList = new ArrayList<>(); + ArrayList<String> nameList = new ArrayList<>(); + for (int i = 0; i < counters.length; i++) { + Profiler.Counter counter = counters[i]; + if (threshold > 0.0) { + long time = counter.getTotalTime(Profiler.Counter.TimeKind.INTERPRETED_AND_COMPILED); + if (time <= threshold) { + continue; + } + } + dataList.add(getFunctionMatrix(counter, scale)); + nameList.add(counter.getName()); + } + Object[] data = new Object[dataList.size()]; + String[] names = new String[nameList.size()]; + return RDataFactory.createList(dataList.toArray(data), RDataFactory.createStringVector(nameList.toArray(names), RDataFactory.COMPLETE_VECTOR)); + } + + @Specialization + @TruffleBoundary + protected Object get(RFunction function, @SuppressWarnings("unused") RAbstractDoubleVector threshold, RAbstractStringVector scaleVec) { + String scale = scaleVec.getDataAt(0); + checkScale(scale); + if (!function.isBuiltin()) { + Profiler.Counter counter = RFunctionProfiler.getCounter(function); + if (counter == null) { + throw RError.error(this, RError.Message.GENERIC, "profiling not enabled"); + } else { + return getFunctionMatrix(counter, scale); + } + } else { + throw RError.error(this, RError.Message.GENERIC, "cannot profile builtin functions"); + } + } + + private static RDoubleVector getFunctionMatrix(Profiler.Counter counter, String scale) { + double[] data = new double[NROWS * NCOLS]; + boolean isTiming = RFunctionProfiler.isTiming(); + boolean complete = isTiming ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR; + for (int r = 0; r < NROWS; r++) { + Profiler.Counter.TimeKind timeKind = Profiler.Counter.TimeKind.values()[r]; + for (int c = 0; c < NCOLS; c++) { + int index = c * NROWS + r; + double value = 0.0; + switch (c) { + case 0: + value = counter.getInvocations(timeKind); + break; + case 1: + value = isTiming ? counter.getTotalTime(timeKind) : RRuntime.DOUBLE_NA; + break; + case 2: + value = isTiming ? counter.getSelfTime(timeKind) : RRuntime.DOUBLE_NA; + } + data[index] = c == 0 ? value : scaledTime(scale, value); + } + } + RDoubleVector result = RDataFactory.createDoubleVector(data, complete, new int[]{3, 3}); + Object[] dimNamesData = new Object[2]; + dimNamesData[0] = ROWNAMES; + dimNamesData[1] = COLNAMES; + RList dimNames = RDataFactory.createList(dimNamesData); + result.setDimNames(dimNames); + return result; + } + + private static double scaledTime(String scale, double time) { + if (RRuntime.isNA(time)) { + return time; + } + switch (scale) { + case "nanos": + return time; + case "micros": + return time / 1000.0; + case "millis": + return time / 1000000.0; + case "secs": + return time / 1000000000.0; + default: + throw RInternalError.shouldNotReachHere(); + } + } + } + + @RBuiltin(name = ".fastr.profiler.reset", kind = RBuiltinKind.PRIMITIVE, parameterNames = {}, visibility = RVisibility.OFF) + public abstract static class Reset extends RBuiltinNode { + @Specialization + @TruffleBoundary + protected Object reset() { + RFunctionProfiler.reset(); + return RNull.instance; + } + } + + @RBuiltin(name = ".fastr.profiler.clear", kind = RBuiltinKind.PRIMITIVE, parameterNames = {}, visibility = RVisibility.OFF) + public abstract static class Clear extends RBuiltinNode { + @Specialization + @TruffleBoundary + protected Object clear() { + RFunctionProfiler.clear(); + return RNull.instance; + } + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionTimer.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionTimer.java deleted file mode 100644 index 1a967545babb8328c37243b0ba4d3f4370188406..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionTimer.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2014, 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.builtin.fastr; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.instrumentation.RNodeTimer; -import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.RBuiltinKind; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RVisibility; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; - -public class FastRFunctionTimer { - - @RBuiltin(name = ".fastr.createtimer", visibility = RVisibility.OFF, kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func"}) - public abstract static class CreateFunctionTimer extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected RNull createFunctionTimer(RFunction function) { - if (!function.isBuiltin()) { - RNodeTimer.StatementListener.installTimer(function); - } - return RNull.instance; - } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "func"); - } - } - - @RBuiltin(name = ".fastr.gettimer", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func", "scale"}) - public abstract static class GetFunctionTimer extends RBuiltinNode { - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, "nanos"}; - } - - @Specialization - @TruffleBoundary - protected Object getFunctionTimer(RFunction function, RAbstractStringVector scale) { - if (!function.isBuiltin()) { - long timeInfo = RNodeTimer.StatementListener.findTimer(function); - if (timeInfo < 0) { - throw RError.error(this, RError.Message.GENERIC, "no associated timer"); - } else { - double timeVal = timeInfo; - switch (scale.getDataAt(0)) { - case "nanos": - break; - case "micros": - timeVal = timeVal / 1000.0; - break; - case "millis": - timeVal = timeVal / 1000000.0; - break; - case "secs": - timeVal = timeVal / 1000000000.0; - break; - default: - throw RError.error(this, RError.Message.GENERIC, "invalid scale: one of 'nanos, micros, millis, secs' expected"); - } - return RDataFactory.createDoubleVectorFromScalar(timeVal); - } - } - return RNull.instance; - } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1, Object a2) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "func"); - } - } -} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java index b8d8a8ead92a39ac7b850f4f4a5e1a8c68921384..06daa8d3da89d6e579c97fd7240d2b04f651bc36 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java @@ -35,7 +35,6 @@ 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.RVisibility; -import com.oracle.truffle.r.runtime.context.Engine; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypedValue; @@ -47,7 +46,7 @@ public class FastRInterop { @Specialization @TruffleBoundary protected Object interopEval(Object mimeType, Object source) { - Source sourceObject = RSource.fromText(RRuntime.asString(source), Engine.EVAL_FUNCTION_NAME, RRuntime.asString(mimeType)); + Source sourceObject = RSource.fromTextInternal(RRuntime.asString(source), RSource.Internal.EVAL_WRAPPER, RRuntime.asString(mimeType)); CallTarget callTarget; 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 7626ff551b9040dbb647d68a5786b3ab193f2228..5534c5b861619ba884e708bda29cf06c25493237 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 @@ -57,7 +57,6 @@ public abstract class BrowserInteractNode extends RNode { public static final int CONTINUE = 2; public static final int FINISH = 3; - private static final String BROWSER_SOURCE = "<browser_input>"; private static String lastEmptyLineCommand = "n"; /** @@ -128,7 +127,7 @@ public abstract class BrowserInteractNode extends RNode { default: try { - RContext.getEngine().parseAndEval(RSource.fromText(input, BROWSER_SOURCE), mFrame, true); + RContext.getEngine().parseAndEval(RSource.fromTextInternal(input, RSource.Internal.BROWSER_INPUT), mFrame, true); } catch (ReturnException e) { exitMode = NEXT; break LW; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java index ad0d6d9ee5f4c5c26987732384ed6ef725f33c26..76c6e1167e48c003fdb5ee32c9fb597514912321 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.builtin.helpers; import java.io.IOException; import java.util.ArrayList; -import java.util.WeakHashMap; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -44,11 +43,10 @@ import com.oracle.truffle.r.nodes.control.AbstractLoopNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags; -import com.oracle.truffle.r.runtime.FunctionUID; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; +import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.RContext; @@ -102,11 +100,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNodeVisitor; */ public class DebugHandling { - /** - * Records all functions that have debug listeners installed. - */ - private static final WeakHashMap<FunctionUID, FunctionStatementsEventListener> listenerMap = new WeakHashMap<>(); - /** * This flag is used to (temporarily) disable all debugging across calls that are used * internally in the implementation. @@ -117,8 +110,7 @@ public class DebugHandling { * Attach the DebugHandling instrument to the FunctionStatementsNode and all syntactic nodes. */ public static boolean enableDebug(RFunction func, Object text, Object condition, boolean once) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); - FunctionStatementsEventListener fbr = listenerMap.get(fdn.getUID()); + FunctionStatementsEventListener fbr = getFunctionStatementsEventListener(func); if (fbr == null) { attachDebugHandler(func, text, condition, once); } else { @@ -128,7 +120,7 @@ public class DebugHandling { } public static boolean undebug(RFunction func) { - FunctionStatementsEventListener fbr = listenerMap.get(((FunctionDefinitionNode) func.getRootNode()).getUID()); + FunctionStatementsEventListener fbr = getFunctionStatementsEventListener(func); if (fbr == null) { return false; } else { @@ -138,10 +130,18 @@ public class DebugHandling { } public static boolean isDebugged(RFunction func) { - FunctionStatementsEventListener fser = listenerMap.get(((FunctionDefinitionNode) func.getRootNode()).getUID()); + FunctionStatementsEventListener fser = getFunctionStatementsEventListener(func); return fser != null && !fser.disabled(); } + private static FunctionStatementsEventListener getFunctionStatementsEventListener(RFunction func) { + return (FunctionStatementsEventListener) RContext.getInstance().stateInstrumentation.getDebugListener(RInstrumentation.getSourceSection(func)); + } + + private static FunctionStatementsEventListener getFunctionStatementsEventListener(FunctionDefinitionNode fdn) { + return (FunctionStatementsEventListener) RContext.getInstance().stateInstrumentation.getDebugListener(fdn.getSourceSection()); + } + /** * Disables/enables debugging globally. Intended to be used for short period, typically while * executing functions used internally by the implementation. @@ -186,7 +186,7 @@ public class DebugHandling { } private static void ensureSingleStep(FunctionDefinitionNode fdn) { - FunctionStatementsEventListener fser = listenerMap.get(fdn.getUID()); + FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn); if (fser == null) { // attach a "once" listener fser = attachDebugHandler(fdn, null, null, true); @@ -262,7 +262,7 @@ public class DebugHandling { * will everything get invalidated? */ stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(), - new StepIntoInstrumentListener(listenerMap.get(functionDefinitionNode.getUID()))); + new StepIntoInstrumentListener(getFunctionStatementsEventListener(functionDefinitionNode))); } break; case BrowserInteractNode.CONTINUE: @@ -275,7 +275,7 @@ public class DebugHandling { AbstractLoopNode loopNode = inLoop(node); if (loopNode != null) { // Have to disable just the body of the loop - FunctionStatementsEventListener fser = listenerMap.get(functionDefinitionNode.getUID()); + FunctionStatementsEventListener fser = getFunctionStatementsEventListener(functionDefinitionNode); fser.setFinishing(loopNode); } else { doContinue(); @@ -285,7 +285,7 @@ public class DebugHandling { } private void doContinue() { - FunctionStatementsEventListener fser = listenerMap.get(functionDefinitionNode.getUID()); + FunctionStatementsEventListener fser = getFunctionStatementsEventListener(functionDefinitionNode); fser.setContinuing(); } @@ -323,7 +323,7 @@ public class DebugHandling { FunctionStatementsEventListener(FunctionDefinitionNode functionDefinitionNode, Object text, Object condition, boolean once) { super(functionDefinitionNode, text, condition); - listenerMap.put(functionDefinitionNode.getUID(), this); + RContext.getInstance().stateInstrumentation.putDebugListener(functionDefinitionNode.getSourceSection(), this); statementListener = new StatementEventListener(functionDefinitionNode, text, condition); this.once = once; } @@ -447,8 +447,8 @@ public class DebugHandling { consoleHandler.print("debug: "); } else { SourceSection source = ((RBaseNode) node).asRSyntaxNode().getSourceSection(); - String path = source.getSource().getPath(); - if (path == null || RInternalSourceDescriptions.isInternal(path)) { + String path = RSource.getPath(source.getSource()); + if (path == null) { path = ""; } consoleHandler.print("debug at " + path + "#" + source.getStartLine() + ": "); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java index 1418ab39e90504bb45fd8867c7bec30ed9562d02..798fd225d0eb4101e79b8ed1b90b3722c0577653 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java @@ -33,7 +33,6 @@ import com.oracle.truffle.api.instrumentation.ExecutionEventListener; import com.oracle.truffle.api.instrumentation.SourceSectionFilter; import com.oracle.truffle.api.instrumentation.StandardTags; import com.oracle.truffle.api.utilities.CyclicAssumption; -import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RArguments; @@ -52,9 +51,8 @@ import com.oracle.truffle.r.runtime.data.RMissing; public class TraceHandling { public static void enableTrace(RFunction func) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); @SuppressWarnings("unchecked") - EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateTraceHandling.get(fdn.getUID()); + EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateInstrumentation.getTraceBinding(RInstrumentation.getSourceSection(func)); if (binding != null) { // only one binding.dispose(); @@ -63,17 +61,16 @@ public class TraceHandling { } public static void disableTrace(RFunction func) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); @SuppressWarnings("unchecked") - EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateTraceHandling.get(fdn.getUID()); + EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateInstrumentation.getTraceBinding(RInstrumentation.getSourceSection(func)); if (binding != null) { binding.dispose(); - RContext.getInstance().stateTraceHandling.put(RInstrumentation.getFunctionDefinitionNode(func).getUID(), null); + RContext.getInstance().stateInstrumentation.putTraceBinding(RInstrumentation.getSourceSection(func), null); } } public static void setTracingState(boolean state) { - Object[] listeners = RContext.getInstance().stateTraceHandling.getListeners(); + EventBinding<?>[] listeners = RContext.getInstance().stateInstrumentation.getTraceBindings(); for (int i = 0; i < listeners.length; i++) { @SuppressWarnings("unchecked") EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) listeners[i]; @@ -97,9 +94,8 @@ public class TraceHandling { } public static boolean enableStatementTrace(RFunction func, RLanguage tracer, @SuppressWarnings("unused") Object exit, Object at, boolean print) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); @SuppressWarnings("unchecked") - EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateTraceHandling.get(fdn.getUID()); + EventBinding<TraceEventListener> binding = (EventBinding<TraceEventListener>) RContext.getInstance().stateInstrumentation.getTraceBinding(RInstrumentation.getSourceSection(func)); if (binding != null) { // only one allowed binding.dispose(); @@ -109,7 +105,7 @@ public class TraceHandling { TracerFunctionEntryEventListener listener = new TracerFunctionEntryEventListener(tracer, print); binding = RInstrumentation.getInstrumenter().attachListener(RInstrumentation.createFunctionStartFilter(func).build(), listener); setOutputHandler(); - RContext.getInstance().stateTraceHandling.put(RInstrumentation.getFunctionDefinitionNode(func).getUID(), binding); + RContext.getInstance().stateInstrumentation.putTraceBinding(RInstrumentation.getSourceSection(func), binding); } return false; } @@ -118,7 +114,7 @@ public class TraceHandling { PrimitiveFunctionEntryEventListener fser = new PrimitiveFunctionEntryEventListener(); EventBinding<TraceEventListener> binding = RInstrumentation.getInstrumenter().attachListener(RInstrumentation.createFunctionStartFilter(func).build(), fser); setOutputHandler(); - RContext.getInstance().stateTraceHandling.put(RInstrumentation.getFunctionDefinitionNode(func).getUID(), binding); + RContext.getInstance().stateInstrumentation.putTraceBinding(RInstrumentation.getSourceSection(func), binding); } private abstract static class TraceEventListener implements ExecutionEventListener { diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java index c3e51b7541755b08a35328f31823bbe0e6b906c2..abd1f3fab05b824fbd86294ccaff489811b72ba1 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestBase.java @@ -45,7 +45,7 @@ public class TestBase { } // clear out warnings (which are stored in shared base env) - private static final Source CLEAR_WARNINGS = RSource.fromText("assign('last.warning', NULL, envir = baseenv())", "<clear_warnings>"); + private static final Source CLEAR_WARNINGS = RSource.fromTextInternal("assign('last.warning', NULL, envir = baseenv())", RSource.Internal.CLEAR_WARNINGS); @AfterClass public static void finishClass() throws IOException { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ALONGFunctionUIDFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ALONGFunctionUIDFactory.java deleted file mode 100644 index f508505dfa5eb8ec196ebf574896c10b90ef6340..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ALONGFunctionUIDFactory.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.function; - -import java.util.concurrent.atomic.AtomicLong; - -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.instrument.FunctionUIDFactory; - -public class ALONGFunctionUIDFactory extends FunctionUIDFactory { - - private static final AtomicLong ID = new AtomicLong(); - - private static final class ALongFunctionUID implements FunctionUID { - - private final long uuid; - - private ALongFunctionUID(long uuid) { - this.uuid = uuid; - } - - @Override - public int compareTo(FunctionUID o) { - ALongFunctionUID oa = (ALongFunctionUID) o; - if (uuid == oa.uuid) { - return 0; - } else if (uuid < oa.uuid) { - return -1; - } else { - return 1; - } - } - - @Override - public String toString() { - return Long.toString(uuid); - } - } - - @Override - public FunctionUID createUID() { - return new ALongFunctionUID(ID.incrementAndGet()); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java index 0baca3d486265f3af9ba19fcb526589a42aa59ca..9e3d611808fd439720b539a5e27f79e9e7889082 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java @@ -47,10 +47,8 @@ import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory; import com.oracle.truffle.r.nodes.control.BreakException; import com.oracle.truffle.r.nodes.control.NextException; -import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.BrowserQuitException; -import com.oracle.truffle.r.runtime.FunctionUID; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; import com.oracle.truffle.r.runtime.RArguments.S3Args; @@ -63,21 +61,19 @@ import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils.DebugExitException; -import com.oracle.truffle.r.runtime.WithFunctionUID; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; -import com.oracle.truffle.r.runtime.instrument.FunctionUIDFactory; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNode, WithFunctionUID, RSyntaxFunction { +public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNode, RSyntaxFunction { @Child private RNode body; // typed as RNode to avoid custom instrument wrapper /** @@ -88,12 +84,10 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo * {@code f <- function}. * <li>The first several characters of the function definition for anonymous functions. * </ul> - * It can be updated later by calling {@link #setDescription}, which is useful for functions - * lazily loaded from packages, where at the point of definition any assignee variable is - * unknown. + * It can be updated later by calling {@link #setName}, which is useful for functions lazily + * loaded from packages, where at the point of definition any assignee variable is unknown. */ - private String description; - private FunctionUID uuid; + private String name; private boolean instrumented = false; private SourceSection sourceSectionR; private final SourceSection[] argSourceSections; @@ -133,12 +127,12 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile(); public static FunctionDefinitionNode create(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, SaveArgumentsNode saveArguments, RSyntaxNode body, - FormalArguments formals, String description, PostProcessArgumentsNode argPostProcess) { - return new FunctionDefinitionNode(src, frameDesc, argSourceSections, saveArguments, body, formals, description, argPostProcess, FunctionUIDFactory.get().createUID()); + FormalArguments formals, String name, PostProcessArgumentsNode argPostProcess) { + return new FunctionDefinitionNode(src, frameDesc, argSourceSections, saveArguments, body, formals, name, argPostProcess); } private FunctionDefinitionNode(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, RNode saveArguments, RSyntaxNode body, FormalArguments formals, - String description, PostProcessArgumentsNode argPostProcess, FunctionUID uuid) { + String name, PostProcessArgumentsNode argPostProcess) { super(null, formals, frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature())); this.argSourceSections = argSourceSections; assert FrameSlotChangeMonitor.isValidFrameDescriptor(frameDesc); @@ -146,13 +140,11 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo this.sourceSectionR = src; this.saveArguments = saveArguments; this.body = body.asRNode(); - this.description = description; + this.name = name; this.onExitSlot = FrameSlotNode.createInitialized(frameDesc, RFrameSlot.OnExit, false); - this.uuid = uuid; this.needsSplitting = needsAnyBuiltinSplitting(); this.containsDispatch = containsAnyDispatch(body); this.argPostProcess = argPostProcess; - RInstrumentation.registerFunctionDefinition(this); } @Override @@ -165,8 +157,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo SourceSection source = argSourceSections == null ? getSourceSection() : argSourceSections[i]; args.add(RCodeBuilder.argument(source, getFormalArguments().getSignature().getName(i), value == null ? null : builder.process(value.asRSyntaxNode()))); } - RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(getSourceSection(), args, builder.process(getBody()), description); - ((FunctionDefinitionNode) callTarget.getRootNode()).uuid = uuid; + RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(getSourceSection(), args, builder.process(getBody()), name); return callTarget; } @@ -236,11 +227,6 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo return needsSplitting; } - @Override - public FunctionUID getUID() { - return uuid; - } - public RSyntaxNode getBody() { return body.asRSyntaxNode(); } @@ -392,7 +378,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo @Override public String getName() { - return description == null ? "<no source>" : description; + return name == null ? "<no source>" : name; } @Override @@ -454,8 +440,8 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo } } - public void setDescription(String name) { - this.description = name; + public void setName(String name) { + this.name = name; } public boolean getInstrumented() { @@ -495,6 +481,6 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo @Override public String getSyntaxDebugName() { - return description; + return name; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java index 4cd2134a87d2f4a531b6019f1617f050e1c9c170..b4dd48549c46b868691e576d6a7e2864bd5f65c9 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java @@ -134,6 +134,6 @@ public final class FunctionExpressionNode extends RSourceSectionNode implements @Override public String getSyntaxDebugName() { - return ((RRootNode) callTarget.getRootNode()).getDescription(); + return ((RRootNode) callTarget.getRootNode()).getName(); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UUIDFunctionUIDFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UUIDFunctionUIDFactory.java deleted file mode 100644 index 3d3a4163f8cb8fb63f8b708b50f4f2cd93d20b84..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UUIDFunctionUIDFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2014, 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.function; - -import java.util.UUID; - -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.instrument.FunctionUIDFactory; - -public class UUIDFunctionUIDFactory extends FunctionUIDFactory { - - private static final class UUIDFunctionUID implements FunctionUID { - - private final UUID uuid; - - private UUIDFunctionUID(UUID uuid) { - this.uuid = uuid; - } - - @Override - public int compareTo(FunctionUID o) { - return uuid.compareTo(((UUIDFunctionUID) o).uuid); - } - - @Override - public String toString() { - return uuid.toString(); - } - } - - @Override - public FunctionUID createUID() { - return new UUIDFunctionUID(UUID.randomUUID()); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/REntryCounters.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/REntryCounters.java deleted file mode 100644 index 33343ce29eb227fb13acccd8deb64c2440d0f20c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/REntryCounters.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2014, 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.instrumentation; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.api.instrumentation.ExecutionEventListener; -import com.oracle.truffle.api.instrumentation.SourceSectionFilter; -import com.oracle.truffle.api.instrumentation.StandardTags; -import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; -import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation.FunctionIdentification; -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.RPerfStats; -import com.oracle.truffle.r.runtime.data.RFunction; - -/** - * Basic support for adding entry/exit counters to nodes. The {@link SourceSection} attribute is is - * used to retrieve the counter associated with a node. - * - */ -public class REntryCounters { - public static final class Counter { - private final Object ident; - private int enterCount; - private int exitCount; - - Counter(Object ident) { - this.ident = ident; - } - - public int getEnterCount() { - return enterCount; - } - - public int getExitCount() { - return exitCount; - } - - public Object getIdent() { - return ident; - } - } - - /** - * Listener that is independent of the kind of node and specific instance being counted. - */ - private abstract static class BasicListener implements ExecutionEventListener { - - private HashMap<SourceSection, Counter> counterMap = new HashMap<>(); - - private Counter getCounter(EventContext context) { - SourceSection ss = context.getInstrumentedSourceSection(); - Counter counter = counterMap.get(ss); - if (counter == null) { - Object obj = counterCreated(context); - counter = new Counter(obj); - counterMap.put(ss, counter); - } - return counter; - } - - protected Counter getCounter(SourceSection sourceSection) { - Counter counter = counterMap.get(sourceSection); - assert counter != null; - return counter; - } - - protected Map<SourceSection, Counter> getCounterMap() { - return counterMap; - } - - @Override - public void onEnter(EventContext context, VirtualFrame frame) { - getCounter(context).enterCount++; - } - - @Override - public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { - getCounter(context).exitCount++; - } - - @Override - public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { - getCounter(context).exitCount++; - } - - protected abstract Object counterCreated(EventContext context); - } - - /** - * A counter that is specialized for function entry, tagged with the {@link FunctionUID}. - */ - public static class FunctionListener extends BasicListener { - private static final FunctionListener singleton = new FunctionListener(); - - static void installCounters() { - if (enabled()) { - SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder(); - builder.tagIs(StandardTags.RootTag.class); - SourceSectionFilter filter = builder.build(); - RInstrumentation.getInstrumenter().attachListener(filter, singleton); - } - } - - public static void installCounter(RFunction func) { - RInstrumentation.getInstrumenter().attachListener(RInstrumentation.createFunctionStartFilter(func).build(), singleton); - } - - public static Counter findCounter(RFunction func) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); - return singleton.getCounter(fdn.getBody().getSourceSection()); - } - - @Override - protected FunctionUID counterCreated(EventContext context) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) context.getInstrumentedNode().getRootNode(); - return fdn.getUID(); - } - - static { - RPerfStats.register(new PerfHandler()); - } - - static boolean enabled() { - return RPerfStats.enabled(PerfHandler.NAME); - } - - private static class PerfHandler implements RPerfStats.Handler { - private static class FunctionCount implements Comparable<FunctionCount> { - int count; - String name; - - FunctionCount(int count, String name) { - this.count = count; - this.name = name; - } - - @Override - public int compareTo(FunctionCount o) { - if (count < o.count) { - return 1; - } else if (count > o.count) { - return -1; - } else { - return name.compareTo(o.name); - } - } - } - - static final String NAME = "functioncounts"; - - @Override - public void initialize(String optionText) { - } - - @Override - public String getName() { - return NAME; - } - - /** - * R's anonymous function definitions don't help with reporting. We make an attempt to - * locate a function name in the global/package environments. - */ - @Override - public void report() { - RPerfStats.out().println("R Function Entry Counts"); - ArrayList<FunctionCount> results = new ArrayList<>(); - for (Map.Entry<SourceSection, Counter> entry : FunctionListener.singleton.getCounterMap().entrySet()) { - Counter counter = entry.getValue(); - FunctionIdentification fdi = RInstrumentation.getFunctionIdentification((FunctionUID) counter.getIdent()); - int count = counter.getEnterCount(); - if (count > 0) { - results.add(new FunctionCount(count, fdi.name)); - } - } - FunctionCount[] sortedCounts = new FunctionCount[results.size()]; - results.toArray(sortedCounts); - Arrays.sort(sortedCounts); - for (FunctionCount functionCount : sortedCounts) { - RPerfStats.out().printf("%6d: %s%n", functionCount.count, functionCount.name); - } - } - } - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RFunctionProfiler.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RFunctionProfiler.java new file mode 100644 index 0000000000000000000000000000000000000000..d3158a4c3e13a058b87ed179d903eaec0db6c873 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RFunctionProfiler.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014, 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.instrumentation; + +import java.util.Arrays; +import java.util.Map; + +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.r.runtime.RPerfStats; +import com.oracle.truffle.r.runtime.RSource; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.tools.Profiler; +import com.oracle.truffle.tools.Profiler.Counter; +import com.oracle.truffle.tools.Profiler.Counter.TimeKind; + +/** + * Interface to the Truffle {@link Profiler}. + */ +public class RFunctionProfiler { + static { + RPerfStats.register(new PerfHandler()); + } + + static boolean enabled() { + return RPerfStats.enabled(PerfHandler.NAME); + } + + /** + * This is called on startup to support {@link RPerfStats}. + */ + static void installTimers(RContext context) { + if (enabled()) { + enableTiming(context, true, true); + } + } + + private static Profiler getProfiler(RContext context) { + PolyglotEngine vm = context.getVM(); + Profiler profiler = Profiler.find(vm); + return profiler; + } + + private static Profiler getProfiler() { + PolyglotEngine vm = RContext.getInstance().getVM(); + Profiler profiler = Profiler.find(vm); + return profiler; + } + + private static void enableTiming(RContext context, @SuppressWarnings("unused") boolean counting, boolean timing) { + Profiler profiler = getProfiler(context); + context.getInstrumentationState().setProfiler(profiler); + profiler.setTiming(timing); + profiler.setCollecting(true); + } + + /** + * (Interactively) installs a timer for a specific function. Currently the {@link Profiler} does + * not support profiling limited to specific functions so this effectively enables everything. + * If {@code func} is {@code null} profile all functions. In principle profiling can be + * restricted to entry counting and timing but currently counting is always on. + * + */ + public static void installTimer(@SuppressWarnings("unused") RFunction func, boolean counting, boolean timing) { + enableTiming(RContext.getInstance(), counting, timing); + } + + public static Counter getCounter(RFunction func) { + Profiler profiler = getProfiler(); + if (profiler.isCollecting()) { + String funcName = func.getTarget().getRootNode().getName(); + Map<SourceSection, Counter> counters = profiler.getCounters(); + for (Counter counter : counters.values()) { + if (counter.getName().equals(funcName)) { + return counter; + } + } + } + return null; + } + + public static void reset() { + Profiler profiler = getProfiler(); + profiler.clearData(); + profiler.setCollecting(false); + } + + public static void clear() { + Profiler profiler = getProfiler(); + profiler.clearData(); + } + + public static Counter[] getCounters() { + Profiler profiler = getProfiler(); + if (profiler.isCollecting()) { + Map<SourceSection, Counter> counters = profiler.getCounters(); + Counter[] result = new Counter[counters.size()]; + counters.values().toArray(result); + return result; + } else { + return null; + } + } + + public static boolean isTiming() { + Profiler profiler = getProfiler(); + return profiler.isTiming(); + } + + private static class PerfHandler implements RPerfStats.Handler { + static final String NAME = "timing"; + @SuppressWarnings("unused") private boolean stmts; + private int threshold; + + @Override + public void initialize(String optionText) { + if (optionText.length() > 0) { + String[] subOptions = optionText.split(":"); + for (String subOption : subOptions) { + if (subOption.equals("stmts")) { + Utils.warn("statement timing is not implemented"); + stmts = true; + } else if (subOption.startsWith("threshold")) { + threshold = Integer.parseInt(subOption.substring(subOption.indexOf('=') + 1)) * 1000; + } + } + } + } + + @Override + public String getName() { + return NAME; + } + + private static class SortableCounter implements Comparable<SortableCounter> { + private Counter counter; + + SortableCounter(Counter counter) { + this.counter = counter; + } + + @Override + public int compareTo(SortableCounter other) { + long myTime = counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + long otherTime = other.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + return myTime < otherTime ? 1 : (myTime > otherTime ? -1 : 0); + } + + } + + /** + * Report the statement timing information at the end of the run. The report is per function + * Functions that consumed less time than requested threshold (default 0) are not included + * in the report. The report is sorted by cumulative time. + */ + @Override + public void report() { + Profiler profiler = RContext.getInstance().getInstrumentationState().getProfiler(); + // profiler.printHistograms(RPerfStats.out()); + Map<SourceSection, Counter> counters = profiler.getCounters(); + long totalTime = 0; + SortableCounter[] sortedCounters = new SortableCounter[counters.size()]; + int i = 0; + for (Counter counter : counters.values()) { + totalTime += counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + sortedCounters[i++] = new SortableCounter(counter); + } + Arrays.sort(sortedCounters); + for (SortableCounter scounter : sortedCounters) { + long time = scounter.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED); + if (time > 0 && time > threshold) { + SourceSection ss = scounter.counter.getSourceSection(); + Source source = ss.getSource(); + RPerfStats.out().println("=========="); + double thisPercent = percent(time, totalTime); + RPerfStats.out().printf("%d ms (%.2f%%): %s, %s%n", time, thisPercent, scounter.counter.getName(), RSource.getOrigin(source)); + } + } + System.console(); + } + + private static double percent(long a, long b) { + return ((double) a * 100) / b; + } + + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java index e245408ffafb1d509b711c00fa2a663f7b75d4d8..c51da1dd105e9f7cda7fddaa74322a28564fa41c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java @@ -22,142 +22,38 @@ */ package com.oracle.truffle.r.nodes.instrumentation; -import java.util.HashMap; -import java.util.Map; - import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.instrumentation.Instrumenter; import com.oracle.truffle.api.instrumentation.SourceSectionFilter; import com.oracle.truffle.api.instrumentation.StandardTags; -import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.runtime.FastROptions; -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.RPerfStats; -import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.env.REnvironment; /** * Handles the initialization of the (NEW) instrumentation system which sets up various instruments - * depending on command line options. + * depending on command line options and provides utility methods for instrumentation-based tools. * */ public class RInstrumentation { - /** - * Collects together all the relevant data for a function, keyed by the {@link FunctionUID}, - * which is unique, for {@link RPerfStats} use. - */ - private static Map<FunctionUID, FunctionData> functionMap; - - /** - * Created lazily as needed. - */ - static class FunctionIdentification { - public final Source source; - public final String name; - public final String origin; - public final FunctionDefinitionNode node; - - FunctionIdentification(Source source, String name, String origin, FunctionDefinitionNode node) { - this.source = source; - this.name = name; - this.origin = origin; - this.node = node; - } - } - - /** - * Created for every {@link FunctionDefinitionNode}. maybe could be lazier. - */ - private static class FunctionData { - private final FunctionUID uid; - private final FunctionDefinitionNode fdn; - private FunctionIdentification ident; - - FunctionData(FunctionUID uid, FunctionDefinitionNode fdn) { - this.uid = uid; - this.fdn = fdn; - } - - private FunctionIdentification getIdentification() { - if (ident == null) { - SourceSection ss = fdn.getSourceSection(); - /* - * The default for "name" is the description associated with "fdn". If the function - * was parsed from text this will be the variable name the function value was - * assigned to, or the first 40 characters of the definition if anonymous. - */ - String idName = fdn.toString(); - Source idSource = null; - String idOrigin = null; - if (ss.getSource() != null) { - idSource = ss.getSource(); - String sourceName = idSource.getName(); - idOrigin = sourceName; - if (sourceName.startsWith("<package:")) { - // try to find the name in the package environments - // format of sourceName is "<package"xxx deparse>" - String functionName = findFunctionName(uid, sourceName.substring(1, sourceName.lastIndexOf(' '))); - if (functionName != null) { - idName = functionName; - } - } else { - idOrigin = sourceName; - } - } else { - // One of the RSyntaxNode "unavailable"s. - idOrigin = idName; - idSource = RSource.fromText(idName, idName); - } - ident = new FunctionIdentification(idSource, idName, idOrigin, fdn); - } - return ident; - - } - } - /** * The function names that were requested to be used in implicit {@code debug(f)} calls, when * those functions are defined. Global to all contexts. */ @CompilationFinal private static String[] debugFunctionNames; - /** - * Called back from {@link FunctionDefinitionNode} so that we can record the {@link FunctionUID} - * and use {@code fdn} as the canonical {@link FunctionDefinitionNode}. - * - * @param fdn - */ - public static void registerFunctionDefinition(FunctionDefinitionNode fdn) { - // For PerfStats we need to record the info on fdn for the report - if (functionMap != null) { - FunctionUID uid = fdn.getUID(); - FunctionData fd = functionMap.get(uid); - if (fd != null) { - // duplicate - return; - } - assert fd == null; - functionMap.put(uid, new FunctionData(uid, fdn)); - } - } - - static FunctionIdentification getFunctionIdentification(FunctionUID uid) { - return functionMap.get(uid).getIdentification(); - } - public static FunctionDefinitionNode getFunctionDefinitionNode(RFunction func) { assert !func.isBuiltin(); return (FunctionDefinitionNode) func.getRootNode(); } + public static SourceSection getSourceSection(RFunction func) { + return getFunctionDefinitionNode(func).getSourceSection(); + } + /** * Create a filter that matches all the statement nodes in {@code func}. */ @@ -183,7 +79,6 @@ public class RInstrumentation { builder.sourceIs(fdns.getSource()); builder.rootSourceSectionEquals(fdns); return builder; - } /** @@ -201,22 +96,20 @@ public class RInstrumentation { * Activate the instrumentation system for {@code context}. Currently this simply checks for the * global (command-line) options for tracing and timing. They are applied to every context. */ - public static void activate(@SuppressWarnings("unused") RContext context) { + public static void activate(RContext context) { String rdebugValue = FastROptions.Rdebug.getStringValue(); if (rdebugValue != null) { debugFunctionNames = rdebugValue.split(","); } - if (REntryCounters.FunctionListener.enabled() || RNodeTimer.StatementListener.enabled()) { - functionMap = new HashMap<>(); - REntryCounters.FunctionListener.installCounters(); - RNodeTimer.StatementListener.installTimers(); + if (RFunctionProfiler.enabled()) { + RFunctionProfiler.installTimers(context); } // Check for function tracing RContext.getRRuntimeASTAccess().traceAllFunctions(); } public static Instrumenter getInstrumenter() { - return RContext.getInstance().getInstrumenter(); + return RContext.getInstance().getInstrumentationState().getInstrumenter(); } public static void checkDebugRequested(RFunction func) { @@ -230,66 +123,4 @@ public class RInstrumentation { } } - private static Map<FunctionUID, String> functionNameMap; - - /** - * Attempts to locate a name for an (assumed) builtin or global function. Returns {@code null} - * if not found. - */ - private static String findFunctionName(FunctionUID uid, String packageName) { - if (functionNameMap == null) { - functionNameMap = new HashMap<>(); - } - String name = functionNameMap.get(uid); - if (name == null) { - name = findFunctionInPackage(uid, packageName); - } - return name; - } - - /** - * Try to find the function identified by uid in the given package. N.B. If we have the uid, the - * promise identifying the lazily loaded function must have been evaluated! So there is no need - * to evaluate any promises. N.B. For packages, we must use the namespace env as that contains - * public and private functions. - */ - private static String findFunctionInPackage(FunctionUID uid, String packageName) { - if (packageName == null) { - return findFunctionInEnv(uid, REnvironment.globalEnv()); - } - REnvironment env = REnvironment.lookupOnSearchPath(packageName); - env = env.getPackageNamespaceEnv(); - return findFunctionInEnv(uid, env); - } - - private static String findFunctionInEnv(FunctionUID uid, REnvironment env) { - // This is rather inefficient, but it doesn't matter - RStringVector names = env.ls(true, null, false); - for (int i = 0; i < names.getLength(); i++) { - String name = names.getDataAt(i); - Object val = env.get(name); - if (val instanceof RPromise) { - RPromise prVal = (RPromise) val; - if (prVal.isEvaluated()) { - val = prVal.getValue(); - } else { - continue; - } - } - if (val instanceof RFunction) { - RFunction func = (RFunction) val; - RootNode rootNode = func.getRootNode(); - if (rootNode instanceof FunctionDefinitionNode) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) rootNode; - if (fdn.getUID().equals(uid)) { - functionNameMap.put(fdn.getUID(), name); - return name; - } - } - } - } - // Most likely a nested function, which is ok - // because they are not lazy and so have names from the parser. - return null; - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RNodeTimer.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RNodeTimer.java deleted file mode 100644 index 84c3cb1927b446d10a3702acd33193a63d837293..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RNodeTimer.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * 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.instrumentation; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.instrumentation.EventContext; -import com.oracle.truffle.api.instrumentation.ExecutionEventListener; -import com.oracle.truffle.api.instrumentation.SourceSectionFilter; -import com.oracle.truffle.api.instrumentation.StandardTags; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.control.BlockNode; -import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; -import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation.FunctionIdentification; -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.RPerfStats; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNodeVisitor; - -/** - * Basic support for adding as timer to a node. Currently limited to "statement" timing. - * - * The instrument records the cumulative time spent executing this node during the process execution - * using {@link System#nanoTime()}. - * - */ -public class RNodeTimer { - - public static final class TimeInfo { - private final Object ident; - protected long enterTime; - protected long cumulativeTime; - - TimeInfo(Object ident) { - this.ident = ident; - } - - public long getTime() { - return cumulativeTime; - } - - public Object getIdent() { - return ident; - } - } - - private abstract static class BasicListener implements ExecutionEventListener { - private HashMap<SourceSection, TimeInfo> timeInfoMap = new HashMap<>(); - - private TimeInfo getTimeInfo(EventContext context) { - SourceSection ss = context.getInstrumentedSourceSection(); - TimeInfo timeInfo = timeInfoMap.get(ss); - if (timeInfo == null) { - Object obj = timeInfoCreated(context); - timeInfo = new TimeInfo(obj); - timeInfoMap.put(ss, timeInfo); - } - return timeInfo; - } - - protected TimeInfo getTimeInfo(SourceSection sourceSection) { - TimeInfo timeInfo = timeInfoMap.get(sourceSection); - assert timeInfo != null; - return timeInfo; - } - - protected Map<SourceSection, TimeInfo> getTimeInfoMap() { - return timeInfoMap; - } - - @Override - public void onEnter(EventContext context, VirtualFrame frame) { - getTimeInfo(context).enterTime = System.nanoTime(); - } - - @Override - public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { - TimeInfo timeInfo = getTimeInfo(context); - timeInfo.cumulativeTime += System.nanoTime() - timeInfo.enterTime; - } - - @Override - public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { - onReturnValue(context, frame, exception); - } - - protected abstract Object timeInfoCreated(EventContext context); - - } - - public static class StatementListener extends BasicListener { - private static final StatementListener singleton = new StatementListener(); - - public static long findTimer(RFunction func) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); - FunctionUID uid = fdn.getUID(); - long cumTime = 0; - for (Map.Entry<SourceSection, TimeInfo> entry : StatementListener.singleton.getTimeInfoMap().entrySet()) { - TimeInfo timeInfo = entry.getValue(); - Node node = (Node) timeInfo.getIdent(); - FunctionDefinitionNode entryFdn = (FunctionDefinitionNode) node.getRootNode(); - FunctionUID entryUid = entryFdn.getUID(); - if (entryUid.equals(uid)) { - // statement in "func" - cumTime += timeInfo.cumulativeTime; - } - } - return cumTime; - } - - static void installTimers() { - if (enabled()) { - SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder(); - builder.tagIs(StandardTags.StatementTag.class); - SourceSectionFilter filter = builder.build(); - RInstrumentation.getInstrumenter().attachListener(filter, singleton); - } - } - - public static void installTimer(RFunction func) { - RInstrumentation.getInstrumenter().attachListener(RInstrumentation.createFunctionStatementFilter(func).build(), singleton); - } - - @Override - protected Node timeInfoCreated(EventContext context) { - return context.getInstrumentedNode(); - } - - // PerfStats support - - static { - RPerfStats.register(new PerfHandler()); - } - - static boolean enabled() { - return RPerfStats.enabled(PerfHandler.NAME); - } - - private static class TimingData implements Comparable<TimingData> { - long time; - FunctionUID functionUID; - - TimingData(FunctionUID functionUID) { - this.functionUID = functionUID; - } - - void addTime(long t) { - this.time += t; - } - - @Override - public int compareTo(TimingData o) { - if (time < o.time) { - return 1; - } else if (time > o.time) { - return -1; - } else { - return 0; - } - } - } - - private static class PerfHandler implements RPerfStats.Handler { - static final String NAME = "timing"; - private boolean stmts; - private int threshold; - - @Override - public void initialize(String optionText) { - if (optionText.length() > 0) { - String[] subOptions = optionText.split(":"); - for (String subOption : subOptions) { - if (subOption.equals("stmts")) { - stmts = true; - } else if (subOption.startsWith("threshold")) { - threshold = Integer.parseInt(subOption.substring(subOption.indexOf('=') + 1)) * 1000; - } - } - } - } - - @Override - public String getName() { - return NAME; - } - - /** - * Report the statement timing information at the end of the run. The report is per - * function {@link FunctionUID}, which uniquely defines a function in the face of call - * target splitting. Functions that consumed less time than requested threshold (default - * 0) are not included in the report. The report is sorted by cumulative time. - */ - @Override - public void report() { - Map<FunctionUID, TimingData> functionMap = new TreeMap<>(); - - for (Map.Entry<SourceSection, TimeInfo> entry : StatementListener.singleton.getTimeInfoMap().entrySet()) { - TimeInfo timeInfo = entry.getValue(); - Node node = (Node) timeInfo.getIdent(); - if (node.getRootNode() instanceof FunctionDefinitionNode) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) node.getRootNode(); - FunctionUID uid = fdn.getUID(); - TimingData timingData = functionMap.get(uid); - if (timingData == null) { - timingData = new TimingData(uid); - functionMap.put(uid, timingData); - } - timingData.addTime(millis(entry.getValue().cumulativeTime)); - } - } - - Collection<TimingData> values = functionMap.values(); - TimingData[] sortedData = new TimingData[values.size()]; - values.toArray(sortedData); - Arrays.sort(sortedData); - long totalTime = 0; - for (TimingData t : sortedData) { - totalTime += t.time; - } - - RPerfStats.out().printf("Total (user) time %d ms%n", totalTime); - for (TimingData t : sortedData) { - if (t.time > 0) { - if (t.time > threshold) { - FunctionIdentification fdi = RInstrumentation.getFunctionIdentification(t.functionUID); - RPerfStats.out().println("=========="); - RPerfStats.out().printf("%d ms (%.2f%%): %s, %s%n", t.time, percent(t.time, totalTime), fdi.name, fdi.origin); - if (stmts) { - SourceSection ss = fdi.node.getSourceSection(); - if (ss == null) { - // wrapper - ss = fdi.node.getBody().getSourceSection(); - if (ss == null) { - RPerfStats.out().println("no source available"); - } - } else { - long[] time = createLineTimes(fdi); - int startLine = ss.getStartLine(); - int lastLine = ss.getEndLine(); - for (int i = startLine; i <= lastLine; i++) { - RPerfStats.out().printf("%8dms: %s%n", time[i], fdi.source.getCode(i)); - } - - } - } - } - } - } - } - } - - private static double percent(long a, long b) { - return ((double) a * 100) / b; - } - - private abstract static class StatementVisitor implements RSyntaxNodeVisitor { - @SuppressWarnings("unused") protected final FunctionUID uid; - - StatementVisitor(FunctionUID uid) { - this.uid = uid; - } - - @Override - public boolean visit(RSyntaxNode node, int depth) { - if (node instanceof BlockNode) { - BlockNode sequenceNode = (BlockNode) node; - RNode[] block = sequenceNode.getSequence(); - for (int i = 0; i < block.length; i++) { - RSyntaxNode n = block[i].unwrap().asRSyntaxNode(); - if (!callback(n)) { - return false; - } - } - } - return true; - } - - protected abstract boolean callback(RSyntaxNode node); - - } - - private static class LineTimesNodeVisitor extends StatementVisitor { - private final long[] times; - - LineTimesNodeVisitor(FunctionUID uid, long[] time) { - super(uid); - this.times = time; - } - - @Override - protected boolean callback(RSyntaxNode node) { - SourceSection ss = node.getSourceSection(); - TimeInfo timeInfo = singleton.getTimeInfoMap().get(ss); - if (timeInfo != null) { - assert ss.getStartLine() != 0; - long stmtTime = millis(timeInfo.cumulativeTime); - times[0] += stmtTime; - times[ss.getStartLine()] += stmtTime; - } else { - /* - * This happens because default arguments are not visited during the AST probe - * walk. - */ - } - return true; - } - } - - private static long millis(long nanos) { - return nanos / 1000000; - } - - private static long[] createLineTimes(FunctionIdentification fdi) { - /* - * Although only those lines occupied by the function will actually have entries in the - * array, addressing is easier if we allocate an array that is as long as the entire - * source. Since there is never a line 0, we use that to compute the total. - */ - final long[] times = new long[fdi.source.getLineCount() + 1]; - RSyntaxNode.accept(fdi.node.getBody().asNode(), 0, new LineTimesNodeVisitor(fdi.node.getUID(), times), false); - return times; - } - } -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java index 12c94d8ddc1457fb26840b926a26fe0cdd0fcc74..dbc9d2dc9bfb59a5bfe699c5380a2b2e7f0fb694 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java @@ -30,7 +30,6 @@ import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RType; @@ -655,7 +654,7 @@ public class CallRFFIHelper { guarantee(symbolObj instanceof RSymbol); RSymbol symbol = (RSymbol) symbolObj; // Works but not remotely efficient - Source source = RSource.fromText("get(\"" + symbol.getName() + "\", mode=\"function\")", RInternalSourceDescriptions.RF_FINDFUN); + Source source = RSource.fromTextInternal("get(\"" + symbol.getName() + "\", mode=\"function\")", RSource.Internal.RF_FINDFUN); try { Object result = RContext.getEngine().parseAndEval(source, env.getFrame(), false); return result; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java index 911146cef4567a13f3ba111f4d933a9608fa392c..8d04af165f9ced86ced2791b37fc76261077f2eb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java @@ -39,7 +39,6 @@ public enum FastROptions { PrintErrorStacktracesToFile("Dumps Java and R stack traces to 'fastr_errors.log' for all errors", true), CheckResultCompleteness("Assert completeness of results vectors after evaluating unit tests and R shell commands", true), Debug("Debug=name1,name2,...; Turn on debugging output for 'name1', 'name2', etc.", null, true), - Instrument("Enable (Old) Instrumentation", false), TraceCalls("Trace all R function calls", false), TraceCallsToFile("TraceCalls output is sent to 'fastr_tracecalls.log'", false), TraceNativeCalls("Trace all native function calls (performed via .Call, .External, etc.)", false), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FunctionUID.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FunctionUID.java deleted file mode 100644 index 891850463405f5fc2871f9096fba8e106ca7d068..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FunctionUID.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 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; - -/** - * An abstract UID for a {@code FunctionDefinitionNode}, used by instrumentation code. There may be - * many clones of a {@code FunctionDefinitionNode}, but they all share the same UID. - */ -public interface FunctionUID extends Comparable<FunctionUID> { - -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java index cbe8a8217396bef609da9399da5c9732b202ee60..0516ba9dac1739769d78185452ac6523eae330e3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java @@ -342,7 +342,7 @@ public class RDeparse { } public void fixupSources() { - Source source = RSource.fromText(sb.toString(), "deparse"); + Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE); for (SourceSectionElement s : sources) { s.element.setSourceSection(source.createSection(null, s.start, s.length)); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 7df6df646122ce7708b1d47e5ebf37e5451f7091..c08fae1d96a9bd7baff6efe01ca89f47d1499ff9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -676,7 +676,9 @@ public final class RError extends RuntimeException { QUIT_ASK("one of \"yes\", \"no\", \"ask\" or \"default\" expected."), QUIT_SAVE("unrecognized value of 'save'"), ENVIRONMENTS_COERCE("environments cannot be coerced to other types"), - CLOSURE_COERCE("cannot coerce type 'closure' to vector of type 'integer'"); + CLOSURE_COERCE("cannot coerce type 'closure' to vector of type 'integer'"), + ROWSUM_NAMES_NOT_CHAR("row names are not character"), + ROWSUM_NON_NUMERIC("non-numeric matrix in rowsum(): this should not happen"); public final String message; final boolean hasArgs; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalSourceDescriptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalSourceDescriptions.java deleted file mode 100644 index 10d57d635a5195989d604f6a6ae3241b4bdf43bf..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalSourceDescriptions.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016, 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 java.util.HashSet; -import java.util.Set; - -import com.oracle.truffle.api.source.Source; - -/** - * Collection of strings that are used to indicate {@link Source} instances that have internal - * descriptions. - */ -public class RInternalSourceDescriptions { - private static final Set<String> set = new HashSet<>(); - - public static final String UNIT_TEST = add("<unit_test>"); - public static final String SHELL_INPUT = add("<shell_input>"); - public static final String EXPRESSION_INPUT = add("<expression_input>"); - public static final String GET_ECHO = add("<get_echo>"); - public static final String QUIT_EOF = add("<<quit_eof>>"); - public static final String STARTUP_SHUTDOWN = add("<startup/shutdown>"); - public static final String REPL_WRAPPER = add("<repl wrapper>"); - public static final String NO_SOURCE = add("<no source>"); - public static final String CONTEXT_EVAL = add("<context_eval>"); - public static final String RF_FINDFUN = add("<Rf_findfun>"); - - private static String add(String s) { - set.add(s); - return s; - } - - public static boolean isInternal(String s) { - return set.contains(s); - } -} 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 532564cb30eea0544f17cc2d848f4142c447e808..b930856972ac8930e17853a30b645baf8858c1ad 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 @@ -310,7 +310,6 @@ public class RSerialize { } private static class Input extends Common { - private static final String UNKNOWN_PACKAGE_SOURCE_PREFIX = "<package:"; protected final PInputStream stream; /** @@ -860,7 +859,7 @@ public class RSerialize { private RExpression parse(Map<String, Object> constants, String deparseRaw) throws IOException { try { - Source source = RSource.fromText(deparseRaw, UNKNOWN_PACKAGE_SOURCE_PREFIX + packageName + " deparse>"); + Source source = RSource.fromPackageTextInternal(deparseRaw, packageName); return RContext.getEngine().parse(constants, source); } catch (Throwable ex) { /* @@ -893,7 +892,7 @@ public class RSerialize { Source source; String name; if (sourcePath == null) { - source = RSource.fromText(deparse, UNKNOWN_PACKAGE_SOURCE_PREFIX + packageName + " deparse>"); + source = RSource.fromPackageTextInternalWithName(deparse, packageName, currentFunctionName); name = currentFunctionName; } else { source = RSource.fromFileName(deparse, sourcePath); @@ -930,7 +929,7 @@ public class RSerialize { } private static final String FAILED_DEPARSE_FUNCTION = "function(...) stop(\"FastR error: proxy for lazily loaded function that did not deparse/parse\")"; - private static final Source FAILED_DEPARSE_FUNCTION_SOURCE = RSource.fromText(FAILED_DEPARSE_FUNCTION, UNKNOWN_PACKAGE_SOURCE_PREFIX + "deparse_error>"); + private static final Source FAILED_DEPARSE_FUNCTION_SOURCE = RSource.fromTextInternal(FAILED_DEPARSE_FUNCTION, RSource.Internal.DEPARSE_ERROR); /** * GnuR uses a pairlist to represent attributes, whereas FastR uses the abstract RAttributes diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java index dd840334c138f07cebcb3bf861e2d7023b40dc78..7b3291b64fe45091dd12cc771c50e722939754aa 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java @@ -30,34 +30,168 @@ import java.net.URL; import com.oracle.truffle.api.source.Source; +/** + * A facade for the creation of Truffle {@link Source} objects, which is complicated in R due the + * the many different ways in which sources can be created. Particularly tricky are sources created + * from deparsing functions from (binary-form) packages and from the {@code source} builtin, as + * these are presented as text strings despite being associated with files. + * + * We separate sources as <i>internal</i> or <i>external</i>, where the former will return + * {@code true} to {@link Source#isInternal()}. External sources always correspond to some external + * data source, e.g., file, url, even if they are not created using the standard methods in + * {@link Source}. An internal source will always return {@code null} to {@link Source#getURI} but + * {@link Source#getName} should return a value that indicates how/why the source was created, a + * value from {@link Internal}. + * + */ public class RSource { + /** + * Collection of strings that are used to indicate {@link Source} instances that have internal + * descriptions. + */ + public enum Internal { + + UNIT_TEST("<unit_test>"), + SHELL_INPUT("<shell_input>"), + EXPRESSION_INPUT("<expression_input>"), + GET_ECHO("<get_echo>"), + QUIT_EOF("<<quit_eof>>"), + STARTUP_SHUTDOWN("<startup/shutdown>"), + REPL_WRAPPER("<repl wrapper>"), + EVAL_WRAPPER("<eval wrapper>"), + NO_SOURCE("<no source>"), + CONTEXT_EVAL("<context_eval>"), + RF_FINDFUN("<Rf_findfun>"), + BROWSER_INPUT("<browser_input>"), + CLEAR_WARNINGS("<clear_warnings>"), + DEPARSE("<deparse>"), + GET_CONTEXT("<get_context>"), + DEBUGTEST_FACTORIAL("<factorial.r>"), + DEBUGTEST_DEBUG("<debugtest.r>"), + DEBUGTEST_EVAL("<evaltest.r>"), + TCK_INIT("<tck_initialization>"), + PACKAGE("<package:%s deparse>"), + DEPARSE_ERROR("<package_deparse_error>"), + LAPPLY("<lapply>"); + + public final String string; + + Internal(String text) { + this.string = text; + } + + } + + /** + * Create an (external) source from the {@code text} that is known to originate from the file + * system path {@code path}. The simulates the behavior of {@link #fromFile}. + */ public static Source fromFileName(String text, String path) { File file = new File(path).getAbsoluteFile(); try { URI uri = new URI("file://" + file.getAbsolutePath()); - return Source.newBuilder(text).name(path).uri(uri).mimeType(RRuntime.R_APP_MIME).build(); + return Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME).build(); } catch (URISyntaxException ex) { throw RInternalError.shouldNotReachHere(ex); } } - public static Source fromText(String text, String name) { - return fromText(text, name, RRuntime.R_APP_MIME); + /** + * Create an {@code internal} source from {@code text} and {@code description}. + */ + public static Source fromTextInternal(String text, Internal description) { + return fromTextInternal(text, description, RRuntime.R_APP_MIME); + } + + /** + * Create an {@code internal} source from {@code text} and {@code description} of given + * {@code mimeType}. + */ + + public static Source fromTextInternal(String text, Internal description, String mimeType) { + return Source.newBuilder(text).name(description.string).mimeType(mimeType).internal().build(); + } + + /** + * Create an {@code internal} source for a deparsed package from {@code text} and + * {@code packageName}. + */ + public static Source fromPackageTextInternal(String text, String packageName) { + String name = String.format(Internal.PACKAGE.string, packageName); + return Source.newBuilder(text).name(name).mimeType(RRuntime.R_APP_MIME).build(); } - public static Source fromText(String text, String name, String mimeType) { - return Source.newBuilder(text).name(name).mimeType(mimeType).build(); + /** + * Create an {@code internal} source for a deparsed package from {@code text} when the function + * name might be known. If {@code functionName} is not {@code null}, use it as the "name" for + * the source, else default to {@link #fromPackageTextInternal(String, String)}. + */ + public static Source fromPackageTextInternalWithName(String text, String packageName, String functionName) { + if (functionName == null) { + return fromPackageTextInternal(text, packageName); + } else { + return Source.newBuilder(text).name(packageName + "::" + functionName).mimeType(RRuntime.R_APP_MIME).build(); + } } + /** + * Create an (external) source from the file system path {@code path}. + */ public static Source fromFileName(String path) throws IOException { return Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME).build(); } + /** + * Create an (external) source from the file system path denoted by {@code file}. + */ public static Source fromFile(File file) throws IOException { return Source.newBuilder(file).name(file.getName()).mimeType(RRuntime.R_APP_MIME).build(); } + /** + * Create an (external) source from {@code url}. + */ public static Source fromURL(URL url, String name) throws IOException { return Source.newBuilder(url).name(name).mimeType(RRuntime.R_APP_MIME).build(); } + + /** + * If {@code source} was created with {@link #fromPackageTextInternal} return the + * "package:name", else {@code null}. This can be used to access the corresponding R + * environment. + */ + public static String getPackageName(Source source) { + String sourceName = source.getName(); + if (sourceName.startsWith("<package:")) { + return sourceName.substring(1, sourceName.lastIndexOf(' ')); + } else { + return null; + } + } + + /** + * If {@code source} is "internal", return {@code null} else return the file system path + * corresponding to the associated {@link URI}. + */ + public static String getPath(Source source) { + if (source == null || source.isInternal()) { + return null; + } + URI uri = source.getURI(); + assert uri != null; + return uri.getPath(); + } + + /** + * Always returns a non-null string even for internal sources. + */ + public static String getOrigin(Source source) { + String path = RSource.getPath(source); + if (path == null) { + return source.getName(); + } else { + return path; + } + } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java index 166e7903ba3b821c385b357e291446c3a0d0b105..061d1f60e025fc4c4537791421d1746b8e0f352f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java @@ -446,10 +446,7 @@ public final class Utils { SourceSection ss = sn != null ? sn.getSourceSection() : null; // fabricate a srcref attribute from ss Source source = ss != null ? ss.getSource() : null; - String path = source != null ? source.getPath() : null; - if (path != null && RInternalSourceDescriptions.isInternal(path)) { - path = null; - } + String path = RSource.getPath(source); RStringVector callerSource = RDataFactory.createStringVectorFromScalar(RContext.getRRuntimeASTAccess().getCallerSource(call)); if (path != null) { callerSource.setAttr(RRuntime.R_SRCREF, RSrcref.createLloc(ss, path)); @@ -531,11 +528,6 @@ public final class Utils { } RCaller call = RArguments.getCall(unwrapped); if (call != null) { - /* - * Log the frame depths as a triple: d,e,p, where 'd' is the actual depth, 'e' is - * the effective depth and 'p' is the promise frame depth, or -1 if no promise - * evaluation in progress. - */ String callSrc = call.isValidCaller() ? RContext.getRRuntimeASTAccess().getCallerSource(call) : "<invalid call>"; int depth = RArguments.getDepth(unwrapped); str.append("Frame(d=").append(depth).append("): ").append(callTarget).append(isVirtual ? " (virtual)" : ""); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/WithFunctionUID.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/WithFunctionUID.java deleted file mode 100644 index b4399e5d19bbc3055b63b0c7afd7e62e2ef296d5..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/WithFunctionUID.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 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; - -public interface WithFunctionUID { - - FunctionUID getUID(); -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java index e725f80386447912401b2a090425d39c93e1a23e..4980ef69ae8ba14be31c4ce41bfe8d2b857e90c1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java @@ -35,9 +35,8 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind; /** * Represents custom initialization state for an R instance. * - * Use {@link #apply(com.oracle.truffle.api.vm.PolyglotEngine.Builder)} to apply this information to - * a newly-built {@link PolyglotEngine} instance (it will be stored in the "fastrContextInfo" global - * symbol). + * Use {@link #createVM()} to apply this information to a newly-built {@link PolyglotEngine} + * instance (it will be stored in the "fastrContextInfo" global symbol). */ public final class ContextInfo implements TruffleObject { static final String GLOBAL_SYMBOL = "fastrContextInfo"; @@ -56,6 +55,7 @@ public final class ContextInfo implements TruffleObject { private final RContext parent; private final ConsoleHandler consoleHandler; private final int id; + private PolyglotEngine vm; private ContextInfo(RCmdOptions options, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id) { this.options = options; @@ -66,8 +66,10 @@ public final class ContextInfo implements TruffleObject { this.id = id; } - public PolyglotEngine.Builder apply(PolyglotEngine.Builder builder) { - return builder.globalSymbol(GLOBAL_SYMBOL, this); + public PolyglotEngine createVM() { + PolyglotEngine newVM = PolyglotEngine.newBuilder().globalSymbol(GLOBAL_SYMBOL, this).build(); + this.vm = newVM; + return newVM; } /** @@ -123,6 +125,10 @@ public final class ContextInfo implements TruffleObject { return id; } + public PolyglotEngine getVM() { + return vm; + } + @Override public ForeignAccess getForeignAccess() { throw new IllegalStateException("cannot access " + ContextInfo.class.getSimpleName() + " via Truffle"); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java index c049318006f67e40e30d220d80d60841a745659c..d80fe6fc61d4656305192dfc3435fe8d935b81e6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java @@ -40,8 +40,6 @@ import com.oracle.truffle.r.runtime.nodes.RNode; public interface Engine { - String EVAL_FUNCTION_NAME = "<eval wrapper>"; - class ParseException extends IOException { private static final long serialVersionUID = 1L; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java index 505500c15023012ef3ec1ef4a8153d06602bc17c..25accd14e61b46ebeb55b1a213a1a119daed0143 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java @@ -71,7 +71,7 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.RFFIContextStateFactory; -import com.oracle.truffle.r.runtime.instrument.TraceState; +import com.oracle.truffle.r.runtime.instrument.InstrumentationState; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; import com.oracle.truffle.r.runtime.rng.RRNG; @@ -172,7 +172,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { */ public static class EvalThread extends ContextThread { - private static final Source GET_CONTEXT = RSource.fromText("invisible(.fastr.context.get())", "<get_context>"); + private static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT); private final Source source; private final ContextInfo info; @@ -189,7 +189,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { @Override public void run() { - PolyglotEngine vm = info.apply(PolyglotEngine.newBuilder()).build(); + PolyglotEngine vm = info.createVM(); try { setContext(vm.eval(GET_CONTEXT).as(RContext.class)); } catch (Exception e1) { @@ -340,8 +340,8 @@ public final class RContext extends ExecutionContext implements TruffleObject { @CompilationFinal private static RContext singleContext; private final Env env; - private final Instrumenter instrumenter; private final HashMap<String, TruffleObject> exportedSymbols = new HashMap<>(); + private final boolean initial; /** * State that is used to support interposing on loadNamespace() for overrides. */ @@ -363,12 +363,12 @@ public final class RContext extends ExecutionContext implements TruffleObject { public final ContextState stateRFFI; public final RSerialize.ContextStateImpl stateRSerialize; public final LazyDBCache.ContextStateImpl stateLazyDBCache; - public final TraceState.ContextStateImpl stateTraceHandling; + public final InstrumentationState stateInstrumentation; public final ContextStateImpl stateInternalCode; private ContextState[] contextStates() { return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize, - stateLazyDBCache, stateTraceHandling}; + stateLazyDBCache, stateInstrumentation}; } private RContext(Env env, Instrumenter instrumenter, boolean isInitial) { @@ -378,6 +378,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { } else { this.info = initialInfo; } + this.initial = isInitial; // this must happen before engine activation in the code below if (info.getKind() == ContextKind.SHARE_NOTHING) { @@ -394,7 +395,6 @@ public final class RContext extends ExecutionContext implements TruffleObject { } this.env = env; - this.instrumenter = instrumenter; if (info.getConsoleHandler() == null) { throw Utils.fail("no console handler set"); } @@ -432,7 +432,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { stateRFFI = RFFIContextStateFactory.newContext(this); stateRSerialize = RSerialize.ContextStateImpl.newContext(this); stateLazyDBCache = LazyDBCache.ContextStateImpl.newContext(this); - stateTraceHandling = TraceState.newContext(this); + stateInstrumentation = InstrumentationState.newContext(this, instrumenter); stateInternalCode = ContextStateImpl.newContext(this); engine.activate(stateREnvironment); @@ -487,8 +487,8 @@ public final class RContext extends ExecutionContext implements TruffleObject { return env; } - public Instrumenter getInstrumenter() { - return instrumenter; + public InstrumentationState getInstrumentationState() { + return stateInstrumentation; } public ContextKind getKind() { @@ -662,6 +662,14 @@ public final class RContext extends ExecutionContext implements TruffleObject { return RContext.getInstance().engine; } + public PolyglotEngine getVM() { + return info.getVM(); + } + + public boolean isInitial() { + return initial; + } + public void setLoadingBase(boolean b) { loadingBase = b; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/FunctionUIDFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/FunctionUIDFactory.java deleted file mode 100644 index c0c02637a774dc0db47a9fe08c0b00bcdd7ecdef..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/FunctionUIDFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2014, 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.instrument; - -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.Utils; - -public abstract class FunctionUIDFactory { - private static final String FACTORY_CLASS_PROPERTY = "fastr.fuid.factory.class"; - private static final String PACKAGE_PREFIX = "com.oracle.truffle.r.nodes.function."; - private static final String SUFFIX = "FunctionUIDFactory"; - private static final String DEFAULT_FACTORY = "along"; - private static final String DEFAULT_FACTORY_CLASS = mapSimpleName(DEFAULT_FACTORY); - - private static String mapSimpleName(String simpleName) { - return PACKAGE_PREFIX + simpleName.toUpperCase() + SUFFIX; - } - - private static FunctionUIDFactory instance; - - static { - String prop = System.getProperty(FACTORY_CLASS_PROPERTY); - if (prop != null) { - if (!prop.contains(".")) { - // simple name - prop = mapSimpleName(prop); - } - } else { - prop = DEFAULT_FACTORY_CLASS; - } - try { - instance = (FunctionUIDFactory) Class.forName(prop).newInstance(); - } catch (Exception ex) { - Utils.fail("Failed to instantiate class: " + prop + ": " + ex); - } - } - - public static FunctionUIDFactory get() { - return instance; - } - - public abstract FunctionUID createUID(); -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java new file mode 100644 index 0000000000000000000000000000000000000000..87b3341dae1bdc444b1f3e64b7657a8835905597 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, 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.instrument; + +import java.io.PrintWriter; +import java.util.WeakHashMap; + +import com.oracle.truffle.api.instrumentation.EventBinding; +import com.oracle.truffle.api.instrumentation.ExecutionEventListener; +import com.oracle.truffle.api.instrumentation.Instrumenter; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.tools.Profiler; + +/** + * The tracingState is a global variable in R, so we store it (and the associated listener objects) + * in the {@link RContext}. We also store related {@code debug} state, as that is also context + * specific. + * + */ +public final class InstrumentationState implements RContext.ContextState { + + /** + * Records all functions that have trace listeners installed. + */ + private final WeakHashMap<SourceSection, EventBinding<?>> traceBindingMap = new WeakHashMap<>(); + + private boolean tracingState = true; + + /** + * Records all functions that have debug listeners installed. + */ + private final WeakHashMap<SourceSection, ExecutionEventListener> debugListenerMap = new WeakHashMap<>(); + + private final Instrumenter instrumenter; + + private Profiler profiler; + + private final RprofState rprofState; + + /** + * State used by {@code Rprof}. + * + */ + public static class RprofState { + private PrintWriter out; + private Thread profileThread; + private ExecutionEventListener statementListener; + private long intervalInMillis; + private boolean lineProfiling; + + public static RprofState newContext(@SuppressWarnings("unused") RContext context) { + return new RprofState(); + } + + public void initialize(PrintWriter outA, Thread profileThreadA, ExecutionEventListener statementListenerA, long intervalInMillisA, + boolean lineProfilingA) { + this.out = outA; + this.profileThread = profileThreadA; + this.statementListener = statementListenerA; + this.intervalInMillis = intervalInMillisA; + this.lineProfiling = lineProfilingA; + } + + public boolean lineProfiling() { + return lineProfiling; + } + + public PrintWriter out() { + return out; + } + + public long intervalInMillis() { + return intervalInMillis; + } + + public ExecutionEventListener statementListener() { + return statementListener; + } + + public Thread profileThread() { + return profileThread; + } + + } + + private InstrumentationState(Instrumenter instrumenter) { + this.instrumenter = instrumenter; + this.rprofState = new RprofState(); + } + + public void putTraceBinding(SourceSection ss, EventBinding<?> binding) { + traceBindingMap.put(ss, binding); + } + + public EventBinding<?> getTraceBinding(SourceSection ss) { + return traceBindingMap.get(ss); + } + + public void putDebugListener(SourceSection ss, ExecutionEventListener listener) { + debugListenerMap.put(ss, listener); + } + + public EventBinding<?>[] getTraceBindings() { + EventBinding<?>[] result = new EventBinding<?>[traceBindingMap.size()]; + traceBindingMap.values().toArray(result); + return result; + + } + + public ExecutionEventListener getDebugListener(SourceSection ss) { + return debugListenerMap.get(ss); + } + + public boolean setTracingState(boolean state) { + boolean prev = tracingState; + tracingState = state; + return prev; + } + + public boolean getTracingState() { + return tracingState; + } + + public void setProfiler(Profiler profiler) { + this.profiler = profiler; + } + + public Profiler getProfiler() { + return profiler; + } + + public Instrumenter getInstrumenter() { + return instrumenter; + } + + public RprofState getRprof() { + return rprofState; + } + + public static InstrumentationState newContext(@SuppressWarnings("unused") RContext context, Instrumenter instrumenter) { + return new InstrumentationState(instrumenter); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/TraceState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/TraceState.java deleted file mode 100644 index 4bbf3d547340fd38c04948b4f776cc6fdd9a626e..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/TraceState.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2013, 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.instrument; - -import java.util.WeakHashMap; - -import com.oracle.truffle.r.runtime.FunctionUID; -import com.oracle.truffle.r.runtime.context.RContext; - -/** - * The tracingState is a global variable in R, so we store it (and the associated listener objects) - * in the {@link RContext}. To finesse the temporary existence of two instrumentation frameworks the - * receiver is typed as {@link Object}. - * - */ -public class TraceState { - public static class ContextStateImpl implements RContext.ContextState { - - /** - * Records all functions that have trace listeners installed. - */ - private final WeakHashMap<FunctionUID, Object> listenerMap = new WeakHashMap<>(); - private boolean tracingState = true; - - public void put(FunctionUID functionUID, Object listener) { - listenerMap.put(functionUID, listener); - } - - public Object get(FunctionUID functionUID) { - return listenerMap.get(functionUID); - } - - public boolean setTracingState(boolean state) { - boolean prev = tracingState; - tracingState = state; - return prev; - } - - public boolean getTracingState() { - return tracingState; - } - - public Object[] getListeners() { - Object[] result = new Object[listenerMap.size()]; - listenerMap.values().toArray(result); - return result; - } - } - - public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) { - return new ContextStateImpl(); - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java index bd86a98e2a0a8f0c4791df93819bf260297aeb5a..9e5d90ea9425a6cfdf0c225f88665c730b832808 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java @@ -19,48 +19,43 @@ public class TestBuiltin_rowsum extends TestBase { @Test public void testrowsum1() { - assertEval(Ignored.Unknown, - "argv <- list(structure(1:12, .Dim = 3:4), c('Y', 'X', 'Y'), c('X', 'Y'), FALSE, c('X', 'Y')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(1:12, .Dim = 3:4), c('Y', 'X', 'Y'), c('X', 'Y'), FALSE, c('X', 'Y')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum2() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.83678930089809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.807183221448213, 0, 0, 0, 0, 0, 0, 0, 2.28512598329689, 0, 2.63247834995855, 0, 2.20238351041917, 0, 0.769295244943351, 0, 0, 0, 0, 0, 2.39247868547682, 2.35872046276927, 0, 1.96863683476113, 1.77908247814048, 0, 0, 0, 1.30635392456315, 0, 1.90387659717817, 0, 0.869405556702986, 1.81335102661978, 2.03683243726846, 0, 0.594853387563489, 0, 0, 0.546043346519582, 2.43847447982989, 0, 0, 2.01202685781755, 0, 2.67064226802904, 2.9177625705488, 0.566296850563958, 0, 1.07001449051313, 1.02747153153177, 0, 1.14719850081019, 2.56380862975493, 0.760732567403466, 0.778199262684211, 0, 0.871444851625711, 2.75724254851229, 1.6366914055543, 0.606628090143204, 1.09201998403296, 0.729518678388558, 2.26406822516583, 2.41699231159873, 1.90058654651511), .Names = c('7', '8', '12', '13', '19', '22', '26', '31', '34', '36', '38', '40', '42', '43', '44', '46', '50', '51', '57', '59', '60', '61', '64', '67', '68', '72', '75', '76', '77', '78', '84', '87', '89', '94', '95', '100', '101', '102', '107', '110', '114', '115', '122', '123', '129', '130', '131', '134', '136', '137', '141', '144', '146', '150', '153', '154', '157', '160', '161', '162', '166', '167', '172', '174', '176', '178', '179', '180', '183', '184', '185', '186', '187', '197', '199', '201', '203', '204', '205', '207', '208', '210', '211', '214', '217', '219', '220', '222', '226', '228')), structure(c(310, 361, 654, 728, 61, 81, 520, 473, 107, 122, 965, 731, 153, 433, 145, 95, 765, 735, 5, 687, 345, 444, 60, 208, 821, 305, 226, 426, 705, 363, 167, 641, 740, 245, 588, 166, 559, 450, 529, 351, 201, 524, 199, 550, 551, 543, 293, 511, 511, 371, 201, 62, 356, 340, 315, 182, 364, 376, 384, 268, 266, 194, 348, 382, 296, 186, 145, 269, 350, 272, 292, 332, 285, 243, 276, 79, 240, 202, 235, 224, 239, 173, 252, 92, 192, 211, 175, 203, 105, 177), .Names = c('7', '8', '12', '13', '19', '22', '26', '31', '34', '36', '38', '40', '42', '43', '44', '46', '50', '51', '57', '59', '60', '61', '64', '67', '68', '72', '75', '76', '77', '78', '84', '87', '89', '94', '95', '100', '101', '102', '107', '110', '114', '115', '122', '123', '129', '130', '131', '134', '136', '137', '141', '144', '146', '150', '153', '154', '157', '160', '161', '162', '166', '167', '172', '174', '176', '178', '179', '180', '183', '184', '185', '186', '187', '197', '199', '201', '203', '204', '205', '207', '208', '210', '211', '214', '217', '219', '220', '222', '226', '228')), c(5, 60, 61, 62, 79, 81, 92, 95, 105, 107, 122, 145, 153, 166, 167, 173, 175, 177, 182, 186, 192, 194, 199, 201, 202, 203, 208, 211, 224, 226, 235, 239, 240, 243, 245, 252, 266, 268, 269, 272, 276, 285, 292, 293, 296, 305, 310, 315, 332, 340, 345, 348, 350, 351, 356, 361, 363, 364, 371, 376, 382, 384, 426, 433, 444, 450, 473, 511, 520, 524, 529, 543, 550, 551, 559, 588, 641, 654, 687, 705, 728, 731, 735, 740, 765, 821, 965), FALSE, c('5', '60', '61', '62', '79', '81', '92', '95', '105', '107', '122', '145', '153', '166', '167', '173', '175', '177', '182', '186', '192', '194', '199', '201', '202', '203', '208', '211', '224', '226', '235', '239', '240', '243', '245', '252', '266', '268', '269', '272', '276', '285', '292', '293', '296', '305', '310', '315', '332', '340', '345', '348', '350', '351', '356', '361', '363', '364', '371', '376', '382', '384', '426', '433', '444', '450', '473', '511', '520', '524', '529', '543', '550', '551', '559', '588', '641', '654', '687', '705', '728', '731', '735', '740', '765', '821', '965')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.83678930089809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.807183221448213, 0, 0, 0, 0, 0, 0, 0, 2.28512598329689, 0, 2.63247834995855, 0, 2.20238351041917, 0, 0.769295244943351, 0, 0, 0, 0, 0, 2.39247868547682, 2.35872046276927, 0, 1.96863683476113, 1.77908247814048, 0, 0, 0, 1.30635392456315, 0, 1.90387659717817, 0, 0.869405556702986, 1.81335102661978, 2.03683243726846, 0, 0.594853387563489, 0, 0, 0.546043346519582, 2.43847447982989, 0, 0, 2.01202685781755, 0, 2.67064226802904, 2.9177625705488, 0.566296850563958, 0, 1.07001449051313, 1.02747153153177, 0, 1.14719850081019, 2.56380862975493, 0.760732567403466, 0.778199262684211, 0, 0.871444851625711, 2.75724254851229, 1.6366914055543, 0.606628090143204, 1.09201998403296, 0.729518678388558, 2.26406822516583, 2.41699231159873, 1.90058654651511), .Names = c('7', '8', '12', '13', '19', '22', '26', '31', '34', '36', '38', '40', '42', '43', '44', '46', '50', '51', '57', '59', '60', '61', '64', '67', '68', '72', '75', '76', '77', '78', '84', '87', '89', '94', '95', '100', '101', '102', '107', '110', '114', '115', '122', '123', '129', '130', '131', '134', '136', '137', '141', '144', '146', '150', '153', '154', '157', '160', '161', '162', '166', '167', '172', '174', '176', '178', '179', '180', '183', '184', '185', '186', '187', '197', '199', '201', '203', '204', '205', '207', '208', '210', '211', '214', '217', '219', '220', '222', '226', '228')), structure(c(310, 361, 654, 728, 61, 81, 520, 473, 107, 122, 965, 731, 153, 433, 145, 95, 765, 735, 5, 687, 345, 444, 60, 208, 821, 305, 226, 426, 705, 363, 167, 641, 740, 245, 588, 166, 559, 450, 529, 351, 201, 524, 199, 550, 551, 543, 293, 511, 511, 371, 201, 62, 356, 340, 315, 182, 364, 376, 384, 268, 266, 194, 348, 382, 296, 186, 145, 269, 350, 272, 292, 332, 285, 243, 276, 79, 240, 202, 235, 224, 239, 173, 252, 92, 192, 211, 175, 203, 105, 177), .Names = c('7', '8', '12', '13', '19', '22', '26', '31', '34', '36', '38', '40', '42', '43', '44', '46', '50', '51', '57', '59', '60', '61', '64', '67', '68', '72', '75', '76', '77', '78', '84', '87', '89', '94', '95', '100', '101', '102', '107', '110', '114', '115', '122', '123', '129', '130', '131', '134', '136', '137', '141', '144', '146', '150', '153', '154', '157', '160', '161', '162', '166', '167', '172', '174', '176', '178', '179', '180', '183', '184', '185', '186', '187', '197', '199', '201', '203', '204', '205', '207', '208', '210', '211', '214', '217', '219', '220', '222', '226', '228')), c(5, 60, 61, 62, 79, 81, 92, 95, 105, 107, 122, 145, 153, 166, 167, 173, 175, 177, 182, 186, 192, 194, 199, 201, 202, 203, 208, 211, 224, 226, 235, 239, 240, 243, 245, 252, 266, 268, 269, 272, 276, 285, 292, 293, 296, 305, 310, 315, 332, 340, 345, 348, 350, 351, 356, 361, 363, 364, 371, 376, 382, 384, 426, 433, 444, 450, 473, 511, 520, 524, 529, 543, 550, 551, 559, 588, 641, 654, 687, 705, 728, 731, 735, 740, 765, 821, 965), FALSE, c('5', '60', '61', '62', '79', '81', '92', '95', '105', '107', '122', '145', '153', '166', '167', '173', '175', '177', '182', '186', '192', '194', '199', '201', '202', '203', '208', '211', '224', '226', '235', '239', '240', '243', '245', '252', '266', '268', '269', '272', '276', '285', '292', '293', '296', '305', '310', '315', '332', '340', '345', '348', '350', '351', '356', '361', '363', '364', '371', '376', '382', '384', '426', '433', '444', '450', '473', '511', '520', '524', '529', '543', '550', '551', '559', '588', '641', '654', '687', '705', '728', '731', '735', '740', '765', '821', '965')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum3() { - assertEval(Ignored.Unknown, "argv <- list(numeric(0), numeric(0), numeric(0), FALSE, character(0)); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(numeric(0), numeric(0), numeric(0), FALSE, character(0)); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.432389384893196, 2.31273022636069, 0, 2.31273022636069, 0.432389384893196, 0), .Names = c('1', '3', '4', '5', '6', '7')), structure(c(9, 1, 1, 6, 6, 8), .Names = c('1', '3', '4', '5', '6', '7')), c(1, 6, 8, 9), FALSE, c('1', '6', '8', '9')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(c(0.432389384893196, 2.31273022636069, 0, 2.31273022636069, 0.432389384893196, 0), .Names = c('1', '3', '4', '5', '6', '7')), structure(c(9, 1, 1, 6, 6, 8), .Names = c('1', '3', '4', '5', '6', '7')), c(1, 6, 8, 9), FALSE, c('1', '6', '8', '9')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum5() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.102430555555556, 0.102430555555556, 0.102430555555556, 0.546875, -0.078125, 0.477430555555556, -0.0642361111111111, 0.102430555555556), .Names = c('1', '2', '3', '4', '5', '6', '7', '8')), structure(1:8, .Label = c('1', '2', '3', '4', '5', '6', '7', '8'), class = 'factor'), structure(1:8, .Label = c('1', '2', '3', '4', '5', '6', '7', '8'), class = 'factor'), FALSE, c('1', '2', '3', '4', '5', '6', '7', '8')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(c(0.102430555555556, 0.102430555555556, 0.102430555555556, 0.546875, -0.078125, 0.477430555555556, -0.0642361111111111, 0.102430555555556), .Names = c('1', '2', '3', '4', '5', '6', '7', '8')), structure(1:8, .Label = c('1', '2', '3', '4', '5', '6', '7', '8'), class = 'factor'), structure(1:8, .Label = c('1', '2', '3', '4', '5', '6', '7', '8'), class = 'factor'), FALSE, c('1', '2', '3', '4', '5', '6', '7', '8')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum6() { - assertEval(Ignored.Unknown, + // NA prints as NaN + assertEval(Ignored.OutputFormatting, "argv <- list(structure(c(0, 0.719170679378362, -0.280829320621638, 0, -0.43834135875385, 0, -0.0525040127116955, 0.783590877798991, -0.365543432545085, -0.0525040127116955, -0.31303941983339, 0, 0, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14')), c(3, 3, 4, 5, 5, 6, 6, 6, 7, 1, 1, 1, 1, 2), c(1, 2, 3, 4, 5, 6, 7), FALSE, c('1', '2', '3', '4', '5', '6', '7')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum7() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.10270237599789, 2.6083215370191, 11.0196744330572, 2.6083215370191, 0.10270237599789, 0.10270237599789, 0.10270237599789, -0.441795512568419, 2.6083215370191, 0.10270237599789, -0.441795512568419), .Dim = c(11L, 1L), .Dimnames = list(c('11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21'), 'x')), structure(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), .Names = c('11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21')), c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), FALSE, c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(c(0.10270237599789, 2.6083215370191, 11.0196744330572, 2.6083215370191, 0.10270237599789, 0.10270237599789, 0.10270237599789, -0.441795512568419, 2.6083215370191, 0.10270237599789, -0.441795512568419), .Dim = c(11L, 1L), .Dimnames = list(c('11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21'), 'x')), structure(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), .Names = c('11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21')), c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), FALSE, c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testrowsum8() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(1.33333333333333, -1.33333333333333, 1, 1.33333333333333, -2, 0.666666666666667, -0.666666666666667, 0.666666666666667, -0.666666666666667), .Dim = c(9L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9'), 'x')), structure(c(1, 1, 2, 2, 2, 2, 3, 4, 5), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9')), c(1, 2, 3, 4, 5), FALSE, c('1', '2', '3', '4', '5')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(c(1.33333333333333, -1.33333333333333, 1, 1.33333333333333, -2, 0.666666666666667, -0.666666666666667, 0.666666666666667, -0.666666666666667), .Dim = c(9L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9'), 'x')), structure(c(1, 1, 2, 2, 2, 2, 3, 4, 5), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9')), c(1, 2, 3, 4, 5), FALSE, c('1', '2', '3', '4', '5')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java index e955f5709063a85d88301d569d56c80e5ee9a09a..b4720533ce8e7378ebe9df32d4c73f6cc2ccf59c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java @@ -38,7 +38,6 @@ import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RInternalSourceDescriptions; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.ContextInfo; @@ -142,7 +141,7 @@ public final class FastRSession implements RSession { return singleton; } - public static final Source GET_CONTEXT = RSource.fromText("invisible(.fastr.context.get())", "<get_context>"); + public static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT); public PolyglotEngine createTestContext(ContextInfo contextInfoArg) { create(); @@ -152,7 +151,7 @@ public final class FastRSession implements RSession { } else { contextInfo = contextInfoArg; } - return contextInfo.apply(PolyglotEngine.newBuilder()).build(); + return contextInfo.createVM(); } public ContextInfo createContextInfo(ContextKind contextKind) { @@ -165,7 +164,7 @@ public final class FastRSession implements RSession { try { RCmdOptions options = RCmdOptions.parseArguments(Client.RSCRIPT, new String[]{"--no-restore"}); ContextInfo info = ContextInfo.create(options, ContextKind.SHARE_NOTHING, null, consoleHandler); - main = info.apply(PolyglotEngine.newBuilder()).build(); + main = info.createVM(); try { mainContext = main.eval(GET_CONTEXT).as(RContext.class); emitIO(); @@ -245,7 +244,7 @@ public final class FastRSession implements RSession { try { String input = consoleHandler.readLine(); while (input != null) { - Source source = RSource.fromText(input, RInternalSourceDescriptions.UNIT_TEST); + Source source = RSource.fromTextInternal(input, RSource.Internal.UNIT_TEST); try { vm.eval(source); input = consoleHandler.readLine(); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java index 7eab4bdb9e6ae9574373b6d691d851e88c6e1baf..318c667e9affa52073115f643799afd861e7c6d8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java @@ -90,7 +90,7 @@ public class FastRDebugTest { } private static Source createFactorial() { - return RSource.fromText("main <- function() {\n" + + return RSource.fromTextInternal("main <- function() {\n" + " res = fac(2)\n" + " res\n" + "}\n" + @@ -104,7 +104,7 @@ public class FastRDebugTest { " res\n" + " }\n" + "}\n", - "factorial.r"); + RSource.Internal.DEBUGTEST_FACTORIAL); } protected final String getOut() { @@ -150,7 +150,7 @@ public class FastRDebugTest { "n", 2.0); continueExecution(); - final Source evalSrc = RSource.fromText("main()\n", "debugtest.r"); + final Source evalSrc = RSource.fromTextInternal("main()\n", RSource.Internal.DEBUGTEST_DEBUG); final Value value = engine.eval(evalSrc); assertExecutedOK(); Assert.assertEquals("[1] 2\n", getOut()); @@ -198,7 +198,7 @@ public class FastRDebugTest { assertLocation(3, "res", "res", 2.0); stepOut(); - final Source evalSource = RSource.fromText("main()\n", "evaltest.r"); + final Source evalSource = RSource.fromTextInternal("main()\n", RSource.Internal.DEBUGTEST_EVAL); final Value value = engine.eval(evalSource); assertExecutedOK(); Assert.assertEquals("[1] 2\n", getOut()); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java index 4453c6ad7eb244fd67375b6fe6e9000628871ecd..0fa17726fa7cf87ef2fa63b2587007471c5b3fc2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java @@ -40,7 +40,7 @@ public class FastRTckTest extends TruffleTCK { } // @formatter:off - private static final Source INITIALIZATION = RSource.fromText( + private static final Source INITIALIZATION = RSource.fromTextInternal( "fourtyTwo <- function() {\n" + " 42L\n" + "}\n" + @@ -100,7 +100,7 @@ public class FastRTckTest extends TruffleTCK { " list('byteValue'=0L, 'shortValue'=0L, 'intValue'=0L, 'longValue'=0L, 'floatValue'=0, 'doubleValue'=0, 'charValue'=48L, 'stringValue'='', 'booleanValue'=FALSE)\n" + "}\n" + ".fastr.interop.export('valuesObject', valuesObject)\n", - "<initialization>" + RSource.Internal.TCK_INIT ); // @formatter:on diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 127e3a5f5a4966ab412b45a45adc8a0ad312ec01..d00961fd8b0f297a0227a0f693c8284c0eda0c20 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -156,6 +156,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java,purdue.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java,purdue.copyright +com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java,purdue.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java,gnu_r_sample.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java,gnu_r_gentleman_ihaka.copyright diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index 0e0bdb7ee83826c271a2af54ae9696c2b69ac053..c8de59b9adc32b88b093e0edb259ab209aa4fff8 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -317,6 +317,7 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "truffle:TRUFFLE_API", + "truffle:TRUFFLE_DEBUG", ], "checkstyle" : "com.oracle.truffle.r.runtime", "javaCompliance" : "1.8",