1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.57 2001/01/10 17:21:18 sewardj Exp $
4 * (c) The GHC Team, 1998-2000
6 * Entry code for various built-in closure types.
8 * ---------------------------------------------------------------------------*/
13 #include "StgMiscClosures.h"
14 #include "HeapStackCheck.h" /* for stg_gen_yield */
16 #include "StoragePriv.h"
17 #include "Profiling.h"
21 #if defined(GRAN) || defined(PAR)
22 # include "GranSimRts.h" /* for DumpRawGranEvent */
23 # include "StgRun.h" /* for StgReturn and register saving */
30 /* ToDo: make the printing of panics more win32-friendly, i.e.,
31 * pop up some lovely message boxes (as well).
33 #define DUMP_ERRMSG(msg) STGCALL2(fprintf,stderr,msg)
36 Template for the entry code of non-enterable closures.
39 #define NON_ENTERABLE_ENTRY_CODE(type) \
40 STGFUN(stg_##type##_entry) \
43 DUMP_ERRMSG(#type " object entered!\n"); \
44 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
50 /* -----------------------------------------------------------------------------
51 Support for the bytecode interpreter.
52 -------------------------------------------------------------------------- */
56 /* 9 bits of return code for constructors created by the interpreter. */
57 FN_(stg_interp_constr_entry)
59 /* R1 points at the constructor */
61 STGCALL2(fprintf,stderr,"stg_interp_constr_entry (direct return)!\n");
62 /* Pointless, since SET_TAG doesn't do anything */
63 SET_TAG( GET_TAG(GET_INFO(R1.cl)));
64 JMP_(ENTRY_CODE((P_)(*Sp)));
68 FN_(stg_interp_constr1_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),0)); FE_ }
69 FN_(stg_interp_constr2_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),1)); FE_ }
70 FN_(stg_interp_constr3_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),2)); FE_ }
71 FN_(stg_interp_constr4_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),3)); FE_ }
72 FN_(stg_interp_constr5_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),4)); FE_ }
73 FN_(stg_interp_constr6_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),5)); FE_ }
74 FN_(stg_interp_constr7_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),6)); FE_ }
75 FN_(stg_interp_constr8_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),7)); FE_ }
77 /* Some info tables to be used when compiled code returns a value to
78 the interpreter, i.e. the interpreter pushes one of these onto the
79 stack before entering a value. What the code does is to
80 impedance-match the compiled return convention (in R1/F1/D1 etc) to
81 the interpreter's convention (returned value is on top of stack),
82 and then cause the scheduler to enter the interpreter.
84 On entry, the stack (growing down) looks like this:
86 ptr to BCO holding return continuation
87 ptr to one of these info tables.
89 The info table code, both direct and vectored, must:
90 * push R1/F1/D1 on the stack
91 * push the BCO (so it's now on the stack twice)
92 * Yield, ie, go to the scheduler.
94 Scheduler examines the t.o.s, discovers it is a BCO, and proceeds
95 directly to the bytecode interpreter. That pops the top element
96 (the BCO, containing the return continuation), and interprets it.
97 Net result: return continuation gets interpreted, with the
101 ptr to the info table just jumped thru
104 which is just what we want -- the "standard" return layout for the
107 Don't ask me how unboxed tuple returns are supposed to work. We
108 haven't got a good story about that yet.
111 /* When the returned value is in R1 ... */
112 #define STG_CtoI_RET_R1_Template(label) \
117 bco = ((StgPtr*)Sp)[1]; \
119 ((StgPtr*)Sp)[0] = R1.p; \
121 ((StgPtr*)Sp)[0] = bco; \
122 JMP_(stg_yield_to_interpreter); \
126 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_entry);
127 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_0_entry);
128 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_1_entry);
129 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_2_entry);
130 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_3_entry);
131 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_4_entry);
132 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_5_entry);
133 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_6_entry);
134 STG_CtoI_RET_R1_Template(stg_ctoi_ret_R1_7_entry);
136 VEC_POLY_INFO_TABLE(stg_ctoi_ret_R1,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
138 /* When the returned value is in F1 ... */
139 #define STG_CtoI_RET_F1_Template(label) \
144 bco = ((StgPtr*)Sp)[1]; \
145 Sp -= sizeofW(StgFloat); \
146 ASSIGN_FLT((W_*)Sp, F1); \
148 ((StgPtr*)Sp)[0] = bco; \
149 JMP_(stg_yield_to_interpreter); \
153 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_entry);
154 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_0_entry);
155 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_1_entry);
156 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_2_entry);
157 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_3_entry);
158 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_4_entry);
159 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_5_entry);
160 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_6_entry);
161 STG_CtoI_RET_F1_Template(stg_ctoi_ret_F1_7_entry);
163 VEC_POLY_INFO_TABLE(stg_ctoi_ret_F1,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
166 /* When the returned value is in D1 ... */
167 #define STG_CtoI_RET_D1_Template(label) \
172 bco = ((StgPtr*)Sp)[1]; \
173 Sp -= sizeofW(StgDouble); \
174 ASSIGN_DBL((W_*)Sp, D1); \
176 ((StgPtr*)Sp)[0] = bco; \
177 JMP_(stg_yield_to_interpreter); \
181 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_entry);
182 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_0_entry);
183 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_1_entry);
184 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_2_entry);
185 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_3_entry);
186 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_4_entry);
187 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_5_entry);
188 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_6_entry);
189 STG_CtoI_RET_D1_Template(stg_ctoi_ret_D1_7_entry);
191 VEC_POLY_INFO_TABLE(stg_ctoi_ret_D1,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
194 /* The other way round: when the interpreter returns a value to
195 compiled code. The stack looks like this:
197 return info table (pushed by compiled code)
198 return value (pushed by interpreter)
200 If the value is ptr-rep'd, the interpreter simply returns to the
201 scheduler, instructing it to ThreadEnterGHC.
203 Otherwise (unboxed return value), we replace the top stack word,
204 which must be the tag, with stg_gc_unbx_r1_info (or f1_info or d1_info),
205 and return to the scheduler, instructing it to ThreadRunGHC.
207 No supporting code needed!
211 /* Entering a BCO. Heave it on the stack and defer to the
213 INFO_TABLE(stg_BCO_info,stg_BCO_entry,4,0,BCO,,EF_,"BCO","BCO");
214 STGFUN(stg_BCO_entry) {
218 JMP_(stg_yield_to_interpreter);
225 /* -----------------------------------------------------------------------------
226 Entry code for an indirection.
227 -------------------------------------------------------------------------- */
229 INFO_TABLE(stg_IND_info,stg_IND_entry,1,0,IND,,EF_,0,0);
230 STGFUN(stg_IND_entry)
233 TICK_ENT_IND(Node); /* tick */
235 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
237 JMP_(ENTRY_CODE(*R1.p));
241 INFO_TABLE(stg_IND_STATIC_info,stg_IND_STATIC_entry,1,0,IND_STATIC,,EF_,0,0);
242 STGFUN(stg_IND_STATIC_entry)
245 TICK_ENT_IND(Node); /* tick */
246 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
248 JMP_(ENTRY_CODE(*R1.p));
252 INFO_TABLE(stg_IND_PERM_info,stg_IND_PERM_entry,1,1,IND_PERM,,EF_,"IND_PERM","IND_PERM");
253 STGFUN(stg_IND_PERM_entry)
256 /* Don't add INDs to granularity cost */
257 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
259 #if defined(TICKY_TICKY) && !defined(PROFILING)
260 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
261 TICK_ENT_PERM_IND(R1.p); /* tick */
264 /* Enter PAP cost centre -- lexical scoping only */
265 ENTER_CCS_PAP_CL(R1.cl);
267 /* For ticky-ticky, change the perm_ind to a normal ind on first
268 * entry, so the number of ent_perm_inds is the number of *thunks*
269 * entered again, not the number of subsequent entries.
271 * Since this screws up cost centres, we die if profiling and
272 * ticky_ticky are on at the same time. KSW 1999-01.
277 # error Profiling and ticky-ticky do not mix at present!
278 # endif /* PROFILING */
279 SET_INFO((StgInd*)R1.p,&IND_info);
280 #endif /* TICKY_TICKY */
282 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
284 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
286 #if defined(TICKY_TICKY) && !defined(PROFILING)
290 JMP_(ENTRY_CODE(*R1.p));
294 INFO_TABLE(stg_IND_OLDGEN_info,stg_IND_OLDGEN_entry,1,1,IND_OLDGEN,,EF_,0,0);
295 STGFUN(stg_IND_OLDGEN_entry)
298 TICK_ENT_IND(Node); /* tick */
300 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
302 JMP_(ENTRY_CODE(*R1.p));
306 INFO_TABLE(stg_IND_OLDGEN_PERM_info,stg_IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,,EF_,0,0);
307 STGFUN(stg_IND_OLDGEN_PERM_entry)
310 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
312 #if defined(TICKY_TICKY) && !defined(PROFILING)
313 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
314 TICK_ENT_PERM_IND(R1.p); /* tick */
317 /* Enter PAP cost centre -- lexical scoping only */
318 ENTER_CCS_PAP_CL(R1.cl);
320 /* see comment in IND_PERM */
323 # error Profiling and ticky-ticky do not mix at present!
324 # endif /* PROFILING */
325 SET_INFO((StgInd*)R1.p,&IND_OLDGEN_info);
326 #endif /* TICKY_TICKY */
328 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
330 JMP_(ENTRY_CODE(*R1.p));
334 /* -----------------------------------------------------------------------------
337 This code assumes R1 is in a register for now.
338 -------------------------------------------------------------------------- */
340 INFO_TABLE(stg_CAF_UNENTERED_info,stg_CAF_UNENTERED_entry,1,3,CAF_UNENTERED,,EF_,0,0);
341 STGFUN(stg_CAF_UNENTERED_entry)
344 /* ToDo: implement directly in GHC */
347 JMP_(stg_yield_to_interpreter);
351 /* 0,4 is entirely bogus; _do not_ rely on this info */
352 INFO_TABLE(stg_CAF_ENTERED_info,stg_CAF_ENTERED_entry,0,4,CAF_ENTERED,,EF_,0,0);
353 STGFUN(stg_CAF_ENTERED_entry)
356 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
358 JMP_(GET_ENTRY(R1.cl));
362 /* -----------------------------------------------------------------------------
363 Entry code for a black hole.
365 Entering a black hole normally causes a cyclic data dependency, but
366 in the concurrent world, black holes are synchronization points,
367 and they are turned into blocking queues when there are threads
368 waiting for the evaluation of the closure to finish.
369 -------------------------------------------------------------------------- */
371 /* Note: a BLACKHOLE and BLACKHOLE_BQ must be big enough to be
372 * overwritten with an indirection/evacuee/catch. Thus we claim it
373 * has 1 non-pointer word of payload (in addition to the pointer word
374 * for the blocking queue in a BQ), which should be big enough for an
375 * old-generation indirection.
378 INFO_TABLE(stg_BLACKHOLE_info, stg_BLACKHOLE_entry,0,2,BLACKHOLE,,EF_,"BLACKHOLE","BLACKHOLE");
379 STGFUN(stg_BLACKHOLE_entry)
383 /* Before overwriting TSO_LINK */
384 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
389 bdescr *bd = Bdescr(R1.p);
390 if (bd->back != (bdescr *)BaseReg) {
391 if (bd->gen->no >= 1 || bd->step->no >= 1) {
392 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
394 EXTFUN_RTS(stg_gc_enter_1_hponly);
395 JMP_(stg_gc_enter_1_hponly);
402 /* Put ourselves on the blocking queue for this black hole */
403 #if defined(GRAN) || defined(PAR)
404 /* in fact, only difference is the type of the end-of-queue marker! */
405 CurrentTSO->link = END_BQ_QUEUE;
406 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
408 CurrentTSO->link = END_TSO_QUEUE;
409 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
411 /* jot down why and on what closure we are blocked */
412 CurrentTSO->why_blocked = BlockedOnBlackHole;
413 CurrentTSO->block_info.closure = R1.cl;
414 /* closure is mutable since something has just been added to its BQ */
415 recordMutable((StgMutClosure *)R1.cl);
416 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
417 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
419 /* PAR: dumping of event now done in blockThread -- HWL */
421 /* stg_gen_block is too heavyweight, use a specialised one */
427 INFO_TABLE(stg_BLACKHOLE_BQ_info, stg_BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,,EF_,"BLACKHOLE","BLACKHOLE");
428 STGFUN(stg_BLACKHOLE_BQ_entry)
432 /* Before overwriting TSO_LINK */
433 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
438 bdescr *bd = Bdescr(R1.p);
439 if (bd->back != (bdescr *)BaseReg) {
440 if (bd->gen->no >= 1 || bd->step->no >= 1) {
441 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
443 EXTFUN_RTS(stg_gc_enter_1_hponly);
444 JMP_(stg_gc_enter_1_hponly);
452 /* Put ourselves on the blocking queue for this black hole */
453 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
454 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
455 /* jot down why and on what closure we are blocked */
456 CurrentTSO->why_blocked = BlockedOnBlackHole;
457 CurrentTSO->block_info.closure = R1.cl;
459 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
462 /* PAR: dumping of event now done in blockThread -- HWL */
464 /* stg_gen_block is too heavyweight, use a specialised one */
470 Revertible black holes are needed in the parallel world, to handle
471 negative acknowledgements of messages containing updatable closures.
472 The idea is that when the original message is transmitted, the closure
473 is turned into a revertible black hole...an object which acts like a
474 black hole when local threads try to enter it, but which can be reverted
475 back to the original closure if necessary.
477 It's actually a lot like a blocking queue (BQ) entry, because revertible
478 black holes are initially set up with an empty blocking queue.
481 #if defined(PAR) || defined(GRAN)
483 INFO_TABLE(stg_RBH_info, stg_RBH_entry,1,1,RBH,,EF_,0,0);
484 STGFUN(stg_RBH_entry)
488 /* mainly statistics gathering for GranSim simulation */
489 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
492 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
493 /* Put ourselves on the blocking queue for this black hole */
494 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
495 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
496 /* jot down why and on what closure we are blocked */
497 CurrentTSO->why_blocked = BlockedOnBlackHole;
498 CurrentTSO->block_info.closure = R1.cl;
500 /* PAR: dumping of event now done in blockThread -- HWL */
502 /* stg_gen_block is too heavyweight, use a specialised one */
507 INFO_TABLE(stg_RBH_Save_0_info, stg_RBH_Save_0_entry,0,2,CONSTR,,EF_,0,0);
508 NON_ENTERABLE_ENTRY_CODE(RBH_Save_0);
510 INFO_TABLE(stg_RBH_Save_1_info, stg_RBH_Save_1_entry,1,1,CONSTR,,EF_,0,0);
511 NON_ENTERABLE_ENTRY_CODE(RBH_Save_1);
513 INFO_TABLE(stg_RBH_Save_2_info, stg_RBH_Save_2_entry,2,0,CONSTR,,EF_,0,0);
514 NON_ENTERABLE_ENTRY_CODE(RBH_Save_2);
515 #endif /* defined(PAR) || defined(GRAN) */
517 /* identical to BLACKHOLEs except for the infotag */
518 INFO_TABLE(stg_CAF_BLACKHOLE_info, stg_CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,,EF_,"CAF_BLACKHOLE","CAF_BLACKHOLE");
519 STGFUN(stg_CAF_BLACKHOLE_entry)
523 /* mainly statistics gathering for GranSim simulation */
524 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
529 bdescr *bd = Bdescr(R1.p);
530 if (bd->back != (bdescr *)BaseReg) {
531 if (bd->gen->no >= 1 || bd->step->no >= 1) {
532 CMPXCHG(R1.cl->header.info, &CAF_BLACKHOLE_info, &WHITEHOLE_info);
534 EXTFUN_RTS(stg_gc_enter_1_hponly);
535 JMP_(stg_gc_enter_1_hponly);
543 /* Put ourselves on the blocking queue for this black hole */
544 #if defined(GRAN) || defined(PAR)
545 /* in fact, only difference is the type of the end-of-queue marker! */
546 CurrentTSO->link = END_BQ_QUEUE;
547 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
549 CurrentTSO->link = END_TSO_QUEUE;
550 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
552 /* jot down why and on what closure we are blocked */
553 CurrentTSO->why_blocked = BlockedOnBlackHole;
554 CurrentTSO->block_info.closure = R1.cl;
555 /* closure is mutable since something has just been added to its BQ */
556 recordMutable((StgMutClosure *)R1.cl);
557 /* Change the CAF_BLACKHOLE into a BLACKHOLE_BQ */
558 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
560 /* PAR: dumping of event now done in blockThread -- HWL */
562 /* stg_gen_block is too heavyweight, use a specialised one */
568 INFO_TABLE(stg_SE_BLACKHOLE_info, stg_SE_BLACKHOLE_entry,0,2,SE_BLACKHOLE,,EF_,0,0);
569 STGFUN(stg_SE_BLACKHOLE_entry)
572 STGCALL3(fprintf,stderr,"SE_BLACKHOLE at %p entered!\n",R1.p);
573 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
577 INFO_TABLE(SE_CAF_BLACKHOLE_info, SE_CAF_BLACKHOLE_entry,0,2,SE_CAF_BLACKHOLE,,EF_,0,0);
578 STGFUN(stg_SE_CAF_BLACKHOLE_entry)
581 STGCALL3(fprintf,stderr,"SE_CAF_BLACKHOLE at %p entered!\n",R1.p);
582 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
588 INFO_TABLE(stg_WHITEHOLE_info, stg_WHITEHOLE_entry,0,2,CONSTR_NOCAF_STATIC,,EF_,0,0);
589 STGFUN(stg_WHITEHOLE_entry)
592 JMP_(GET_ENTRY(R1.cl));
597 /* -----------------------------------------------------------------------------
598 Some static info tables for things that don't get entered, and
599 therefore don't need entry code (i.e. boxed but unpointed objects)
600 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
601 -------------------------------------------------------------------------- */
603 INFO_TABLE(stg_TSO_info, stg_TSO_entry, 0,0,TSO,,EF_,"TSO","TSO");
604 NON_ENTERABLE_ENTRY_CODE(TSO);
606 /* -----------------------------------------------------------------------------
607 Evacuees are left behind by the garbage collector. Any attempt to enter
609 -------------------------------------------------------------------------- */
611 INFO_TABLE(stg_EVACUATED_info,stg_EVACUATED_entry,1,0,EVACUATED,,EF_,0,0);
612 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
614 /* -----------------------------------------------------------------------------
617 Live weak pointers have a special closure type. Dead ones are just
618 nullary constructors (although they live on the heap - we overwrite
619 live weak pointers with dead ones).
620 -------------------------------------------------------------------------- */
622 INFO_TABLE(stg_WEAK_info,stg_WEAK_entry,0,4,WEAK,,EF_,"WEAK","WEAK");
623 NON_ENTERABLE_ENTRY_CODE(WEAK);
625 INFO_TABLE_CONSTR(stg_DEAD_WEAK_info,stg_DEAD_WEAK_entry,0,1,0,CONSTR,,EF_,"DEAD_WEAK","DEAD_WEAK");
626 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
628 /* -----------------------------------------------------------------------------
631 This is a static nullary constructor (like []) that we use to mark an empty
632 finalizer in a weak pointer object.
633 -------------------------------------------------------------------------- */
635 INFO_TABLE_CONSTR(stg_NO_FINALIZER_info,stg_NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
636 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
638 SET_STATIC_HDR(stg_NO_FINALIZER_closure,stg_NO_FINALIZER_info,0/*CC*/,,EI_)
641 /* -----------------------------------------------------------------------------
642 Foreign Objects are unlifted and therefore never entered.
643 -------------------------------------------------------------------------- */
645 INFO_TABLE(stg_FOREIGN_info,stg_FOREIGN_entry,0,1,FOREIGN,,EF_,"FOREIGN","FOREIGN");
646 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
648 /* -----------------------------------------------------------------------------
649 Stable Names are unlifted too.
650 -------------------------------------------------------------------------- */
652 INFO_TABLE(stg_STABLE_NAME_info,stg_STABLE_NAME_entry,0,1,STABLE_NAME,,EF_,"STABLE_NAME","STABLE_NAME");
653 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
655 /* -----------------------------------------------------------------------------
658 There are two kinds of these: full and empty. We need an info table
659 and entry code for each type.
660 -------------------------------------------------------------------------- */
662 INFO_TABLE(stg_FULL_MVAR_info,stg_FULL_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
663 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
665 INFO_TABLE(stg_EMPTY_MVAR_info,stg_EMPTY_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
666 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
668 /* -----------------------------------------------------------------------------
671 This is a static nullary constructor (like []) that we use to mark the
672 end of a linked TSO queue.
673 -------------------------------------------------------------------------- */
675 INFO_TABLE_CONSTR(stg_END_TSO_QUEUE_info,stg_END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
676 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
678 SET_STATIC_HDR(stg_END_TSO_QUEUE_closure,stg_END_TSO_QUEUE_info,0/*CC*/,,EI_)
681 /* -----------------------------------------------------------------------------
684 Mutable lists (used by the garbage collector) consist of a chain of
685 StgMutClosures connected through their mut_link fields, ending in
686 an END_MUT_LIST closure.
687 -------------------------------------------------------------------------- */
689 INFO_TABLE_CONSTR(stg_END_MUT_LIST_info,stg_END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
690 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
692 SET_STATIC_HDR(stg_END_MUT_LIST_closure,stg_END_MUT_LIST_info,0/*CC*/,,EI_)
695 INFO_TABLE(stg_MUT_CONS_info, stg_MUT_CONS_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
696 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
698 /* -----------------------------------------------------------------------------
700 -------------------------------------------------------------------------- */
702 INFO_TABLE_CONSTR(stg_END_EXCEPTION_LIST_info,stg_END_EXCEPTION_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
703 NON_ENTERABLE_ENTRY_CODE(END_EXCEPTION_LIST);
705 SET_STATIC_HDR(stg_END_EXCEPTION_LIST_closure,stg_END_EXCEPTION_LIST_info,0/*CC*/,,EI_)
708 INFO_TABLE(stg_EXCEPTION_CONS_info, stg_EXCEPTION_CONS_entry, 1, 1, CONSTR, , EF_, 0, 0);
709 NON_ENTERABLE_ENTRY_CODE(EXCEPTION_CONS);
711 /* -----------------------------------------------------------------------------
714 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
715 pointers (StgArrPtrs). They all have a similar layout:
717 ___________________________
718 | Info | No. of | data....
720 ---------------------------
722 These are *unpointed* objects: i.e. they cannot be entered.
724 -------------------------------------------------------------------------- */
726 #define ArrayInfo(type) \
727 INFO_TABLE(stg_##type##_info, stg_##type##_entry, 0, 0, type, , EF_,"" # type "","" # type "");
729 ArrayInfo(ARR_WORDS);
730 NON_ENTERABLE_ENTRY_CODE(ARR_WORDS);
731 ArrayInfo(MUT_ARR_PTRS);
732 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS);
733 ArrayInfo(MUT_ARR_PTRS_FROZEN);
734 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS_FROZEN);
738 /* -----------------------------------------------------------------------------
740 -------------------------------------------------------------------------- */
742 INFO_TABLE(stg_MUT_VAR_info, stg_MUT_VAR_entry, 1, 1, MUT_VAR, , EF_, "MUT_VAR", "MUT_VAR");
743 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
745 /* -----------------------------------------------------------------------------
746 Standard Error Entry.
748 This is used for filling in vector-table entries that can never happen,
750 -------------------------------------------------------------------------- */
751 /* No longer used; we use NULL, because a) it never happens, right? and b)
752 Windows doesn't like DLL entry points being used as static initialisers
753 STGFUN(stg_error_entry) \
756 DUMP_ERRMSG("fatal: stg_error_entry"); \
757 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
762 /* -----------------------------------------------------------------------------
765 Entering this closure will just return to the address on the top of the
766 stack. Useful for getting a thread in a canonical form where we can
767 just enter the top stack word to start the thread. (see deleteThread)
768 * -------------------------------------------------------------------------- */
770 INFO_TABLE(stg_dummy_ret_info, stg_dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, , EF_, 0, 0);
771 STGFUN(stg_dummy_ret_entry)
777 JMP_(ENTRY_CODE(ret_addr));
780 SET_STATIC_HDR(stg_dummy_ret_closure,stg_dummy_ret_info,CCS_DONT_CARE,,EI_)
783 /* -----------------------------------------------------------------------------
784 Strict IO application - performing an IO action and entering its result.
786 rts_evalIO() lets you perform Haskell IO actions from outside of Haskell-land,
787 returning back to you their result. Want this result to be evaluated to WHNF
788 by that time, so that we can easily get at the int/char/whatever using the
789 various get{Ty} functions provided by the RTS API.
791 forceIO takes care of this, performing the IO action and entering the
792 results that comes back.
794 * -------------------------------------------------------------------------- */
797 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
798 STGFUN(stg_forceIO_ret_entry)
802 Sp -= sizeofW(StgSeqFrame);
804 JMP_(GET_ENTRY(R1.cl));
807 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
808 STGFUN(forceIO_ret_entry)
812 rval = (StgClosure *)Sp[0];
814 Sp -= sizeofW(StgSeqFrame);
817 JMP_(GET_ENTRY(R1.cl));
821 INFO_TABLE(stg_forceIO_info,stg_forceIO_entry,1,0,FUN_STATIC,,EF_,0,0);
822 FN_(stg_forceIO_entry)
825 /* Sp[0] contains the IO action we want to perform */
827 /* Replace it with the return continuation that enters the result. */
828 Sp[0] = (W_)&stg_forceIO_ret_info;
830 /* Push the RealWorld# tag and enter */
831 Sp[0] =(W_)REALWORLD_TAG;
832 JMP_(GET_ENTRY(R1.cl));
835 SET_STATIC_HDR(stg_forceIO_closure,stg_forceIO_info,CCS_DONT_CARE,,EI_)
839 /* -----------------------------------------------------------------------------
840 CHARLIKE and INTLIKE closures.
842 These are static representations of Chars and small Ints, so that
843 we can remove dynamic Chars and Ints during garbage collection and
844 replace them with references to the static objects.
845 -------------------------------------------------------------------------- */
847 #if defined(INTERPRETER) || defined(ENABLE_WIN32_DLL_SUPPORT)
849 * When sticking the RTS in a DLL, we delay populating the
850 * Charlike and Intlike tables until load-time, which is only
851 * when we've got the real addresses to the C# and I# closures.
854 static INFO_TBL_CONST StgInfoTable czh_static_info;
855 static INFO_TBL_CONST StgInfoTable izh_static_info;
856 #define Char_hash_static_info czh_static_info
857 #define Int_hash_static_info izh_static_info
859 #define Char_hash_static_info PrelBase_Czh_static_info
860 #define Int_hash_static_info PrelBase_Izh_static_info
863 #define CHARLIKE_HDR(n) \
865 STATIC_HDR(Char_hash_static_info, /* C# */ \
870 #define INTLIKE_HDR(n) \
872 STATIC_HDR(Int_hash_static_info, /* I# */ \
877 /* put these in the *data* section, since the garbage collector relies
878 * on the fact that static closures live in the data section.
881 /* end the name with _closure, to convince the mangler this is a closure */
883 StgIntCharlikeClosure stg_CHARLIKE_closure[] = {
1142 StgIntCharlikeClosure stg_INTLIKE_closure[] = {
1143 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
1175 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */