4141package com .oracle .graal .python .lib ;
4242
4343import com .oracle .graal .python .PythonLanguage ;
44- import com .oracle .graal .python .builtins .objects .common .SequenceNodes .GetObjectArrayNode ;
45- import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
44+ import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes ;
4645import com .oracle .graal .python .nodes .PGuards ;
4746import com .oracle .graal .python .nodes .PNodeWithContext ;
47+ import com .oracle .graal .python .nodes .builtins .TupleNodes ;
4848import com .oracle .graal .python .runtime .ExecutionContext .BoundaryCallContext ;
4949import com .oracle .graal .python .runtime .IndirectCallData .BoundaryCallData ;
5050import com .oracle .graal .python .runtime .PythonOptions ;
5151import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
5252import com .oracle .truffle .api .dsl .Bind ;
5353import com .oracle .truffle .api .dsl .Cached ;
54- import com .oracle .truffle .api .dsl .Cached .Shared ;
5554import com .oracle .truffle .api .dsl .GenerateCached ;
5655import com .oracle .truffle .api .dsl .GenerateInline ;
5756import com .oracle .truffle .api .dsl .Idempotent ;
6059import com .oracle .truffle .api .dsl .Specialization ;
6160import com .oracle .truffle .api .frame .Frame ;
6261import com .oracle .truffle .api .frame .VirtualFrame ;
63- import com .oracle .truffle .api .nodes .ExplodeLoop ;
64- import com .oracle .truffle .api .nodes .ExplodeLoop .LoopExplosionKind ;
6562import com .oracle .truffle .api .nodes .Node ;
6663import com .oracle .truffle .api .nodes .UnadoptableNode ;
6764
7471@ GenerateCached (false )
7572@ SuppressWarnings ("truffle-neverdefault" )
7673abstract class PyObjectRecursiveBinaryCheckNode extends PNodeWithContext {
77- static final int MAX_EXPLODE_LOOP = 16 ; // is also shifted to the left by recursion depth
78-
7974 public final boolean execute (Frame frame , Object arg , Object classinfo ) {
8075 return executeInternal (frame , arg , classinfo , 0 );
8176 }
@@ -87,78 +82,64 @@ public final boolean execute(Frame frame, Object arg, Object classinfo) {
8782
8883 abstract PyObjectRecursiveBinaryCheckNode getUncachedRecursive ();
8984
90- @ Idempotent
91- protected static int getMaxExplodeLoop (int depth ) {
92- return MAX_EXPLODE_LOOP >> depth ;
93- }
94-
95- @ Specialization (guards = {"depth < getNodeRecursionLimit(language)" , "getLength(clsTuple) == cachedLen" , "cachedLen < getMaxExplodeLoop(depth)" }, //
96- limit = "getVariableArgumentInlineCacheLimit()" , excludeForUncached = true )
97- @ ExplodeLoop (kind = LoopExplosionKind .FULL_UNROLL_UNTIL_RETURN )
98- static boolean doTupleConstantLen (VirtualFrame frame , Object arg , PTuple clsTuple , int depth ,
85+ @ Specialization (guards = {"depth < getNodeRecursionLimit(language)" , "tupleCheck.execute(inliningTarget, clsTuple)" }, limit = "1" , excludeForUncached = true )
86+ static boolean doRecursiveWithNode (VirtualFrame frame , Object arg , Object clsTuple , int depth ,
9987 @ Bind Node inliningTarget ,
10088 @ SuppressWarnings ("unused" ) @ Bind PythonLanguage language ,
101- @ Cached ("getLength(clsTuple)" ) int cachedLen ,
102- @ Shared @ Cached GetObjectArrayNode getObjectArrayNode ,
103- @ Shared @ Cached ("createRecursive()" ) PyObjectRecursiveBinaryCheckNode recursiveNode ) {
104- Object [] array = getObjectArrayNode .execute (inliningTarget , clsTuple );
105- int newDepth = depth + 1 ;
106- for (int i = 0 ; i < cachedLen ; i ++) {
107- Object cls = array [i ];
108- if (recursiveNode .executeInternal (frame , arg , cls , newDepth )) {
109- return true ;
110- }
111- }
112- return false ;
113- }
114-
115- @ Specialization (guards = "depth < getNodeRecursionLimit(language)" , replaces = "doTupleConstantLen" , excludeForUncached = true )
116- static boolean doRecursiveWithNode (VirtualFrame frame , Object arg , PTuple clsTuple , int depth ,
117- @ Bind Node inliningTarget ,
118- @ SuppressWarnings ("unused" ) @ Bind PythonLanguage language ,
119- @ Shared @ Cached GetObjectArrayNode getObjectArrayNode ,
120- @ Shared @ Cached ("createRecursive()" ) PyObjectRecursiveBinaryCheckNode recursiveNode ) {
121- return loopRecursive (frame , arg , clsTuple , inliningTarget , getObjectArrayNode , recursiveNode , depth + 1 );
89+ @ SuppressWarnings ("unused" ) @ Cached PyTupleCheckNode tupleCheck ,
90+ @ Cached TupleNodes .GetTupleStorage getTupleStorage ,
91+ @ Cached SequenceStorageNodes .ToArrayNode toArrayNode ,
92+ @ Cached ("createRecursive()" ) PyObjectRecursiveBinaryCheckNode recursiveNode ) {
93+ return loopRecursive (frame , arg , clsTuple , inliningTarget , getTupleStorage , toArrayNode , recursiveNode , depth + 1 );
12294 }
12395
124- @ Specialization (guards = {"depth >= getNodeRecursionLimit(language)" }, excludeForUncached = true )
125- boolean doRecursiveTransition (VirtualFrame frame , Object arg , PTuple clsTuple , @ SuppressWarnings ("unused" ) int depth ,
96+ @ SuppressWarnings ("truffle-static-method" )
97+ @ Specialization (guards = {"depth >= getNodeRecursionLimit(language)" , "tupleCheck.execute(inliningTarget, clsTuple)" }, limit = "1" , excludeForUncached = true )
98+ boolean doRecursiveTransition (VirtualFrame frame , Object arg , Object clsTuple , @ SuppressWarnings ("unused" ) int depth ,
12699 @ Bind Node inliningTarget ,
127100 @ SuppressWarnings ("unused" ) @ Bind PythonLanguage language ,
128101 @ Cached ("createFor($node)" ) BoundaryCallData boundaryCallData ,
129- @ Shared @ Cached GetObjectArrayNode getObjectArrayNode ) {
102+ @ SuppressWarnings ("unused" ) @ Cached PyTupleCheckNode tupleCheck ,
103+ @ Cached TupleNodes .GetTupleStorage getTupleStorage ,
104+ @ Cached SequenceStorageNodes .ToArrayNode toArrayNode ) {
130105 Object state = BoundaryCallContext .enter (frame , boundaryCallData );
131106 try {
132107 // Note: we need actual recursion to trigger the stack overflow error like CPython.
133- return callRecursiveWithNodeTruffleBoundary (inliningTarget , arg , clsTuple , getObjectArrayNode );
108+ return callRecursiveWithNodeTruffleBoundary (inliningTarget , arg , clsTuple , getTupleStorage , toArrayNode );
134109 } finally {
135110 BoundaryCallContext .exit (frame , boundaryCallData , state );
136111 }
137112 }
138113
139- @ Specialization
140- boolean doRecursiveUncached (VirtualFrame frame , Object arg , PTuple clsTuple , @ SuppressWarnings ("unused" ) int depth ) {
114+ @ SuppressWarnings ("truffle-static-method" )
115+ @ Specialization (guards = "tupleCheck.execute(inliningTarget, clsTuple)" , limit = "1" )
116+ boolean doRecursiveUncached (VirtualFrame frame , Object arg , Object clsTuple , @ SuppressWarnings ("unused" ) int depth ,
117+ @ Bind Node inliningTarget ,
118+ @ SuppressWarnings ("unused" ) @ Cached PyTupleCheckNode tupleCheck ,
119+ @ Cached TupleNodes .GetTupleStorage getTupleStorage ,
120+ @ Cached SequenceStorageNodes .ToArrayNode toArrayNode ) {
141121 assert this instanceof UnadoptableNode ;
142- return loopRecursive (frame , arg , clsTuple , null , GetObjectArrayNode . getUncached () , this , -1 );
122+ return loopRecursive (frame , arg , clsTuple , inliningTarget , getTupleStorage , toArrayNode , this , -1 );
143123 }
144124
145125 @ TruffleBoundary
146- private boolean callRecursiveWithNodeTruffleBoundary (Node inliningTarget , Object arg , PTuple clsTuple , GetObjectArrayNode getObjectArrayNode ) {
147- return loopRecursive (null , arg , clsTuple , inliningTarget , getObjectArrayNode , getUncachedRecursive (), -1 );
126+ private boolean callRecursiveWithNodeTruffleBoundary (Node inliningTarget , Object arg , Object clsTuple , TupleNodes .GetTupleStorage getTupleStorage ,
127+ SequenceStorageNodes .ToArrayNode toArrayNode ) {
128+ return loopRecursive (null , arg , clsTuple , inliningTarget , getTupleStorage , toArrayNode , getUncachedRecursive (), -1 );
148129 }
149130
150- private static boolean loopRecursive (VirtualFrame frame , Object arg , PTuple clsTuple , Node inliningTarget , GetObjectArrayNode getObjectArrayNode , PyObjectRecursiveBinaryCheckNode node ,
151- int depth ) {
152- for (Object cls : getObjectArrayNode . execute (inliningTarget , clsTuple )) {
131+ private static boolean loopRecursive (VirtualFrame frame , Object arg , Object clsTuple , Node inliningTarget , TupleNodes . GetTupleStorage getTupleStorage ,
132+ SequenceStorageNodes . ToArrayNode toArrayNode , PyObjectRecursiveBinaryCheckNode node , int depth ) {
133+ for (Object cls : getTupleArray (inliningTarget , clsTuple , getTupleStorage , toArrayNode )) {
153134 if (node .executeInternal (frame , arg , cls , depth )) {
154135 return true ;
155136 }
156137 }
157138 return false ;
158139 }
159140
160- protected static int getLength ( PTuple t ) {
161- return t . getSequenceStorage (). length ( );
141+ private static Object [] getTupleArray ( Node inliningTarget , Object clsTuple , TupleNodes . GetTupleStorage getTupleStorage , SequenceStorageNodes . ToArrayNode toArrayNode ) {
142+ return toArrayNode . execute ( inliningTarget , getTupleStorage . execute ( inliningTarget , clsTuple ) );
162143 }
163144
164145 @ Idempotent
0 commit comments