merge
[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 #if defined(PROFILING)
20 #define UPD_FRAME_PARAMS W_ unused1, W_ unused2, P_ unused3
21 #else
22 #define UPD_FRAME_PARAMS P_ unused1
23 #endif
24
25 /* The update fragment has been tuned so as to generate good
26    code with gcc, which accounts for some of the strangeness in the
27    way it is written.  
28
29    In particular, the JMP_(ret) bit is passed down and pinned on the
30    end of each branch (there end up being two major branches in the
31    code), since we don't mind duplicating this jump.
32 */
33
34 /* on entry to the update code
35    (1) R1 points to the closure being returned
36    (2) Sp points to the update frame
37 */
38
39 INFO_TABLE_RET( stg_upd_frame, UPDATE_FRAME, UPD_FRAME_PARAMS)
40 {
41     W_ updatee;
42     
43     updatee = StgUpdateFrame_updatee(Sp);
44
45     /* remove the update frame from the stack */
46     Sp = Sp + SIZEOF_StgUpdateFrame;
47     
48     /* ToDo: it might be a PAP, so we should check... */
49     TICK_UPD_CON_IN_NEW(sizeW_fromITBL(%GET_STD_INFO(updatee)));
50     
51     updateWithIndirection(updatee,
52                           R1,
53                           jump %ENTRY_CODE(Sp(0)));
54 }
55
56
57 INFO_TABLE_RET( stg_marked_upd_frame, UPDATE_FRAME, UPD_FRAME_PARAMS)
58 {
59     W_ updatee, v, i, tso, link;
60
61     // we know the closure is a BLACKHOLE
62     updatee = StgUpdateFrame_updatee(Sp);
63     v = StgInd_indirectee(updatee);
64
65     // remove the update frame from the stack
66     Sp = Sp + SIZEOF_StgUpdateFrame;
67     
68     if (GETTAG(v) != 0) {
69         // updated by someone else: discard our value and use the
70         // other one to increase sharing, but check the blocking
71         // queues to see if any threads were waiting on this BLACKHOLE.
72         R1 = v;
73         foreign "C" checkBlockingQueues(MyCapability() "ptr",
74                                         CurrentTSO "ptr") [R1];
75         jump %ENTRY_CODE(Sp(0));
76     }
77
78     // common case: it is still our BLACKHOLE
79     if (v == CurrentTSO) {
80         updateWithIndirection(updatee,
81                               R1,
82                               jump %ENTRY_CODE(Sp(0)));
83     }
84
85     // The other cases are all handled by the generic code
86     foreign "C" updateThunk (MyCapability() "ptr", CurrentTSO "ptr", 
87                              updatee "ptr", R1 "ptr") [R1];
88
89     jump %ENTRY_CODE(Sp(0));
90 }
91
92 // Special update frame code for CAFs and eager-blackholed thunks: it
93 // knows how to update blackholes, but is distinct from
94 // stg_marked_upd_frame so that lazy blackholing won't treat it as the
95 // high watermark.
96 INFO_TABLE_RET (stg_bh_upd_frame, UPDATE_FRAME, UPD_FRAME_PARAMS)
97 {
98     jump RET_LBL(stg_marked_upd_frame);
99 }