1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.50 2000/11/13 14:40:37 simonmar 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 metacircular interpreter.
52 -------------------------------------------------------------------------- */
56 /* 9 bits of return code for constructors created by mci_make_constr. */
57 FN_(stg_mci_constr_entry)
59 /* R1 points at the constructor */
61 STGCALL2(fprintf,stderr,"mci_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_mci_constr1_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),0)); FE_ }
69 FN_(stg_mci_constr2_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),1)); FE_ }
70 FN_(stg_mci_constr3_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),2)); FE_ }
71 FN_(stg_mci_constr4_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),3)); FE_ }
72 FN_(stg_mci_constr5_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),4)); FE_ }
73 FN_(stg_mci_constr6_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),5)); FE_ }
74 FN_(stg_mci_constr7_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),6)); FE_ }
75 FN_(stg_mci_constr8_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),7)); FE_ }
78 /* Since this stuff is ostensibly in some other module, we need
79 to supply an __init_ function.
81 EF_(__init_MCIzumakezuconstr);
82 START_MOD_INIT(__init_MCIzumakezuconstr)
86 INFO_TABLE(mci_make_constr_info, mci_make_constr_entry, 0,0,FUN_STATIC,static,EF_,0,0);
87 INFO_TABLE(mci_make_constrI_info, mci_make_constrI_entry, 0,0,FUN_STATIC,static,EF_,0,0);
88 INFO_TABLE(mci_make_constrP_info, mci_make_constrP_entry, 0,0,FUN_STATIC,static,EF_,0,0);
89 INFO_TABLE(mci_make_constrPP_info, mci_make_constrPP_entry, 0,0,FUN_STATIC,static,EF_,0,0);
90 INFO_TABLE(mci_make_constrPPP_info,mci_make_constrPPP_entry,0,0,FUN_STATIC,static,EF_,0,0);
92 SET_STATIC_HDR(MCIzumakezuconstr_mcizumakezuconstr_closure,
93 mci_make_constr_info,0,,EI_)
96 SET_STATIC_HDR(MCIzumakezuconstr_mcizumakezuconstrI_closure,
97 mci_make_constrI_info,0,,EI_)
100 SET_STATIC_HDR(MCIzumakezuconstr_mcizumakezuconstrP_closure,
101 mci_make_constrP_info,0,,EI_)
104 SET_STATIC_HDR(MCIzumakezuconstr_mcizumakezuconstrPP_closure,
105 mci_make_constrPP_info,0,,EI_)
108 SET_STATIC_HDR(MCIzumakezuconstr_mcizumakezuconstrPPP_closure,
109 mci_make_constrPPP_info,0,,EI_)
114 /* Make a constructor with no args. */
115 STGFUN(mci_make_constr_entry)
121 /* Sp[0 & 1] are tag, Addr#
123 itbl = ((StgInfoTable**)Sp)[1];
124 np = INFO_PTR_TO_STRUCT(itbl)->layout.payload.ptrs;
125 nw = INFO_PTR_TO_STRUCT(itbl)->layout.payload.nptrs;
126 size = sizeofW(StgHeader) + stg_max(MIN_NONUPD_SIZE, np+nw);
127 /* STGCALL5(fprintf,stderr,"np %d nw %d size %d\n",np,nw,size); */
129 /* The total number of words to copy off the stack is np + nw.
130 That doesn't include tag words, tho.
132 HP_CHK_GEN_TICKY(size, NO_PTRS, mci_make_constr_entry, );
133 TICK_ALLOC_PRIM(sizeofW(StgHeader), size-sizeofW(StgHeader), 0);
134 CCS_ALLOC(CCCS,size); /* ccs prof */
136 con = (StgClosure*)(Hp + 1 - size);
137 SET_HDR(con, itbl,CCCS);
139 Sp = Sp +2; /* Zap the Addr# arg */
142 JMP_(ENTRY_CODE(GET_INFO(R1.cl)));
146 /* Make a constructor with 1 Int# arg */
147 STGFUN(mci_make_constrI_entry)
153 /* Sp[0 & 1] are tag, Addr#
154 Sp[2 & 3] are tag, Int#
156 itbl = ((StgInfoTable**)Sp)[1];
157 np = INFO_PTR_TO_STRUCT(itbl)->layout.payload.ptrs;
158 nw = INFO_PTR_TO_STRUCT(itbl)->layout.payload.nptrs;
159 size = sizeofW(StgHeader) + stg_max(MIN_NONUPD_SIZE, np+nw);
160 /* STGCALL5(fprintf,stderr,"np %d nw %d size %d\n",np,nw,size); */
162 /* The total number of words to copy off the stack is np + nw.
163 That doesn't include tag words, tho.
165 HP_CHK_GEN_TICKY(size, NO_PTRS, mci_make_constrI_entry, );
166 TICK_ALLOC_PRIM(sizeofW(StgHeader), size-sizeofW(StgHeader), 0);
167 CCS_ALLOC(CCCS,size); /* ccs prof */
169 con = (StgClosure*)(Hp + 1 - size);
170 SET_HDR(con, itbl,CCCS);
172 con->payload[0] = ((StgClosure**)Sp)[3];
173 Sp = Sp +1/*word*/ +1/*tag*/; /* Zap the Int# arg */
174 Sp = Sp +2; /* Zap the Addr# arg */
177 JMP_(ENTRY_CODE(GET_INFO(R1.cl)));
181 STGFUN(mci_make_constrP_entry)
184 DUMP_ERRMSG("mci_make_constrP_entry: unimplemented!\n");
185 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
191 /* Make a constructor with 2 pointer args. */
192 STGFUN(mci_make_constrPP_entry)
198 /* Sp[0 & 1] are tag, Addr#
202 itbl = ((StgInfoTable**)Sp)[1];
203 np = INFO_PTR_TO_STRUCT(itbl)->layout.payload.ptrs;
204 nw = INFO_PTR_TO_STRUCT(itbl)->layout.payload.nptrs;
205 size = sizeofW(StgHeader) + stg_max(MIN_NONUPD_SIZE, np+nw);
206 /* STGCALL5(fprintf,stderr,"np %d nw %d size %d\n",np,nw,size); */
208 /* The total number of words to copy off the stack is np + nw.
209 That doesn't include tag words, tho.
211 HP_CHK_GEN_TICKY(size, NO_PTRS, mci_make_constrPP_entry, );
212 TICK_ALLOC_PRIM(sizeofW(StgHeader), size-sizeofW(StgHeader), 0);
213 CCS_ALLOC(CCCS,size); /* ccs prof */
215 con = (StgClosure*)(Hp + 1 - size);
216 SET_HDR(con, itbl,CCCS);
218 con->payload[0] = ((StgClosure**)Sp)[2];
219 con->payload[1] = ((StgClosure**)Sp)[3];
220 Sp = Sp +2; /* Zap 2 ptr args */
221 Sp = Sp +2; /* Zap the Addr# arg */
224 JMP_(ENTRY_CODE(GET_INFO(R1.cl)));
229 STGFUN(mci_make_constrPPP_entry)
232 DUMP_ERRMSG("mci_make_constrPPP_entry: unimplemented!\n");
233 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
239 /* It would be nice if this worked, but it doesn't. Yet. */
240 STGFUN(mci_make_constr_entry)
242 nat size, np, nw_heap, nw_really, w;
247 itbl = ((StgInfoTable**)Sp)[0];
248 STGCALL3(fprintf,stderr,"mmc: itbl = %d\n",itbl);
250 STGCALL3(fprintf,stderr,"mmc: sp-4 = %d\n", ((W_*)Sp)[-4] );
251 STGCALL3(fprintf,stderr,"mmc: sp-3 = %d\n", ((W_*)Sp)[-3] );
252 STGCALL3(fprintf,stderr,"mmc: sp-2 = %d\n", ((W_*)Sp)[-2] );
253 STGCALL3(fprintf,stderr,"mmc: sp-1 = %d\n", ((W_*)Sp)[-1] );
254 STGCALL3(fprintf,stderr,"mmc: sp+0 = %d\n", ((W_*)Sp)[0] );
255 STGCALL3(fprintf,stderr,"mmc: sp+1 = %d\n", ((W_*)Sp)[1] );
256 STGCALL3(fprintf,stderr,"mmc: sp+2 = %d\n", ((W_*)Sp)[2] );
257 STGCALL3(fprintf,stderr,"mmc: sp+3 = %d\n", ((W_*)Sp)[3] );
258 STGCALL3(fprintf,stderr,"mmc: sp+4 = %d\n", ((W_*)Sp)[4] );
259 np = itbl->layout.payload.ptrs;
260 nw_really = itbl->layout.payload.nptrs;
261 nw_heap = stg_max(nw_really, MIN_NONUPD_SIZE-np);
262 size = CONSTR_sizeW( np, nw_heap );
264 /* The total number of words to copy off the stack is np + nw.
265 That doesn't include tag words, tho.
267 HP_CHK_GEN_TICKY(size, NO_PTRS, mci_make_constr_entry, );
268 TICK_ALLOC_PRIM(sizeofW(StgHeader), size-sizeofW(StgHeader), 0);
269 CCS_ALLOC(CCCS,size); /* ccs prof */
271 con = (StgClosure*)(Hp + 1 - size);
272 SET_HDR(con, itbl,CCCS);
274 /* Copy into the closure. */
278 if (w == np + nw) break;
280 if (IS_ARG_TAG(*r)) {
283 con->payload[w++] = (StgClosure*)(*r++);
285 con->payload[w++] = (StgClosure*)(*r++);
287 ASSERT((P_)r <= (P_)Su);
290 /* Remove all the args we've used. */
294 JMP_(ENTRY_CODE(R1.cl));
302 /* -----------------------------------------------------------------------------
303 Entry code for an indirection.
304 -------------------------------------------------------------------------- */
306 INFO_TABLE(stg_IND_info,stg_IND_entry,1,0,IND,,EF_,0,0);
307 STGFUN(stg_IND_entry)
310 TICK_ENT_IND(Node); /* tick */
312 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
314 JMP_(ENTRY_CODE(*R1.p));
318 INFO_TABLE(stg_IND_STATIC_info,stg_IND_STATIC_entry,1,0,IND_STATIC,,EF_,0,0);
319 STGFUN(stg_IND_STATIC_entry)
322 TICK_ENT_IND(Node); /* tick */
323 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
325 JMP_(ENTRY_CODE(*R1.p));
329 INFO_TABLE(stg_IND_PERM_info,stg_IND_PERM_entry,1,1,IND_PERM,,EF_,"IND_PERM","IND_PERM");
330 STGFUN(stg_IND_PERM_entry)
333 /* Don't add INDs to granularity cost */
334 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
336 #if defined(TICKY_TICKY) && !defined(PROFILING)
337 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
338 TICK_ENT_PERM_IND(R1.p); /* tick */
341 /* Enter PAP cost centre -- lexical scoping only */
342 ENTER_CCS_PAP_CL(R1.cl);
344 /* For ticky-ticky, change the perm_ind to a normal ind on first
345 * entry, so the number of ent_perm_inds is the number of *thunks*
346 * entered again, not the number of subsequent entries.
348 * Since this screws up cost centres, we die if profiling and
349 * ticky_ticky are on at the same time. KSW 1999-01.
354 # error Profiling and ticky-ticky do not mix at present!
355 # endif /* PROFILING */
356 SET_INFO((StgInd*)R1.p,&IND_info);
357 #endif /* TICKY_TICKY */
359 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
361 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
363 #if defined(TICKY_TICKY) && !defined(PROFILING)
367 JMP_(ENTRY_CODE(*R1.p));
371 INFO_TABLE(stg_IND_OLDGEN_info,stg_IND_OLDGEN_entry,1,1,IND_OLDGEN,,EF_,0,0);
372 STGFUN(stg_IND_OLDGEN_entry)
375 TICK_ENT_IND(Node); /* tick */
377 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
379 JMP_(ENTRY_CODE(*R1.p));
383 INFO_TABLE(stg_IND_OLDGEN_PERM_info,stg_IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,,EF_,0,0);
384 STGFUN(stg_IND_OLDGEN_PERM_entry)
387 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
389 #if defined(TICKY_TICKY) && !defined(PROFILING)
390 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
391 TICK_ENT_PERM_IND(R1.p); /* tick */
394 /* Enter PAP cost centre -- lexical scoping only */
395 ENTER_CCS_PAP_CL(R1.cl);
397 /* see comment in IND_PERM */
400 # error Profiling and ticky-ticky do not mix at present!
401 # endif /* PROFILING */
402 SET_INFO((StgInd*)R1.p,&IND_OLDGEN_info);
403 #endif /* TICKY_TICKY */
405 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
407 JMP_(ENTRY_CODE(*R1.p));
411 /* -----------------------------------------------------------------------------
414 This code assumes R1 is in a register for now.
415 -------------------------------------------------------------------------- */
417 INFO_TABLE(stg_CAF_UNENTERED_info,stg_CAF_UNENTERED_entry,1,3,CAF_UNENTERED,,EF_,0,0);
418 STGFUN(stg_CAF_UNENTERED_entry)
421 /* ToDo: implement directly in GHC */
424 JMP_(stg_yield_to_Hugs);
428 /* 0,4 is entirely bogus; _do not_ rely on this info */
429 INFO_TABLE(stg_CAF_ENTERED_info,stg_CAF_ENTERED_entry,0,4,CAF_ENTERED,,EF_,0,0);
430 STGFUN(stg_CAF_ENTERED_entry)
433 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
435 JMP_(GET_ENTRY(R1.cl));
439 /* -----------------------------------------------------------------------------
440 Entry code for a black hole.
442 Entering a black hole normally causes a cyclic data dependency, but
443 in the concurrent world, black holes are synchronization points,
444 and they are turned into blocking queues when there are threads
445 waiting for the evaluation of the closure to finish.
446 -------------------------------------------------------------------------- */
448 /* Note: a BLACKHOLE and BLACKHOLE_BQ must be big enough to be
449 * overwritten with an indirection/evacuee/catch. Thus we claim it
450 * has 1 non-pointer word of payload (in addition to the pointer word
451 * for the blocking queue in a BQ), which should be big enough for an
452 * old-generation indirection.
455 INFO_TABLE(stg_BLACKHOLE_info, stg_BLACKHOLE_entry,0,2,BLACKHOLE,,EF_,"BLACKHOLE","BLACKHOLE");
456 STGFUN(stg_BLACKHOLE_entry)
460 /* Before overwriting TSO_LINK */
461 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
466 bdescr *bd = Bdescr(R1.p);
467 if (bd->back != (bdescr *)BaseReg) {
468 if (bd->gen->no >= 1 || bd->step->no >= 1) {
469 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
471 EXTFUN_RTS(stg_gc_enter_1_hponly);
472 JMP_(stg_gc_enter_1_hponly);
479 /* Put ourselves on the blocking queue for this black hole */
480 #if defined(GRAN) || defined(PAR)
481 /* in fact, only difference is the type of the end-of-queue marker! */
482 CurrentTSO->link = END_BQ_QUEUE;
483 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
485 CurrentTSO->link = END_TSO_QUEUE;
486 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
488 /* jot down why and on what closure we are blocked */
489 CurrentTSO->why_blocked = BlockedOnBlackHole;
490 CurrentTSO->block_info.closure = R1.cl;
491 /* closure is mutable since something has just been added to its BQ */
492 recordMutable((StgMutClosure *)R1.cl);
493 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
494 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
496 /* PAR: dumping of event now done in blockThread -- HWL */
498 /* stg_gen_block is too heavyweight, use a specialised one */
504 INFO_TABLE(stg_BLACKHOLE_BQ_info, stg_BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,,EF_,"BLACKHOLE","BLACKHOLE");
505 STGFUN(stg_BLACKHOLE_BQ_entry)
509 /* Before overwriting TSO_LINK */
510 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
515 bdescr *bd = Bdescr(R1.p);
516 if (bd->back != (bdescr *)BaseReg) {
517 if (bd->gen->no >= 1 || bd->step->no >= 1) {
518 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
520 EXTFUN_RTS(stg_gc_enter_1_hponly);
521 JMP_(stg_gc_enter_1_hponly);
529 /* Put ourselves on the blocking queue for this black hole */
530 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
531 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
532 /* jot down why and on what closure we are blocked */
533 CurrentTSO->why_blocked = BlockedOnBlackHole;
534 CurrentTSO->block_info.closure = R1.cl;
536 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
539 /* PAR: dumping of event now done in blockThread -- HWL */
541 /* stg_gen_block is too heavyweight, use a specialised one */
547 Revertible black holes are needed in the parallel world, to handle
548 negative acknowledgements of messages containing updatable closures.
549 The idea is that when the original message is transmitted, the closure
550 is turned into a revertible black hole...an object which acts like a
551 black hole when local threads try to enter it, but which can be reverted
552 back to the original closure if necessary.
554 It's actually a lot like a blocking queue (BQ) entry, because revertible
555 black holes are initially set up with an empty blocking queue.
558 #if defined(PAR) || defined(GRAN)
560 INFO_TABLE(stg_RBH_info, stg_RBH_entry,1,1,RBH,,EF_,0,0);
561 STGFUN(stg_RBH_entry)
565 /* mainly statistics gathering for GranSim simulation */
566 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
569 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
570 /* Put ourselves on the blocking queue for this black hole */
571 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
572 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
573 /* jot down why and on what closure we are blocked */
574 CurrentTSO->why_blocked = BlockedOnBlackHole;
575 CurrentTSO->block_info.closure = R1.cl;
577 /* PAR: dumping of event now done in blockThread -- HWL */
579 /* stg_gen_block is too heavyweight, use a specialised one */
584 INFO_TABLE(RBH_Save_0_info, RBH_Save_0_entry,0,2,CONSTR,,EF_,0,0);
585 NON_ENTERABLE_ENTRY_CODE(RBH_Save_0);
587 INFO_TABLE(RBH_Save_1_info, RBH_Save_1_entry,1,1,CONSTR,,EF_,0,0);
588 NON_ENTERABLE_ENTRY_CODE(RBH_Save_1);
590 INFO_TABLE(RBH_Save_2_info, RBH_Save_2_entry,2,0,CONSTR,,EF_,0,0);
591 NON_ENTERABLE_ENTRY_CODE(RBH_Save_2);
592 #endif /* defined(PAR) || defined(GRAN) */
594 /* identical to BLACKHOLEs except for the infotag */
595 INFO_TABLE(CAF_BLACKHOLE_info, CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,,EF_,"CAF_BLACKHOLE","CAF_BLACKHOLE");
596 STGFUN(stg_CAF_BLACKHOLE_entry)
600 /* mainly statistics gathering for GranSim simulation */
601 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
606 bdescr *bd = Bdescr(R1.p);
607 if (bd->back != (bdescr *)BaseReg) {
608 if (bd->gen->no >= 1 || bd->step->no >= 1) {
609 CMPXCHG(R1.cl->header.info, &CAF_BLACKHOLE_info, &WHITEHOLE_info);
611 EXTFUN_RTS(stg_gc_enter_1_hponly);
612 JMP_(stg_gc_enter_1_hponly);
620 /* Put ourselves on the blocking queue for this black hole */
621 #if defined(GRAN) || defined(PAR)
622 /* in fact, only difference is the type of the end-of-queue marker! */
623 CurrentTSO->link = END_BQ_QUEUE;
624 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
626 CurrentTSO->link = END_TSO_QUEUE;
627 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
629 /* jot down why and on what closure we are blocked */
630 CurrentTSO->why_blocked = BlockedOnBlackHole;
631 CurrentTSO->block_info.closure = R1.cl;
632 /* closure is mutable since something has just been added to its BQ */
633 recordMutable((StgMutClosure *)R1.cl);
634 /* Change the CAF_BLACKHOLE into a BLACKHOLE_BQ */
635 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
637 /* PAR: dumping of event now done in blockThread -- HWL */
639 /* stg_gen_block is too heavyweight, use a specialised one */
645 INFO_TABLE(stg_SE_BLACKHOLE_info, stg_SE_BLACKHOLE_entry,0,2,SE_BLACKHOLE,,EF_,0,0);
646 STGFUN(stg_SE_BLACKHOLE_entry)
649 STGCALL3(fprintf,stderr,"SE_BLACKHOLE at %p entered!\n",R1.p);
650 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
654 INFO_TABLE(SE_CAF_BLACKHOLE_info, SE_CAF_BLACKHOLE_entry,0,2,SE_CAF_BLACKHOLE,,EF_,0,0);
655 STGFUN(stg_SE_CAF_BLACKHOLE_entry)
658 STGCALL3(fprintf,stderr,"SE_CAF_BLACKHOLE at %p entered!\n",R1.p);
659 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
665 INFO_TABLE(stg_WHITEHOLE_info, stg_WHITEHOLE_entry,0,2,CONSTR_NOCAF_STATIC,,EF_,0,0);
666 STGFUN(stg_WHITEHOLE_entry)
669 JMP_(GET_ENTRY(R1.cl));
674 /* -----------------------------------------------------------------------------
675 The code for a BCO returns to the scheduler
676 -------------------------------------------------------------------------- */
677 INFO_TABLE(stg_BCO_info,stg_BCO_entry,0,0,BCO,,EF_,"BCO","BCO");
678 STGFUN(stg_BCO_entry) {
682 JMP_(stg_yield_to_Hugs);
686 /* -----------------------------------------------------------------------------
687 Some static info tables for things that don't get entered, and
688 therefore don't need entry code (i.e. boxed but unpointed objects)
689 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
690 -------------------------------------------------------------------------- */
692 INFO_TABLE(stg_TSO_info, stg_TSO_entry, 0,0,TSO,,EF_,"TSO","TSO");
693 NON_ENTERABLE_ENTRY_CODE(TSO);
695 /* -----------------------------------------------------------------------------
696 Evacuees are left behind by the garbage collector. Any attempt to enter
698 -------------------------------------------------------------------------- */
700 INFO_TABLE(stg_EVACUATED_info,stg_EVACUATED_entry,1,0,EVACUATED,,EF_,0,0);
701 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
703 /* -----------------------------------------------------------------------------
706 Live weak pointers have a special closure type. Dead ones are just
707 nullary constructors (although they live on the heap - we overwrite
708 live weak pointers with dead ones).
709 -------------------------------------------------------------------------- */
711 INFO_TABLE(stg_WEAK_info,stg_WEAK_entry,0,4,WEAK,,EF_,"WEAK","WEAK");
712 NON_ENTERABLE_ENTRY_CODE(WEAK);
714 INFO_TABLE_CONSTR(stg_DEAD_WEAK_info,stg_DEAD_WEAK_entry,0,1,0,CONSTR,,EF_,"DEAD_WEAK","DEAD_WEAK");
715 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
717 /* -----------------------------------------------------------------------------
720 This is a static nullary constructor (like []) that we use to mark an empty
721 finalizer in a weak pointer object.
722 -------------------------------------------------------------------------- */
724 INFO_TABLE_CONSTR(stg_NO_FINALIZER_info,stg_NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
725 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
727 SET_STATIC_HDR(stg_NO_FINALIZER_closure,NO_FINALIZER_info,0/*CC*/,,EI_)
730 /* -----------------------------------------------------------------------------
731 Foreign Objects are unlifted and therefore never entered.
732 -------------------------------------------------------------------------- */
734 INFO_TABLE(stg_FOREIGN_info,stg_FOREIGN_entry,0,1,FOREIGN,,EF_,"FOREIGN","FOREIGN");
735 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
737 /* -----------------------------------------------------------------------------
738 Stable Names are unlifted too.
739 -------------------------------------------------------------------------- */
741 INFO_TABLE(stg_STABLE_NAME_info,stg_STABLE_NAME_entry,0,1,STABLE_NAME,,EF_,"STABLE_NAME","STABLE_NAME");
742 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
744 /* -----------------------------------------------------------------------------
747 There are two kinds of these: full and empty. We need an info table
748 and entry code for each type.
749 -------------------------------------------------------------------------- */
751 INFO_TABLE(stg_FULL_MVAR_info,stg_FULL_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
752 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
754 INFO_TABLE(stg_EMPTY_MVAR_info,stg_EMPTY_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
755 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
757 /* -----------------------------------------------------------------------------
760 This is a static nullary constructor (like []) that we use to mark the
761 end of a linked TSO queue.
762 -------------------------------------------------------------------------- */
764 INFO_TABLE_CONSTR(stg_END_TSO_QUEUE_info,stg_END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
765 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
767 SET_STATIC_HDR(stg_END_TSO_QUEUE_closure,stg_END_TSO_QUEUE_info,0/*CC*/,,EI_)
770 /* -----------------------------------------------------------------------------
773 Mutable lists (used by the garbage collector) consist of a chain of
774 StgMutClosures connected through their mut_link fields, ending in
775 an END_MUT_LIST closure.
776 -------------------------------------------------------------------------- */
778 INFO_TABLE_CONSTR(stg_END_MUT_LIST_info,stg_END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
779 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
781 SET_STATIC_HDR(stg_END_MUT_LIST_closure,stg_END_MUT_LIST_info,0/*CC*/,,EI_)
784 INFO_TABLE(stg_MUT_CONS_info, stg_MUT_CONS_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
785 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
787 /* -----------------------------------------------------------------------------
789 -------------------------------------------------------------------------- */
791 INFO_TABLE_CONSTR(stg_END_EXCEPTION_LIST_info,stg_END_EXCEPTION_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
792 NON_ENTERABLE_ENTRY_CODE(END_EXCEPTION_LIST);
794 SET_STATIC_HDR(stg_END_EXCEPTION_LIST_closure,stg_END_EXCEPTION_LIST_info,0/*CC*/,,EI_)
797 INFO_TABLE(stg_EXCEPTION_CONS_info, stg_EXCEPTION_CONS_entry, 1, 1, CONSTR, , EF_, 0, 0);
798 NON_ENTERABLE_ENTRY_CODE(EXCEPTION_CONS);
800 /* -----------------------------------------------------------------------------
803 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
804 pointers (StgArrPtrs). They all have a similar layout:
806 ___________________________
807 | Info | No. of | data....
809 ---------------------------
811 These are *unpointed* objects: i.e. they cannot be entered.
813 -------------------------------------------------------------------------- */
815 #define ArrayInfo(type) \
816 INFO_TABLE(stg_##type##_info, stg_##type##_entry, 0, 0, type, , EF_,"" # type "","" # type "");
818 ArrayInfo(ARR_WORDS);
819 NON_ENTERABLE_ENTRY_CODE(ARR_WORDS);
820 ArrayInfo(MUT_ARR_PTRS);
821 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS);
822 ArrayInfo(MUT_ARR_PTRS_FROZEN);
823 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS_FROZEN);
827 /* -----------------------------------------------------------------------------
829 -------------------------------------------------------------------------- */
831 INFO_TABLE(stg_MUT_VAR_info, stg_MUT_VAR_entry, 1, 1, MUT_VAR, , EF_, "MUT_VAR", "MUT_VAR");
832 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
834 /* -----------------------------------------------------------------------------
835 Standard Error Entry.
837 This is used for filling in vector-table entries that can never happen,
839 -------------------------------------------------------------------------- */
840 /* No longer used; we use NULL, because a) it never happens, right? and b)
841 Windows doesn't like DLL entry points being used as static initialisers
842 STGFUN(stg_error_entry) \
845 DUMP_ERRMSG("fatal: stg_error_entry"); \
846 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
851 /* -----------------------------------------------------------------------------
854 Entering this closure will just return to the address on the top of the
855 stack. Useful for getting a thread in a canonical form where we can
856 just enter the top stack word to start the thread. (see deleteThread)
857 * -------------------------------------------------------------------------- */
859 INFO_TABLE(stg_dummy_ret_info, stg_dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, , EF_, 0, 0);
860 STGFUN(stg_dummy_ret_entry)
866 JMP_(ENTRY_CODE(ret_addr));
869 SET_STATIC_HDR(stg_dummy_ret_closure,stg_dummy_ret_info,CCS_DONT_CARE,,EI_)
872 /* -----------------------------------------------------------------------------
873 Strict IO application - performing an IO action and entering its result.
875 rts_evalIO() lets you perform Haskell IO actions from outside of Haskell-land,
876 returning back to you their result. Want this result to be evaluated to WHNF
877 by that time, so that we can easily get at the int/char/whatever using the
878 various get{Ty} functions provided by the RTS API.
880 forceIO takes care of this, performing the IO action and entering the
881 results that comes back.
883 * -------------------------------------------------------------------------- */
886 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
887 STGFUN(stg_forceIO_ret_entry)
891 Sp -= sizeofW(StgSeqFrame);
893 JMP_(GET_ENTRY(R1.cl));
896 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
897 STGFUN(forceIO_ret_entry)
901 rval = (StgClosure *)Sp[0];
903 Sp -= sizeofW(StgSeqFrame);
906 JMP_(GET_ENTRY(R1.cl));
910 INFO_TABLE(stg_forceIO_info,stg_forceIO_entry,1,0,FUN_STATIC,,EF_,0,0);
911 FN_(stg_forceIO_entry)
914 /* Sp[0] contains the IO action we want to perform */
916 /* Replace it with the return continuation that enters the result. */
917 Sp[0] = (W_)&stg_forceIO_ret_info;
919 /* Push the RealWorld# tag and enter */
920 Sp[0] =(W_)REALWORLD_TAG;
921 JMP_(GET_ENTRY(R1.cl));
924 SET_STATIC_HDR(stg_forceIO_closure,stg_forceIO_info,CCS_DONT_CARE,,EI_)
928 /* -----------------------------------------------------------------------------
929 Standard Infotables (for use in interpreter)
930 -------------------------------------------------------------------------- */
934 STGFUN(stg_Hugs_CONSTR_entry)
936 /* R1 points at the constructor */
937 JMP_(ENTRY_CODE(((StgPtr*)Sp)[0]));
940 #define RET_BCO_ENTRY_TEMPLATE(label) \
945 ((StgPtr*)Sp)[0] = R1.p; \
946 JMP_(stg_yield_to_Hugs); \
950 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_entry );
951 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_0_entry);
952 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_1_entry);
953 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_2_entry);
954 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_3_entry);
955 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_4_entry);
956 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_5_entry);
957 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_6_entry);
958 RET_BCO_ENTRY_TEMPLATE(stg_ret_bco_7_entry);
960 VEC_POLY_INFO_TABLE(stg_ret_bco,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
962 #endif /* INTERPRETER */
964 /* -----------------------------------------------------------------------------
965 CHARLIKE and INTLIKE closures.
967 These are static representations of Chars and small Ints, so that
968 we can remove dynamic Chars and Ints during garbage collection and
969 replace them with references to the static objects.
970 -------------------------------------------------------------------------- */
972 #if defined(INTERPRETER) || defined(ENABLE_WIN32_DLL_SUPPORT)
974 * When sticking the RTS in a DLL, we delay populating the
975 * Charlike and Intlike tables until load-time, which is only
976 * when we've got the real addresses to the C# and I# closures.
979 static INFO_TBL_CONST StgInfoTable czh_static_info;
980 static INFO_TBL_CONST StgInfoTable izh_static_info;
981 #define Char_hash_static_info czh_static_info
982 #define Int_hash_static_info izh_static_info
984 #define Char_hash_static_info PrelBase_Czh_static_info
985 #define Int_hash_static_info PrelBase_Izh_static_info
988 #define CHARLIKE_HDR(n) \
990 STATIC_HDR(Char_hash_static_info, /* C# */ \
995 #define INTLIKE_HDR(n) \
997 STATIC_HDR(Int_hash_static_info, /* I# */ \
1002 /* put these in the *data* section, since the garbage collector relies
1003 * on the fact that static closures live in the data section.
1006 /* end the name with _closure, to convince the mangler this is a closure */
1008 StgIntCharlikeClosure stg_CHARLIKE_closure[] = {
1267 StgIntCharlikeClosure stg_INTLIKE_closure[] = {
1268 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
1300 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */