Skip to content

Commit 060acff

Browse files
author
Jaroslav Tulach
committed
Merge pull request #7 in G/truffle from ~JAROSLAV.TULACH_ORACLE.COM/truffle:FasterExecute to master
* commit '2433f9c6627870eea575477a51dd83c6a7b45774': (47 commits) Removing typo - additional l in the class name Using constant value fields rather than magical numbers Don't wrap the TruffleObject in case of single threaded execution. Assume people will manipulate them carefully on the right thread. Adding assumption checks per Christian's request Move Context support next to PolyglotEngine as package private classes Apply proper formatting Multiply by two Removing unneeded constructor Removing redundant modifiers and spaces Comparing speed of direct SLFunction execution with overhead of PolyglotEngine.Value.execute Simplify cached object access. Add missing transferToInterpreter. Hide debug events behind boundaries. Turn checkThread into assertion DirectValue allows us to skip executor == null check when execute method is being called Hide the communication with debugger behind an assumption. Let executionStarted be part of Truffle compilation - it is optimized now. argumentLength is no longer needed Use direct value for eval when there is no executor Use condition profile to track whether boxing is needed at all Use recursive version instead of loop of two ...
2 parents ece7af2 + 2433f9c commit 060acff

File tree

20 files changed

+959
-255
lines changed

20 files changed

+959
-255
lines changed

