1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.21 2002/12/11 15:36:54 simonmar Exp $
4 * (c) The GHC Team, 1998-2000
6 * Canned "Standard Form" Thunks
8 * ---------------------------------------------------------------------------*/
12 #include "StoragePriv.h"
14 /* -----------------------------------------------------------------------------
15 The code for a thunk that simply extracts a field from a
16 single-constructor datatype depends only on the offset of the field
19 Here we define some canned "selector" thunks that do just that; any
20 selector thunk appearing in a program will refer to one of these
21 instead of being compiled independently.
23 The garbage collector spots selector thunks and reduces them if
24 possible, in order to avoid space leaks resulting from lazy pattern
26 -------------------------------------------------------------------------- */
28 #define UPD_FRAME_SIZE (sizeofW(StgUpdateFrame)+sizeofW(StgHeader))
29 #define NOUPD_FRAME_SIZE (sizeofW(StgHeader))
32 #define SAVE_CCCS(fs) CCS_HDR(Sp-fs)=CCCS
33 #define GET_SAVED_CCCS RESTORE_CCCS(CCS_HDR(Sp))
34 #define ENTER_CCS(p) ENTER_CCS_TCL(p)
36 #define RET_FRAMESIZE 2
38 #define SAVE_CCCS(fs) /* empty */
39 #define GET_SAVED_CCCS /* empty */
40 #define ENTER_CCS(p) /* empty */
42 #define RET_FRAMESIZE 0
45 #define SELECTOR_CODE_UPD(offset) \
46 IF_(stg_sel_ret_##offset##_upd_ret); \
47 INFO_TABLE_RET(stg_sel_ret_##offset##_upd_info,stg_sel_ret_##offset##_upd_ret, MK_SMALL_BITMAP(RET_FRAMESIZE, RET_BITMAP), 0, 0, 0, RET_SMALL, static, EF_, 0, 0); \
48 EF_(stg_sel_ret_##offset##_upd_ret) { \
50 R1.p=(P_)R1.cl->payload[offset]; \
52 Sp=Sp+sizeofW(StgHeader); \
57 EF_(stg_sel_##offset##_upd_entry); \
58 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");\
59 EF_(stg_sel_##offset##_upd_entry) { \
61 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */ \
62 STK_CHK_NP(UPD_FRAME_SIZE,); \
63 UPD_BH_UPDATABLE(&stg_sel_##offset##_upd_info); \
65 PUSH_UPD_FRAME(R1.p,0); \
67 SAVE_CCCS(UPD_FRAME_SIZE); \
68 Sp[-UPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_upd_info; \
69 R1.p = (P_)R1.cl->payload[0]; \
70 Sp=Sp-UPD_FRAME_SIZE; \
85 SELECTOR_CODE_UPD(10);
86 SELECTOR_CODE_UPD(11);
87 SELECTOR_CODE_UPD(12);
88 SELECTOR_CODE_UPD(13);
89 SELECTOR_CODE_UPD(14);
90 SELECTOR_CODE_UPD(15);
92 #define SELECTOR_CODE_NOUPD(offset) \
93 IF_(stg_sel_ret_##offset##_noupd_ret); \
94 INFO_TABLE_RET(stg_sel_ret_##offset##_noupd_info, stg_sel_ret_##offset##_noupd_ret, MK_SMALL_BITMAP(RET_FRAMESIZE, RET_BITMAP), 0, 0, 0, RET_SMALL, static, EF_, 0, 0); \
95 IF_(stg_sel_ret_##offset##_noupd_ret) { \
97 R1.p=(P_)R1.cl->payload[offset]; \
99 Sp=Sp+sizeofW(StgHeader); \
100 JMP_(ENTRY_CODE(*R1.p)); \
104 EF_(stg_sel_##offset##_noupd_entry); \
105 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");\
106 EF_(stg_sel_##offset##_noupd_entry) { \
108 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */ \
109 STK_CHK_NP(NOUPD_FRAME_SIZE,) \
110 UPD_BH_SINGLE_ENTRY(&stg_sel_##offset##_noupd_info); \
112 TICK_UPDF_OMITTED(); \
114 SAVE_CCCS(NOUPD_FRAME_SIZE); \
115 Sp[-NOUPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_noupd_info; \
116 R1.p = (P_)R1.cl->payload[0]; \
117 Sp=Sp-NOUPD_FRAME_SIZE; \
118 JMP_(ENTRY_CODE(*R1.p)); \
122 SELECTOR_CODE_NOUPD(0);
123 SELECTOR_CODE_NOUPD(1);
124 SELECTOR_CODE_NOUPD(2);
125 SELECTOR_CODE_NOUPD(3);
126 SELECTOR_CODE_NOUPD(4);
127 SELECTOR_CODE_NOUPD(5);
128 SELECTOR_CODE_NOUPD(6);
129 SELECTOR_CODE_NOUPD(7);
130 SELECTOR_CODE_NOUPD(8);
131 SELECTOR_CODE_NOUPD(9);
132 SELECTOR_CODE_NOUPD(10);
133 SELECTOR_CODE_NOUPD(11);
134 SELECTOR_CODE_NOUPD(12);
135 SELECTOR_CODE_NOUPD(13);
136 SELECTOR_CODE_NOUPD(14);
137 SELECTOR_CODE_NOUPD(15);
139 /* -----------------------------------------------------------------------------
142 An apply thunk is a thunk of the form
144 let z = [x1...xn] \u x1...xn
147 We pre-compile some of these because the code is always the same.
149 These have to be independent of the update frame size, so the code
150 works when profiling etc.
151 -------------------------------------------------------------------------- */
153 FN_(stg_ap_1_upd_entry);
154 FN_(stg_ap_2_upd_entry);
155 FN_(stg_ap_3_upd_entry);
156 FN_(stg_ap_4_upd_entry);
157 FN_(stg_ap_5_upd_entry);
158 FN_(stg_ap_6_upd_entry);
159 FN_(stg_ap_7_upd_entry);
160 FN_(stg_ap_8_upd_entry);
162 #define UF_SIZE (sizeofW(StgUpdateFrame))
164 /* stg_ap_1_upd_info is a bit redundant, but there appears to be a bug
165 * in the compiler that means stg_ap_1 is generated occasionally (ToDo)
168 INFO_TABLE_THUNK(stg_ap_1_upd_info,stg_ap_1_upd_entry,1,1,0,0,0,THUNK_1_0,,EF_,"stg_ap_1_upd_info","stg_ap_1_upd_info");
169 FN_(stg_ap_1_upd_entry) {
171 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
172 STK_CHK_NP(sizeofW(StgUpdateFrame),);
173 UPD_BH_UPDATABLE(&stg_ap_1_upd_info);
176 PUSH_UPD_FRAME(R1.p,0);
177 R1.p=(P_)(R1.cl->payload[0]);
178 Sp -= sizeofW(StgUpdateFrame);
179 Sp--; // for stg_ap_0_ret
184 INFO_TABLE_THUNK(stg_ap_2_upd_info,stg_ap_2_upd_entry,2,0,0,0,0,THUNK_2_0,,EF_,"stg_ap_2_upd_info","stg_ap_2_upd_info");
185 FN_(stg_ap_2_upd_entry) {
187 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
188 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,);
189 UPD_BH_UPDATABLE(&stg_ap_2_upd_info);
192 PUSH_UPD_FRAME(R1.p,0);
193 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
194 R1.p=(P_)(R1.cl->payload[0]);
195 Sp -= sizeofW(StgUpdateFrame)+1;
196 Sp--; // for stg_ap_1_ret
201 INFO_TABLE_THUNK(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");
202 FN_(stg_ap_3_upd_entry) {
204 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
205 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,);
206 UPD_BH_UPDATABLE(&stg_ap_3_upd_info);
209 PUSH_UPD_FRAME(R1.p,0);
210 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
211 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
212 R1.p=(P_)(R1.cl->payload[0]);
213 Sp -= sizeofW(StgUpdateFrame)+2;
214 Sp--; // for stg_ap_pp_ret
219 INFO_TABLE_THUNK(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");
220 FN_(stg_ap_4_upd_entry) {
222 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
223 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,);
224 UPD_BH_UPDATABLE(&stg_ap_4_upd_info);
227 PUSH_UPD_FRAME(R1.p,0);
228 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
229 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
230 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
231 R1.p=(P_)(R1.cl->payload[0]);
232 Sp = Sp - (sizeofW(StgUpdateFrame)+3);
233 Sp--; // for stg_ap_ppp_ret
234 JMP_(stg_ap_ppp_ret);
238 INFO_TABLE_THUNK(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");
239 FN_(stg_ap_5_upd_entry) {
241 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
242 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,);
243 UPD_BH_UPDATABLE(&stg_ap_5_upd_info);
246 PUSH_UPD_FRAME(R1.p,0);
247 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
248 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
249 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
250 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
251 R1.p=(P_)(R1.cl->payload[0]);
252 Sp = Sp - (sizeofW(StgUpdateFrame)+4);
253 Sp--; // for stg_ap_pppp_ret
254 JMP_(stg_ap_pppp_ret);
258 INFO_TABLE_THUNK(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");
259 FN_(stg_ap_6_upd_entry) {
261 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
262 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,);
263 UPD_BH_UPDATABLE(&stg_ap_6_upd_info);
266 PUSH_UPD_FRAME(R1.p,0);
267 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
268 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
269 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
270 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
271 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
272 R1.p=(P_)(R1.cl->payload[0]);
273 Sp = Sp - (sizeofW(StgUpdateFrame)+5);
274 Sp--; // for stg_ap_ppppp_ret
275 JMP_(stg_ap_ppppp_ret);
279 INFO_TABLE_THUNK(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");
280 FN_(stg_ap_7_upd_entry) {
282 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
283 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,);
284 UPD_BH_UPDATABLE(&stg_ap_7_upd_info);
287 PUSH_UPD_FRAME(R1.p,0);
288 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
289 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
290 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
291 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
292 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
293 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
294 R1.p=(P_)(R1.cl->payload[0]);
295 Sp = Sp - (sizeofW(StgUpdateFrame)+6);
296 Sp--; // for stg_ap_pppppp_ret
297 JMP_(stg_ap_pppppp_ret);
301 INFO_TABLE_THUNK(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");
302 FN_(stg_ap_8_upd_entry) {
304 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
305 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,);
306 UPD_BH_UPDATABLE(&stg_ap_8_upd_info);
309 PUSH_UPD_FRAME(R1.p,0);
310 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
311 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
312 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
313 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
314 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
315 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
316 Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
317 R1.p=(P_)(R1.cl->payload[0]);
318 Sp = Sp - (sizeofW(StgUpdateFrame)+7);
319 Sp--; // for stg_ap_ppppppp_ret
320 JMP_(stg_ap_ppppppp_ret);