1 /* -----------------------------------------------------------------------------
2 * $Id: StgStdThunks.hc,v 1.17 2001/11/08 12:46:31 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)
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 STK_CHK_NP(UPD_FRAME_SIZE,1,); \
60 UPD_BH_UPDATABLE(&stg_sel_##offset##_upd_info); \
61 PUSH_UPD_FRAME(R1.p,0); \
63 SAVE_CCCS(UPD_FRAME_SIZE); \
64 Sp[-UPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_upd_info; \
65 R1.p = (P_)R1.cl->payload[0]; \
66 Sp=Sp-UPD_FRAME_SIZE; \
67 JMP_(ENTRY_CODE(*R1.p)); \
81 SELECTOR_CODE_UPD(10);
82 SELECTOR_CODE_UPD(11);
83 SELECTOR_CODE_UPD(12);
84 SELECTOR_CODE_UPD(13);
85 SELECTOR_CODE_UPD(14);
86 SELECTOR_CODE_UPD(15);
88 #define SELECTOR_CODE_NOUPD(offset) \
89 IF_(stg_sel_ret_##offset##_noupd_ret); \
90 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); \
91 IF_(stg_sel_ret_##offset##_noupd_ret) { \
93 R1.p=(P_)R1.cl->payload[offset]; \
95 Sp=Sp+sizeofW(StgHeader); \
96 JMP_(ENTRY_CODE(*R1.p)); \
100 EF_(stg_sel_##offset##_noupd_entry); \
101 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");\
102 EF_(stg_sel_##offset##_noupd_entry) { \
104 STK_CHK_NP(NOUPD_FRAME_SIZE,1,) \
105 UPD_BH_SINGLE_ENTRY(&stg_sel_##offset##_noupd_info); \
107 SAVE_CCCS(NOUPD_FRAME_SIZE); \
108 Sp[-NOUPD_FRAME_SIZE]=(W_)&stg_sel_ret_##offset##_noupd_info; \
109 R1.p = (P_)R1.cl->payload[0]; \
110 Sp=Sp-NOUPD_FRAME_SIZE; \
111 JMP_(ENTRY_CODE(*R1.p)); \
115 SELECTOR_CODE_NOUPD(0);
116 SELECTOR_CODE_NOUPD(1);
117 SELECTOR_CODE_NOUPD(2);
118 SELECTOR_CODE_NOUPD(3);
119 SELECTOR_CODE_NOUPD(4);
120 SELECTOR_CODE_NOUPD(5);
121 SELECTOR_CODE_NOUPD(6);
122 SELECTOR_CODE_NOUPD(7);
123 SELECTOR_CODE_NOUPD(8);
124 SELECTOR_CODE_NOUPD(9);
125 SELECTOR_CODE_NOUPD(10);
126 SELECTOR_CODE_NOUPD(11);
127 SELECTOR_CODE_NOUPD(12);
128 SELECTOR_CODE_NOUPD(13);
129 SELECTOR_CODE_NOUPD(14);
130 SELECTOR_CODE_NOUPD(15);
132 /* -----------------------------------------------------------------------------
135 An apply thunk is a thunk of the form
137 let z = [x1...xn] \u x1...xn
140 We pre-compile some of these because the code is always the same.
142 These have to be independent of the update frame size, so the code
143 works when profiling etc.
144 -------------------------------------------------------------------------- */
146 FN_(stg_ap_1_upd_entry);
147 FN_(stg_ap_2_upd_entry);
148 FN_(stg_ap_3_upd_entry);
149 FN_(stg_ap_4_upd_entry);
150 FN_(stg_ap_5_upd_entry);
151 FN_(stg_ap_6_upd_entry);
152 FN_(stg_ap_7_upd_entry);
153 FN_(stg_ap_8_upd_entry);
155 #define UF_SIZE (sizeofW(StgUpdateFrame))
157 /* stg_ap_1_upd_info is a bit redundant, but there appears to be a bug
158 * in the compiler that means stg_ap_1 is generated occasionally (ToDo)
161 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");
162 FN_(stg_ap_1_upd_entry) {
164 STK_CHK_NP(sizeofW(StgUpdateFrame),1,);
165 UPD_BH_UPDATABLE(&stg_ap_1_upd_info);
167 PUSH_UPD_FRAME(R1.p,0);
168 R1.p=(P_)(R1.cl->payload[0]);
169 Sp = Sp - sizeofW(StgUpdateFrame);
170 JMP_(ENTRY_CODE(*R1.p));
174 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");
175 FN_(stg_ap_2_upd_entry) {
177 STK_CHK_NP(sizeofW(StgUpdateFrame)+1,1,);
178 UPD_BH_UPDATABLE(&stg_ap_2_upd_info);
180 PUSH_UPD_FRAME(R1.p,0);
181 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[1]);
182 R1.p=(P_)(R1.cl->payload[0]);
183 Sp = Sp - (sizeofW(StgUpdateFrame)+1);
184 JMP_(ENTRY_CODE(*R1.p));
188 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");
189 FN_(stg_ap_3_upd_entry) {
191 STK_CHK_NP(sizeofW(StgUpdateFrame)+2,1,);
192 UPD_BH_UPDATABLE(&stg_ap_3_upd_info);
194 PUSH_UPD_FRAME(R1.p,0);
195 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[2]);
196 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[1]);
197 R1.p=(P_)(R1.cl->payload[0]);
198 Sp = Sp - (sizeofW(StgUpdateFrame)+2);
199 JMP_(ENTRY_CODE(*R1.p));
203 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");
204 FN_(stg_ap_4_upd_entry) {
206 STK_CHK_NP(sizeofW(StgUpdateFrame)+3,1,);
207 UPD_BH_UPDATABLE(&stg_ap_4_upd_info);
209 PUSH_UPD_FRAME(R1.p,0);
210 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[3]);
211 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[2]);
212 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[1]);
213 R1.p=(P_)(R1.cl->payload[0]);
214 Sp = Sp - (sizeofW(StgUpdateFrame)+3);
215 JMP_(ENTRY_CODE(*R1.p));
219 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");
220 FN_(stg_ap_5_upd_entry) {
222 STK_CHK_NP(sizeofW(StgUpdateFrame)+4,1,);
223 UPD_BH_UPDATABLE(&stg_ap_5_upd_info);
225 PUSH_UPD_FRAME(R1.p,0);
226 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[4]);
227 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[3]);
228 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[2]);
229 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[1]);
230 R1.p=(P_)(R1.cl->payload[0]);
231 Sp = Sp - (sizeofW(StgUpdateFrame)+4);
232 JMP_(ENTRY_CODE(*R1.p));
236 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");
237 FN_(stg_ap_6_upd_entry) {
239 STK_CHK_NP(sizeofW(StgUpdateFrame)+5,1,);
240 UPD_BH_UPDATABLE(&stg_ap_6_upd_info);
242 PUSH_UPD_FRAME(R1.p,0);
243 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[5]);
244 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[4]);
245 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[3]);
246 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[2]);
247 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[1]);
248 R1.p=(P_)(R1.cl->payload[0]);
249 Sp = Sp - (sizeofW(StgUpdateFrame)+5);
250 JMP_(ENTRY_CODE(*R1.p));
254 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");
255 FN_(stg_ap_7_upd_entry) {
257 STK_CHK_NP(sizeofW(StgUpdateFrame)+6,1,);
258 UPD_BH_UPDATABLE(&stg_ap_7_upd_info);
260 PUSH_UPD_FRAME(R1.p,0);
261 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[6]);
262 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[5]);
263 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[4]);
264 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[3]);
265 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[2]);
266 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[1]);
267 R1.p=(P_)(R1.cl->payload[0]);
268 Sp = Sp - (sizeofW(StgUpdateFrame)+6);
269 JMP_(ENTRY_CODE(*R1.p));
273 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");
274 FN_(stg_ap_8_upd_entry) {
276 STK_CHK_NP(sizeofW(StgUpdateFrame)+7,1,);
277 UPD_BH_UPDATABLE(&stg_ap_8_upd_info);
279 PUSH_UPD_FRAME(R1.p,0);
280 Sp[-UF_SIZE-1]=(W_)(R1.cl->payload[7]);
281 Sp[-UF_SIZE-2]=(W_)(R1.cl->payload[6]);
282 Sp[-UF_SIZE-3]=(W_)(R1.cl->payload[5]);
283 Sp[-UF_SIZE-4]=(W_)(R1.cl->payload[4]);
284 Sp[-UF_SIZE-5]=(W_)(R1.cl->payload[3]);
285 Sp[-UF_SIZE-6]=(W_)(R1.cl->payload[2]);
286 Sp[-UF_SIZE-7]=(W_)(R1.cl->payload[1]);
287 R1.p=(P_)(R1.cl->payload[0]);
289 JMP_(ENTRY_CODE(*R1.p));