Skip to content

Commit f082eb4

Browse files
committed
Add 'terminating return' optimization for interpreter performance
Adds additional execute method to the StatementNode. This method is allowed perform Python level return via Java level return. This can be safely done only for the last statement given normal structured control flow without any jumps.
1 parent b9d24b1 commit f082eb4

File tree

7 files changed

+55
-25
lines changed

7 files changed

+55
-25
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/BaseBlockNode.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727

2828
import java.util.List;
2929

30+
import com.oracle.graal.python.builtins.objects.PNone;
3031
import com.oracle.graal.python.nodes.statement.StatementNode;
3132
import com.oracle.graal.python.util.PythonUtils;
33+
import com.oracle.truffle.api.frame.VirtualFrame;
34+
import com.oracle.truffle.api.nodes.ExplodeLoop;
3235

3336
public abstract class BaseBlockNode extends StatementNode {
3437

@@ -66,4 +69,25 @@ protected StatementNode[] insertStatementsBefore(StatementNode insertBefore, Lis
6669
public final StatementNode[] getStatements() {
6770
return statements;
6871
}
72+
73+
@Override
74+
@ExplodeLoop
75+
public void executeVoid(VirtualFrame frame) {
76+
for (int i = 0; i < statements.length; i++) {
77+
statements[i].executeVoid(frame);
78+
}
79+
}
80+
81+
@Override
82+
@ExplodeLoop
83+
public Object returnExecute(VirtualFrame frame) {
84+
for (int i = 0; i < statements.length - 1; i++) {
85+
statements[i].executeVoid(frame);
86+
}
87+
if (statements.length > 0) {
88+
return statements[statements.length - 1].returnExecute(frame);
89+
} else {
90+
return PNone.NONE;
91+
}
92+
}
6993
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/BlockNode.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
package com.oracle.graal.python.nodes.control;
2727

2828
import com.oracle.graal.python.nodes.statement.StatementNode;
29-
import com.oracle.truffle.api.frame.VirtualFrame;
30-
import com.oracle.truffle.api.nodes.ExplodeLoop;
3129

3230
public final class BlockNode extends BaseBlockNode {
3331

@@ -46,12 +44,4 @@ public static StatementNode create(StatementNode... statements) {
4644
return new BlockNode(statements);
4745
}
4846
}
49-
50-
@Override
51-
@ExplodeLoop
52-
public void executeVoid(VirtualFrame frame) {
53-
for (int i = 0; i < statements.length; i++) {
54-
statements[i].executeVoid(frame);
55-
}
56-
}
5747
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/ReturnNode.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525
*/
2626
package com.oracle.graal.python.nodes.control;
2727

28+
import com.oracle.graal.python.builtins.objects.PNone;
2829
import com.oracle.graal.python.nodes.PNode;
30+
import com.oracle.graal.python.nodes.frame.WriteFrameSlotNode;
31+
import com.oracle.graal.python.nodes.expression.ExpressionNode;
32+
import com.oracle.graal.python.nodes.frame.WriteIdentifierNode;
2933
import com.oracle.graal.python.nodes.statement.StatementNode;
3034
import com.oracle.graal.python.runtime.exception.ReturnException;
3135
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -37,6 +41,11 @@ public void executeVoid(VirtualFrame frame) {
3741
throw ReturnException.INSTANCE;
3842
}
3943

44+
@Override
45+
public Object returnExecute(VirtualFrame frame) {
46+
return PNone.NONE;
47+
}
48+
4049
public static final class FrameReturnNode extends ReturnNode {
4150
@Child private StatementNode right;
4251

@@ -53,5 +62,10 @@ public void executeVoid(VirtualFrame frame) {
5362
right.executeVoid(frame);
5463
throw ReturnException.INSTANCE;
5564
}
65+
66+
@Override
67+
public Object returnExecute(VirtualFrame frame) {
68+
return right.getRhs().execute(frame);
69+
}
5670
}
5771
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/control/ReturnTargetNode.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,11 @@ public ExpressionNode getReturn() {
5555
@Override
5656
public Object execute(VirtualFrame frame) {
5757
try {
58-
body.executeVoid(frame);
59-
fallthroughProfile.enter();
60-
return PNone.NONE;
58+
return body.returnExecute(frame);
6159
} catch (ReturnException ire) {
62-
returnProfile.enter();
63-
return returnValue.execute(frame);
60+
// fall-though
6461
}
62+
returnProfile.enter();
63+
return returnValue.execute(frame);
6564
}
6665
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/FunctionBodyNode.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,8 @@
4242

4343
import com.oracle.graal.python.nodes.control.BaseBlockNode;
4444
import com.oracle.graal.python.nodes.statement.StatementNode;
45-
import com.oracle.truffle.api.frame.VirtualFrame;
4645
import com.oracle.truffle.api.instrumentation.StandardTags;
4746
import com.oracle.truffle.api.instrumentation.Tag;
48-
import com.oracle.truffle.api.nodes.ExplodeLoop;
4947

5048
public class FunctionBodyNode extends BaseBlockNode {
5149

@@ -57,14 +55,6 @@ public static FunctionBodyNode create(StatementNode... statements) {
5755
return statements.length == 0 ? new FunctionBodyNode(new StatementNode[0]) : new FunctionBodyNode(statements);
5856
}
5957

60-
@Override
61-
@ExplodeLoop
62-
public void executeVoid(VirtualFrame frame) {
63-
for (int i = 0; i < statements.length; i++) {
64-
statements[i].executeVoid(frame);
65-
}
66-
}
67-
6858
@Override
6959
public boolean hasTag(Class<? extends Tag> tag) {
7060
return StandardTags.RootBodyTag.class == tag;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorBlockNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.oracle.graal.python.nodes.generator;
2727

28+
import com.oracle.graal.python.builtins.objects.PNone;
2829
import com.oracle.graal.python.nodes.control.BaseBlockNode;
2930
import com.oracle.graal.python.nodes.statement.StatementNode;
3031
import com.oracle.graal.python.parser.GeneratorInfo;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/StatementNode.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.oracle.graal.python.nodes.statement;
2727

28+
import com.oracle.graal.python.builtins.objects.PNone;
2829
import com.oracle.graal.python.nodes.PNode;
2930
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
3031
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -42,6 +43,16 @@ public abstract class StatementNode extends PNode {
4243

4344
public abstract void executeVoid(VirtualFrame frame);
4445

46+
/**
47+
* Execution can directly return the value from return statement if it is the last statement
48+
* that was executed. This method may still throw
49+
* {@link com.oracle.graal.python.runtime.exception.ReturnException}.
50+
*/
51+
public Object returnExecute(VirtualFrame frame) {
52+
executeVoid(frame);
53+
return PNone.NONE;
54+
}
55+
4556
public void markAsTryBlock() {
4657
isTryBlock = true;
4758
}
@@ -50,6 +61,7 @@ public boolean isTryBlock() {
5061
return isTryBlock;
5162
}
5263

64+
@Override
5365
public WrapperNode createWrapper(ProbeNode probe) {
5466
return new StatementNodeWrapper(this, probe);
5567
}

0 commit comments

Comments
 (0)