mx.truffle/suite.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"sourceDirs" : ["src"],
5959
"dependencies" : [
6060
"com.oracle.truffle.api.interop.java",
61+
"com.oracle.truffle.api.profiles",
6162
"com.oracle.truffle.api.instrumentation",
6263
],
6364
"checkstyle" : "com.oracle.truffle.api",
@@ -346,10 +347,12 @@
346347
"dependencies" : [
347348
"com.oracle.truffle.tck",
348349
"com.oracle.truffle.sl",
350+
"mx:JMH",
349351
],
350352
"checkstyle" : "com.oracle.truffle.sl",
351353
"javaCompliance" : "1.7",
352354
"workingSets" : "Truffle,SimpleLanguage,Test",
355+
"annotationProcessors" : ["mx:JMH"],
353356
"license" : "UPL",
354357
},
355358
},
@@ -422,6 +425,10 @@
422425
"com.oracle.truffle.sl",
423426
"com.oracle.truffle.sl.test"
424427
],
428+
"exclude" : [
429+
"mx:JUNIT",
430+
"mx:JMH"
431+
],
425432
"distDependencies" : [
426433
"TRUFFLE_API",
427434
"TRUFFLE_TCK",

truffle/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/Debugger.java

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,13 @@
2424
*/
2525
package com.oracle.truffle.api.debug;
2626

27-
import java.io.Closeable;
27+
import com.oracle.truffle.api.Assumption;
2828
import java.io.IOException;
2929
import java.io.PrintStream;
3030
import java.util.ArrayList;
3131
import java.util.Collection;
3232
import java.util.Collections;
3333
import java.util.List;
34-
import java.util.concurrent.Callable;
3534

3635
import com.oracle.truffle.api.CallTarget;
3736
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -88,6 +87,7 @@ public final class Debugger {
8887

8988
private static final SourceSectionFilter CALL_FILTER = SourceSectionFilter.newBuilder().tagIs(CallTag.class).build();
9089
private static final SourceSectionFilter HALT_FILTER = SourceSectionFilter.newBuilder().tagIs(StatementTag.class).build();
90+
private static final Assumption NO_DEBUGGER = Truffle.getRuntime().createAssumption("No debugger assumption");
9191

9292
/** Counter for externally requested step actions. */
9393
private static int nextActionID = 0;
@@ -126,7 +126,7 @@ public Debugger create(PolyglotEngine engine, Instrumenter instrumenter) {
126126
}
127127
};
128128

129-
private static Debugger find(PolyglotEngine engine, boolean create) {
129+
static Debugger find(PolyglotEngine engine, boolean create) {
130130
PolyglotEngine.Instrument instrument = engine.getInstruments().get(DebuggerInstrument.ID);
131131
if (instrument == null) {
132132
throw new IllegalStateException();
@@ -151,6 +151,7 @@ private static Debugger find(PolyglotEngine engine, boolean create) {
151151
this.engine = engine;
152152
this.instrumenter = instrumenter;
153153
this.breakpoints = new BreakpointFactory(instrumenter, breakpointCallback, warningLog);
154+
NO_DEBUGGER.invalidate();
154155
}
155156

156157
interface BreakpointCallback {
@@ -872,7 +873,7 @@ public FrameInstance visitFrame(FrameInstance frameInstance) {
872873
try {
873874
// Pass control to the debug client with current execution suspended
874875
SuspendedEvent event = new SuspendedEvent(Debugger.this, haltedEventContext.getInstrumentedNode(), haltedFrame, contextStack, recentWarnings);
875-
AccessorDebug.engineAccess().dispatchEvent(engine, event);
876+
AccessorDebug.engineAccess().dispatchEvent(engine, event, Accessor.EngineSupport.SUSPENDED_EVENT);
876877
if (event.isKillPrepared()) {
877878
trace("KILL");
878879
throw new KillException();
@@ -938,7 +939,7 @@ public Void visitFrame(FrameInstance frameInstance) {
938939
return count[0] == 0 ? 0 : count[0] + 1;
939940
}
940941

941-
private void executionStarted(int depth, Source source) {
942+
void executionStarted(int depth, Source source) {
942943
Source execSource = source;
943944
if (execSource == null) {
944945
execSource = lastSource;
@@ -993,32 +994,32 @@ static Accessor.EngineSupport engineAccess() {
993994
}
994995

995996
@Override
996-
protected Closeable executionStart(Object vm, final int currentDepth, final boolean initializeDebugger, final Source s) {
997-
final PolyglotEngine engine = (PolyglotEngine) vm;
998-
final Debugger[] debugger = {find(engine, initializeDebugger)};
999-
if (debugger[0] != null) {
1000-
debugger[0].executionStarted(currentDepth, s);
1001-
engineAccess().dispatchEvent(engine, new ExecutionEvent(debugger[0]));
1002-
} else {
1003-
engineAccess().dispatchEvent(engine, new ExecutionEvent(new Callable<Debugger>() {
1004-
@Override
1005-
public Debugger call() throws Exception {
1006-
if (debugger[0] == null) {
1007-
debugger[0] = find(engine, true);
1008-
debugger[0].executionStarted(currentDepth, s);
1009-
}
1010-
return debugger[0];
1011-
}
1012-
}));
997+
protected DebugSupport debugSupport() {
998+
return new DebugImpl();
999+
}
1000+
1001+
private static final class DebugImpl extends DebugSupport {
1002+
@Override
1003+
public void executionStarted(Object vm, final int currentDepth, final Object[] debugger, final Source s) {
1004+
final PolyglotEngine engine = (PolyglotEngine) vm;
1005+
if (debugger[0] != null) {
1006+
final Debugger dbg = (Debugger) debugger[0];
1007+
dbg.executionStarted(currentDepth, s);
1008+
}
1009+
engineAccess().dispatchEvent(engine, new ExecutionEvent(engine, currentDepth, debugger, s), EngineSupport.EXECUTION_EVENT);
10131010
}
1014-
return new Closeable() {
1015-
@Override
1016-
public void close() throws IOException {
1017-
if (debugger[0] != null) {
1018-
debugger[0].executionEnded();
1019-
}
1011+
1012+
@Override
1013+
public void executionEnded(Object vm, Object[] debugger) {
1014+
if (debugger[0] != null) {
1015+
((Debugger) debugger[0]).executionEnded();
10201016
}
1021-
};
1017+
}
1018+
1019+
@Override
1020+
public Assumption assumeNoDebugger() {
1021+
return NO_DEBUGGER;
1022+
}
10221023
}
10231024

10241025
@SuppressWarnings("rawtypes")

truffle/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/ExecutionEvent.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
*/
2525
package com.oracle.truffle.api.debug;
2626

27-
import java.util.concurrent.Callable;
27+
import com.oracle.truffle.api.source.Source;
28+
import com.oracle.truffle.api.vm.PolyglotEngine;
2829

2930
/**
3031
* This event is delivered to all
@@ -43,14 +44,16 @@
4344
*/
4445
@SuppressWarnings("javadoc")
4546
public final class ExecutionEvent {
46-
private Object debugger;
47+
private final Object[] debugger;
48+
private final PolyglotEngine engine;
49+
private final int currentDepth;
50+
private final Source source;
4751

48-
ExecutionEvent(Debugger debugger) {
49-
this.debugger = debugger;
50-
}
51-
52-
ExecutionEvent(Callable<Debugger> debugger) {
52+
ExecutionEvent(PolyglotEngine engine, int currentDepth, Object[] debugger, Source source) {
5353
this.debugger = debugger;
54+
this.engine = engine;
55+
this.currentDepth = currentDepth;
56+
this.source = source;
5457
}
5558

5659
/**
@@ -63,15 +66,17 @@ public final class ExecutionEvent {
6366
* @since 0.9
6467
*/
6568
public Debugger getDebugger() {
66-
if (debugger instanceof Debugger) {
67-
return (Debugger) debugger;
69+
if (debugger[0] instanceof Debugger) {
70+
return (Debugger) debugger[0];
6871
}
6972
try {
70-
debugger = ((Callable<?>) debugger).call();
73+
final Debugger dbg = Debugger.find(engine, true);
74+
dbg.executionStarted(currentDepth, source);
75+
debugger[0] = dbg;
7176
} catch (Exception ex) {
7277
throw new IllegalStateException(ex);
7378
}
74-
return (Debugger) debugger;
79+
return (Debugger) debugger[0];
7580
}
7681

7782
/**

truffle/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/InstrumentationHandler.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ private abstract class AbstractBindingsVisitor extends AbstractNodeVisitor {
502502

503503
@Override
504504
boolean shouldVisit() {
505+
if (root == null) {
506+
return false;
507+
}
505508
SourceSection sourceSection = root.getSourceSection();
506509
for (int i = 0; i < bindings.size(); i++) {
507510
EventBinding<?> binding = bindings.get(i);

truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/CachedObjectAccessNode.java

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,30 @@
2828
import com.oracle.truffle.api.nodes.DirectCallNode;
2929

3030
final class CachedObjectAccessNode extends ObjectAccessNode {
31-
@Child private DirectCallNode callTarget;
31+
@Child private DirectCallNode callNode;
3232
@Child private ObjectAccessNode next;
3333
private final ForeignAccess languageCheck;
3434

3535
@Child private ForeignAccessArguments accessArguments = new ForeignAccessArguments();
3636

37-
protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) {
38-
this.callTarget = callTarget;
37+
protected CachedObjectAccessNode(DirectCallNode callNode, ObjectAccessNode next, ForeignAccess languageCheck) {
38+
this.callNode = callNode;
3939
this.next = next;
4040
this.languageCheck = languageCheck;
41-
this.callTarget.forceInlining();
41+
this.callNode.forceInlining();
4242
}
4343

4444
protected CachedObjectAccessNode(CachedObjectAccessNode prev) {
45-
this(prev.callTarget, prev.next, prev.languageCheck);
45+
this(prev.callNode, prev.next, prev.languageCheck);
4646
}
4747

4848
@Override
4949
public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
50-
return doAccess(frame, receiver, arguments);
51-
}
52-
53-
private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
5450
if (languageCheck.canHandle(receiver)) {
55-
return callTarget.call(frame, accessArguments.executeCreate(receiver, arguments));
51+
return callNode.call(frame, accessArguments.executeCreate(receiver, arguments));
5652
} else {
57-
return doNext(frame, receiver, arguments);
53+
return next.executeWith(frame, receiver, arguments);
5854
}
5955
}
6056

61-
private Object doNext(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
62-
return next.executeWith(frame, receiver, arguments);
63-
}
64-
6557
}

truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import com.oracle.truffle.api.CallTarget;
3030
import com.oracle.truffle.api.CompilerAsserts;
31+
import com.oracle.truffle.api.CompilerDirectives;
3132
import com.oracle.truffle.api.frame.Frame;
3233
import com.oracle.truffle.api.frame.VirtualFrame;
3334
import com.oracle.truffle.api.interop.impl.ReadOnlyArrayList;
@@ -38,7 +39,7 @@
3839
* foreign language implementations, you need to implement {@link TruffleObject} and its
3940
* {@link TruffleObject#getForeignAccess()} method. To create instance of <code>ForeignAccess</code>
4041
* , use one of the factory methods available in this class.
41-
*
42+
*
4243
* @since 0.8 or earlier
4344
*/
4445
public final class ForeignAccess {
@@ -247,8 +248,10 @@ public static Object sendExecute(Node executeNode, VirtualFrame frame, TruffleOb
247248
try {
248249
return fn.executeForeignImpl(frame, receiver, arguments);
249250
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
251+
CompilerDirectives.transferToInterpreter();
250252
throw e;
251253
} catch (InteropException e) {
254+
CompilerDirectives.transferToInterpreter();
252255
throw new AssertionError("Unexpected exception catched.", e);
253256
}
254257
}
@@ -490,7 +493,7 @@ boolean canHandle(TruffleObject receiver) {
490493
* that provides an AST snippet for a given {@link Message}. Rather than using this generic
491494
* {@code Factory}, consider implementing {@link Factory10} interface that captures the set of
492495
* messages each language should implement as of Truffle version 1.0.
493-
*
496+
*
494497
* @since 0.8 or earlier
495498
*/
496499
public interface Factory {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package com.oracle.truffle.api.vm;
24+
25+
import java.util.concurrent.Executors;
26+
import static org.junit.Assert.assertEquals;
27+
import org.junit.Test;
28+
29+
public class ContextStoreProfileTest {
30+
@Test
31+
public void switchFromConstantToMultipleThreads() throws Exception {
32+
final ContextStoreProfile profile = new ContextStoreProfile(null);
33+
ContextStore store1 = new ContextStore(null, 0);
34+
final ContextStore store2 = new ContextStore(null, 0);
35+
profile.enter(store1);
36+
assertEquals("Store associated", store1, profile.get());
37+
final ContextStore[] check = {null};
38+
Executors.newSingleThreadExecutor().submit(new Runnable() {
39+
@Override
40+
public void run() {
41+
profile.enter(store2);
42+
check[0] = profile.get();
43+
}
44+
}).get();
45+
assertEquals("Store on other thread associated", store2, check[0]);
46+
assertEquals("1st thread store is still there", store1, profile.get());
47+
}
48+
49+
@Test
50+
public void switchFromDynamicToMultipleThreads() throws Exception {
51+
final ContextStoreProfile profile = new ContextStoreProfile(null);
52+
ContextStore store1 = new ContextStore(null, 0);
53+
ContextStore store2 = new ContextStore(null, 0);
54+
final ContextStore store3 = new ContextStore(null, 0);
55+
profile.enter(store1);
56+
assertEquals("Store associated", store1, profile.get());
57+
profile.enter(store2);
58+
assertEquals("Store associated", store2, profile.get());
59+
final ContextStore[] check = {null};
60+
Executors.newSingleThreadExecutor().submit(new Runnable() {
61+
@Override
62+
public void run() {
63+
profile.enter(store3);
64+
check[0] = profile.get();
65+
}
66+
}).get();
67+
assertEquals("Store on other thread associated", store3, check[0]);
68+
assertEquals("1st thread store is still there", store2, profile.get());
69+
}
70+
}

0 commit comments

Comments
 (0)