Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • rts/Interpreter.c
    ... ... @@ -271,6 +271,24 @@ See also Note [Width of parameters] for some more motivation.
    271 271
     #define WITHIN_CHUNK_BOUNDS_W(n, s)  \
    
    272 272
         (RTS_LIKELY(((StgWord*) Sp_plusW(n)) < ((s)->stack + (s)->stack_size - sizeofW(StgUnderflowFrame))))
    
    273 273
     
    
    274
    +/* Note [Checking for underflow frames]
    
    275
    +   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    276
    +
    
    277
    +   We look at the stack slot at offset sizeof(StgUnderflowFrame) from
    
    278
    +   the start of the chunk to check if we're in the first check chunk.
    
    279
    +   Every non-first stack chunk has an underflow frame header at that offset.
    
    280
    +
    
    281
    +   We really should change this check, since this stack slot in the first
    
    282
    +   chunk may not be the start of a stack frame and could in theory contain
    
    283
    +   an arbitrary value.
    
    284
    +
    
    285
    +   In practice we're unlikely to have interpreted frames that low on the stack.
    
    286
    + */
    
    287
    +#define IS_UNDERFLOW_FRAME(info) \
    
    288
    +    ((info) == &stg_stack_underflow_frame_d_info ||   \
    
    289
    +     (info) == &stg_stack_underflow_frame_v16_info || \
    
    290
    +     (info) == &stg_stack_underflow_frame_v32_info || \
    
    291
    +     (info) == &stg_stack_underflow_frame_v64_info)
    
    274 292
     
    
    275 293
     #define W64_TO_WDS(n) ((n * sizeof(StgWord64) / sizeof(StgWord)))
    
    276 294
     
    
    ... ... @@ -681,11 +699,9 @@ slow_spw(void *Sp, StgStack *cur_stack, StgWord offset_words){
    681 699
         frame = (StgUnderflowFrame*)(cur_stack->stack + cur_stack->stack_size
    
    682 700
                    - sizeofW(StgUnderflowFrame));
    
    683 701
     
    
    684
    -    // 2a. Check it is an underflow frame (the top stack chunk won't have one).
    
    685
    -    if( frame->info == &stg_stack_underflow_frame_d_info
    
    686
    -       || frame->info == &stg_stack_underflow_frame_v16_info
    
    687
    -       || frame->info == &stg_stack_underflow_frame_v32_info
    
    688
    -       || frame->info == &stg_stack_underflow_frame_v64_info )
    
    702
    +    // 2a. Check it is an underflow frame (the first stack chunk won't have one).
    
    703
    +    //     See Note [Checking for underflow frames]
    
    704
    +    if( IS_UNDERFLOW_FRAME(frame->info) )
    
    689 705
         {
    
    690 706
     
    
    691 707
           INTERP_TICK(it_underflow_lookups);
    
    ... ... @@ -702,9 +718,11 @@ slow_spw(void *Sp, StgStack *cur_stack, StgWord offset_words){
    702 718
         }
    
    703 719
         // 2b. Access the element if there is no underflow frame, it must be right
    
    704 720
         // at the top of the stack.
    
    705
    -    else {
    
    706
    -        // Not actually in the underflow case
    
    721
    +    else if(Sp_plusW(offset_words) < (StgPtr)(cur_stack->stack + cur_stack->stack_size)) {
    
    722
    +        // Still inside the stack chunk
    
    707 723
             return Sp_plusW(offset_words);
    
    724
    +    } else {
    
    725
    +        barf("slow_spw: offset_words %d is out of bounds", (int)offset_words);
    
    708 726
         }
    
    709 727
       }
    
    710 728
     }
    
    ... ... @@ -2425,8 +2443,39 @@ run_BCO:
    2425 2443
                  *           =>
    
    2426 2444
                  * a_1 ... a_n, k
    
    2427 2445
                  */
    
    2428
    -            while(n-- > 0) {
    
    2429
    -                SpW(n+by) = ReadSpW(n);
    
    2446
    +            if (n == 0 || WITHIN_CAP_CHUNK_BOUNDS_W(n - 1 + by)) {
    
    2447
    +                while(n-- > 0) {
    
    2448
    +                    SpW(n+by) = ReadSpW(n);
    
    2449
    +                }
    
    2450
    +            } else {
    
    2451
    +                // We write across a chunk boundary: Use safe access
    
    2452
    +                while(n-- > 0) {
    
    2453
    +                    *((StgWord*)SafeSpWP(n+by)) = ReadSpW(n);
    
    2454
    +                }
    
    2455
    +            }
    
    2456
    +
    
    2457
    +            // If we SLIDE Sp past the chunk bounds we need to handle the underflow
    
    2458
    +            // (possibly multiple times)
    
    2459
    +            while (!WITHIN_CAP_CHUNK_BOUNDS_W(by)) {
    
    2460
    +                StgStack *stk = cap->r.rCurrentTSO->stackobj;
    
    2461
    +                StgUnderflowFrame *uf = (StgUnderflowFrame*)
    
    2462
    +                    (stk->stack + stk->stack_size
    
    2463
    +                     - sizeofW(StgUnderflowFrame));
    
    2464
    +                // See Note [Checking for underflow frames]
    
    2465
    +                if (IS_UNDERFLOW_FRAME(uf->info)) {
    
    2466
    +                    W_ sp_to_uf = (StgWord*)uf - (StgWord*)Sp;
    
    2467
    +                    Sp = (StgPtr)uf;
    
    2468
    +                    SAVE_STACK_POINTERS;
    
    2469
    +                    threadStackUnderflow(cap, cap->r.rCurrentTSO);
    
    2470
    +                    LOAD_STACK_POINTERS;
    
    2471
    +                    by -= sp_to_uf;
    
    2472
    +                } else if (Sp_plusW(by) < (StgPtr)(stk->stack + stk->stack_size)) {
    
    2473
    +                    // we're within the first stack chunk, this chunk has
    
    2474
    +                    // no underflow frame
    
    2475
    +                    break;
    
    2476
    +                } else {
    
    2477
    +                    barf("bci_SLIDE: Sp+by outside stack bounds");
    
    2478
    +                }
    
    2430 2479
                 }
    
    2431 2480
                 Sp_addW(by);
    
    2432 2481
                 INTERP_TICK(it_slides);
    

  • testsuite/tests/bytecode/T27001.hs
    1
    +{-# LANGUAGE BangPatterns #-}
    
    2
    +-- Test that SLIDE works correctly when it crosses a stack chunk boundary.
    
    3
    +-- See #27001.
    
    4
    +module Main where
    
    5
    +
    
    6
    +go :: Int -> Double -> Double
    
    7
    +go 0 !acc = acc
    
    8
    +go n !acc = go (n - 1) (acc + 1.0)
    
    9
    +
    
    10
    +result :: Double
    
    11
    +result = go 100000 0.0
    
    12
    +
    
    13
    +main :: IO ()
    
    14
    +main = print result

  • testsuite/tests/bytecode/T27001.stdout
    1
    +100000.0

  • testsuite/tests/bytecode/all.T
    ... ... @@ -12,3 +12,8 @@ test('T26640', extra_files(["T26640.hs"]), ghci_script, ['T26640.script'])
    12 12
     
    
    13 13
     # Nullary data constructors
    
    14 14
     test('T26216', extra_files(["T26216_aux.hs"]), ghci_script, ['T26216.script'])
    
    15
    +
    
    16
    +# SLIDE across stack chunk boundary (#27001)
    
    17
    +test('T27001', [extra_files(['T27001.hs']), req_interp],
    
    18
    +     run_command,
    
    19
    +     ['{compiler} -e main -O -fno-unoptimized-core-for-interpreter T27001.hs'])