| ... |
... |
@@ -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);
|