77
77
import java .math .BigInteger ;
78
78
import java .nio .charset .Charset ;
79
79
import java .nio .charset .CodingErrorAction ;
80
- import java .util .ArrayDeque ;
81
80
import java .util .ArrayList ;
82
81
import java .util .Arrays ;
83
82
import java .util .List ;
179
178
import com .oracle .graal .python .nodes .util .CastToJavaIntExactNode ;
180
179
import com .oracle .graal .python .nodes .util .CastToJavaLongExactNode ;
181
180
import com .oracle .graal .python .nodes .util .CastToJavaStringNode ;
181
+ import com .oracle .graal .python .runtime .ExecutionContext .IndirectCallContext ;
182
182
import com .oracle .graal .python .runtime .PythonContext ;
183
183
import com .oracle .graal .python .runtime .PythonCore ;
184
184
import com .oracle .graal .python .runtime .PythonOptions ;
@@ -1068,13 +1068,12 @@ protected int getMaxExplodeLoop() {
1068
1068
return MAX_EXPLODE_LOOP >> depth ;
1069
1069
}
1070
1070
1071
- @ Specialization (guards = {"depth != STOP_RECURSION" , "depth < getNodeRecursionLimit()" , //
1072
- "getLength(clsTuple) == cachedLen" , "cachedLen < getMaxExplodeLoop()" }, //
1071
+ @ Specialization (guards = {"depth < getNodeRecursionLimit()" , "getLength(clsTuple) == cachedLen" , "cachedLen < getMaxExplodeLoop()" }, //
1073
1072
limit = "getVariableArgumentInlineCacheLimit()" )
1074
1073
@ ExplodeLoop (kind = LoopExplosionKind .FULL_UNROLL_UNTIL_RETURN )
1075
1074
final boolean doTupleConstantLen (VirtualFrame frame , Object instance , PTuple clsTuple ,
1076
1075
@ Cached ("getLength(clsTuple)" ) int cachedLen ,
1077
- @ Cached ("createRecursive(depth )" ) RecursiveBinaryCheckBaseNode recursiveNode ) {
1076
+ @ Cached ("createRecursive()" ) RecursiveBinaryCheckBaseNode recursiveNode ) {
1078
1077
Object [] array = getArray (clsTuple );
1079
1078
for (int i = 0 ; i < cachedLen ; i ++) {
1080
1079
Object cls = array [i ];
@@ -1085,9 +1084,9 @@ final boolean doTupleConstantLen(VirtualFrame frame, Object instance, PTuple cls
1085
1084
return false ;
1086
1085
}
1087
1086
1088
- @ Specialization (guards = { "depth != STOP_RECURSION" , "depth < getNodeRecursionLimit()"} , replaces = "doTupleConstantLen" )
1087
+ @ Specialization (guards = "depth < getNodeRecursionLimit()" , replaces = "doTupleConstantLen" )
1089
1088
final boolean doRecursiveWithNode (VirtualFrame frame , Object instance , PTuple clsTuple ,
1090
- @ Cached ("createRecursive(depth )" ) RecursiveBinaryCheckBaseNode recursiveNode ) {
1089
+ @ Cached ("createRecursive()" ) RecursiveBinaryCheckBaseNode recursiveNode ) {
1091
1090
for (Object cls : getArray (clsTuple )) {
1092
1091
if (recursiveNode .executeWith (frame , instance , cls )) {
1093
1092
return true ;
@@ -1096,26 +1095,20 @@ final boolean doRecursiveWithNode(VirtualFrame frame, Object instance, PTuple cl
1096
1095
return false ;
1097
1096
}
1098
1097
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 );
1117
1106
}
1118
- return false ;
1107
+ }
1108
+
1109
+ @ TruffleBoundary
1110
+ private boolean callRecursiveWithNodeTruffleBoundary (Object instance , PTuple clsTuple ) {
1111
+ return doRecursiveWithNode (null , instance , clsTuple , this );
1119
1112
}
1120
1113
1121
1114
protected final int getLength (PTuple t ) {
0 commit comments