Mercurial > hg > graal-jvmci-8
changeset 16992:5a1d764f6afc
Truffle: added support for Runtime#getCallTargets()
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Thu, 28 Aug 2014 15:35:29 +0200 |
parents | 4a6d852dbb68 |
children | 81eb0d77e9f9 |
files | CHANGELOG.md graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java |
diffstat | 5 files changed, 134 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGELOG.md Thu Aug 28 11:42:02 2014 +0200 +++ b/CHANGELOG.md Thu Aug 28 15:35:29 2014 +0200 @@ -5,7 +5,7 @@ * ... ### Truffle -* ... +* Added TruffleRuntime#getCallTargets() to get all call targets that were created and are still referenced. ## Version 0.4 19-Aug-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.4)
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Aug 28 11:42:02 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Aug 28 15:35:29 2014 +0200 @@ -81,6 +81,7 @@ private final ResolvedJavaMethod[] callNodeMethod; private final ResolvedJavaMethod[] callTargetMethod; private final ResolvedJavaMethod[] anyFrameMethod; + private final Map<RootCallTarget, Void> callTargets = Collections.synchronizedMap(new WeakHashMap<RootCallTarget, Void>()); private HotSpotTruffleRuntime() { installOptimizedCallTargetCallMethod(); @@ -115,7 +116,10 @@ } else { compilationPolicy = new InterpreterOnlyCompilationPolicy(); } - return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog()); + OptimizedCallTarget target = new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, + new HotSpotSpeculationLog()); + callTargets.put(target, null); + return target; } public LoopNode createLoopNode(RepeatingNode repeating) { @@ -361,6 +365,11 @@ installOptimizedCallTargetCallMethod(); } + @Override + public List<RootCallTarget> getCallTargets() { + return new ArrayList<>(callTargets.keySet()); + } + public void notifyTransferToInterpreter() { CompilerAsserts.neverPartOfCompilation(); if (TraceTruffleTransferToInterpreter.getValue()) {
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java Thu Aug 28 11:42:02 2014 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java Thu Aug 28 15:35:29 2014 +0200 @@ -22,13 +22,20 @@ */ package com.oracle.truffle.api.test; +import static org.junit.Assert.*; + +import java.util.*; + import org.junit.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; /** * <h3>Accessing the Truffle Runtime</h3> - * + * * <p> * The Truffle runtime can be accessed at any point in time globally using the static method * {@link Truffle#getRuntime()}. This method is guaranteed to return a non-null Truffle runtime @@ -36,7 +43,7 @@ * default implementation of the {@link TruffleRuntime} interface with its own implementation for * providing improved performance. * </p> - * + * * <p> * The next part of the Truffle API introduction is at * {@link com.oracle.truffle.api.test.RootNodeTest}. @@ -44,10 +51,104 @@ */ public class TruffleRuntimeTest { + private TruffleRuntime runtime; + + @Before + public void setup() { + this.runtime = Truffle.getRuntime(); + } + + private static RootNode createTestRootNode() { + return new RootNode() { + @Override + public Object execute(VirtualFrame frame) { + return 42; + } + }; + } + @Test public void test() { - TruffleRuntime runtime = Truffle.getRuntime(); - Assert.assertNotNull(runtime); - Assert.assertNotNull(runtime.getName()); + assertNotNull(runtime); + assertNotNull(runtime.getName()); + } + + @Test + public void testCreateCallTarget() { + RootNode rootNode = createTestRootNode(); + RootCallTarget target = runtime.createCallTarget(rootNode); + assertNotNull(target); + assertEquals(target.call(), 42); + assertSame(rootNode, target.getRootNode()); + } + + @Test + public void testGetCallTargets1() { + RootNode rootNode = createTestRootNode(); + RootCallTarget target = runtime.createCallTarget(rootNode); + assertTrue(runtime.getCallTargets().indexOf(target) != -1); + } + + @Test + public void testGetCallTargets2() { + RootNode rootNode = createTestRootNode(); + RootCallTarget target1 = runtime.createCallTarget(rootNode); + RootCallTarget target2 = runtime.createCallTarget(rootNode); + assertTrue(runtime.getCallTargets().indexOf(target1) != -1); + assertTrue(runtime.getCallTargets().indexOf(target2) != -1); + } + + /* + * This test case documents the use case for profilers and debuggers where they need to access + * multiple call targets for the same source section. This case may happen when the optimization + * system decides to duplicate call targets to achieve better performance. + */ + @Test + public void testGetCallTargets3() { + Source source1 = Source.fromText("a\nb\n", ""); + SourceSection sourceSection1 = source1.createSection("foo", 1); + SourceSection sourceSection2 = source1.createSection("bar", 2); + + RootNode rootNode1 = createTestRootNode(); + rootNode1.assignSourceSection(sourceSection1); + RootNode rootNode2 = createTestRootNode(); + rootNode2.assignSourceSection(sourceSection2); + RootNode rootNode2Copy = NodeUtil.cloneNode(rootNode2); + + assertSame(rootNode2.getSourceSection(), rootNode2Copy.getSourceSection()); + + RootCallTarget target1 = runtime.createCallTarget(rootNode1); + RootCallTarget target2 = runtime.createCallTarget(rootNode2); + RootCallTarget target2Copy = runtime.createCallTarget(rootNode2Copy); + + Map<SourceSection, List<RootCallTarget>> groupedTargets = groupUniqueCallTargets(); + + List<RootCallTarget> targets1 = groupedTargets.get(sourceSection1); + assertEquals(1, targets1.size()); + assertEquals(target1, targets1.get(0)); + + List<RootCallTarget> targets2 = groupedTargets.get(sourceSection2); + assertEquals(2, targets2.size()); + // order of targets2 is not guaranteed + assertTrue(target2 == targets2.get(0) ^ target2Copy == targets2.get(0)); + assertTrue(target2 == targets2.get(1) ^ target2Copy == targets2.get(1)); + } + + private static Map<SourceSection, List<RootCallTarget>> groupUniqueCallTargets() { + Map<SourceSection, List<RootCallTarget>> groupedTargets = new HashMap<>(); + for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) { + SourceSection section = target.getRootNode().getSourceSection(); + if (section == null) { + // can not identify root node to a unique call target. Print warning? + continue; + } + List<RootCallTarget> targets = groupedTargets.get(section); + if (targets == null) { + targets = new ArrayList<>(); + groupedTargets.put(section, targets); + } + targets.add(target); + } + return groupedTargets; } }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Thu Aug 28 11:42:02 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Thu Aug 28 15:35:29 2014 +0200 @@ -24,6 +24,8 @@ */ package com.oracle.truffle.api; +import java.util.*; + import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -137,6 +139,12 @@ FrameInstance getCurrentFrame(); /** + * Returns a list of all still referenced {@link RootCallTarget} instances that were created + * using {@link #createCallTarget(RootNode)}. + */ + List<RootCallTarget> getCallTargets(); + + /** * Internal API method. Do not use. */ void notifyTransferToInterpreter();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Thu Aug 28 11:42:02 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Thu Aug 28 15:35:29 2014 +0200 @@ -41,6 +41,7 @@ private ThreadLocal<LinkedList<FrameInstance>> stackTraces = new ThreadLocal<>(); private ThreadLocal<FrameInstance> currentFrames = new ThreadLocal<>(); + private final Map<RootCallTarget, Void> callTargets = Collections.synchronizedMap(new WeakHashMap<RootCallTarget, Void>()); public DefaultTruffleRuntime() { if (Truffle.getRuntime() != null) { @@ -55,7 +56,9 @@ @Override public RootCallTarget createCallTarget(RootNode rootNode) { - return new DefaultCallTarget(rootNode, this); + DefaultCallTarget target = new DefaultCallTarget(rootNode, this); + callTargets.put(target, null); + return target; } public DirectCallNode createDirectCallNode(CallTarget target) { @@ -132,6 +135,11 @@ } @Override + public List<RootCallTarget> getCallTargets() { + return new ArrayList<>(callTargets.keySet()); + } + + @Override public FrameInstance getCurrentFrame() { return currentFrames.get(); }