1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-2004
5 * Canned Heap-Check and Stack-Check sequences.
7 * This file is written in a subset of C--, extended with various
8 * features specific to GHC. It is compiled by GHC directly. For the
9 * syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
11 * ---------------------------------------------------------------------------*/
15 /* Stack/Heap Check Failure
16 * ------------------------
18 * On discovering that a stack or heap check has failed, we do the following:
20 * - If the context_switch flag is set, indicating that there are more
21 * threads waiting to run, we yield to the scheduler
22 * (return ThreadYielding).
24 * - If Hp > HpLim, we've had a heap check failure. This means we've
25 * come to the end of the current heap block, so we try to chain
26 * another block on with ExtendNursery().
28 * - If this succeeds, we carry on without returning to the
31 * - If it fails, we return to the scheduler claiming HeapOverflow
32 * so that a garbage collection can be performed.
34 * - If Hp <= HpLim, it must have been a stack check that failed. In
35 * which case, we return to the scheduler claiming StackOverflow, the
36 * scheduler will either increase the size of our stack, or raise
37 * an exception if the stack is already too big.
39 * The effect of checking for context switch only in the heap/stack check
40 * failure code is that we'll switch threads after the current thread has
41 * reached the end of its heap block. If a thread isn't allocating
42 * at all, it won't yield. Hopefully this won't be a problem in practice.
45 #define PRE_RETURN(why,what_next) \
46 StgTSO_what_next(CurrentTSO) = what_next::I16; \
47 StgRegTable_rRet(BaseReg) = why; \
50 /* Remember that the return address is *removed* when returning to a
51 * ThreadRunGHC thread.
55 DEBUG_ONLY(foreign "C" heapCheckFail()); \
57 Hp = Hp - HpAlloc/*in bytes*/; \
58 if (HpAlloc <= BLOCK_SIZE \
59 && bdescr_link(CurrentNursery) != NULL) { \
61 CurrentNursery = bdescr_link(CurrentNursery); \
63 if (CInt[context_switch] != 0 :: CInt) { \
64 R1 = ThreadYielding; \
67 jump %ENTRY_CODE(Sp(0)); \
77 PRE_RETURN(R1,ThreadRunGHC); \
78 jump stg_returnToSched;
81 PRE_RETURN(HeapOverflow, ThreadRunGHC) \
82 jump stg_returnToSched;
84 #define BLOCK_GENERIC \
85 PRE_RETURN(ThreadBlocked, ThreadRunGHC) \
86 jump stg_returnToSched;
88 #define YIELD_GENERIC \
89 PRE_RETURN(ThreadYielding, ThreadRunGHC) \
90 jump stg_returnToSched;
92 #define BLOCK_BUT_FIRST(c) \
93 PRE_RETURN(ThreadBlocked, ThreadRunGHC) \
95 jump stg_returnToSchedButFirst;
97 #define YIELD_TO_INTERPRETER \
98 PRE_RETURN(ThreadYielding, ThreadInterpret) \
99 jump stg_returnToSchedNotPaused;
101 /* -----------------------------------------------------------------------------
102 Heap checks in thunks/functions.
104 In these cases, node always points to the function closure. This gives
105 us an easy way to return to the function: just leave R1 on the top of
106 the stack, and have the scheduler enter it to return.
108 There are canned sequences for 'n' pointer values in registers.
109 -------------------------------------------------------------------------- */
111 INFO_TABLE_RET( stg_enter, RET_SMALL, "ptr" W_ unused)
122 Sp(0) = stg_enter_info;
128 ToDo: merge the block and yield macros, calling something like BLOCK(N)
133 Should we actually ever do a yield in such a case?? -- HWL
138 TSO_what_next(CurrentTSO) = ThreadRunGHC;
148 TSO_what_next(CurrentTSO) = ThreadRunGHC;
153 /*- 2 Regs--------------------------------------------------------------------*/
161 TSO_what_next(CurrentTSO) = ThreadRunGHC;
166 /*- 3 Regs -------------------------------------------------------------------*/
175 TSO_what_next(CurrentTSO) = ThreadRunGHC;
180 /*- 4 Regs -------------------------------------------------------------------*/
190 TSO_what_next(CurrentTSO) = ThreadRunGHC;
195 /*- 5 Regs -------------------------------------------------------------------*/
206 TSO_what_next(CurrentTSO) = ThreadRunGHC;
211 /*- 6 Regs -------------------------------------------------------------------*/
223 TSO_what_next(CurrentTSO) = ThreadRunGHC;
228 /*- 7 Regs -------------------------------------------------------------------*/
241 TSO_what_next(CurrentTSO) = ThreadRunGHC;
246 /*- 8 Regs -------------------------------------------------------------------*/
260 TSO_what_next(CurrentTSO) = ThreadRunGHC;
265 // the same routines but with a block rather than a yield
272 TSO_what_next(CurrentTSO) = ThreadRunGHC;
277 /*- 2 Regs--------------------------------------------------------------------*/
285 TSO_what_next(CurrentTSO) = ThreadRunGHC;
290 /*- 3 Regs -------------------------------------------------------------------*/
299 TSO_what_next(CurrentTSO) = ThreadRunGHC;
304 /*- 4 Regs -------------------------------------------------------------------*/
314 TSO_what_next(CurrentTSO) = ThreadRunGHC;
319 /*- 5 Regs -------------------------------------------------------------------*/
330 TSO_what_next(CurrentTSO) = ThreadRunGHC;
335 /*- 6 Regs -------------------------------------------------------------------*/
347 TSO_what_next(CurrentTSO) = ThreadRunGHC;
352 /*- 7 Regs -------------------------------------------------------------------*/
365 TSO_what_next(CurrentTSO) = ThreadRunGHC;
370 /*- 8 Regs -------------------------------------------------------------------*/
384 TSO_what_next(CurrentTSO) = ThreadRunGHC;
391 #if 0 && defined(PAR)
394 Similar to stg_block_1 (called via StgMacro BLOCK_NP) but separates the
395 saving of the thread state from the actual jump via an StgReturn.
396 We need this separation because we call RTS routines in blocking entry codes
397 before jumping back into the RTS (see parallel/FetchMe.hc).
409 TSO_what_next(CurrentTSO) = ThreadRunGHC;
416 /* -----------------------------------------------------------------------------
417 Heap checks in Primitive case alternatives
419 A primitive case alternative is entered with a value either in
420 R1, FloatReg1 or D1 depending on the return convention. All the
421 cases are covered below.
422 -------------------------------------------------------------------------- */
424 /*-- No Registers live ------------------------------------------------------ */
431 /*-- void return ------------------------------------------------------------ */
433 INFO_TABLE_RET( stg_gc_void, RET_SMALL)
436 jump %ENTRY_CODE(Sp(0));
439 /*-- R1 is boxed/unpointed -------------------------------------------------- */
441 INFO_TABLE_RET( stg_gc_unpt_r1, RET_SMALL, "ptr" W_ unused)
445 jump %ENTRY_CODE(Sp(0));
452 Sp(0) = stg_gc_unpt_r1_info;
456 /*-- R1 is unboxed -------------------------------------------------- */
458 /* the 1 is a bitmap - i.e. 1 non-pointer word on the stack. */
459 INFO_TABLE_RET( stg_gc_unbx_r1, RET_SMALL, W_ unused )
463 jump %ENTRY_CODE(Sp(0));
470 Sp(0) = stg_gc_unbx_r1_info;
474 /*-- F1 contains a float ------------------------------------------------- */
476 INFO_TABLE_RET( stg_gc_f1, RET_SMALL, F_ unused )
480 jump %ENTRY_CODE(Sp(0));
486 F_[Sp + WDS(1)] = F1;
487 Sp(0) = stg_gc_f1_info;
491 /*-- D1 contains a double ------------------------------------------------- */
493 INFO_TABLE_RET( stg_gc_d1, RET_SMALL, D_ unused )
495 D1 = D_[Sp + WDS(1)];
496 Sp = Sp + WDS(1) + SIZEOF_StgDouble;
497 jump %ENTRY_CODE(Sp(0));
502 Sp = Sp - WDS(1) - SIZEOF_StgDouble;
503 D_[Sp + WDS(1)] = D1;
504 Sp(0) = stg_gc_d1_info;
509 /*-- L1 contains an int64 ------------------------------------------------- */
511 INFO_TABLE_RET( stg_gc_l1, RET_SMALL, L_ unused )
513 L1 = L_[Sp + WDS(1)];
514 Sp_adj(1) + SIZEOF_StgWord64;
515 jump %ENTRY_CODE(Sp(0));
520 Sp_adj(-1) - SIZEOF_StgWord64;
521 L_[Sp + WDS(1)] = L1;
522 Sp(0) = stg_gc_l1_info;
526 /*-- Unboxed tuple return, one pointer (unregisterised build only) ---------- */
528 INFO_TABLE_RET( stg_ut_1_0_unreg, RET_SMALL, "ptr" W_ unused )
531 // one ptr is on the stack (Sp(0))
532 jump %ENTRY_CODE(Sp(1));
535 /* -----------------------------------------------------------------------------
536 Generic function entry heap check code.
538 At a function entry point, the arguments are as per the calling convention,
539 i.e. some in regs and some on the stack. There may or may not be
540 a pointer to the function closure in R1 - if there isn't, then the heap
541 check failure code in the function will arrange to load it.
543 The function's argument types are described in its info table, so we
544 can just jump to this bit of generic code to save away all the
545 registers and return to the scheduler.
547 This code arranges the stack like this:
551 +---------------------+
553 +---------------------+
555 +- - - - - - - - - - -+
557 +---------------------+
559 +---------------------+
561 The size is the number of words of arguments on the stack, and is cached
562 in the frame in order to simplify stack walking: otherwise the size of
563 this stack frame would have to be calculated by looking at f's info table.
565 -------------------------------------------------------------------------- */
576 info = %GET_FUN_INFO(UNTAG(R1));
579 type = TO_W_(StgFunInfoExtra_fun_type(info));
580 if (type == ARG_GEN) {
581 size = BITMAP_SIZE(StgFunInfoExtra_bitmap(info));
583 if (type == ARG_GEN_BIG) {
584 #ifdef TABLES_NEXT_TO_CODE
585 // bitmap field holds an offset
586 size = StgLargeBitmap_size( StgFunInfoExtra_bitmap(info)
587 + %GET_ENTRY(UNTAG(R1)) /* ### */ );
589 size = StgLargeBitmap_size( StgFunInfoExtra_bitmap(info) );
592 size = BITMAP_SIZE(W_[stg_arg_bitmaps + WDS(type)]);
597 // we don't have to save any registers away
599 Sp(0) = stg_gc_fun_info;
601 StgRetFun_size(ret_fun) = HALF_W_(size);
602 StgRetFun_tag(ret_fun) = HALF_W_(tag);
603 StgRetFun_fun(ret_fun) = R1;
607 type = TO_W_(StgFunInfoExtra_fun_type(info));
609 if (type == ARG_GEN || type == ARG_GEN_BIG) {
610 // regs already saved by the heap check code
612 Sp(0) = stg_gc_fun_info;
614 StgRetFun_size(ret_fun) = HALF_W_(size);
615 StgRetFun_tag(ret_fun) = HALF_W_(tag);
616 StgRetFun_fun(ret_fun) = R1;
617 // DEBUG_ONLY(foreign "C" debugBelch("stg_fun_gc_gen(ARG_GEN)"););
620 jump W_[stg_stack_save_entries + WDS(type)];
621 // jumps to stg_gc_noregs after saving stuff
623 #endif /* !NO_ARG_REGS */
626 /* -----------------------------------------------------------------------------
627 Generic Apply (return point)
629 The dual to stg_fun_gc_gen (above): this fragment returns to the
630 function, passing arguments in the stack and in registers
631 appropriately. The stack layout is given above.
632 -------------------------------------------------------------------------- */
634 INFO_TABLE_RET( stg_gc_fun, RET_FUN )
636 // Grab the fun, but remember to add in the tag. The GC doesn't
637 // guarantee to retain the tag on the pointer, so we have to do
638 // it manually, because the function entry code assumes it.
641 R1 = StgRetFun_fun(ret_fun) | TO_W_(StgRetFun_tag(ret_fun));
644 // Minor optimisation: there are no argument registers to load up,
645 // so we can just jump straight to the function's entry point.
646 jump %GET_ENTRY(UNTAG(R1));
651 info = %GET_FUN_INFO(UNTAG(R1));
652 type = TO_W_(StgFunInfoExtra_fun_type(info));
653 if (type == ARG_GEN || type == ARG_GEN_BIG) {
654 jump StgFunInfoExtra_slow_apply(info);
656 if (type == ARG_BCO) {
657 // cover this case just to be on the safe side
660 Sp(0) = stg_apply_interp_info;
661 jump stg_yield_to_interpreter;
663 jump W_[stg_ap_stack_entries + WDS(type)];
669 /* -----------------------------------------------------------------------------
670 Generic Heap Check Code.
672 Called with Liveness mask in R9, Return address in R10.
673 Stack must be consistent (containing all necessary info pointers
676 See StgMacros.h for a description of the RET_DYN stack frame.
678 We also define an stg_gen_yield here, because it's very similar.
679 -------------------------------------------------------------------------- */
681 // For simplicity, we assume that SIZEOF_DOUBLE == 2*SIZEOF_VOID_P
682 // on a 64-bit machine, we'll end up wasting a couple of words, but
683 // it's not a big deal.
685 #define RESTORE_EVERYTHING \
686 L1 = L_[Sp + WDS(19)]; \
687 D2 = D_[Sp + WDS(17)]; \
688 D1 = D_[Sp + WDS(15)]; \
689 F4 = F_[Sp + WDS(14)]; \
690 F3 = F_[Sp + WDS(13)]; \
691 F2 = F_[Sp + WDS(12)]; \
692 F1 = F_[Sp + WDS(11)]; \
703 #define RET_OFFSET (-19)
705 #define SAVE_EVERYTHING \
707 L_[Sp + WDS(19)] = L1; \
708 D_[Sp + WDS(17)] = D2; \
709 D_[Sp + WDS(15)] = D1; \
710 F_[Sp + WDS(14)] = F4; \
711 F_[Sp + WDS(13)] = F3; \
712 F_[Sp + WDS(12)] = F2; \
713 F_[Sp + WDS(11)] = F1; \
722 Sp(2) = R10; /* return address */ \
723 Sp(1) = R9; /* liveness mask */ \
724 Sp(0) = stg_gc_gen_info;
726 INFO_TABLE_RET( stg_gc_gen, RET_DYN )
727 /* bitmap in the above info table is unused, the real one is on the stack. */
730 jump Sp(RET_OFFSET); /* No %ENTRY_CODE( - this is an actual code ptr */
739 // A heap check at an unboxed tuple return point. The return address
740 // is on the stack, and we can find it by using the offsets given
741 // to us in the liveness mask.
744 R10 = %ENTRY_CODE(Sp(RET_DYN_NONPTRS(R9) + RET_DYN_PTRS(R9)));
750 * stg_gen_hp is used by MAYBE_GC, where we can't use GC_GENERIC
751 * because we've just failed doYouWantToGC(), not a standard heap
752 * check. GC_GENERIC would end up returning StackOverflow.
760 /* -----------------------------------------------------------------------------
762 -------------------------------------------------------------------------- */
775 /* -----------------------------------------------------------------------------
776 Yielding to the interpreter... top of stack says what to do next.
777 -------------------------------------------------------------------------- */
779 stg_yield_to_interpreter
781 YIELD_TO_INTERPRETER;
784 /* -----------------------------------------------------------------------------
786 -------------------------------------------------------------------------- */
803 Sp(0) = stg_enter_info;
807 /* -----------------------------------------------------------------------------
808 * takeMVar/putMVar-specific blocks
810 * Stack layout for a thread blocked in takeMVar:
814 * stg_block_takemvar_info
816 * Stack layout for a thread blocked in putMVar:
821 * stg_block_putmvar_info
823 * See PrimOps.hc for a description of the workings of take/putMVar.
825 * -------------------------------------------------------------------------- */
827 INFO_TABLE_RET( stg_block_takemvar, RET_SMALL, "ptr" W_ unused )
831 jump takeMVarzh_fast;
834 // code fragment executed just before we return to the scheduler
835 stg_block_takemvar_finally
838 unlockClosure(R3, stg_EMPTY_MVAR_info);
847 Sp(0) = stg_block_takemvar_info;
849 BLOCK_BUT_FIRST(stg_block_takemvar_finally);
852 INFO_TABLE_RET( stg_block_putmvar, RET_SMALL, "ptr" W_ unused1, "ptr" W_ unused2 )
860 // code fragment executed just before we return to the scheduler
861 stg_block_putmvar_finally
864 unlockClosure(R3, stg_FULL_MVAR_info);
874 Sp(0) = stg_block_putmvar_info;
876 BLOCK_BUT_FIRST(stg_block_putmvar_finally);
879 // code fragment executed just before we return to the scheduler
880 stg_block_blackhole_finally
882 #if defined(THREADED_RTS)
883 // The last thing we do is release sched_lock, which is
884 // preventing other threads from accessing blackhole_queue and
885 // picking up this thread before we are finished with it.
886 foreign "C" RELEASE_LOCK(sched_mutex "ptr");
895 Sp(0) = stg_enter_info;
896 BLOCK_BUT_FIRST(stg_block_blackhole_finally);
899 INFO_TABLE_RET( stg_block_throwto, RET_SMALL, "ptr" W_ unused, "ptr" W_ unused )
904 jump killThreadzh_fast;
907 stg_block_throwto_finally
910 foreign "C" throwToReleaseTarget (R3 "ptr");
920 Sp(0) = stg_block_throwto_info;
921 BLOCK_BUT_FIRST(stg_block_throwto_finally);
924 #ifdef mingw32_HOST_OS
925 INFO_TABLE_RET( stg_block_async, RET_SMALL )
930 ares = StgTSO_block_info(CurrentTSO);
931 len = StgAsyncIOResult_len(ares);
932 errC = StgAsyncIOResult_errCode(ares);
933 StgTSO_block_info(CurrentTSO) = NULL;
934 foreign "C" free(ares "ptr");
937 jump %ENTRY_CODE(Sp(1));
943 Sp(0) = stg_block_async_info;
947 /* Used by threadDelay implementation; it would be desirable to get rid of
948 * this free()'ing void return continuation.
950 INFO_TABLE_RET( stg_block_async_void, RET_SMALL )
954 ares = StgTSO_block_info(CurrentTSO);
955 StgTSO_block_info(CurrentTSO) = NULL;
956 foreign "C" free(ares "ptr");
958 jump %ENTRY_CODE(Sp(0));
964 Sp(0) = stg_block_async_void_info;
970 /* -----------------------------------------------------------------------------
972 -------------------------------------------------------------------------- */
974 stg_block_stmwait_finally
976 foreign "C" stmWaitUnlock(MyCapability() "ptr", R3 "ptr");
982 BLOCK_BUT_FIRST(stg_block_stmwait_finally);