Skip to content

Commit 27b0a31

Browse files
committed
Limit inlining of builtins to avoid compilation bailouts for large
functions.
1 parent ca746a1 commit 27b0a31

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,12 @@ protected void finalizeContext(PythonContext context) {
160160
protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues newOptions) {
161161
// internal sources were marked during context initialization
162162
return (firstOptions.get(PythonOptions.ExposeInternalSources).equals(newOptions.get(PythonOptions.ExposeInternalSources)) &&
163-
// we cache WithThread on the lanugage
163+
// we cache WithThread on the language
164164
firstOptions.get(PythonOptions.WithThread).equals(newOptions.get(PythonOptions.WithThread)) &&
165165
// we cache CatchAllExceptions hard on TryExceptNode
166-
firstOptions.get(PythonOptions.CatchAllExceptions).equals(newOptions.get(PythonOptions.CatchAllExceptions)));
166+
firstOptions.get(PythonOptions.CatchAllExceptions).equals(newOptions.get(PythonOptions.CatchAllExceptions)) &&
167+
// we cache BuiltinsInliningMaxCallerSize on the language
168+
firstOptions.get(PythonOptions.BuiltinsInliningMaxCallerSize).equals(newOptions.get(PythonOptions.BuiltinsInliningMaxCallerSize)));
167169
}
168170

169171
private boolean areOptionsCompatibleWithPreinitializedContext(OptionValues firstOptions, OptionValues newOptions) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/CallSpecialMethodNode.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,64 +55,77 @@
5555
import com.oracle.graal.python.nodes.truffle.PythonTypes;
5656
import com.oracle.graal.python.runtime.PythonOptions;
5757
import com.oracle.truffle.api.Assumption;
58+
import com.oracle.truffle.api.CompilerAsserts;
5859
import com.oracle.truffle.api.RootCallTarget;
5960
import com.oracle.truffle.api.dsl.ImportStatic;
6061
import com.oracle.truffle.api.dsl.NodeFactory;
6162
import com.oracle.truffle.api.dsl.ReportPolymorphism;
6263
import com.oracle.truffle.api.dsl.TypeSystemReference;
6364
import com.oracle.truffle.api.nodes.Node;
65+
import com.oracle.truffle.api.nodes.NodeUtil;
6466
import com.oracle.truffle.api.nodes.RootNode;
6567

6668
@TypeSystemReference(PythonTypes.class)
6769
@ImportStatic(PythonOptions.class)
6870
@ReportPolymorphism
6971
abstract class CallSpecialMethodNode extends Node {
72+
7073
/**
7174
* Returns a new instanceof the builtin if it's a subclass of the given class, and null
7275
* otherwise.
7376
*/
74-
private static <T extends PythonBuiltinBaseNode> T getBuiltin(PBuiltinFunction func, Class<T> clazz) {
77+
private <T extends PythonBuiltinBaseNode> T getBuiltin(PBuiltinFunction func, Class<T> clazz) {
78+
CompilerAsserts.neverPartOfCompilation();
7579
NodeFactory<? extends PythonBuiltinBaseNode> builtinNodeFactory = func.getBuiltinNodeFactory();
76-
if (builtinNodeFactory != null) {
80+
if (builtinNodeFactory != null && !callerExceedsMaxSize()) {
7781
return clazz.isAssignableFrom(builtinNodeFactory.getNodeClass()) ? clazz.cast(func.getBuiltinNodeFactory().createNode()) : null;
7882
} else {
7983
return null;
8084
}
8185
}
8286

87+
private boolean callerExceedsMaxSize() {
88+
CompilerAsserts.neverPartOfCompilation();
89+
int n = NodeUtil.countNodes(getRootNode());
90+
// nb: option 'BuiltinsInliningMaxCallerSize' is defined as a compatible option, i.e., ASTs
91+
// will only we shared between contexts that have the same value for this option.
92+
int maxSize = PythonOptions.getOption(lookupContextReference(PythonLanguage.class).get(), PythonOptions.BuiltinsInliningMaxCallerSize);
93+
return n >= maxSize;
94+
}
95+
8396
protected Assumption singleContextAssumption() {
8497
return PythonLanguage.getCurrent().singleContextAssumption;
8598
}
8699

87-
protected static PythonUnaryBuiltinNode getUnary(Object func) {
100+
PythonUnaryBuiltinNode getUnary(Object func) {
88101
if (func instanceof PBuiltinFunction) {
89102
return getBuiltin((PBuiltinFunction) func, PythonUnaryBuiltinNode.class);
90103
}
91104
return null;
92105
}
93106

94-
protected static PythonBinaryBuiltinNode getBinary(Object func) {
107+
PythonBinaryBuiltinNode getBinary(Object func) {
95108
if (func instanceof PBuiltinFunction) {
96109
return getBuiltin((PBuiltinFunction) func, PythonBinaryBuiltinNode.class);
97110
}
98111
return null;
99112
}
100113

101-
protected static PythonTernaryBuiltinNode getTernary(Object func) {
114+
PythonTernaryBuiltinNode getTernary(Object func) {
102115
if (func instanceof PBuiltinFunction) {
103116
return getBuiltin((PBuiltinFunction) func, PythonTernaryBuiltinNode.class);
104117
}
105118
return null;
106119
}
107120

108-
protected static PythonQuaternaryBuiltinNode getQuaternary(Object func) {
121+
PythonQuaternaryBuiltinNode getQuaternary(Object func) {
109122
if (func instanceof PBuiltinFunction) {
110123
return getBuiltin((PBuiltinFunction) func, PythonQuaternaryBuiltinNode.class);
111124
}
112125
return null;
113126
}
114127

115-
protected static PythonVarargsBuiltinNode getVarargs(Object func) {
128+
PythonVarargsBuiltinNode getVarargs(Object func) {
116129
if (func instanceof PBuiltinFunction) {
117130
return getBuiltin((PBuiltinFunction) func, PythonVarargsBuiltinNode.class);
118131
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ private PythonOptions() {
154154
@Option(category = OptionCategory.EXPERT, help = "Embedder option: what to print in response to PythonLanguage#toString.") //
155155
public static final OptionKey<Boolean> UseReprForPrintString = new OptionKey<>(true);
156156

157+
@Option(category = OptionCategory.EXPERT, help = "Stop inlining of builtins if caller's cumulative tree size would exceed this limit") //
158+
public static final OptionKey<Integer> BuiltinsInliningMaxCallerSize = new OptionKey<>(2250);
159+
157160
public static OptionDescriptors createDescriptors() {
158161
return new PythonOptionsOptionDescriptors();
159162
}

0 commit comments

Comments
 (0)