Skip to content

Commit

Permalink
[GR-31460] Safepoint based CPU Sampler.
Browse files Browse the repository at this point in the history
PullRequest: graal/9064
  • Loading branch information
boris-spas committed Jul 23, 2021
2 parents 3a4a4af + d4f32e0 commit c157cec
Show file tree
Hide file tree
Showing 25 changed files with 1,443 additions and 803 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 org.graalvm.compiler.truffle.runtime;

import com.oracle.truffle.api.CompilerDirectives;

public enum CompilationState {

INTERPRETED,

FIRST_TIER_ROOT,
LAST_TIER_ROOT,

FIRST_TIER_INLINED,
LAST_TIER_INLINED;

boolean isCompilationRoot() {
return this == FIRST_TIER_ROOT || this == LAST_TIER_ROOT;
}

boolean isCompiled() {
return this != INTERPRETED;
}

int getTier() {
switch (this) {
case INTERPRETED:
return 0;
case FIRST_TIER_INLINED:
case FIRST_TIER_ROOT:
return 1;
case LAST_TIER_INLINED:
case LAST_TIER_ROOT:
return 2;
default:
throw CompilerDirectives.shouldNotReachHere("invalid state");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public final class GraalFrameInstance implements FrameInstance {

private static final int CALL_TARGET_INDEX = 0;
private static final int CALL_TARGET_FRAME_INDEX = 1;
private static final int OPTIMIZATION_TIER_FRAME_INDEX = 2;

private static final int CALL_NODE_NOTIFY_INDEX = 1;

Expand All @@ -58,7 +59,7 @@ public final class GraalFrameInstance implements FrameInstance {
CALL_INLINED_CALL = GraalRuntimeSupport.class.getDeclaredMethod(GraalRuntimeSupport.CALL_INLINED_METHOD_NAME, Node.class, CallTarget.class, Object[].class);
CALL_INDIRECT = OptimizedCallTarget.class.getDeclaredMethod("callIndirect", Node.class, Object[].class);

CALL_TARGET_METHOD = OptimizedCallTarget.class.getDeclaredMethod("executeRootNode", VirtualFrame.class);
CALL_TARGET_METHOD = OptimizedCallTarget.class.getDeclaredMethod("executeRootNode", VirtualFrame.class, CompilationState.class);
CALL_OSR_METHOD = OptimizedOSRLoopNode.OSRRootNode.class.getDeclaredMethod("callProxy", OSRRootNode.class, VirtualFrame.class);
} catch (NoSuchMethodException | SecurityException e) {
throw new InternalError(e);
Expand Down Expand Up @@ -93,6 +94,16 @@ public boolean isVirtualFrame() {
return callTargetFrame.isVirtual(CALL_TARGET_FRAME_INDEX);
}

@Override
public int getCompilationTier() {
return ((CompilationState) callTargetFrame.getLocal(OPTIMIZATION_TIER_FRAME_INDEX)).getTier();
}

@Override
public boolean isCompilationRoot() {
return ((CompilationState) callTargetFrame.getLocal(OPTIMIZATION_TIER_FRAME_INDEX)).isCompilationRoot();
}

@Override
public CallTarget getCallTarget() {
return (CallTarget) callTargetFrame.getLocal(CALL_TARGET_INDEX);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@
*
* The end-goal of executing a {@link OptimizedCallTarget} is executing its root node. The following
* call-graph shows all the paths that can be taken from calling a call target (through all the
* public <code>call*</code> methods) to the {@linkplain #executeRootNode(VirtualFrame) execution of
* the root node} depending on the type of call.
* public <code>call*</code> methods) to the
* {@linkplain #executeRootNode(VirtualFrame, CompilationState) execution of the root node}
* depending on the type of call.
*
* <pre>
* GraalRuntimeSupport#callProfiled GraalRuntimeSupport#callInlined
Expand Down Expand Up @@ -497,13 +498,33 @@ public final Object callDirect(Node location, Object... args) {
public final Object callInlined(Node location, Object... arguments) {
try {
ensureInitialized();
return executeRootNode(createFrame(getRootNode().getFrameDescriptor(), arguments));
return executeRootNode(createFrame(getRootNode().getFrameDescriptor(), arguments), getTier());
} finally {
// this assertion is needed to keep the values from being cleared as non-live locals
assert keepAlive(location);
}
}

private static CompilationState getTier() {
if (CompilerDirectives.inCompiledCode()) {
if (GraalCompilerDirectives.hasNextTier()) {
if (CompilerDirectives.inCompilationRoot()) {
return CompilationState.FIRST_TIER_ROOT;
} else {
return CompilationState.FIRST_TIER_INLINED;
}
} else {
if (CompilerDirectives.inCompilationRoot()) {
return CompilationState.LAST_TIER_ROOT;
} else {
return CompilationState.LAST_TIER_INLINED;
}
}
} else {
return CompilationState.INTERPRETED;
}
}

private static boolean keepAlive(@SuppressWarnings("unused") Object o) {
return true;
}
Expand Down Expand Up @@ -600,7 +621,7 @@ protected final Object profiledPERoot(Object[] originalArguments) {
if (CompilerDirectives.inCompiledCode()) {
args = injectArgumentsProfile(originalArguments);
}
Object result = executeRootNode(createFrame(getRootNode().getFrameDescriptor(), args));
Object result = executeRootNode(createFrame(getRootNode().getFrameDescriptor(), args), getTier());
profileReturnValue(result);
return result;
}
Expand All @@ -626,8 +647,7 @@ private boolean lastTierCompile() {
return compile(true);
}

private Object executeRootNode(VirtualFrame frame) {
final boolean inCompiled = CompilerDirectives.inCompilationRoot();
private Object executeRootNode(VirtualFrame frame, CompilationState tier) {
try {
Object toRet = rootNode.execute(frame);
TruffleSafepoint.poll(rootNode);
Expand All @@ -639,11 +659,11 @@ private Object executeRootNode(VirtualFrame frame) {
GraalRuntimeAccessor.LANGUAGE.onThrowable(null, this, profiledT, frame);
throw rethrow(profiledT);
} finally {
if (CompilerDirectives.inInterpreter() && inCompiled) {
if (CompilerDirectives.inInterpreter() && tier != CompilationState.INTERPRETED) {
notifyDeoptimized(frame);
}
// this assertion is needed to keep the values from being cleared as non-live locals
assert frame != null && this != null;
assert frame != null && this != null && tier != null;
}
}

Expand Down
3 changes: 3 additions & 0 deletions tools/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

This changelog summarizes major changes between Truffle Tools versions.

## Version 21.3.0
* Reimplemented CPUSampler to use the Truffle language safepoints thus deprecating several API functions.

## Version 21.1.0

* Use `--heap.dump=/path/to/file/to/generate.hprof` to enable [Heap Dumping via Insight](docs/Insight-Manual.md#Heap-Dumping)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.oracle.truffle.tools.utils.json.JSONArray;
import com.oracle.truffle.tools.utils.json.JSONObject;

import com.oracle.truffle.api.InstrumentInfo;
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
import com.oracle.truffle.api.instrumentation.StandardTags;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;

import com.oracle.truffle.tools.chromeinspector.commands.Params;
import com.oracle.truffle.tools.chromeinspector.domains.ProfilerDomain;
import com.oracle.truffle.tools.chromeinspector.instrument.Enabler;
Expand All @@ -59,12 +55,13 @@
import com.oracle.truffle.tools.chromeinspector.types.ScriptTypeProfile;
import com.oracle.truffle.tools.chromeinspector.types.TypeObject;
import com.oracle.truffle.tools.chromeinspector.types.TypeProfileEntry;

import com.oracle.truffle.tools.profiler.CPUSampler;
import com.oracle.truffle.tools.profiler.CPUTracer;
import com.oracle.truffle.tools.profiler.ProfilerNode;
import com.oracle.truffle.tools.profiler.impl.CPUSamplerInstrument;
import com.oracle.truffle.tools.profiler.impl.CPUTracerInstrument;
import com.oracle.truffle.tools.utils.json.JSONArray;
import com.oracle.truffle.tools.utils.json.JSONObject;

public final class InspectorProfiler extends ProfilerDomain {

Expand Down Expand Up @@ -119,14 +116,14 @@ public void start() {
synchronized (sampler) {
oldGatherSelfHitTimes = sampler.isGatherSelfHitTimes();
sampler.setGatherSelfHitTimes(true);
sampler.setMode(CPUSampler.Mode.ROOTS);
sampler.setFilter(SourceSectionFilter.newBuilder().includeInternal(context.isInspectInternal()).build());
sampler.setCollecting(true);
}
startTimestamp = System.currentTimeMillis();
}

@Override
@SuppressWarnings("deprecation")
public Params stop() {
long time = System.currentTimeMillis();
synchronized (sampler) {
Expand Down
Loading

0 comments on commit c157cec

Please sign in to comment.