Skip to content

Commit 7375cfa

Browse files
committed
Builtins isinstance and issubclass actually need to be recursive after all
1 parent 6480427 commit 7375cfa

File tree

1 file changed

+18
-25
lines changed

1 file changed

+18
-25
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
import java.math.BigInteger;
7878
import java.nio.charset.Charset;
7979
import java.nio.charset.CodingErrorAction;
80-
import java.util.ArrayDeque;
8180
import java.util.ArrayList;
8281
import java.util.Arrays;
8382
import java.util.List;
@@ -179,6 +178,7 @@
179178
import com.oracle.graal.python.nodes.util.CastToJavaIntExactNode;
180179
import com.oracle.graal.python.nodes.util.CastToJavaLongExactNode;
181180
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
181+
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
182182
import com.oracle.graal.python.runtime.PythonContext;
183183
import com.oracle.graal.python.runtime.PythonCore;
184184
import com.oracle.graal.python.runtime.PythonOptions;
@@ -1068,13 +1068,12 @@ protected int getMaxExplodeLoop() {
10681068
return MAX_EXPLODE_LOOP >> depth;
10691069
}
10701070

1071-
@Specialization(guards = {"depth != STOP_RECURSION", "depth < getNodeRecursionLimit()", //
1072-
"getLength(clsTuple) == cachedLen", "cachedLen < getMaxExplodeLoop()"}, //
1071+
@Specialization(guards = {"depth < getNodeRecursionLimit()", "getLength(clsTuple) == cachedLen", "cachedLen < getMaxExplodeLoop()"}, //
10731072
limit = "getVariableArgumentInlineCacheLimit()")
10741073
@ExplodeLoop(kind = LoopExplosionKind.FULL_UNROLL_UNTIL_RETURN)
10751074
final boolean doTupleConstantLen(VirtualFrame frame, Object instance, PTuple clsTuple,
10761075
@Cached("getLength(clsTuple)") int cachedLen,
1077-
@Cached("createRecursive(depth)") RecursiveBinaryCheckBaseNode recursiveNode) {
1076+
@Cached("createRecursive()") RecursiveBinaryCheckBaseNode recursiveNode) {
10781077
Object[] array = getArray(clsTuple);
10791078
for (int i = 0; i < cachedLen; i++) {
10801079
Object cls = array[i];
@@ -1085,9 +1084,9 @@ final boolean doTupleConstantLen(VirtualFrame frame, Object instance, PTuple cls
10851084
return false;
10861085
}
10871086

1088-
@Specialization(guards = {"depth != STOP_RECURSION", "depth < getNodeRecursionLimit()"}, replaces = "doTupleConstantLen")
1087+
@Specialization(guards = "depth < getNodeRecursionLimit()", replaces = "doTupleConstantLen")
10891088
final boolean doRecursiveWithNode(VirtualFrame frame, Object instance, PTuple clsTuple,
1090-
@Cached("createRecursive(depth)") RecursiveBinaryCheckBaseNode recursiveNode) {
1089+
@Cached("createRecursive()") RecursiveBinaryCheckBaseNode recursiveNode) {
10911090
for (Object cls : getArray(clsTuple)) {
10921091
if (recursiveNode.executeWith(frame, instance, cls)) {
10931092
return true;
@@ -1096,26 +1095,20 @@ final boolean doRecursiveWithNode(VirtualFrame frame, Object instance, PTuple cl
10961095
return false;
10971096
}
10981097

1099-
@Specialization(guards = {"depth != STOP_RECURSION", "depth >= getNodeRecursionLimit()"})
1100-
final boolean doRecursiveWithLoop(VirtualFrame frame, Object instance, PTuple clsTuple,
1101-
@Cached("createRecursive(STOP_RECURSION)") RecursiveBinaryCheckBaseNode nonRecursiveNode) {
1102-
// Note: we do not put this behind TB to avoid frame materialization, an alternative can
1103-
// be to use IndirectCallNode, null frame and put this algorithm behind TB
1104-
ArrayDeque<Object> classes = PythonUtils.newDeque();
1105-
PythonUtils.push(classes, clsTuple);
1106-
while (!classes.isEmpty()) {
1107-
Object currentKlass = PythonUtils.pop(classes);
1108-
if (currentKlass instanceof PTuple) {
1109-
Object[] tupleItems = getArray((PTuple) currentKlass);
1110-
// push them in reverse order to pop them in the necessary order
1111-
for (int i = tupleItems.length - 1; i >= 0; i--) {
1112-
PythonUtils.push(classes, tupleItems[i]);
1113-
}
1114-
} else if (nonRecursiveNode.executeWith(frame, instance, currentKlass)) {
1115-
return true;
1116-
}
1098+
@Specialization(guards = "depth >= getNodeRecursionLimit()")
1099+
final boolean doRecursiveWithLoop(VirtualFrame frame, Object instance, PTuple clsTuple) {
1100+
Object state = IndirectCallContext.enter(frame, getContext(), this);
1101+
try {
1102+
// Note: we need actual recursion to trigger the stack overflow error like CPython
1103+
return callRecursiveWithNodeTruffleBoundary(instance, clsTuple);
1104+
} finally {
1105+
IndirectCallContext.exit(frame, getContext(), state);
11171106
}
1118-
return false;
1107+
}
1108+
1109+
@TruffleBoundary
1110+
private boolean callRecursiveWithNodeTruffleBoundary(Object instance, PTuple clsTuple) {
1111+
return doRecursiveWithNode(null, instance, clsTuple, this);
11191112
}
11201113

11211114
protected final int getLength(PTuple t) {

0 commit comments

Comments
 (0)