1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2013
4  *
5  * Performing updates.
6  *
7  * ---------------------------------------------------------------------------*/
8 
9 #pragma once
10 
11 #if !defined(CMINUSMINUS)
12 #include "BeginPrivate.h"
13 #endif
14 
15 /* -----------------------------------------------------------------------------
16    Updates
17    -------------------------------------------------------------------------- */
18 
19 /* LDV profiling:
20  *   After all, we do *NOT* need to call LDV_RECORD_CREATE() for IND
21  *   closures because they are inherently used. But, it corrupts
22  *   the invariants that every closure keeps its creation time in the profiling
23  *  field. So, we call LDV_RECORD_CREATE().
24  */
25 
26 /*
27  * We have two versions of this macro (sadly), one for use in C-- code,
28  * and the other for C.
29  *
30  * The and_then argument is a performance hack so that we can paste in
31  * the continuation code directly.  It helps shave a couple of
32  * instructions off the common case in the update code, which is
33  * worthwhile (the update code is often part of the inner loop).
34  */
35 #if defined(CMINUSMINUS)
36 
37 #define UPDATE_FRAME_FIELDS(w_,p_,info_ptr,ccs,p2,updatee)      \
38                  w_ info_ptr,                           \
39                  PROF_HDR_FIELDS(w_,ccs,p2)              \
40                  p_ updatee
41 
42 /*
43  * Getting the memory barriers correct here is quite tricky. Essentially
44  * the write barrier ensures that any writes to the new indirectee are visible
45  * before we introduce the indirection.
46  * See Note [Heap memory barriers] in SMP.h.
47  */
48 #define updateWithIndirection(p1, p2, and_then) \
49     W_ bd;                                                      \
50                                                                 \
51     prim_write_barrier;                                         \
52     bd = Bdescr(p1);                                            \
53     if (bdescr_gen_no(bd) != 0 :: bits16) {                     \
54       IF_NONMOVING_WRITE_BARRIER_ENABLED {                      \
55         ccall updateRemembSetPushThunk_(BaseReg, p1 "ptr");     \
56       }                                                         \
57       recordMutableCap(p1, TO_W_(bdescr_gen_no(bd)));           \
58       TICK_UPD_OLD_IND();                                       \
59     } else {                                                    \
60       TICK_UPD_NEW_IND();                                       \
61     }                                                           \
62     OVERWRITING_CLOSURE(p1);                                    \
63     StgInd_indirectee(p1) = p2;                                 \
64     prim_write_barrier;                                         \
65     SET_INFO(p1, stg_BLACKHOLE_info);                           \
66     LDV_RECORD_CREATE(p1);                                      \
67     and_then;
68 
69 #else /* !CMINUSMINUS */
70 
updateWithIndirection(Capability * cap,StgClosure * p1,StgClosure * p2)71 INLINE_HEADER void updateWithIndirection (Capability *cap,
72                                           StgClosure *p1,
73                                           StgClosure *p2)
74 {
75     ASSERT( (P_)p1 != (P_)p2 );
76     /* not necessarily true: ASSERT( !closure_IND(p1) ); */
77     /* occurs in RaiseAsync.c:raiseAsync() */
78     /* See Note [Heap memory barriers] in SMP.h */
79     bdescr *bd = Bdescr((StgPtr)p1);
80     if (bd->gen_no != 0) {
81       IF_NONMOVING_WRITE_BARRIER_ENABLED {
82           updateRemembSetPushThunk(cap, (StgThunk*)p1);
83       }
84         recordMutableCap(p1, cap, bd->gen_no);
85         TICK_UPD_OLD_IND();
86     } else {
87         TICK_UPD_NEW_IND();
88     }
89     OVERWRITING_CLOSURE(p1);
90     RELEASE_STORE(&((StgInd *)p1)->indirectee, p2);
91     SET_INFO_RELEASE(p1, &stg_BLACKHOLE_info);
92     LDV_RECORD_CREATE(p1);
93 }
94 
95 #endif /* CMINUSMINUS */
96 
97 #if !defined(CMINUSMINUS)
98 #include "EndPrivate.h"
99 #endif
100