57
57
58
58
import com .oracle .graal .python .PythonLanguage ;
59
59
import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
60
+ import com .oracle .graal .python .builtins .modules .SysModuleBuiltins ;
60
61
import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes ;
61
62
import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .PCallCapiFunction ;
62
63
import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodes .ToSulongNode ;
@@ -2333,26 +2334,44 @@ public abstract static class ConcatNode extends SequenceStorageBaseNode {
2333
2334
2334
2335
private final Supplier <GeneralizationNode > genNodeProvider ;
2335
2336
2336
- ConcatNode (Supplier <GeneralizationNode > genNodeProvider ) {
2337
+ /*
2338
+ * CPython is inconsistent when too repeats are done. Most types raise MemoryError, but
2339
+ * e.g. bytes raises OverflowError when the memory might be available but the size overflows
2340
+ * sys.maxint
2341
+ */
2342
+ private final PythonBuiltinClassType errorForOverflow ;
2343
+
2344
+ ConcatNode (Supplier <GeneralizationNode > genNodeProvider , PythonBuiltinClassType errorForOverflow ) {
2337
2345
this .genNodeProvider = genNodeProvider ;
2346
+ this .errorForOverflow = errorForOverflow ;
2338
2347
}
2339
2348
2340
2349
public abstract SequenceStorage execute (SequenceStorage left , SequenceStorage right );
2341
2350
2342
2351
@ Specialization
2343
2352
SequenceStorage doRight (SequenceStorage left , SequenceStorage right ,
2353
+ @ Cached ConditionProfile shouldOverflow ,
2344
2354
@ Cached PRaiseNode raiseNode ,
2345
2355
@ Cached LenNode lenNode ,
2346
2356
@ Cached BranchProfile outOfMemProfile ) {
2357
+ int destlen = 0 ;
2347
2358
try {
2348
2359
int len1 = lenNode .execute (left );
2349
2360
int len2 = lenNode .execute (right );
2350
2361
// we eagerly generalize the store to avoid possible cascading generalizations
2351
- SequenceStorage generalized = generalizeStore (createEmpty (left , right , Math .addExact (len1 , len2 )), right );
2362
+ destlen = PythonUtils .addExact (len1 , len2 );
2363
+ if (errorForOverflow == OverflowError && shouldOverflow .profile (destlen >= SysModuleBuiltins .MAXSIZE )) {
2364
+ // cpython raises an overflow error when this happens
2365
+ throw raiseNode .raise (OverflowError );
2366
+ }
2367
+ SequenceStorage generalized = generalizeStore (createEmpty (left , right , destlen ), right );
2352
2368
return doConcat (generalized , left , right );
2353
- } catch (ArithmeticException | OutOfMemoryError e ) {
2369
+ } catch (OutOfMemoryError e ) {
2354
2370
outOfMemProfile .enter ();
2355
2371
throw raiseNode .raise (MemoryError );
2372
+ } catch (OverflowException e ) {
2373
+ outOfMemProfile .enter ();
2374
+ throw raiseNode .raise (errorForOverflow );
2356
2375
}
2357
2376
}
2358
2377
@@ -2381,15 +2400,23 @@ private SequenceStorage generalizeStore(SequenceStorage storage, Object value) {
2381
2400
}
2382
2401
2383
2402
public static ConcatNode create () {
2384
- return ConcatNodeGen .create (() -> NoGeneralizationCustomMessageNode .create (DEFAULT_ERROR_MSG ));
2403
+ return create (() -> NoGeneralizationCustomMessageNode .create (DEFAULT_ERROR_MSG ), MemoryError );
2404
+ }
2405
+
2406
+ public static ConcatNode createWithOverflowError () {
2407
+ return create (() -> NoGeneralizationCustomMessageNode .create (DEFAULT_ERROR_MSG ), OverflowError );
2385
2408
}
2386
2409
2387
2410
public static ConcatNode create (String msg ) {
2388
- return ConcatNodeGen . create (() -> NoGeneralizationCustomMessageNode .create (msg ));
2411
+ return create (() -> NoGeneralizationCustomMessageNode .create (msg ), MemoryError );
2389
2412
}
2390
2413
2391
2414
public static ConcatNode create (Supplier <GeneralizationNode > genNodeProvider ) {
2392
- return ConcatNodeGen .create (genNodeProvider );
2415
+ return create (genNodeProvider , MemoryError );
2416
+ }
2417
+
2418
+ private static ConcatNode create (Supplier <GeneralizationNode > genNodeProvider , PythonBuiltinClassType errorForOverflow ) {
2419
+ return ConcatNodeGen .create (genNodeProvider , errorForOverflow );
2393
2420
}
2394
2421
}
2395
2422
@@ -2491,6 +2518,17 @@ public abstract static class RepeatNode extends SequenceStorageBaseNode {
2491
2518
@ Child private GetItemScalarNode getItemNode ;
2492
2519
@ Child private RepeatNode recursive ;
2493
2520
2521
+ /*
2522
+ * CPython is inconsistent when too repeats are done. Most types raise MemoryError, but
2523
+ * e.g. bytes raises OverflowError when the memory might be available but the size overflows
2524
+ * sys.maxint
2525
+ */
2526
+ private final PythonBuiltinClassType errorForOverflow ;
2527
+
2528
+ protected RepeatNode (PythonBuiltinClassType errorForOverflow ) {
2529
+ this .errorForOverflow = errorForOverflow ;
2530
+ }
2531
+
2494
2532
public abstract SequenceStorage execute (VirtualFrame frame , SequenceStorage left , Object times );
2495
2533
2496
2534
public abstract SequenceStorage execute (VirtualFrame frame , SequenceStorage left , int times );
@@ -2508,127 +2546,151 @@ static SequenceStorage doZeroRepeat(SequenceStorage s, @SuppressWarnings("unused
2508
2546
2509
2547
/* special but common case: something like '[False] * n' */
2510
2548
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2511
- static BoolSequenceStorage doBoolSingleElement (BoolSequenceStorage s , int times ,
2549
+ BoolSequenceStorage doBoolSingleElement (BoolSequenceStorage s , int times ,
2512
2550
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2513
2551
@ Cached BranchProfile outOfMemProfile ) {
2514
2552
try {
2515
- boolean [] repeated = new boolean [Math .multiplyExact (s .length (), times )];
2553
+ boolean [] repeated = new boolean [PythonUtils .multiplyExact (s .length (), times )];
2516
2554
Arrays .fill (repeated , s .getBoolItemNormalized (0 ));
2517
2555
return new BoolSequenceStorage (repeated );
2518
- } catch (OutOfMemoryError | ArithmeticException e ) {
2556
+ } catch (OutOfMemoryError e ) {
2519
2557
outOfMemProfile .enter ();
2520
2558
throw raiseNode .raise (MemoryError );
2559
+ } catch (OverflowException e ) {
2560
+ outOfMemProfile .enter ();
2561
+ throw raiseNode .raise (errorForOverflow );
2521
2562
}
2522
2563
}
2523
2564
2524
2565
/* special but common case: something like '["\x00"] * n' */
2525
2566
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2526
- static ByteSequenceStorage doByteSingleElement (ByteSequenceStorage s , int times ,
2567
+ ByteSequenceStorage doByteSingleElement (ByteSequenceStorage s , int times ,
2527
2568
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2528
2569
@ Cached BranchProfile outOfMemProfile ) {
2529
2570
try {
2530
- byte [] repeated = new byte [Math .multiplyExact (s .length (), times )];
2571
+ byte [] repeated = new byte [PythonUtils .multiplyExact (s .length (), times )];
2531
2572
Arrays .fill (repeated , s .getByteItemNormalized (0 ));
2532
2573
return new ByteSequenceStorage (repeated );
2533
- } catch (OutOfMemoryError | ArithmeticException e ) {
2574
+ } catch (OutOfMemoryError e ) {
2534
2575
outOfMemProfile .enter ();
2535
2576
throw raiseNode .raise (MemoryError );
2577
+ } catch (OverflowException e ) {
2578
+ outOfMemProfile .enter ();
2579
+ throw raiseNode .raise (errorForOverflow );
2536
2580
}
2537
2581
}
2538
2582
2539
2583
/* special but common case: something like '["0"] * n' */
2540
2584
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2541
- static CharSequenceStorage doCharSingleElement (CharSequenceStorage s , int times ,
2585
+ CharSequenceStorage doCharSingleElement (CharSequenceStorage s , int times ,
2542
2586
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2543
2587
@ Cached BranchProfile outOfMemProfile ) {
2544
2588
try {
2545
- char [] repeated = new char [Math .multiplyExact (s .length (), times )];
2589
+ char [] repeated = new char [PythonUtils .multiplyExact (s .length (), times )];
2546
2590
Arrays .fill (repeated , s .getCharItemNormalized (0 ));
2547
2591
return new CharSequenceStorage (repeated );
2548
- } catch (OutOfMemoryError | ArithmeticException e ) {
2592
+ } catch (OutOfMemoryError e ) {
2549
2593
outOfMemProfile .enter ();
2550
2594
throw raiseNode .raise (MemoryError );
2595
+ } catch (OverflowException e ) {
2596
+ outOfMemProfile .enter ();
2597
+ throw raiseNode .raise (errorForOverflow );
2551
2598
}
2552
2599
}
2553
2600
2554
2601
/* special but common case: something like '[0] * n' */
2555
2602
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2556
- static IntSequenceStorage doIntSingleElement (IntSequenceStorage s , int times ,
2603
+ IntSequenceStorage doIntSingleElement (IntSequenceStorage s , int times ,
2557
2604
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2558
2605
@ Cached BranchProfile outOfMemProfile ) {
2559
2606
try {
2560
- int [] repeated = new int [Math .multiplyExact (s .length (), times )];
2607
+ int [] repeated = new int [PythonUtils .multiplyExact (s .length (), times )];
2561
2608
Arrays .fill (repeated , s .getIntItemNormalized (0 ));
2562
2609
return new IntSequenceStorage (repeated );
2563
- } catch (OutOfMemoryError | ArithmeticException e ) {
2610
+ } catch (OutOfMemoryError e ) {
2564
2611
outOfMemProfile .enter ();
2565
2612
throw raiseNode .raise (MemoryError );
2613
+ } catch (OverflowException e ) {
2614
+ outOfMemProfile .enter ();
2615
+ throw raiseNode .raise (errorForOverflow );
2566
2616
}
2567
2617
}
2568
2618
2569
2619
/* special but common case: something like '[0L] * n' */
2570
2620
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2571
- static LongSequenceStorage doLongSingleElement (LongSequenceStorage s , int times ,
2621
+ LongSequenceStorage doLongSingleElement (LongSequenceStorage s , int times ,
2572
2622
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2573
2623
@ Cached BranchProfile outOfMemProfile ) {
2574
2624
try {
2575
- long [] repeated = new long [Math .multiplyExact (s .length (), times )];
2625
+ long [] repeated = new long [PythonUtils .multiplyExact (s .length (), times )];
2576
2626
Arrays .fill (repeated , s .getLongItemNormalized (0 ));
2577
2627
return new LongSequenceStorage (repeated );
2578
- } catch (OutOfMemoryError | ArithmeticException e ) {
2628
+ } catch (OutOfMemoryError e ) {
2579
2629
outOfMemProfile .enter ();
2580
2630
throw raiseNode .raise (MemoryError );
2631
+ } catch (OverflowException e ) {
2632
+ outOfMemProfile .enter ();
2633
+ throw raiseNode .raise (errorForOverflow );
2581
2634
}
2582
2635
}
2583
2636
2584
2637
/* special but common case: something like '[0.0] * n' */
2585
2638
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2586
- static DoubleSequenceStorage doDoubleSingleElement (DoubleSequenceStorage s , int times ,
2639
+ DoubleSequenceStorage doDoubleSingleElement (DoubleSequenceStorage s , int times ,
2587
2640
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2588
2641
@ Cached BranchProfile outOfMemProfile ) {
2589
2642
try {
2590
- double [] repeated = new double [Math .multiplyExact (s .length (), times )];
2643
+ double [] repeated = new double [PythonUtils .multiplyExact (s .length (), times )];
2591
2644
Arrays .fill (repeated , s .getDoubleItemNormalized (0 ));
2592
2645
return new DoubleSequenceStorage (repeated );
2593
- } catch (OutOfMemoryError | ArithmeticException e ) {
2646
+ } catch (OutOfMemoryError e ) {
2594
2647
outOfMemProfile .enter ();
2595
2648
throw raiseNode .raise (MemoryError );
2649
+ } catch (OverflowException e ) {
2650
+ outOfMemProfile .enter ();
2651
+ throw raiseNode .raise (errorForOverflow );
2596
2652
}
2597
2653
}
2598
2654
2599
2655
/* special but common case: something like '[None] * n' */
2600
2656
@ Specialization (guards = {"s.length() == 1" , "times > 0" })
2601
- static ObjectSequenceStorage doObjectSingleElement (ObjectSequenceStorage s , int times ,
2657
+ ObjectSequenceStorage doObjectSingleElement (ObjectSequenceStorage s , int times ,
2602
2658
@ Shared ("raiseNode" ) @ Cached PRaiseNode raiseNode ,
2603
2659
@ Cached BranchProfile outOfMemProfile ) {
2604
2660
try {
2605
- Object [] repeated = new Object [Math .multiplyExact (s .length (), times )];
2661
+ Object [] repeated = new Object [PythonUtils .multiplyExact (s .length (), times )];
2606
2662
Arrays .fill (repeated , s .getItemNormalized (0 ));
2607
2663
return new ObjectSequenceStorage (repeated );
2608
- } catch (OutOfMemoryError | ArithmeticException e ) {
2664
+ } catch (OutOfMemoryError e ) {
2609
2665
outOfMemProfile .enter ();
2610
2666
throw raiseNode .raise (MemoryError );
2667
+ } catch (OverflowException e ) {
2668
+ outOfMemProfile .enter ();
2669
+ throw raiseNode .raise (errorForOverflow );
2611
2670
}
2612
2671
}
2613
2672
2614
2673
@ Specialization (limit = "MAX_ARRAY_STORAGES" , guards = {"times > 0" , "!isNative(s)" , "s.getClass() == cachedClass" })
2615
- static SequenceStorage doManaged (BasicSequenceStorage s , int times ,
2674
+ SequenceStorage doManaged (BasicSequenceStorage s , int times ,
2616
2675
@ Exclusive @ Cached PRaiseNode raiseNode ,
2617
2676
@ Cached ("create()" ) BranchProfile outOfMemProfile ,
2618
2677
@ Cached ("s.getClass()" ) Class <? extends SequenceStorage > cachedClass ) {
2619
2678
try {
2620
2679
SequenceStorage profiled = cachedClass .cast (s );
2621
2680
Object arr1 = profiled .getInternalArrayObject ();
2622
2681
int len = profiled .length ();
2623
- int newLength = Math .multiplyExact (len , times );
2682
+ int newLength = PythonUtils .multiplyExact (len , times );
2624
2683
SequenceStorage repeated = profiled .createEmpty (newLength );
2625
2684
Object destArr = repeated .getInternalArrayObject ();
2626
2685
repeat (destArr , arr1 , len , times );
2627
2686
repeated .setNewLength (newLength );
2628
2687
return repeated ;
2629
- } catch (OutOfMemoryError | ArithmeticException e ) {
2688
+ } catch (OutOfMemoryError e ) {
2630
2689
outOfMemProfile .enter ();
2631
2690
throw raiseNode .raise (MemoryError );
2691
+ } catch (OverflowException e ) {
2692
+ outOfMemProfile .enter ();
2693
+ throw raiseNode .raise (errorForOverflow );
2632
2694
}
2633
2695
}
2634
2696
@@ -2642,7 +2704,7 @@ SequenceStorage doGeneric(SequenceStorage s, int times,
2642
2704
@ Cached ("create()" ) LenNode lenNode ) {
2643
2705
try {
2644
2706
int len = lenNode .execute (s );
2645
- int newLen = Math .multiplyExact (len , times );
2707
+ int newLen = PythonUtils .multiplyExact (len , times );
2646
2708
SequenceStorage repeated = createEmptyNode .execute (s , newLen , -1 );
2647
2709
2648
2710
for (int i = 0 ; i < len ; i ++) {
@@ -2658,9 +2720,12 @@ SequenceStorage doGeneric(SequenceStorage s, int times,
2658
2720
2659
2721
repeated .setNewLength (newLen );
2660
2722
return repeated ;
2661
- } catch (OutOfMemoryError | ArithmeticException e ) {
2723
+ } catch (OutOfMemoryError e ) {
2662
2724
outOfMemProfile .enter ();
2663
2725
throw raiseNode .raise (MemoryError );
2726
+ } catch (OverflowException e ) {
2727
+ outOfMemProfile .enter ();
2728
+ throw raiseNode .raise (errorForOverflow );
2664
2729
}
2665
2730
}
2666
2731
@@ -2671,7 +2736,7 @@ SequenceStorage doNonInt(VirtualFrame frame, SequenceStorage s, Object times,
2671
2736
int i = toIndex (frame , times , raiseNode , lib );
2672
2737
if (recursive == null ) {
2673
2738
CompilerDirectives .transferToInterpreterAndInvalidate ();
2674
- recursive = insert (RepeatNodeGen .create ());
2739
+ recursive = insert (RepeatNodeGen .create (errorForOverflow ));
2675
2740
}
2676
2741
return recursive .execute (frame , s , i );
2677
2742
}
@@ -2702,7 +2767,11 @@ private static int toIndex(VirtualFrame frame, Object times, PRaiseNode raiseNod
2702
2767
}
2703
2768
2704
2769
public static RepeatNode create () {
2705
- return RepeatNodeGen .create ();
2770
+ return RepeatNodeGen .create (MemoryError );
2771
+ }
2772
+
2773
+ public static RepeatNode createWithOverflowError () {
2774
+ return RepeatNodeGen .create (OverflowError );
2706
2775
}
2707
2776
}
2708
2777
@@ -3279,9 +3348,9 @@ static BasicSequenceStorage doManaged(BasicSequenceStorage s, int cap,
3279
3348
BasicSequenceStorage profiled = cachedClass .cast (s );
3280
3349
profiled .ensureCapacity (cap );
3281
3350
return profiled ;
3282
- } catch (ArithmeticException | OutOfMemoryError e ) {
3351
+ } catch (OutOfMemoryError | ArithmeticException e ) {
3283
3352
overflowErrorProfile .enter ();
3284
- throw raiseNode .raise (OverflowError );
3353
+ throw raiseNode .raise (MemoryError );
3285
3354
}
3286
3355
}
3287
3356
0 commit comments