Skip to content
Snippets Groups Projects
Commit e720f635 authored by Mick Jordan's avatar Mick Jordan
Browse files

Rprof: move state into RContext

parent 8334b748
Branches
No related tags found
No related merge requests found
......@@ -49,37 +49,36 @@ 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.context.RprofState;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
public abstract class Rprof extends RExternalBuiltinNode.Arg8 {
private PrintWriter out;
private ProfileThread profileThread;
private StatementListener statementListener;
private long intervalInMillis;
private boolean lineProfiling;
@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().stateRprof;
String filename = filenameVec.getDataAt(0);
if (filename.length() == 0) {
// disable
endProfiling();
} else {
// enable
if (out != null) {
if (profState.out() != null) {
endProfiling();
}
boolean append = RRuntime.fromLogical(appendL);
boolean memProfiling = RRuntime.fromLogical(memProfilingL);
boolean gcProfiling = RRuntime.fromLogical(gcProfilingL);
lineProfiling = RRuntime.fromLogical(lineProfilingL);
try {
out = new PrintWriter(new FileWriter(filename, append));
PrintWriter out = new PrintWriter(new FileWriter(filename, append));
if (memProfiling) {
RError.warning(this, RError.Message.GENERIC, "Rprof: memory profiling not supported");
}
......@@ -87,10 +86,11 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 {
RError.warning(this, RError.Message.GENERIC, "Rprof: gc profiling not supported");
}
// interval is in seconds, we convert to millis
intervalInMillis = (long) (1E3 * intervalD);
statementListener = new StatementListener();
profileThread = new ProfileThread(intervalInMillis, statementListener);
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));
......@@ -99,14 +99,18 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 {
return RNull.instance;
}
private void endProfiling() {
private static void endProfiling() {
RprofState profState = RContext.getInstance().stateRprof;
ProfileThread profileThread = (ProfileThread) profState.profileThread();
profileThread.running = false;
HashMap<String, Integer> fileMap = null;
if (lineProfiling) {
PrintWriter out = profState.out();
StatementListener statementListener = (StatementListener) profState.statementListener();
if (profState.lineProfiling()) {
out.print("line profiling: ");
}
out.printf("sample.interval=%d\n", intervalInMillis * 1000);
if (lineProfiling) {
out.printf("sample.interval=%d\n", profState.intervalInMillis() * 1000);
if (profState.lineProfiling()) {
// scan stacks to find files
fileMap = new HashMap<>();
int fileIndex = 0;
......@@ -125,7 +129,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 {
RootNode rootNode = node.asRNode().getRootNode();
if (rootNode instanceof FunctionDefinitionNode) {
String name = rootNode.getName();
if (lineProfiling) {
if (profState.lineProfiling()) {
Integer fileIndex = fileMap.get(getPath(node));
if (fileIndex != null) {
out.printf("%d#%d ", fileIndex, node.getSourceSection().getStartLine());
......
......@@ -367,6 +367,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
private final Env env;
private final InstrumentationState instrumentationState;
private final HashMap<String, TruffleObject> exportedSymbols = new HashMap<>();
private final boolean initial;
/**
* State that is used to support interposing on loadNamespace() for overrides.
*/
......@@ -390,10 +391,11 @@ public final class RContext extends ExecutionContext implements TruffleObject {
public final LazyDBCache.ContextStateImpl stateLazyDBCache;
public final TraceState.ContextStateImpl stateTraceHandling;
public final ContextStateImpl stateInternalCode;
public final RprofState stateRprof;
private ContextState[] contextStates() {
return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize,
stateLazyDBCache, stateTraceHandling};
stateLazyDBCache, stateTraceHandling, stateRprof};
}
private RContext(Env env, Instrumenter instrumenter, boolean isInitial) {
......@@ -403,6 +405,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) {
......@@ -459,6 +462,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
stateLazyDBCache = LazyDBCache.ContextStateImpl.newContext(this);
stateTraceHandling = TraceState.newContext(this);
stateInternalCode = ContextStateImpl.newContext(this);
stateRprof = RprofState.newContext(this);
engine.activate(stateREnvironment);
if (info.getKind() == ContextKind.SHARE_PARENT_RW) {
......@@ -691,6 +695,10 @@ public final class RContext extends ExecutionContext implements TruffleObject {
return info.getVM();
}
public boolean isInitial() {
return initial;
}
public void setLoadingBase(boolean b) {
loadingBase = b;
}
......
/*
* 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.context;
import java.io.PrintWriter;
import com.oracle.truffle.api.instrumentation.ExecutionEventListener;
public class RprofState implements RContext.ContextState {
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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment