Merge branch 'master' of darcs.haskell.org:/srv/darcs//ghc
[ghc.git] / rts / Updates.cmm
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2004
4  *
5  * Code to perform updates.
6  *
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.
10  *
11  * ---------------------------------------------------------------------------*/
12
13
14 #include "Cmm.h"
15 #include "rts/prof/LDV.h"
16
17 #include "Updates.h"
18
19 /*
20  * The update code is PERFORMANCE CRITICAL, if you make any changes
21  * here make sure you eyeball the assembly and check that the fast
22  * path (update in generation 0) is optimal.
23  *
24  * The return(ret) bit is passed down and pinned on the end of each
25  * branch (there end up being two major branches in the code), since
26  * we don't mind duplicating this jump.
27  */
28 INFO_TABLE_RET ( stg_upd_frame, UPDATE_FRAME,
29                  UPDATE_FRAME_FIELDS(W_,P_,info_ptr,_ccs,_unused,updatee) )
30     return (P_ ret) /* the closure being returned */
31 {
32     /* ToDo: it might be a PAP, so we should check... */
33     TICK_UPD_CON_IN_NEW(sizeW_fromITBL(%GET_STD_INFO(updatee)));
34
35     updateWithIndirection(updatee, ret, return (ret));
36 }
37
38 /*
39  * An update frame where the updatee has been replaced by a BLACKHOLE
40  * closure by threadPaused.  We may have threads to wake up, and we
41  * also have to check whether the blackhole has been updated by
42  * another thread in the meantime.
43  */
44 INFO_TABLE_RET ( stg_marked_upd_frame, UPDATE_FRAME,
45                  UPDATE_FRAME_FIELDS(W_,P_,info_ptr,_ccs,_unused,updatee) )
46     return (P_ ret) /* the closure being returned */
47 {
48     W_ v, i, tso, link;
49
50     // we know the closure is a BLACKHOLE
51     v = StgInd_indirectee(updatee);
52
53     if (GETTAG(v) != 0) {
54         // updated by someone else: discard our value and use the
55         // other one to increase sharing, but check the blocking
56         // queues to see if any threads were waiting on this BLACKHOLE.
57         ccall checkBlockingQueues(MyCapability() "ptr", CurrentTSO "ptr");
58         return (v);
59     }
60
61     // common case: it is still our BLACKHOLE
62     if (v == CurrentTSO) {
63         updateWithIndirection(updatee, ret, return (ret));
64     }
65
66     // The other cases are all handled by the generic code
67     ccall updateThunk (MyCapability() "ptr", CurrentTSO "ptr",
68                        updatee "ptr", ret "ptr");
69
70     return (ret);
71 }
72
73 /*
74  * Special update frame code for CAFs and eager-blackholed thunks: it
75  * knows how to update blackholes, but is distinct from
76  * stg_marked_upd_frame so that lazy blackholing won't treat it as the
77  * high watermark.
78  */
79 INFO_TABLE_RET ( stg_bh_upd_frame, UPDATE_FRAME,
80                  UPDATE_FRAME_FIELDS(W_,P_,info_ptr,ccs,_unused,updatee) )
81     return (P_ ret) /* the closure being returned */
82 {
83     // This all compiles away to a single jump instruction (sigh)
84     jump RET_LBL(stg_marked_upd_frame)
85         ( UPDATE_FRAME_FIELDS(,,info_ptr,ccs,_unused,updatee) )
86         (ret);
87 }