169
169
import com .oracle .graal .python .lib .RichCmpOp ;
170
170
import com .oracle .graal .python .compiler .Compiler ;
171
171
import com .oracle .graal .python .compiler .RaisePythonExceptionErrorCallback ;
172
+ import com .oracle .graal .python .lib .IteratorExhausted ;
172
173
import com .oracle .graal .python .lib .PyCallableCheckNode ;
173
174
import com .oracle .graal .python .lib .PyEvalGetGlobals ;
174
175
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
}
@@ -1584,8 +1583,10 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
1584
1583
Object keywordArg = kwArgsAreNone ? null : keywordArgIn ;
1585
1584
1586
1585
Object iterator = getIter .execute (frame , inliningTarget , arg1 );
1587
- Object currentValue = nextNode .execute (frame , inliningTarget , iterator );
1588
- if (PyIterNextNode .isExhausted (currentValue )) {
1586
+ Object currentValue ;
1587
+ try {
1588
+ currentValue = nextNode .execute (frame , inliningTarget , iterator );
1589
+ } catch (IteratorExhausted e ) {
1589
1590
if (hasDefaultProfile .profile (inliningTarget , isNoValue (defaultVal ))) {
1590
1591
throw raiseNode .raise (inliningTarget , PythonErrorType .ValueError , ErrorMessages .ARG_IS_EMPTY_SEQ , name );
1591
1592
} else {
@@ -1594,23 +1595,23 @@ static Object minmaxSequenceWithKey(VirtualFrame frame, Node inliningTarget, Obj
1594
1595
}
1595
1596
Object currentKey = applyKeyFunction (frame , inliningTarget , keywordArg , keyCall , currentValue );
1596
1597
int loopCount = 0 ;
1597
- try {
1598
- while ( true ) {
1598
+ while ( true ) {
1599
+ try {
1599
1600
Object nextValue = nextNode .execute (frame , inliningTarget , iterator );
1600
- if (PyIterNextNode .isExhausted (nextValue )) {
1601
- break ;
1602
- }
1603
1601
Object nextKey = applyKeyFunction (frame , inliningTarget , keywordArg , keyCall , nextValue );
1604
1602
boolean isTrue = compareNode .execute (frame , inliningTarget , nextKey , currentKey , op );
1605
1603
if (isTrue ) {
1606
1604
currentKey = nextKey ;
1607
1605
currentValue = nextValue ;
1608
1606
}
1609
1607
loopCount ++;
1608
+ } catch (IteratorExhausted e ) {
1609
+ break ;
1610
+ } finally {
1611
+ LoopNode .reportLoopCount (inliningTarget , loopCount < 0 ? Integer .MAX_VALUE : loopCount );
1610
1612
}
1611
- } finally {
1612
- LoopNode .reportLoopCount (inliningTarget , loopCount < 0 ? Integer .MAX_VALUE : loopCount );
1613
1613
}
1614
+
1614
1615
return currentValue ;
1615
1616
}
1616
1617
@@ -1709,29 +1710,26 @@ static Object next(VirtualFrame frame, Object iterator, Object defaultObject,
1709
1710
if (!PyIterCheckNode .checkSlots (slots )) {
1710
1711
throw raiseTypeError .raise (inliningTarget , TypeError , ErrorMessages .OBJ_ISNT_ITERATOR , iterator );
1711
1712
}
1712
- Object result ;
1713
1713
try {
1714
- result = callIterNext .execute (frame , inliningTarget , slots .tp_iternext (), iterator );
1715
- } catch (PException e ) {
1714
+ return callIterNext .execute (frame , inliningTarget , slots .tp_iternext (), iterator );
1715
+ } catch (IteratorExhausted e ) {
1716
1716
if (defaultIsNoValue .profile (inliningTarget , defaultObject == NO_VALUE )) {
1717
- throw e ;
1717
+ throw raiseStopIteration . raise ( inliningTarget , StopIteration ) ;
1718
1718
} else {
1719
- e .expectStopIteration (inliningTarget , stopIterationProfile );
1720
1719
return defaultObject ;
1721
1720
}
1722
- }
1723
- if (PyIterNextNode .isExhausted (result )) {
1721
+ } catch (PException e ) {
1724
1722
if (defaultIsNoValue .profile (inliningTarget , defaultObject == NO_VALUE )) {
1725
- throw raiseStopIteration . raise ( inliningTarget , StopIteration ) ;
1723
+ throw e ;
1726
1724
} else {
1725
+ e .expectStopIteration (inliningTarget , stopIterationProfile );
1727
1726
return defaultObject ;
1728
1727
}
1729
1728
}
1730
- return result ;
1731
1729
}
1732
1730
}
1733
1731
1734
- // ord(c)
1732
+ // ord(c)
1735
1733
@ Builtin (name = J_ORD , minNumOfPositionalArgs = 1 )
1736
1734
@ GenerateNodeFactory
1737
1735
@ ImportStatic (PGuards .class )
@@ -1777,7 +1775,7 @@ static Object ord(@SuppressWarnings("unused") Object obj,
1777
1775
}
1778
1776
}
1779
1777
1780
- // print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
1778
+ // print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
1781
1779
@ Builtin (name = J_PRINT , takesVarArgs = true , keywordOnlyNames = {"sep" , "end" , "file" , "flush" }, doc = "\n " +
1782
1780
"print(value, ..., sep=' ', end='\\ n', file=sys.stdout, flush=False)\n " +
1783
1781
"\n " +
@@ -2191,61 +2189,90 @@ static Object sumGeneric(VirtualFrame frame, Node inliningTarget, Object iterato
2191
2189
@ Cached PyIterNextNode nextNode ,
2192
2190
@ Shared @ Cached PyNumberAddNode addNode ,
2193
2191
@ Shared @ Cached InlinedConditionProfile resultFitsInInt ,
2192
+ @ Exclusive @ Cached InlinedBranchProfile seenObject ,
2194
2193
@ Exclusive @ Cached InlinedBranchProfile seenInt ,
2195
2194
@ Exclusive @ Cached InlinedBranchProfile seenDouble ,
2196
- @ Exclusive @ Cached InlinedBranchProfile seenObject ) {
2195
+ @ Exclusive @ Cached InlinedBranchProfile genericBranch ) {
2197
2196
/*
2198
2197
* Peel the first iteration to see what's the type.
2199
2198
*/
2200
- Object next = nextNode .execute (frame , inliningTarget , iterator );
2201
- if (!PyIterNextNode .isExhausted (next )) {
2202
- Object acc = addNode .execute (frame , inliningTarget , start , next );
2203
- /*
2204
- * We try to process integers/longs/doubles as long as we can. Then we always
2205
- * fall through to the generic path. `next` and `acc` are always properly set so
2206
- * that the generic path can check if there are remaining items and resume if
2207
- * necessary.
2208
- */
2209
- if (acc instanceof Integer || acc instanceof Long ) {
2210
- seenInt .enter (inliningTarget );
2211
- long longAcc = acc instanceof Integer ? (int ) acc : (long ) acc ;
2212
- while (loopProfilePrimitive .profile (inliningTarget , !PyIterNextNode .isExhausted (next = nextNode .execute (frame , inliningTarget , iterator )))) {
2213
- try {
2214
- if (next instanceof Integer nextInt ) {
2215
- longAcc = PythonUtils .addExact (longAcc , nextInt );
2216
- } else if (next instanceof Long nextLong ) {
2217
- longAcc = PythonUtils .addExact (longAcc , nextLong );
2218
- } else {
2219
- break ;
2220
- }
2221
- } catch (OverflowException e ) {
2222
- break ;
2199
+ Object next ;
2200
+ try {
2201
+ next = nextNode .execute (frame , inliningTarget , iterator );
2202
+ } catch (IteratorExhausted e ) {
2203
+ return start ;
2204
+ }
2205
+ Object acc = addNode .execute (frame , inliningTarget , start , next );
2206
+ /*
2207
+ * We try to process integers/longs/doubles as long as we can. Then we always fall
2208
+ * through to the generic path. `next` and `acc` are always properly set so that the
2209
+ * generic path can check if there are remaining items and resume if necessary.
2210
+ */
2211
+ if (acc instanceof Integer || acc instanceof Long ) {
2212
+ seenInt .enter (inliningTarget );
2213
+ long longAcc = acc instanceof Integer ? (int ) acc : (long ) acc ;
2214
+ boolean exitLoop = false , exhausted = false ;
2215
+ while (loopProfilePrimitive .profile (inliningTarget , !exitLoop )) {
2216
+ try {
2217
+ next = nextNode .execute (frame , inliningTarget , iterator );
2218
+ if (next instanceof Integer nextInt ) {
2219
+ longAcc = PythonUtils .addExact (longAcc , nextInt );
2220
+ } else if (next instanceof Long nextLong ) {
2221
+ longAcc = PythonUtils .addExact (longAcc , nextLong );
2222
+ } else {
2223
+ exitLoop = true ;
2223
2224
}
2225
+ } catch (OverflowException e ) {
2226
+ exitLoop = true ;
2227
+ } catch (IteratorExhausted e ) {
2228
+ exitLoop = true ;
2229
+ exhausted = true ;
2224
2230
}
2225
- acc = maybeInt (inliningTarget , resultFitsInInt , longAcc );
2226
- } else if (acc instanceof Double doubleAcc ) {
2227
- seenDouble .enter (inliningTarget );
2228
- while (loopProfilePrimitive .profile (inliningTarget , !PyIterNextNode .isExhausted (next = nextNode .execute (frame , inliningTarget , iterator )))) {
2231
+ }
2232
+ if (exhausted ) {
2233
+ return maybeInt (inliningTarget , resultFitsInInt , longAcc );
2234
+ }
2235
+ genericBranch .enter (inliningTarget );
2236
+ acc = longAcc ;
2237
+ } else if (acc instanceof Double doubleAcc ) {
2238
+ seenDouble .enter (inliningTarget );
2239
+ boolean exitLoop = false , exhausted = false ;
2240
+ while (loopProfilePrimitive .profile (inliningTarget , !exitLoop )) {
2241
+ try {
2242
+ next = nextNode .execute (frame , inliningTarget , iterator );
2229
2243
if (next instanceof Double nextDouble ) {
2230
2244
doubleAcc += nextDouble ;
2231
2245
} else {
2232
- break ;
2246
+ exitLoop = true ;
2233
2247
}
2248
+ } catch (IteratorExhausted e ) {
2249
+ exitLoop = true ;
2250
+ exhausted = true ;
2234
2251
}
2235
- acc = doubleAcc ;
2236
- } else {
2237
- next = nextNode .execute (frame , inliningTarget , iterator );
2238
2252
}
2239
- if (!PyIterNextNode .isExhausted (next )) {
2240
- seenObject .enter (inliningTarget );
2241
- do {
2242
- acc = addNode .execute (frame , inliningTarget , acc , next );
2243
- } while (loopProfileGeneric .profile (inliningTarget , !PyIterNextNode .isExhausted (next = nextNode .execute (frame , inliningTarget , iterator ))));
2253
+ if (exhausted ) {
2254
+ return doubleAcc ;
2244
2255
}
2245
- return acc ;
2256
+ genericBranch .enter (inliningTarget );
2257
+ acc = doubleAcc ;
2246
2258
} else {
2247
- return start ;
2259
+ seenObject .enter (inliningTarget );
2260
+ try {
2261
+ next = nextNode .execute (frame , inliningTarget , iterator );
2262
+ } catch (IteratorExhausted e ) {
2263
+ return acc ;
2264
+ }
2248
2265
}
2266
+ boolean exhausted = false ;
2267
+ do {
2268
+ acc = addNode .execute (frame , inliningTarget , acc , next );
2269
+ try {
2270
+ next = nextNode .execute (frame , inliningTarget , iterator );
2271
+ } catch (IteratorExhausted e ) {
2272
+ exhausted = true ;
2273
+ }
2274
+ } while (loopProfileGeneric .profile (inliningTarget , !exhausted ));
2275
+ return acc ;
2249
2276
}
2250
2277
2251
2278
private static long maybeInt (Node inliningTarget , InlinedConditionProfile resultFitsInInt , long result ) {
0 commit comments