1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.14 1999/02/11 14:22:54 simonm Exp $
4 * (c) The GHC Team, 1998-1999
6 * Entry code for various built-in closure types.
8 * ---------------------------------------------------------------------------*/
12 #include "StgMiscClosures.h"
13 #include "HeapStackCheck.h" /* for stg_gen_yield */
15 #include "StoragePriv.h"
21 /* -----------------------------------------------------------------------------
22 Entry code for an indirection.
24 This code assumes R1 is in a register for now.
25 -------------------------------------------------------------------------- */
27 INFO_TABLE(IND_info,IND_entry,1,0,IND,const,EF_,0,0);
31 TICK_ENT_IND(Node); /* tick */
33 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
39 INFO_TABLE(IND_STATIC_info,IND_STATIC_entry,1,0,IND_STATIC,const,EF_,0,0);
40 STGFUN(IND_STATIC_entry)
43 TICK_ENT_IND(Node); /* tick */
45 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
51 INFO_TABLE(IND_PERM_info,IND_PERM_entry,1,0,IND_PERM,const,EF_,0,0);
52 STGFUN(IND_PERM_entry)
55 /* Don't add INDs to granularity cost */
57 /* Dont: ENT_IND(Node); for ticky-ticky; this ind is here only to help profi
60 /* Enter PAP cost centre -- lexical scoping only */
61 ENTER_CCS_PAP_CL(R1.cl);
63 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
65 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
71 INFO_TABLE(IND_OLDGEN_info,IND_OLDGEN_entry,1,1,IND_OLDGEN,const,EF_,0,0);
72 STGFUN(IND_OLDGEN_entry)
75 TICK_ENT_IND(Node); /* tick */
77 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
83 INFO_TABLE(IND_OLDGEN_PERM_info,IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,const,EF_,0,0);
84 STGFUN(IND_OLDGEN_PERM_entry)
87 TICK_ENT_IND(Node); /* tick */
89 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
95 /* -----------------------------------------------------------------------------
98 This code assumes R1 is in a register for now.
99 -------------------------------------------------------------------------- */
101 INFO_TABLE(CAF_UNENTERED_info,CAF_UNENTERED_entry,1,2,CAF_UNENTERED,const,EF_,0,0);
102 STGFUN(CAF_UNENTERED_entry)
105 /* ToDo: implement directly in GHC */
108 JMP_(stg_yield_to_Hugs);
112 INFO_TABLE(CAF_ENTERED_info,CAF_ENTERED_entry,2,1,CAF_ENTERED,const,EF_,0,0);
113 STGFUN(CAF_ENTERED_entry)
116 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
118 JMP_(GET_ENTRY(R1.cl));
122 /* -----------------------------------------------------------------------------
123 Entry code for a black hole.
125 Entering a black hole normally causes a cyclic data dependency, but
126 in the concurrent world, black holes are synchronization points,
127 and they are turned into blocking queues when there are threads
128 waiting for the evaluation of the closure to finish.
129 -------------------------------------------------------------------------- */
131 /* Note: a black hole must be big enough to be overwritten with an
132 * indirection/evacuee/catch. Thus we claim it has 1 non-pointer word of
133 * payload (in addition to the pointer word for the blocking queue), which
134 * should be big enough for an old-generation indirection.
137 INFO_TABLE(BLACKHOLE_info, BLACKHOLE_entry,0,2,BLACKHOLE,const,EF_,0,0);
138 STGFUN(BLACKHOLE_entry)
143 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
144 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
145 /* Put ourselves on the blocking queue for this black hole */
146 CurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
147 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
148 recordMutable((StgMutClosure *)R1.cl);
150 /* stg_gen_block is too heavyweight, use a specialised one */
155 INFO_TABLE(BLACKHOLE_BQ_info, BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,const,EF_,0,0);
156 STGFUN(BLACKHOLE_BQ_entry)
161 /* Put ourselves on the blocking queue for this black hole */
162 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
163 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
165 /* stg_gen_block is too heavyweight, use a specialised one */
170 /* identical to BLACKHOLEs except for the infotag */
171 INFO_TABLE(CAF_BLACKHOLE_info, CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,const,EF_,0,0);
172 STGFUN(CAF_BLACKHOLE_entry)
177 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
178 ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info;
179 /* Put ourselves on the blocking queue for this black hole */
180 CurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
181 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
182 recordMutable((StgMutClosure *)R1.cl);
184 /* stg_gen_block is too heavyweight, use a specialised one */
189 /* -----------------------------------------------------------------------------
190 The code for a BCO returns to the scheduler
191 -------------------------------------------------------------------------- */
192 INFO_TABLE(BCO_info,BCO_entry,0,0,BCO,const,EF_,0,0);
197 JMP_(stg_yield_to_Hugs);
201 /* -----------------------------------------------------------------------------
202 Some static info tables for things that don't get entered, and
203 therefore don't need entry code (i.e. boxed but unpointed objects)
204 -------------------------------------------------------------------------- */
206 #define NON_ENTERABLE_ENTRY_CODE(type) \
207 STGFUN(type##_entry) \
210 STGCALL1(fflush,stdout); \
211 STGCALL2(fprintf,stderr,#type " object entered!\n"); \
212 STGCALL1(raiseError, errorHandler); \
213 stg_exit(EXIT_FAILURE); /* not executed */ \
217 INFO_TABLE(TSO_info, TSO_entry, 0,0,TSO,const,EF_,0,0);
218 NON_ENTERABLE_ENTRY_CODE(TSO);
220 /* -----------------------------------------------------------------------------
221 Evacuees are left behind by the garbage collector. Any attempt to enter
223 -------------------------------------------------------------------------- */
225 INFO_TABLE(EVACUATED_info,EVACUATED_entry,1,0,EVACUATED,const,EF_,0,0);
226 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
228 /* -----------------------------------------------------------------------------
231 Live weak pointers have a special closure type. Dead ones are just
232 nullary constructors (although they live on the heap - we overwrite
233 live weak pointers with dead ones).
234 -------------------------------------------------------------------------- */
236 INFO_TABLE(WEAK_info,WEAK_entry,0,4,WEAK,const,EF_,0,0);
237 NON_ENTERABLE_ENTRY_CODE(WEAK);
239 INFO_TABLE_CONSTR(DEAD_WEAK_info,DEAD_WEAK_entry,0,1,0,CONSTR,const,EF_,0,0);
240 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
242 /* -----------------------------------------------------------------------------
245 This is a static nullary constructor (like []) that we use to mark an empty
246 finalizer in a weak pointer object.
247 -------------------------------------------------------------------------- */
249 INFO_TABLE_CONSTR(NO_FINALIZER_info,NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
250 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
252 SET_STATIC_HDR(NO_FINALIZER_closure,NO_FINALIZER_info,0/*CC*/,,EI_)
255 /* -----------------------------------------------------------------------------
256 Foreign Objects are unlifted and therefore never entered.
257 -------------------------------------------------------------------------- */
259 INFO_TABLE(FOREIGN_info,FOREIGN_entry,0,1,FOREIGN,const,EF_,0,0);
260 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
262 /* -----------------------------------------------------------------------------
263 Stable Names are unlifted too.
264 -------------------------------------------------------------------------- */
266 INFO_TABLE(STABLE_NAME_info,STABLE_NAME_entry,0,1,STABLE_NAME,const,EF_,0,0);
267 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
269 /* -----------------------------------------------------------------------------
272 There are two kinds of these: full and empty. We need an info table
273 and entry code for each type.
274 -------------------------------------------------------------------------- */
276 INFO_TABLE(FULL_MVAR_info,FULL_MVAR_entry,4,0,MVAR,const,EF_,0,0);
277 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
279 INFO_TABLE(EMPTY_MVAR_info,EMPTY_MVAR_entry,4,0,MVAR,const,EF_,0,0);
280 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
282 /* -----------------------------------------------------------------------------
285 This is a static nullary constructor (like []) that we use to mark the
286 end of a linked TSO queue.
287 -------------------------------------------------------------------------- */
289 INFO_TABLE_CONSTR(END_TSO_QUEUE_info,END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
290 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
292 SET_STATIC_HDR(END_TSO_QUEUE_closure,END_TSO_QUEUE_info,0/*CC*/,,EI_)
295 /* -----------------------------------------------------------------------------
298 Mutable lists (used by the garbage collector) consist of a chain of
299 StgMutClosures connected through their mut_link fields, ending in
300 an END_MUT_LIST closure.
301 -------------------------------------------------------------------------- */
303 INFO_TABLE_CONSTR(END_MUT_LIST_info,END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
304 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
306 SET_STATIC_HDR(END_MUT_LIST_closure,END_MUT_LIST_info,0/*CC*/,,EI_)
309 INFO_TABLE(MUT_CONS_info, MUT_CONS_entry, 1, 1, MUT_VAR, const, EF_, 0, 0);
310 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
312 /* -----------------------------------------------------------------------------
315 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
316 pointers (StgArrPtrs). They all have a similar layout:
318 ___________________________
319 | Info | No. of | data....
321 ---------------------------
323 These are *unpointed* objects: i.e. they cannot be entered.
325 -------------------------------------------------------------------------- */
327 #define ArrayInfo(type) \
328 INFO_TABLE(type##_info, type##_entry, 0, 0, type, const, EF_,0,0); \
329 NON_ENTERABLE_ENTRY_CODE(type);
331 ArrayInfo(ARR_WORDS);
332 ArrayInfo(MUT_ARR_PTRS);
333 ArrayInfo(MUT_ARR_PTRS_FROZEN);
337 /* -----------------------------------------------------------------------------
339 -------------------------------------------------------------------------- */
341 INFO_TABLE(MUT_VAR_info, MUT_VAR_entry, 1, 1, MUT_VAR, const, EF_, 0, 0);
342 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
344 /* -----------------------------------------------------------------------------
345 Standard Error Entry.
347 This is used for filling in vector-table entries that can never happen,
349 -------------------------------------------------------------------------- */
351 STGFUN(stg_error_entry) \
354 STGCALL1(fflush,stdout); \
355 STGCALL2(fprintf,stderr,"fatal: stg_error_entry"); \
356 STGCALL1(raiseError, errorHandler); \
357 exit(EXIT_FAILURE); /* not executed */ \
361 /* -----------------------------------------------------------------------------
364 Entering this closure will just return to the address on the top of the
365 stack. Useful for getting a thread in a canonical form where we can
366 just enter the top stack word to start the thread. (see deleteThread)
367 * -------------------------------------------------------------------------- */
369 INFO_TABLE(dummy_ret_info, dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, const, EF_, 0, 0);
376 JMP_(ENTRY_CODE(ret_addr));
379 SET_STATIC_HDR(dummy_ret_closure,dummy_ret_info,CCS_DONTZuCARE,,EI_)
382 /* -----------------------------------------------------------------------------
383 Standard Infotables (for use in interpreter)
384 -------------------------------------------------------------------------- */
388 STGFUN(Hugs_CONSTR_entry)
391 ((StgPtr*)Sp)[0] = R1.p;
392 /* vectored: JMP_(RET_VEC(((StgPtr*)Sp)[1],constrTag(?))); */
393 JMP_(ENTRY_CODE(((StgPtr*)Sp)[1]));
396 #define RET_BCO_ENTRY_TEMPLATE(label) \
401 ((StgPtr*)Sp)[0] = R1.p; \
402 JMP_(stg_yield_to_Hugs); \
406 RET_BCO_ENTRY_TEMPLATE(ret_bco_entry );
407 RET_BCO_ENTRY_TEMPLATE(ret_bco_0_entry);
408 RET_BCO_ENTRY_TEMPLATE(ret_bco_1_entry);
409 RET_BCO_ENTRY_TEMPLATE(ret_bco_2_entry);
410 RET_BCO_ENTRY_TEMPLATE(ret_bco_3_entry);
411 RET_BCO_ENTRY_TEMPLATE(ret_bco_4_entry);
412 RET_BCO_ENTRY_TEMPLATE(ret_bco_5_entry);
413 RET_BCO_ENTRY_TEMPLATE(ret_bco_6_entry);
414 RET_BCO_ENTRY_TEMPLATE(ret_bco_7_entry);
416 VEC_POLY_INFO_TABLE(ret_bco,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO);
418 #endif /* INTERPRETER */
422 INFO_TABLE_CONSTR(Czh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgChar),0,CONSTR,const,EF_,0,0);
423 INFO_TABLE_CONSTR(Izh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgInt),0,CONSTR,const,EF_,0,0);
424 INFO_TABLE_CONSTR(I64zh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgInt64),0,CONSTR,const,EF_,0,0);
425 INFO_TABLE_CONSTR(Fzh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgFloat),0,CONSTR,const,EF_,0,0);
426 INFO_TABLE_CONSTR(Dzh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgDouble),0,CONSTR,const,EF_,0,0);
427 INFO_TABLE_CONSTR(Azh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgAddr),0,CONSTR,const,EF_,0,0);
428 INFO_TABLE_CONSTR(Wzh_con_info,Hugs_CONSTR_entry,0,sizeofW(StgWord),0,CONSTR,const,EF_,0,0);
429 INFO_TABLE_CONSTR(StablePtr_con_info,Hugs_CONSTR_entry,0,sizeofW(StgStablePtr),0,CONSTR,const,EF_,0,0);
431 /* These might seem redundant but {I,C}zh_static_info are used in
432 * {INT,CHAR}LIKE and the rest are used in RtsAPI.c
434 INFO_TABLE_CONSTR(Czh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgChar),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
435 INFO_TABLE_CONSTR(Izh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgInt),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
436 INFO_TABLE_CONSTR(I64zh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgInt64),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
437 INFO_TABLE_CONSTR(Fzh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgFloat),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
438 INFO_TABLE_CONSTR(Dzh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgDouble),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
439 INFO_TABLE_CONSTR(Azh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgAddr),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
440 INFO_TABLE_CONSTR(Wzh_static_info,Hugs_CONSTR_entry,0,sizeofW(StgWord),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
441 INFO_TABLE_CONSTR(StablePtr_static_info,Hugs_CONSTR_entry,0,sizeofW(StgStablePtr),0,CONSTR_NOCAF_STATIC,const,EF_,0,0);
443 #endif /* !defined(COMPILER) */
445 /* -----------------------------------------------------------------------------
446 CHARLIKE and INTLIKE closures.
448 These are static representations of Chars and small Ints, so that
449 we can remove dynamic Chars and Ints during garbage collection and
450 replace them with references to the static objects.
451 -------------------------------------------------------------------------- */
453 #define CHARLIKE_HDR(n) \
455 STATIC_HDR(Czh_static_info, /* C# */ \
460 #define INTLIKE_HDR(n) \
462 STATIC_HDR(Izh_static_info, /* I# */ \
467 /* put these in the *data* section, since the garbage collector relies
468 * on the fact that static closures live in the data section.
471 /* end the name with _closure, to convince the mangler this is a closure */
473 StgIntCharlikeClosure CHARLIKE_closure[] = {
732 StgIntCharlikeClosure INTLIKE_closure[] = {
733 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
765 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */