1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.16 2001/05/31 10:59:14 simonmar Exp $
4 * (c) The GHC Team, 1998-2000
6 * Canned "Standard Form" Thunks
8 * ---------------------------------------------------------------------------*/
12 #include "StoragePriv.h"
13 #include "HeapStackCheck.h"
15 /* -----------------------------------------------------------------------------
16 The code for a thunk that simply extracts a field from a
17 single-constructor datatype depends only on the offset of the field
20 Here we define some canned "selector" thunks that do just that; any
21 selector thunk appearing in a program will refer to one of these
22 instead of being compiled independently.
24 The garbage collector spots selector thunks and reduces them if
25 possible, in order to avoid space leaks resulting from lazy pattern
27 -------------------------------------------------------------------------- */
29 #define UPD_FRAME_SIZE (sizeofW(StgUpdateFrame)+sizeofW(StgHeader))
30 #define NOUPD_FRAME_SIZE (sizeofW(StgHeader))
33 #define SAVE_CCCS(fs) CCS_HDR(Sp-fs)=CCCS
34 #define GET_SAVED_CCCS RESTORE_CCCS(CCS_HDR(Sp))
35 #define ENTER_CCS(p) ENTER_CCS_TCL(p)
38 #define SAVE_CCCS(fs) /* empty */
39 #define GET_SAVED_CCCS /* empty */
40 #define ENTER_CCS(p) /* empty */
44 #define SELECTOR_CODE_UPD(offset) \
45 IF_(stg_sel_ret_##offset##_upd_ret); \
46 INFO_TABLE_SRT_BITMAP(stg_sel_ret_##offset##_upd_info,stg_sel_ret_##offset##_upd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static, EF_, 0, 0); \
47 EF_(stg_sel_ret_##offset##_upd_ret) { \
49 R1.p=(P_)R1.cl->payload[offset]; \
51 Sp=Sp+sizeofW(StgHeader); \
52 JMP_(ENTRY_CODE(*R1.p)); \
56 EF_(stg_sel_##offset##_upd_entry); \
57 INFO_TABLE_SELECTOR(stg_sel_##offset##_upd_info, stg_sel_##offset##_upd_entry, offset,, EF_, "stg_sel" #offset "_upd_entry", "stg_sel" #offset "_upd_entry");\
58 EF_(stg_sel_##offset##_upd_entry) { \
60 STK_CHK_NP(UPD_FRAME_SIZE,1,); \
61 UPD_BH_UPDATABLE(&stg_sel_##offset##_upd_info); \
62 PUSH_UPD_FRAME(R1.p,0); \
64 SAVE_CCCS(UPD_FRAME_SIZE); \
65 Sp[-UPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_upd_info; \
66 R1.p = (P_)R1.cl->payload[0]; \
67 Sp=Sp-UPD_FRAME_SIZE; \
68 JMP_(ENTRY_CODE(*R1.p)); \
82 SELECTOR_CODE_UPD(10);
83 SELECTOR_CODE_UPD(11);
84 SELECTOR_CODE_UPD(12);
85 SELECTOR_CODE_UPD(13);
86 SELECTOR_CODE_UPD(14);
87 SELECTOR_CODE_UPD(15);
89 #define SELECTOR_CODE_NOUPD(offset) \
90 IF_(stg_sel_ret_##offset##_noupd_ret); \
91 INFO_TABLE_SRT_BITMAP(stg_sel_ret_##offset##_noupd_info, stg_sel_ret_##offset##_noupd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static, EF_, 0, 0); \
92 IF_(stg_sel_ret_##offset##_noupd_ret) { \
94 R1.p=(P_)R1.cl->payload[offset]; \
96 Sp=Sp+sizeofW(StgHeader); \
97 JMP_(ENTRY_CODE(*R1.p)); \
101 EF_(stg_sel_##offset##_noupd_entry); \
102 INFO_TABLE_SELECTOR(stg_sel_##offset##_noupd_info, stg_sel_##offset##_noupd_entry, offset,, EF_, "stg_sel" #offset "_noupd_entry", "stg_sel" #offset "_noupd_entry");\
103 EF_(stg_sel_##offset##_noupd_entry) { \
105 STK_CHK_NP(NOUPD_FRAME_SIZE,1,) \
106 UPD_BH_SINGLE_ENTRY(&stg_sel_##offset##_noupd_info); \
108 SAVE_CCCS(NOUPD_FRAME_SIZE); \
109 Sp[-NOUPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_noupd_info; \
110 R1.p = (P_)R1.cl->payload[0]; \
111 Sp=Sp-NOUPD_FRAME_SIZE; \
112 JMP_(ENTRY_CODE(*R1.p)); \
116 SELECTOR_CODE_NOUPD(0);
117 SELECTOR_CODE_NOUPD(1);
118 SELECTOR_CODE_NOUPD(2);
119 SELECTOR_CODE_NOUPD(3);
120 SELECTOR_CODE_NOUPD(4);
121 SELECTOR_CODE_NOUPD(5);
122 SELECTOR_CODE_NOUPD(6);
123 SELECTOR_CODE_NOUPD(7);
124 SELECTOR_CODE_NOUPD(8);
125 SELECTOR_CODE_NOUPD(9);
126 SELECTOR_CODE_NOUPD(10);
127 SELECTOR_CODE_NOUPD(11);
128 SELECTOR_CODE_NOUPD(12);
129 SELECTOR_CODE_NOUPD(13);
130 SELECTOR_CODE_NOUPD(14);
131 SELECTOR_CODE_NOUPD(15);
133 /* -----------------------------------------------------------------------------
136 An apply thunk is a thunk of the form
138 let z = [x1...xn] \u x1...xn
141 We pre-compile some of these because the code is always the same.
143 These have to be independent of the update frame size, so the code
144 works when profiling etc.
145 -------------------------------------------------------------------------- */
147 FN_(stg_ap_1_upd_entry);
148 FN_(stg_ap_2_upd_entry);
149 FN_(stg_ap_3_upd_entry);
150 FN_(stg_ap_4_upd_entry);
151 FN_(stg_ap_5_upd_entry);
152 FN_(stg_ap_6_upd_entry);
153 FN_(stg_ap_7_upd_entry);
154 FN_(stg_ap_8_upd_entry);
156 #define UF_SIZE (sizeofW(StgUpdateFrame))
158 /* stg_ap_1_upd_info is a bit redundant, but there appears to be a bug
159 * in the compiler that means stg_ap_1 is generated occasionally (ToDo)
162 INFO_TABLE_SRT(stg_ap_1_upd_info,stg_ap_1_upd_entry,1,1,0,0,0,THUNK,,EF_,"stg_ap_1_upd_info","stg_ap_1_upd_info");
163 FN_(stg_ap_1_upd_entry) {
165 STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
166 UPD_BH_UPDATABLE(&stg_ap_1_upd_info);
168 PUSH_UPD_FRAME(R1.p,0);
169 R1.p=(P_)(R1.cl->payload[0]);
170 Sp = Sp - sizeofW(StgUpdateFrame);
171 JMP_(ENTRY_CODE(*R1.p));
175 INFO_TABLE_SRT(stg_ap_2_upd_info,stg_ap_2_upd_entry,2,0,0,0,0,THUNK,,EF_,"stg_ap_2_upd_info","stg_ap_2_upd_info");
176 FN_(stg_ap_2_upd_entry) {
178 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
179 UPD_BH_UPDATABLE(&stg_ap_2_upd_info);
181 PUSH_UPD_FRAME(R1.p,0);
182 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
183 R1.p=(P_)(R1.cl->payload[0]);
184 Sp = Sp - (sizeofW(StgUpdateFrame)+1);
185 JMP_(ENTRY_CODE(*R1.p));
189 INFO_TABLE_SRT(stg_ap_3_upd_info,stg_ap_3_upd_entry,3,0,0,0,0,THUNK,,EF_,"stg_ap_3_upd_info","stg_ap_3_upd_info");
190 FN_(stg_ap_3_upd_entry) {
192 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
193 UPD_BH_UPDATABLE(&stg_ap_3_upd_info);
195 PUSH_UPD_FRAME(R1.p,0);
196 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
197 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
198 R1.p=(P_)(R1.cl->payload[0]);
199 Sp = Sp - (sizeofW(StgUpdateFrame)+2);
200 JMP_(ENTRY_CODE(*R1.p));
204 INFO_TABLE_SRT(stg_ap_4_upd_info,stg_ap_4_upd_entry,4,0,0,0,0,THUNK,,EF_,"stg_ap_4_upd_info","stg_ap_4_upd_info");
205 FN_(stg_ap_4_upd_entry) {
207 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
208 UPD_BH_UPDATABLE(&stg_ap_4_upd_info);
210 PUSH_UPD_FRAME(R1.p,0);
211 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
212 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
213 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
214 R1.p=(P_)(R1.cl->payload[0]);
215 Sp = Sp - (sizeofW(StgUpdateFrame)+3);
216 JMP_(ENTRY_CODE(*R1.p));
220 INFO_TABLE_SRT(stg_ap_5_upd_info,stg_ap_5_upd_entry,5,0,0,0,0,THUNK,,EF_,"stg_ap_5_upd_info","stg_ap_5_upd_info");
221 FN_(stg_ap_5_upd_entry) {
223 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
224 UPD_BH_UPDATABLE(&stg_ap_5_upd_info);
226 PUSH_UPD_FRAME(R1.p,0);
227 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
228 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
229 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
230 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
231 R1.p=(P_)(R1.cl->payload[0]);
232 Sp = Sp - (sizeofW(StgUpdateFrame)+4);
233 JMP_(ENTRY_CODE(*R1.p));
237 INFO_TABLE_SRT(stg_ap_6_upd_info,stg_ap_6_upd_entry,6,0,0,0,0,THUNK,,EF_,"stg_ap_6_upd_info","stg_ap_6_upd_info");
238 FN_(stg_ap_6_upd_entry) {
240 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
241 UPD_BH_UPDATABLE(&stg_ap_6_upd_info);
243 PUSH_UPD_FRAME(R1.p,0);
244 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
245 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
246 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
247 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
248 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
249 R1.p=(P_)(R1.cl->payload[0]);
250 Sp = Sp - (sizeofW(StgUpdateFrame)+5);
251 JMP_(ENTRY_CODE(*R1.p));
255 INFO_TABLE_SRT(stg_ap_7_upd_info,stg_ap_7_upd_entry,7,0,0,0,0,THUNK,,EF_,"stg_ap_7_upd_info","stg_ap_7_upd_info");
256 FN_(stg_ap_7_upd_entry) {
258 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
259 UPD_BH_UPDATABLE(&stg_ap_7_upd_info);
261 PUSH_UPD_FRAME(R1.p,0);
262 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
263 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
264 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
265 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
266 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
267 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
268 R1.p=(P_)(R1.cl->payload[0]);
269 Sp = Sp - (sizeofW(StgUpdateFrame)+6);
270 JMP_(ENTRY_CODE(*R1.p));
274 INFO_TABLE_SRT(stg_ap_8_upd_info,stg_ap_8_upd_entry,8,0,0,0,0,THUNK,,EF_,"stg_ap_8_upd_info","stg_ap_8_upd_info");
275 FN_(stg_ap_8_upd_entry) {
277 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
278 UPD_BH_UPDATABLE(&stg_ap_8_upd_info);
280 PUSH_UPD_FRAME(R1.p,0);
281 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
282 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
283 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
284 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
285 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
286 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
287 Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
288 R1.p=(P_)(R1.cl->payload[0]);
290 JMP_(ENTRY_CODE(*R1.p));