1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.3 1999/01/13 17:25:46 simonm Exp $
4 * Entry code for various built-in closure types.
6 * ---------------------------------------------------------------------------*/
10 #include "StgMiscClosures.h"
11 #include "HeapStackCheck.h" /* for stg_gen_yield */
17 /* -----------------------------------------------------------------------------
18 Entry code for an indirection.
20 This code assumes R1 is in a register for now.
21 -------------------------------------------------------------------------- */
23 INFO_TABLE(IND_info,IND_entry,1,0,IND,const,EF_,0,0);
27 TICK_ENT_IND(Node); /* tick */
29 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
35 INFO_TABLE(IND_STATIC_info,IND_STATIC_entry,1,0,IND_STATIC,const,EF_,0,0);
36 STGFUN(IND_STATIC_entry)
39 TICK_ENT_IND(Node); /* tick */
41 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
47 INFO_TABLE(IND_PERM_info,IND_PERM_entry,1,0,IND_PERM,const,EF_,0,0);
48 STGFUN(IND_PERM_entry)
51 /* Don't add INDs to granularity cost */
53 /* Dont: ENT_IND(Node); for ticky-ticky; this ind is here only to help profi
56 /* Enter PAP cost centre -- lexical scoping only */
57 ENTER_CCS_PAP_CL(R1.cl);
59 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
61 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
67 INFO_TABLE(IND_OLDGEN_info,IND_OLDGEN_entry,1,1,IND_OLDGEN,const,EF_,0,0);
68 STGFUN(IND_OLDGEN_entry)
71 TICK_ENT_IND(Node); /* tick */
73 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
79 INFO_TABLE(IND_OLDGEN_PERM_info,IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,const,EF_,0,0);
80 STGFUN(IND_OLDGEN_PERM_entry)
83 TICK_ENT_IND(Node); /* tick */
85 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
91 /* -----------------------------------------------------------------------------
94 This code assumes R1 is in a register for now.
95 -------------------------------------------------------------------------- */
97 INFO_TABLE(CAF_UNENTERED_info,CAF_UNENTERED_entry,1,2,CAF_UNENTERED,const,EF_,0,0);
98 STGFUN(CAF_UNENTERED_entry)
101 /* ToDo: implement directly in GHC */
104 JMP_(stg_yield_to_Hugs);
108 INFO_TABLE(CAF_ENTERED_info,CAF_ENTERED_entry,2,1,CAF_ENTERED,const,EF_,0,0);
109 STGFUN(CAF_ENTERED_entry)
112 TICK_ENT_CAF_ENTERED(Node); /* tick */
114 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
116 JMP_(GET_ENTRY(R1.cl));
120 /* -----------------------------------------------------------------------------
121 Entry code for a black hole.
123 Entering a black hole normally causes a cyclic data dependency, but
124 in the concurrent world, black holes are synchronization points,
125 and they are turned into blocking queues when there are threads
126 waiting for the evaluation of the closure to finish.
127 -------------------------------------------------------------------------- */
129 /* Note: a black hole must be big enough to be overwritten with an
130 * indirection/evacuee/catch. Thus we claim it has 1 non-pointer word of
131 * payload (in addition to the pointer word for the blocking queue), which
132 * should be big enough for an old-generation indirection.
135 INFO_TABLE(BLACKHOLE_info, BLACKHOLE_entry,1,1,BLACKHOLE,const,EF_,0,0);
136 STGFUN(BLACKHOLE_entry)
139 /* Put ourselves on the blocking queue for this black hole */
140 CurrentTSO->link = ((StgBlackHole *)R1.p)->blocking_queue;
141 ((StgBlackHole *)R1.p)->blocking_queue = CurrentTSO;
143 /* stg_gen_block is too heavyweight, use a specialised one */
148 /* identical to BLACKHOLEs except for the infotag */
149 INFO_TABLE(CAF_BLACKHOLE_info, CAF_BLACKHOLE_entry,1,1,CAF_BLACKHOLE,const,EF_,0,0);
150 STGFUN(CAF_BLACKHOLE_entry)
153 /* Put ourselves on the blocking queue for this black hole */
154 CurrentTSO->link = ((StgBlackHole *)R1.p)->blocking_queue;
155 ((StgBlackHole *)R1.p)->blocking_queue = CurrentTSO;
157 /* stg_gen_block is too heavyweight, use a specialised one */
162 /* -----------------------------------------------------------------------------
163 The code for a BCO returns to the scheduler
164 -------------------------------------------------------------------------- */
165 INFO_TABLE(BCO_info,BCO_entry,0,0,BCO,const,EF_,0,0);
170 JMP_(stg_yield_to_Hugs);
174 /* -----------------------------------------------------------------------------
175 Some static info tables for things that don't get entered, and
176 therefore don't need entry code (i.e. boxed but unpointed objects)
177 -------------------------------------------------------------------------- */
179 #define NON_ENTERABLE_ENTRY_CODE(type) \
180 STGFUN(type##_entry) \
183 STGCALL1(fflush,stdout); \
184 STGCALL2(fprintf,stderr,#type " object entered!\n"); \
185 STGCALL1(raiseError, errorHandler); \
186 stg_exit(EXIT_FAILURE); /* not executed */ \
190 INFO_TABLE(TSO_info, TSO_entry, 0,0,TSO,const,EF_,0,0);
191 NON_ENTERABLE_ENTRY_CODE(TSO);
193 /* -----------------------------------------------------------------------------
194 Evacuees are left behind by the garbage collector. Any attempt to enter
196 -------------------------------------------------------------------------- */
198 INFO_TABLE(EVACUATED_info,EVACUATED_entry,1,0,EVACUATED,const,EF_,0,0);
199 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
201 /* -----------------------------------------------------------------------------
204 Live weak pointers have a special closure type. Dead ones are just
205 nullary constructors (although they live on the heap - we overwrite
206 live weak pointers with dead ones).
207 -------------------------------------------------------------------------- */
209 INFO_TABLE(WEAK_info,WEAK_entry,0,4,WEAK,const,EF_,0,0);
210 NON_ENTERABLE_ENTRY_CODE(WEAK);
212 INFO_TABLE_CONSTR(DEAD_WEAK_info,DEAD_WEAK_entry,0,1,0,CONSTR,const,EF_,0,0);
213 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
215 /* -----------------------------------------------------------------------------
216 Foreign Objects are unlifted and therefore never entered.
217 -------------------------------------------------------------------------- */
219 INFO_TABLE(FOREIGN_info,FOREIGN_entry,0,1,FOREIGN,const,EF_,0,0);
220 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
222 /* -----------------------------------------------------------------------------
225 There are two kinds of these: full and empty. We need an info table
226 and entry code for each type.
227 -------------------------------------------------------------------------- */
229 INFO_TABLE(FULL_MVAR_info,FULL_MVAR_entry,4,0,MVAR,const,EF_,0,0);
230 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
232 INFO_TABLE(EMPTY_MVAR_info,EMPTY_MVAR_entry,4,0,MVAR,const,EF_,0,0);
233 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
235 /* -----------------------------------------------------------------------------
238 This is a static nullary constructor (like []) that we use to mark the
239 end of a linked TSO queue.
240 -------------------------------------------------------------------------- */
242 INFO_TABLE_CONSTR(END_TSO_QUEUE_info,END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
243 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
245 SET_STATIC_HDR(END_TSO_QUEUE_closure,END_TSO_QUEUE_info,0/*CC*/,const,EI_)
248 /* -----------------------------------------------------------------------------
251 Mutable lists (used by the garbage collector) consist of a chain of
252 StgMutClosures connected through their mut_link fields, ending in
253 an END_MUT_LIST closure.
254 -------------------------------------------------------------------------- */
256 INFO_TABLE_CONSTR(END_MUT_LIST_info,END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
257 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
259 SET_STATIC_HDR(END_MUT_LIST_closure,END_MUT_LIST_info,0/*CC*/,const,EI_)
262 INFO_TABLE(MUT_CONS_info, MUT_CONS_entry, 1, 1, MUT_VAR, const, EF_, 0, 0);
263 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
265 /* -----------------------------------------------------------------------------
268 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
269 pointers (StgArrPtrs). They all have a similar layout:
271 ___________________________
272 | Info | No. of | data....
274 ---------------------------
276 These are *unpointed* objects: i.e. they cannot be entered.
278 -------------------------------------------------------------------------- */
280 #define ArrayInfo(type) \
281 INFO_TABLE(type##_info, type##_entry, 0, 0, type, const, EF_,0,0); \
282 NON_ENTERABLE_ENTRY_CODE(type);
284 ArrayInfo(ARR_WORDS);
285 ArrayInfo(MUT_ARR_WORDS);
286 ArrayInfo(MUT_ARR_PTRS);
287 ArrayInfo(MUT_ARR_PTRS_FROZEN);
291 /* -----------------------------------------------------------------------------
293 -------------------------------------------------------------------------- */
295 INFO_TABLE(MUT_VAR_info, MUT_VAR_entry, 1, 1, MUT_VAR, const, EF_, 0, 0);
296 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
298 /* -----------------------------------------------------------------------------
299 Standard Error Entry.
301 This is used for filling in vector-table entries that can never happen,
303 -------------------------------------------------------------------------- */
305 STGFUN(stg_error_entry) \
308 STGCALL1(fflush,stdout); \
309 STGCALL2(fprintf,stderr,"fatal: stg_error_entry"); \
310 STGCALL1(raiseError, errorHandler); \
311 exit(EXIT_FAILURE); /* not executed */ \
315 /* -----------------------------------------------------------------------------
318 Entering this closure will just return to the address on the top of the
319 stack. Useful for getting a thread in a canonical form where we can
320 just enter the top stack word to start the thread. (see deleteThread)
321 * -------------------------------------------------------------------------- */
323 INFO_TABLE(dummy_ret_info, dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, const, EF_, 0, 0);
330 JMP_(ENTRY_CODE(ret_addr));
332 SET_STATIC_HDR(dummy_ret_closure,dummy_ret_info,CCS_DONTZuCARE,const,EI_)
335 /* -----------------------------------------------------------------------------
336 Standard Infotables (for use in interpreter)
337 -------------------------------------------------------------------------- */
341 STGFUN(Hugs_CONSTR_entry)
344 ((StgPtr*)Sp)[0] = R1.p;
345 /* vectored: JMP_(RET_VEC(((StgPtr*)Sp)[1],constrTag(?))); */
346 JMP_(ENTRY_CODE(((StgPtr*)Sp)[1]));
349 #define RET_BCO_ENTRY_TEMPLATE(label) \
354 ((StgPtr*)Sp)[0] = R1.p; \
355 JMP_(stg_yield_to_Hugs); \
359 RET_BCO_ENTRY_TEMPLATE(ret_bco_entry );
360 RET_BCO_ENTRY_TEMPLATE(ret_bco_0_entry);
361 RET_BCO_ENTRY_TEMPLATE(ret_bco_1_entry);
362 RET_BCO_ENTRY_TEMPLATE(ret_bco_2_entry);
363 RET_BCO_ENTRY_TEMPLATE(ret_bco_3_entry);
364 RET_BCO_ENTRY_TEMPLATE(ret_bco_4_entry);
365 RET_BCO_ENTRY_TEMPLATE(ret_bco_5_entry);
366 RET_BCO_ENTRY_TEMPLATE(ret_bco_6_entry);
367 RET_BCO_ENTRY_TEMPLATE(ret_bco_7_entry);
369 VEC_POLY_INFO_TABLE(ret_bco,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO);
371 #endif /* INTERPRETER */
375 INFO_TABLE_CONSTR(CZh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgChar),0,CONSTR,const,EF_,0,0);
376 INFO_TABLE_CONSTR(IZh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgInt),0,CONSTR,const,EF_,0,0);
377 INFO_TABLE_CONSTR(I64Zh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgInt64),0,CONSTR,const,EF_,0,0);
378 INFO_TABLE_CONSTR(FZh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgFloat),0,CONSTR,const,EF_,0,0);
379 INFO_TABLE_CONSTR(DZh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgDouble),0,CONSTR,const,EF_,0,0);
380 INFO_TABLE_CONSTR(AZh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgAddr),0,CONSTR,const,EF_,0,0);
381 INFO_TABLE_CONSTR(WZh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgWord),0,CONSTR,const,EF_,0,0);
382 INFO_TABLE_CONSTR(StablePtr_con_info,Hugs_CONSTR_entry,0,sizeofW(StgStablePtr),0,CONSTR,const,EF_,0,0);
384 /* These might seem redundant but {I,C}Zh_static_info are used in
385 * {INT,CHAR}LIKE and the rest are used in RtsAPI.c
387 INFO_TABLE_CONSTR(CZh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgChar),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
388 INFO_TABLE_CONSTR(IZh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgInt),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
389 INFO_TABLE_CONSTR(I64Zh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgInt64),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
390 INFO_TABLE_CONSTR(FZh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgFloat),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
391 INFO_TABLE_CONSTR(DZh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgDouble),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
392 INFO_TABLE_CONSTR(AZh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgAddr),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
393 INFO_TABLE_CONSTR(WZh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgWord),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
394 INFO_TABLE_CONSTR(StablePtr_static_info,Hugs_CONSTR_entry,0,sizeofW(StgStablePtr),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
396 #endif /* !defined(COMPILER) */
398 /* -----------------------------------------------------------------------------
399 CHARLIKE and INTLIKE closures.
401 These are static representations of Chars and small Ints, so that
402 we can remove dynamic Chars and Ints during garbage collection and
403 replace them with references to the static objects.
404 -------------------------------------------------------------------------- */
406 #define CHARLIKE_HDR(n) \
408 STATIC_HDR(CZh_static_info, /* C# */ \
413 #define INTLIKE_HDR(n) \
415 STATIC_HDR(IZh_static_info, /* I# */ \
420 /* put these in the *data* section, since the garbage collector relies
421 * on the fact that static closures live in the data section.
424 /* end the name with _closure, to convince the mangler this is a closure */
426 StgIntCharlikeClosure CHARLIKE_closure[] = {
685 StgIntCharlikeClosure INTLIKE_closure[] = {
686 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
718 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */