1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.8 1999/10/21 09:18:02 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Canned "Standard Form" Thunks
8 * ---------------------------------------------------------------------------*/
12 /* -----------------------------------------------------------------------------
13 The code for a thunk that simply extracts a field from a
14 single-constructor datatype depends only on the offset of the field
17 Here we define some canned "selector" thunks that do just that; any
18 selector thunk appearing in a program will refer to one of these
19 instead of being compiled independently.
21 The garbage collector spots selector thunks and reduces them if
22 possible, in order to avoid space leaks resulting from lazy pattern
24 -------------------------------------------------------------------------- */
26 #define UPD_FRAME_SIZE (sizeofW(StgUpdateFrame)+sizeofW(StgHeader))
27 #define NOUPD_FRAME_SIZE (sizeofW(StgHeader))
30 #define SAVE_CCCS(fs) CCS_HDR(Sp-fs)=CCCS
31 #define GET_SAVED_CCCS RESTORE_CCCS(CCS_HDR(Sp))
32 #define ENTER_CCS(p) ENTER_CCS_TCL(p)
35 #define SAVE_CCCS(fs) /* empty */
36 #define GET_SAVED_CCCS /* empty */
37 #define ENTER_CCS(p) /* empty */
41 #define SELECTOR_CODE_UPD(offset) \
42 EF_(__sel_ret_##offset##_upd_ret); \
43 INFO_TABLE_SRT_BITMAP(__sel_ret_##offset##_upd_info,__sel_ret_##offset##_upd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static, EF_, 0, 0); \
44 EF_(__sel_ret_##offset##_upd_ret) { \
46 R1.p=(P_)R1.cl->payload[offset]; \
48 Sp=Sp+sizeofW(StgHeader); \
49 TICK_ENT_VIA_NODE(); \
50 JMP_(ENTRY_CODE(*R1.p)); \
54 EF_(__sel_##offset##_upd_entry); \
55 INFO_TABLE_SELECTOR(__sel_##offset##_upd_info, __sel_##offset##_upd_entry, offset,, EF_, 0,0);\
56 EF_(__sel_##offset##_upd_entry) { \
59 STK_CHK_NP(UPD_FRAME_SIZE,1,); \
60 UPD_BH_UPDATABLE(R1.p); \
61 PUSH_UPD_FRAME(R1.p,0); \
63 SAVE_CCCS(UPD_FRAME_SIZE); \
64 Sp[-UPD_FRAME_SIZE]=(W_)&__sel_ret_##offset##_upd_info; \
65 R1.p = (P_)R1.cl->payload[0]; \
66 Sp=Sp-UPD_FRAME_SIZE; \
67 TICK_ENT_VIA_NODE(); \
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 INFO_TABLE_SRT_BITMAP(__sel_ret_##offset##_noupd_info, __sel_ret_##offset##_noupd_ret, RET_BITMAP, 0, 0, 0, RET_SMALL, static, EF_, 0, 0); \
91 EF_(__sel_ret_##offset##_noupd_ret) { \
93 R1.p=(P_)R1.cl->payload[offset]; \
95 Sp=Sp+sizeofW(StgHeader); \
96 TICK_ENT_VIA_NODE(); \
97 JMP_(ENTRY_CODE(*R1.p)); \
101 EF_(__sel_##offset##_noupd_entry); \
102 INFO_TABLE_SELECTOR(__sel_##offset##_noupd_info, __sel_##offset##_noupd_entry, offset,, EF_, 0,0);\
103 EF_(__sel_##offset##_noupd_entry) { \
106 STK_CHK_NP(NOUPD_FRAME_SIZE,1,) \
108 SAVE_CCCS(NOUPD_FRAME_SIZE); \
109 Sp[-NOUPD_FRAME_SIZE]=(W_)&__sel_ret_##offset##_noupd_info; \
110 R1.p = (P_)R1.cl->payload[0]; \
111 Sp=Sp-NOUPD_FRAME_SIZE; \
112 TICK_ENT_VIA_NODE(); \
113 JMP_(ENTRY_CODE(*R1.p)); \
117 SELECTOR_CODE_NOUPD(0);
118 SELECTOR_CODE_NOUPD(1);
119 SELECTOR_CODE_NOUPD(2);
120 SELECTOR_CODE_NOUPD(3);
121 SELECTOR_CODE_NOUPD(4);
122 SELECTOR_CODE_NOUPD(5);
123 SELECTOR_CODE_NOUPD(6);
124 SELECTOR_CODE_NOUPD(7);
125 SELECTOR_CODE_NOUPD(8);
126 SELECTOR_CODE_NOUPD(9);
127 SELECTOR_CODE_NOUPD(10);
128 SELECTOR_CODE_NOUPD(11);
129 SELECTOR_CODE_NOUPD(12);
130 SELECTOR_CODE_NOUPD(13);
131 SELECTOR_CODE_NOUPD(14);
132 SELECTOR_CODE_NOUPD(15);
134 /* -----------------------------------------------------------------------------
137 An apply thunk is a thunk of the form
139 let z = [x1...xn] \u x1...xn
142 We pre-compile some of these because the code is always the same.
144 These have to be independent of the update frame size, so the code
145 works when profiling etc.
146 -------------------------------------------------------------------------- */
148 FN_(__ap_1_upd_entry);
149 FN_(__ap_2_upd_entry);
150 FN_(__ap_3_upd_entry);
151 FN_(__ap_4_upd_entry);
152 FN_(__ap_5_upd_entry);
153 FN_(__ap_6_upd_entry);
154 FN_(__ap_7_upd_entry);
155 FN_(__ap_8_upd_entry);
157 #define UF_SIZE (sizeofW(StgUpdateFrame))
159 /* __ap_1_upd_info is a bit redundant, but there appears to be a bug
160 * in the compiler that means __ap_1 is generated occasionally (ToDo)
163 INFO_TABLE_SRT(__ap_1_upd_info,__ap_1_upd_entry,1,0,0,0,0,THUNK,,EF_,0,0);
164 FN_(__ap_1_upd_entry) {
167 STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
168 UPD_BH_UPDATABLE(R1.p);
170 PUSH_UPD_FRAME(R1.p,0);
171 R1.p=(P_)(R1.cl->payload[0]);
172 Sp = Sp - sizeofW(StgUpdateFrame);
174 JMP_(ENTRY_CODE(*R1.p));
178 INFO_TABLE_SRT(__ap_2_upd_info,__ap_2_upd_entry,2,0,0,0,0,THUNK,,EF_,0,0);
179 FN_(__ap_2_upd_entry) {
182 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
183 UPD_BH_UPDATABLE(R1.p);
185 PUSH_UPD_FRAME(R1.p,0);
186 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
187 R1.p=(P_)(R1.cl->payload[0]);
188 Sp = Sp - (sizeofW(StgUpdateFrame)+1);
190 JMP_(ENTRY_CODE(*R1.p));
194 INFO_TABLE_SRT(__ap_3_upd_info,__ap_3_upd_entry,3,0,0,0,0,THUNK,,EF_,0,0);
195 FN_(__ap_3_upd_entry) {
198 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
199 UPD_BH_UPDATABLE(R1.p);
201 PUSH_UPD_FRAME(R1.p,0);
202 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
203 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
204 R1.p=(P_)(R1.cl->payload[0]);
205 Sp = Sp - (sizeofW(StgUpdateFrame)+2);
207 JMP_(ENTRY_CODE(*R1.p));
211 INFO_TABLE_SRT(__ap_4_upd_info,__ap_4_upd_entry,4,0,0,0,0,THUNK,,EF_,0,0);
212 FN_(__ap_4_upd_entry) {
215 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
216 UPD_BH_UPDATABLE(R1.p);
218 PUSH_UPD_FRAME(R1.p,0);
219 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
220 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
221 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
222 R1.p=(P_)(R1.cl->payload[0]);
223 Sp = Sp - (sizeofW(StgUpdateFrame)+3);
225 JMP_(ENTRY_CODE(*R1.p));
229 INFO_TABLE_SRT(__ap_5_upd_info,__ap_5_upd_entry,5,0,0,0,0,THUNK,,EF_,0,0);
230 FN_(__ap_5_upd_entry) {
233 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
234 UPD_BH_UPDATABLE(R1.p);
236 PUSH_UPD_FRAME(R1.p,0);
237 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
238 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
239 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
240 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
241 R1.p=(P_)(R1.cl->payload[0]);
242 Sp = Sp - (sizeofW(StgUpdateFrame)+4);
244 JMP_(ENTRY_CODE(*R1.p));
248 INFO_TABLE_SRT(__ap_6_upd_info,__ap_6_upd_entry,6,0,0,0,0,THUNK,,EF_,0,0);
249 FN_(__ap_6_upd_entry) {
252 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
253 UPD_BH_UPDATABLE(R1.p);
255 PUSH_UPD_FRAME(R1.p,0);
256 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
257 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
258 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
259 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
260 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
261 R1.p=(P_)(R1.cl->payload[0]);
262 Sp = Sp - (sizeofW(StgUpdateFrame)+5);
264 JMP_(ENTRY_CODE(*R1.p));
268 INFO_TABLE_SRT(__ap_7_upd_info,__ap_7_upd_entry,7,0,0,0,0,THUNK,,EF_,0,0);
269 FN_(__ap_7_upd_entry) {
272 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
273 UPD_BH_UPDATABLE(R1.p);
275 PUSH_UPD_FRAME(R1.p,0);
276 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
277 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
278 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
279 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
280 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
281 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
282 R1.p=(P_)(R1.cl->payload[0]);
283 Sp = Sp - (sizeofW(StgUpdateFrame)+6);
285 JMP_(ENTRY_CODE(*R1.p));
289 INFO_TABLE_SRT(__ap_8_upd_info,__ap_8_upd_entry,8,0,0,0,0,THUNK,,EF_,0,0);
290 FN_(__ap_8_upd_entry) {
293 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
294 UPD_BH_UPDATABLE(R1.p);
296 PUSH_UPD_FRAME(R1.p,0);
297 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
298 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
299 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
300 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
301 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
302 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
303 Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
304 R1.p=(P_)(R1.cl->payload[0]);
307 JMP_(ENTRY_CODE(*R1.p));