| 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)) [R1]); |
|---|
| 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)) [R1]; |
|---|
| 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)) [R1]); |
|---|
| 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)) [R1]; |
|---|
| 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) [R1]; |
|---|
| 99 | } |
|---|