168
168
import com .oracle .graal .python .builtins .objects .type .slots .TpSlotIterNext .CallSlotTpIterNextNode ;
169
169
import com .oracle .graal .python .compiler .Compiler ;
170
170
import com .oracle .graal .python .compiler .RaisePythonExceptionErrorCallback ;
171
+ import com .oracle .graal .python .lib .IteratorExhausted ;
171
172
import com .oracle .graal .python .lib .PyCallableCheckNode ;
172
173
import com .oracle .graal .python .lib .PyEvalGetGlobals ;
173
174
import com .oracle .graal .python .lib .PyEvalGetLocals ;
@@ -486,13 +487,12 @@ static boolean doObject(VirtualFrame frame, Object object,
486
487
while (true ) {
487
488
try {
488
489
Object next = nextNode .execute (frame , inliningTarget , iterator );
489
- if (PyIterNextNode .isExhausted (next )) {
490
- break ;
491
- }
492
490
nbrIter ++;
493
491
if (!isTrueNode .execute (frame , next )) {
494
492
return false ;
495
493
}
494
+ } catch (IteratorExhausted e ) {
495
+ break ;
496
496
} finally {
497
497
LoopNode .reportLoopCount (inliningTarget , nbrIter );
498
498
}
@@ -538,13 +538,12 @@ static boolean doObject(VirtualFrame frame, Object object,
538
538
while (true ) {
539
539
try {
540
540
Object next = nextNode .execute (frame , inliningTarget , iterator );
541
- if (PyIterNextNode .isExhausted (next )) {
542
- break ;
543
- }
544
541
nbrIter ++;
545
542
if (isTrueNode .execute (frame , next )) {
546
543
return true ;
547
544
}
545
+ } catch (IteratorExhausted e ) {
546
+ break ;
548
547
} finally {
549
548
LoopNode .reportLoopCount (inliningTarget , nbrIter );
550
549
}
@@ -1583,8 +1582,10 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
1583
1582
Object keywordArg = kwArgsAreNone ? null : keywordArgIn ;
1584
1583
1585
1584
Object iterator = getIter .execute (frame , inliningTarget , arg1 );
1586
- Object currentValue = nextNode .execute (frame , inliningTarget , iterator );
1587
- if (PyIterNextNode .isExhausted (currentValue )) {
1585
+ Object currentValue ;
1586
+ try {
1587
+ currentValue = nextNode .execute (frame , inliningTarget , iterator );
1588
+ } catch (IteratorExhausted e ) {
1588
1589
if (hasDefaultProfile .profile (inliningTarget , isNoValue (defaultVal ))) {
1589
1590
throw raiseNode .raise (inliningTarget , PythonErrorType .ValueError , ErrorMessages .ARG_IS_EMPTY_SEQ , name );
1590
1591
} else {
@@ -1593,12 +1594,9 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
1593
1594
}
1594
1595
Object currentKey = applyKeyFunction (frame , inliningTarget , keywordArg , keyCall , currentValue );
1595
1596
int loopCount = 0 ;
1596
- try {
1597
- while ( true ) {
1597
+ while ( true ) {
1598
+ try {
1598
1599
Object nextValue = nextNode .execute (frame , inliningTarget , iterator );
1599
- if (PyIterNextNode .isExhausted (nextValue )) {
1600
- break ;
1601
- }
1602
1600
Object nextKey = applyKeyFunction (frame , inliningTarget , keywordArg , keyCall , nextValue );
1603
1601
boolean isTrue ;
1604
1602
if (!seenNonBoolean .wasEntered (inliningTarget )) {
@@ -1616,10 +1614,13 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
1616
1614
currentValue = nextValue ;
1617
1615
}
1618
1616
loopCount ++;
1617
+ } catch (IteratorExhausted e ) {
1618
+ break ;
1619
+ } finally {
1620
+ LoopNode .reportLoopCount (inliningTarget , loopCount < 0 ? Integer .MAX_VALUE : loopCount );
1619
1621
}
1620
- } finally {
1621
- LoopNode .reportLoopCount (inliningTarget , loopCount < 0 ? Integer .MAX_VALUE : loopCount );
1622
1622
}
1623
+
1623
1624
return currentValue ;
1624
1625
}
1625
1626
@@ -1737,29 +1738,26 @@ static Object next(VirtualFrame frame, Object iterator, Object defaultObject,
1737
1738
if (!PyIterCheckNode .checkSlots (slots )) {
1738
1739
throw raiseTypeError .raise (inliningTarget , TypeError , ErrorMessages .OBJ_ISNT_ITERATOR , iterator );
1739
1740
}
1740
- Object result ;
1741
1741
try {
1742
- result = callIterNext .execute (frame , inliningTarget , slots .tp_iternext (), iterator );
1743
- } catch (PException e ) {
1742
+ return callIterNext .execute (frame , inliningTarget , slots .tp_iternext (), iterator );
1743
+ } catch (IteratorExhausted e ) {
1744
1744
if (defaultIsNoValue .profile (inliningTarget , defaultObject == NO_VALUE )) {
1745
- throw e ;
1745
+ throw raiseStopIteration . raise ( inliningTarget , StopIteration ) ;
1746
1746
} else {
1747
- e .expectStopIteration (inliningTarget , stopIterationProfile );
1748
1747
return defaultObject ;
1749
1748
}
1750
- }
1751
- if (PyIterNextNode .isExhausted (result )) {
1749
+ } catch (PException e ) {
1752
1750
if (defaultIsNoValue .profile (inliningTarget , defaultObject == NO_VALUE )) {
1753
- throw raiseStopIteration . raise ( inliningTarget , StopIteration ) ;
1751
+ throw e ;
1754
1752
} else {
1753
+ e .expectStopIteration (inliningTarget , stopIterationProfile );
1755
1754
return defaultObject ;
1756
1755
}
1757
1756
}
1758
- return result ;
1759
1757
}
1760
1758
}
1761
1759
1762
- // ord(c)
1760
+ // ord(c)
1763
1761
@ Builtin (name = J_ORD , minNumOfPositionalArgs = 1 )
1764
1762
@ GenerateNodeFactory
1765
1763
@ ImportStatic (PGuards .class )
@@ -1805,7 +1803,7 @@ static Object ord(@SuppressWarnings("unused") Object obj,
1805
1803
}
1806
1804
}
1807
1805
1808
- // print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
1806
+ // print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
1809
1807
@ Builtin (name = J_PRINT , takesVarArgs = true , keywordOnlyNames = {"sep" , "end" , "file" , "flush" }, doc = "\n " +
1810
1808
"print(value, ..., sep=' ', end='\\ n', file=sys.stdout, flush=False)\n " +
1811
1809
"\n " +
@@ -2219,61 +2217,90 @@ static Object sumGeneric(VirtualFrame frame, Node inliningTarget, Object iterato
2219
2217
@ Cached PyIterNextNode nextNode ,
2220
2218
@ Shared @ Cached PyNumberAddNode addNode ,
2221
2219
@ Shared @ Cached InlinedConditionProfile resultFitsInInt ,
2220
+ @ Exclusive @ Cached InlinedBranchProfile seenObject ,
2222
2221
@ Exclusive @ Cached InlinedBranchProfile seenInt ,
2223
2222
@ Exclusive @ Cached InlinedBranchProfile seenDouble ,
2224
- @ Exclusive @ Cached InlinedBranchProfile seenObject ) {
2223
+ @ Exclusive @ Cached InlinedBranchProfile genericBranch ) {
2225
2224
/*
2226
2225
* Peel the first iteration to see what's the type.
2227
2226
*/
2228
- Object next = nextNode .execute (frame , inliningTarget , iterator );
2229
- if (!PyIterNextNode .isExhausted (next )) {
2230
- Object acc = addNode .execute (frame , inliningTarget , start , next );
2231
- /*
2232
- * We try to process integers/longs/doubles as long as we can. Then we always
2233
- * fall through to the generic path. `next` and `acc` are always properly set so
2234
- * that the generic path can check if there are remaining items and resume if
2235
- * necessary.
2236
- */
2237
- if (acc instanceof Integer || acc instanceof Long ) {
2238
- seenInt .enter (inliningTarget );
2239
- long longAcc = acc instanceof Integer ? (int ) acc : (long ) acc ;
2240
- while (loopProfilePrimitive .profile (inliningTarget , !PyIterNextNode .isExhausted (next = nextNode .execute (frame , inliningTarget , iterator )))) {
2241
- try {
2242
- if (next instanceof Integer nextInt ) {
2243
- longAcc = PythonUtils .addExact (longAcc , nextInt );
2244
- } else if (next instanceof Long nextLong ) {
2245
- longAcc = PythonUtils .addExact (longAcc , nextLong );
2246
- } else {
2247
- break ;
2248
- }
2249
- } catch (OverflowException e ) {
2250
- break ;
2227
+ Object next ;
2228
+ try {
2229
+ next = nextNode .execute (frame , inliningTarget , iterator );
2230
+ } catch (IteratorExhausted e ) {
2231
+ return start ;
2232
+ }
2233
+ Object acc = addNode .execute (frame , inliningTarget , start , next );
2234
+ /*
2235
+ * We try to process integers/longs/doubles as long as we can. Then we always fall
2236
+ * through to the generic path. `next` and `acc` are always properly set so that the
2237
+ * generic path can check if there are remaining items and resume if necessary.
2238
+ */
2239
+ if (acc instanceof Integer || acc instanceof Long ) {
2240
+ seenInt .enter (inliningTarget );
2241
+ long longAcc = acc instanceof Integer ? (int ) acc : (long ) acc ;
2242
+ boolean exitLoop = false , exhausted = false ;
2243
+ while (loopProfilePrimitive .profile (inliningTarget , !exitLoop )) {
2244
+ try {
2245
+ next = nextNode .execute (frame , inliningTarget , iterator );
2246
+ if (next instanceof Integer nextInt ) {
2247
+ longAcc = PythonUtils .addExact (longAcc , nextInt );
2248
+ } else if (next instanceof Long nextLong ) {
2249
+ longAcc = PythonUtils .addExact (longAcc , nextLong );
2250
+ } else {
2251
+ exitLoop = true ;
2251
2252
}
2253
+ } catch (OverflowException e ) {
2254
+ exitLoop = true ;
2255
+ } catch (IteratorExhausted e ) {
2256
+ exitLoop = true ;
2257
+ exhausted = true ;
2252
2258
}
2253
- acc = maybeInt (inliningTarget , resultFitsInInt , longAcc );
2254
- } else if (acc instanceof Double doubleAcc ) {
2255
- seenDouble .enter (inliningTarget );
2256
- while (loopProfilePrimitive .profile (inliningTarget , !PyIterNextNode .isExhausted (next = nextNode .execute (frame , inliningTarget , iterator )))) {
2259
+ }
2260
+ if (exhausted ) {
2261
+ return maybeInt (inliningTarget , resultFitsInInt , longAcc );
2262
+ }
2263
+ genericBranch .enter (inliningTarget );
2264
+ acc = longAcc ;
2265
+ } else if (acc instanceof Double doubleAcc ) {
2266
+ seenDouble .enter (inliningTarget );
2267
+ boolean exitLoop = false , exhausted = false ;
2268
+ while (loopProfilePrimitive .profile (inliningTarget , !exitLoop )) {
2269
+ try {
2270
+ next = nextNode .execute (frame , inliningTarget , iterator );
2257
2271
if (next instanceof Double nextDouble ) {
2258
2272
doubleAcc += nextDouble ;
2259
2273
} else {
2260
- break ;
2274
+ exitLoop = true ;
2261
2275
}
2276
+ } catch (IteratorExhausted e ) {
2277
+ exitLoop = true ;
2278
+ exhausted = true ;
2262
2279
}
2263
- acc = doubleAcc ;
2264
- } else {
2265
- next = nextNode .execute (frame , inliningTarget , iterator );
2266
2280
}
2267
- if (!PyIterNextNode .isExhausted (next )) {
2268
- seenObject .enter (inliningTarget );
2269
- do {
2270
- acc = addNode .execute (frame , inliningTarget , acc , next );
2271
- } while (loopProfileGeneric .profile (inliningTarget , !PyIterNextNode .isExhausted (next = nextNode .execute (frame , inliningTarget , iterator ))));
2281
+ if (exhausted ) {
2282
+ return doubleAcc ;
2272
2283
}
2273
- return acc ;
2284
+ genericBranch .enter (inliningTarget );
2285
+ acc = doubleAcc ;
2274
2286
} else {
2275
- return start ;
2287
+ seenObject .enter (inliningTarget );
2288
+ try {
2289
+ next = nextNode .execute (frame , inliningTarget , iterator );
2290
+ } catch (IteratorExhausted e ) {
2291
+ return acc ;
2292
+ }
2276
2293
}
2294
+ boolean exhausted = false ;
2295
+ do {
2296
+ acc = addNode .execute (frame , inliningTarget , acc , next );
2297
+ try {
2298
+ next = nextNode .execute (frame , inliningTarget , iterator );
2299
+ } catch (IteratorExhausted e ) {
2300
+ exhausted = true ;
2301
+ }
2302
+ } while (loopProfileGeneric .profile (inliningTarget , !exhausted ));
2303
+ return acc ;
2277
2304
}
2278
2305
2279
2306
private static long maybeInt (Node inliningTarget , InlinedConditionProfile resultFitsInInt , long result ) {
0 commit comments