1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.20 2002/03/01 18:28:15 keithw 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)
37 #define SAVE_CCCS(fs) /* empty */
38 #define GET_SAVED_CCCS /* empty */
39 #define ENTER_CCS(p) /* empty */
43 #define SELECTOR_CODE_UPD(offset) \
44 IF_(stg_sel_ret_##offset##_upd_ret); \
45 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); \
46 EF_(stg_sel_ret_##offset##_upd_ret) { \
48 R1.p=(P_)R1.cl->payload[offset]; \
50 Sp=Sp+sizeofW(StgHeader); \
51 JMP_(ENTRY_CODE(*R1.p)); \
55 EF_(stg_sel_##offset##_upd_entry); \
56 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");\
57 EF_(stg_sel_##offset##_upd_entry) { \
59 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */ \
60 STK_CHK_NP(UPD_FRAME_SIZE,1,); \
61 UPD_BH_UPDATABLE(&stg_sel_##offset##_upd_info); \
63 PUSH_UPD_FRAME(R1.p,0); \
65 SAVE_CCCS(UPD_FRAME_SIZE); \
66 Sp[-UPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_upd_info; \
67 R1.p = (P_)R1.cl->payload[0]; \
68 Sp=Sp-UPD_FRAME_SIZE; \
69 JMP_(ENTRY_CODE(*R1.p)); \
83 SELECTOR_CODE_UPD(10);
84 SELECTOR_CODE_UPD(11);
85 SELECTOR_CODE_UPD(12);
86 SELECTOR_CODE_UPD(13);
87 SELECTOR_CODE_UPD(14);
88 SELECTOR_CODE_UPD(15);
90 #define SELECTOR_CODE_NOUPD(offset) \
91 IF_(stg_sel_ret_##offset##_noupd_ret); \
92 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); \
93 IF_(stg_sel_ret_##offset##_noupd_ret) { \
95 R1.p=(P_)R1.cl->payload[offset]; \
97 Sp=Sp+sizeofW(StgHeader); \
98 JMP_(ENTRY_CODE(*R1.p)); \
102 EF_(stg_sel_##offset##_noupd_entry); \
103 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");\
104 EF_(stg_sel_##offset##_noupd_entry) { \
106 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */ \
107 STK_CHK_NP(NOUPD_FRAME_SIZE,1,) \
108 UPD_BH_SINGLE_ENTRY(&stg_sel_##offset##_noupd_info); \
110 TICK_UPDF_OMITTED(); \
112 SAVE_CCCS(NOUPD_FRAME_SIZE); \
113 Sp[-NOUPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_noupd_info; \
114 R1.p = (P_)R1.cl->payload[0]; \
115 Sp=Sp-NOUPD_FRAME_SIZE; \
116 JMP_(ENTRY_CODE(*R1.p)); \
120 SELECTOR_CODE_NOUPD(0);
121 SELECTOR_CODE_NOUPD(1);
122 SELECTOR_CODE_NOUPD(2);
123 SELECTOR_CODE_NOUPD(3);
124 SELECTOR_CODE_NOUPD(4);
125 SELECTOR_CODE_NOUPD(5);
126 SELECTOR_CODE_NOUPD(6);
127 SELECTOR_CODE_NOUPD(7);
128 SELECTOR_CODE_NOUPD(8);
129 SELECTOR_CODE_NOUPD(9);
130 SELECTOR_CODE_NOUPD(10);
131 SELECTOR_CODE_NOUPD(11);
132 SELECTOR_CODE_NOUPD(12);
133 SELECTOR_CODE_NOUPD(13);
134 SELECTOR_CODE_NOUPD(14);
135 SELECTOR_CODE_NOUPD(15);
137 /* -----------------------------------------------------------------------------
140 An apply thunk is a thunk of the form
142 let z = [x1...xn] \u x1...xn
145 We pre-compile some of these because the code is always the same.
147 These have to be independent of the update frame size, so the code
148 works when profiling etc.
149 -------------------------------------------------------------------------- */
151 FN_(stg_ap_1_upd_entry);
152 FN_(stg_ap_2_upd_entry);
153 FN_(stg_ap_3_upd_entry);
154 FN_(stg_ap_4_upd_entry);
155 FN_(stg_ap_5_upd_entry);
156 FN_(stg_ap_6_upd_entry);
157 FN_(stg_ap_7_upd_entry);
158 FN_(stg_ap_8_upd_entry);
160 #define UF_SIZE (sizeofW(StgUpdateFrame))
162 /* stg_ap_1_upd_info is a bit redundant, but there appears to be a bug
163 * in the compiler that means stg_ap_1 is generated occasionally (ToDo)
166 INFO_TABLE_SRT(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");
167 FN_(stg_ap_1_upd_entry) {
169 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
170 STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
171 UPD_BH_UPDATABLE(&stg_ap_1_upd_info);
174 PUSH_UPD_FRAME(R1.p,0);
175 R1.p=(P_)(R1.cl->payload[0]);
176 Sp = Sp - sizeofW(StgUpdateFrame);
177 JMP_(ENTRY_CODE(*R1.p));
181 INFO_TABLE_SRT(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");
182 FN_(stg_ap_2_upd_entry) {
184 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
185 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
186 UPD_BH_UPDATABLE(&stg_ap_2_upd_info);
189 PUSH_UPD_FRAME(R1.p,0);
190 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
191 R1.p=(P_)(R1.cl->payload[0]);
192 Sp = Sp - (sizeofW(StgUpdateFrame)+1);
193 JMP_(ENTRY_CODE(*R1.p));
197 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");
198 FN_(stg_ap_3_upd_entry) {
200 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
201 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
202 UPD_BH_UPDATABLE(&stg_ap_3_upd_info);
205 PUSH_UPD_FRAME(R1.p,0);
206 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
207 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
208 R1.p=(P_)(R1.cl->payload[0]);
209 Sp = Sp - (sizeofW(StgUpdateFrame)+2);
210 JMP_(ENTRY_CODE(*R1.p));
214 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");
215 FN_(stg_ap_4_upd_entry) {
217 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
218 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
219 UPD_BH_UPDATABLE(&stg_ap_4_upd_info);
222 PUSH_UPD_FRAME(R1.p,0);
223 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
224 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
225 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
226 R1.p=(P_)(R1.cl->payload[0]);
227 Sp = Sp - (sizeofW(StgUpdateFrame)+3);
228 JMP_(ENTRY_CODE(*R1.p));
232 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");
233 FN_(stg_ap_5_upd_entry) {
235 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
236 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
237 UPD_BH_UPDATABLE(&stg_ap_5_upd_info);
240 PUSH_UPD_FRAME(R1.p,0);
241 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
242 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
243 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
244 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
245 R1.p=(P_)(R1.cl->payload[0]);
246 Sp = Sp - (sizeofW(StgUpdateFrame)+4);
247 JMP_(ENTRY_CODE(*R1.p));
251 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");
252 FN_(stg_ap_6_upd_entry) {
254 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
255 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
256 UPD_BH_UPDATABLE(&stg_ap_6_upd_info);
259 PUSH_UPD_FRAME(R1.p,0);
260 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
261 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
262 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
263 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
264 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
265 R1.p=(P_)(R1.cl->payload[0]);
266 Sp = Sp - (sizeofW(StgUpdateFrame)+5);
267 JMP_(ENTRY_CODE(*R1.p));
271 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");
272 FN_(stg_ap_7_upd_entry) {
274 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
275 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
276 UPD_BH_UPDATABLE(&stg_ap_7_upd_info);
279 PUSH_UPD_FRAME(R1.p,0);
280 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
281 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
282 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
283 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
284 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
285 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
286 R1.p=(P_)(R1.cl->payload[0]);
287 Sp = Sp - (sizeofW(StgUpdateFrame)+6);
288 JMP_(ENTRY_CODE(*R1.p));
292 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");
293 FN_(stg_ap_8_upd_entry) {
295 TICK_ENT_DYN_THK(); /* is it static or dynamic?? */
296 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
297 UPD_BH_UPDATABLE(&stg_ap_8_upd_info);
300 PUSH_UPD_FRAME(R1.p,0);
301 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
302 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
303 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
304 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
305 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
306 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
307 Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
308 R1.p=(P_)(R1.cl->payload[0]);
310 JMP_(ENTRY_CODE(*R1.p));