1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.54 2000/12/14 15:19:48 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 mci_make_constr. */
57 FN_(stg_bco_constr_entry)
59 /* R1 points at the constructor */
61 STGCALL2(fprintf,stderr,"stg_bco_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_bco_constr1_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),0)); FE_ }
69 FN_(stg_bco_constr2_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),1)); FE_ }
70 FN_(stg_bco_constr3_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),2)); FE_ }
71 FN_(stg_bco_constr4_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),3)); FE_ }
72 FN_(stg_bco_constr5_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),4)); FE_ }
73 FN_(stg_bco_constr6_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),5)); FE_ }
74 FN_(stg_bco_constr7_entry) { FB_ JMP_(RET_VEC((P_)(*Sp),6)); FE_ }
75 FN_(stg_bco_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_BCORET_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_BCORET_R1_Template(stg_bcoret_R1_entry);
127 STG_BCORET_R1_Template(stg_bcoret_R1_0_entry);
128 STG_BCORET_R1_Template(stg_bcoret_R1_1_entry);
129 STG_BCORET_R1_Template(stg_bcoret_R1_2_entry);
130 STG_BCORET_R1_Template(stg_bcoret_R1_3_entry);
131 STG_BCORET_R1_Template(stg_bcoret_R1_4_entry);
132 STG_BCORET_R1_Template(stg_bcoret_R1_5_entry);
133 STG_BCORET_R1_Template(stg_bcoret_R1_6_entry);
134 STG_BCORET_R1_Template(stg_bcoret_R1_7_entry);
136 VEC_POLY_INFO_TABLE(stg_bcoret_R1,0, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, RET_BCO,, EF_);
139 /* Entering a BCO. Heave it on the stack and defer to the
141 INFO_TABLE(stg_BCO_info,stg_BCO_entry,3,0,BCO,,EF_,"BCO","BCO");
142 STGFUN(stg_BCO_entry) {
146 JMP_(stg_yield_to_interpreter);
153 /* -----------------------------------------------------------------------------
154 Entry code for an indirection.
155 -------------------------------------------------------------------------- */
157 INFO_TABLE(stg_IND_info,stg_IND_entry,1,0,IND,,EF_,0,0);
158 STGFUN(stg_IND_entry)
161 TICK_ENT_IND(Node); /* tick */
163 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
165 JMP_(ENTRY_CODE(*R1.p));
169 INFO_TABLE(stg_IND_STATIC_info,stg_IND_STATIC_entry,1,0,IND_STATIC,,EF_,0,0);
170 STGFUN(stg_IND_STATIC_entry)
173 TICK_ENT_IND(Node); /* tick */
174 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
176 JMP_(ENTRY_CODE(*R1.p));
180 INFO_TABLE(stg_IND_PERM_info,stg_IND_PERM_entry,1,1,IND_PERM,,EF_,"IND_PERM","IND_PERM");
181 STGFUN(stg_IND_PERM_entry)
184 /* Don't add INDs to granularity cost */
185 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
187 #if defined(TICKY_TICKY) && !defined(PROFILING)
188 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
189 TICK_ENT_PERM_IND(R1.p); /* tick */
192 /* Enter PAP cost centre -- lexical scoping only */
193 ENTER_CCS_PAP_CL(R1.cl);
195 /* For ticky-ticky, change the perm_ind to a normal ind on first
196 * entry, so the number of ent_perm_inds is the number of *thunks*
197 * entered again, not the number of subsequent entries.
199 * Since this screws up cost centres, we die if profiling and
200 * ticky_ticky are on at the same time. KSW 1999-01.
205 # error Profiling and ticky-ticky do not mix at present!
206 # endif /* PROFILING */
207 SET_INFO((StgInd*)R1.p,&IND_info);
208 #endif /* TICKY_TICKY */
210 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
212 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
214 #if defined(TICKY_TICKY) && !defined(PROFILING)
218 JMP_(ENTRY_CODE(*R1.p));
222 INFO_TABLE(stg_IND_OLDGEN_info,stg_IND_OLDGEN_entry,1,1,IND_OLDGEN,,EF_,0,0);
223 STGFUN(stg_IND_OLDGEN_entry)
226 TICK_ENT_IND(Node); /* tick */
228 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
230 JMP_(ENTRY_CODE(*R1.p));
234 INFO_TABLE(stg_IND_OLDGEN_PERM_info,stg_IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,,EF_,0,0);
235 STGFUN(stg_IND_OLDGEN_PERM_entry)
238 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
240 #if defined(TICKY_TICKY) && !defined(PROFILING)
241 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
242 TICK_ENT_PERM_IND(R1.p); /* tick */
245 /* Enter PAP cost centre -- lexical scoping only */
246 ENTER_CCS_PAP_CL(R1.cl);
248 /* see comment in IND_PERM */
251 # error Profiling and ticky-ticky do not mix at present!
252 # endif /* PROFILING */
253 SET_INFO((StgInd*)R1.p,&IND_OLDGEN_info);
254 #endif /* TICKY_TICKY */
256 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
258 JMP_(ENTRY_CODE(*R1.p));
262 /* -----------------------------------------------------------------------------
265 This code assumes R1 is in a register for now.
266 -------------------------------------------------------------------------- */
268 INFO_TABLE(stg_CAF_UNENTERED_info,stg_CAF_UNENTERED_entry,1,3,CAF_UNENTERED,,EF_,0,0);
269 STGFUN(stg_CAF_UNENTERED_entry)
272 /* ToDo: implement directly in GHC */
275 JMP_(stg_yield_to_interpreter);
279 /* 0,4 is entirely bogus; _do not_ rely on this info */
280 INFO_TABLE(stg_CAF_ENTERED_info,stg_CAF_ENTERED_entry,0,4,CAF_ENTERED,,EF_,0,0);
281 STGFUN(stg_CAF_ENTERED_entry)
284 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
286 JMP_(GET_ENTRY(R1.cl));
290 /* -----------------------------------------------------------------------------
291 Entry code for a black hole.
293 Entering a black hole normally causes a cyclic data dependency, but
294 in the concurrent world, black holes are synchronization points,
295 and they are turned into blocking queues when there are threads
296 waiting for the evaluation of the closure to finish.
297 -------------------------------------------------------------------------- */
299 /* Note: a BLACKHOLE and BLACKHOLE_BQ must be big enough to be
300 * overwritten with an indirection/evacuee/catch. Thus we claim it
301 * has 1 non-pointer word of payload (in addition to the pointer word
302 * for the blocking queue in a BQ), which should be big enough for an
303 * old-generation indirection.
306 INFO_TABLE(stg_BLACKHOLE_info, stg_BLACKHOLE_entry,0,2,BLACKHOLE,,EF_,"BLACKHOLE","BLACKHOLE");
307 STGFUN(stg_BLACKHOLE_entry)
311 /* Before overwriting TSO_LINK */
312 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
317 bdescr *bd = Bdescr(R1.p);
318 if (bd->back != (bdescr *)BaseReg) {
319 if (bd->gen->no >= 1 || bd->step->no >= 1) {
320 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
322 EXTFUN_RTS(stg_gc_enter_1_hponly);
323 JMP_(stg_gc_enter_1_hponly);
330 /* Put ourselves on the blocking queue for this black hole */
331 #if defined(GRAN) || defined(PAR)
332 /* in fact, only difference is the type of the end-of-queue marker! */
333 CurrentTSO->link = END_BQ_QUEUE;
334 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
336 CurrentTSO->link = END_TSO_QUEUE;
337 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
339 /* jot down why and on what closure we are blocked */
340 CurrentTSO->why_blocked = BlockedOnBlackHole;
341 CurrentTSO->block_info.closure = R1.cl;
342 /* closure is mutable since something has just been added to its BQ */
343 recordMutable((StgMutClosure *)R1.cl);
344 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
345 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
347 /* PAR: dumping of event now done in blockThread -- HWL */
349 /* stg_gen_block is too heavyweight, use a specialised one */
355 INFO_TABLE(stg_BLACKHOLE_BQ_info, stg_BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,,EF_,"BLACKHOLE","BLACKHOLE");
356 STGFUN(stg_BLACKHOLE_BQ_entry)
360 /* Before overwriting TSO_LINK */
361 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
366 bdescr *bd = Bdescr(R1.p);
367 if (bd->back != (bdescr *)BaseReg) {
368 if (bd->gen->no >= 1 || bd->step->no >= 1) {
369 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
371 EXTFUN_RTS(stg_gc_enter_1_hponly);
372 JMP_(stg_gc_enter_1_hponly);
380 /* Put ourselves on the blocking queue for this black hole */
381 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
382 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
383 /* jot down why and on what closure we are blocked */
384 CurrentTSO->why_blocked = BlockedOnBlackHole;
385 CurrentTSO->block_info.closure = R1.cl;
387 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
390 /* PAR: dumping of event now done in blockThread -- HWL */
392 /* stg_gen_block is too heavyweight, use a specialised one */
398 Revertible black holes are needed in the parallel world, to handle
399 negative acknowledgements of messages containing updatable closures.
400 The idea is that when the original message is transmitted, the closure
401 is turned into a revertible black hole...an object which acts like a
402 black hole when local threads try to enter it, but which can be reverted
403 back to the original closure if necessary.
405 It's actually a lot like a blocking queue (BQ) entry, because revertible
406 black holes are initially set up with an empty blocking queue.
409 #if defined(PAR) || defined(GRAN)
411 INFO_TABLE(stg_RBH_info, stg_RBH_entry,1,1,RBH,,EF_,0,0);
412 STGFUN(stg_RBH_entry)
416 /* mainly statistics gathering for GranSim simulation */
417 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
420 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
421 /* Put ourselves on the blocking queue for this black hole */
422 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
423 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
424 /* jot down why and on what closure we are blocked */
425 CurrentTSO->why_blocked = BlockedOnBlackHole;
426 CurrentTSO->block_info.closure = R1.cl;
428 /* PAR: dumping of event now done in blockThread -- HWL */
430 /* stg_gen_block is too heavyweight, use a specialised one */
435 INFO_TABLE(stg_RBH_Save_0_info, stg_RBH_Save_0_entry,0,2,CONSTR,,EF_,0,0);
436 NON_ENTERABLE_ENTRY_CODE(RBH_Save_0);
438 INFO_TABLE(stg_RBH_Save_1_info, stg_RBH_Save_1_entry,1,1,CONSTR,,EF_,0,0);
439 NON_ENTERABLE_ENTRY_CODE(RBH_Save_1);
441 INFO_TABLE(stg_RBH_Save_2_info, stg_RBH_Save_2_entry,2,0,CONSTR,,EF_,0,0);
442 NON_ENTERABLE_ENTRY_CODE(RBH_Save_2);
443 #endif /* defined(PAR) || defined(GRAN) */
445 /* identical to BLACKHOLEs except for the infotag */
446 INFO_TABLE(stg_CAF_BLACKHOLE_info, stg_CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,,EF_,"CAF_BLACKHOLE","CAF_BLACKHOLE");
447 STGFUN(stg_CAF_BLACKHOLE_entry)
451 /* mainly statistics gathering for GranSim simulation */
452 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
457 bdescr *bd = Bdescr(R1.p);
458 if (bd->back != (bdescr *)BaseReg) {
459 if (bd->gen->no >= 1 || bd->step->no >= 1) {
460 CMPXCHG(R1.cl->header.info, &CAF_BLACKHOLE_info, &WHITEHOLE_info);
462 EXTFUN_RTS(stg_gc_enter_1_hponly);
463 JMP_(stg_gc_enter_1_hponly);
471 /* Put ourselves on the blocking queue for this black hole */
472 #if defined(GRAN) || defined(PAR)
473 /* in fact, only difference is the type of the end-of-queue marker! */
474 CurrentTSO->link = END_BQ_QUEUE;
475 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
477 CurrentTSO->link = END_TSO_QUEUE;
478 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
480 /* jot down why and on what closure we are blocked */
481 CurrentTSO->why_blocked = BlockedOnBlackHole;
482 CurrentTSO->block_info.closure = R1.cl;
483 /* closure is mutable since something has just been added to its BQ */
484 recordMutable((StgMutClosure *)R1.cl);
485 /* Change the CAF_BLACKHOLE into a BLACKHOLE_BQ */
486 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
488 /* PAR: dumping of event now done in blockThread -- HWL */
490 /* stg_gen_block is too heavyweight, use a specialised one */
496 INFO_TABLE(stg_SE_BLACKHOLE_info, stg_SE_BLACKHOLE_entry,0,2,SE_BLACKHOLE,,EF_,0,0);
497 STGFUN(stg_SE_BLACKHOLE_entry)
500 STGCALL3(fprintf,stderr,"SE_BLACKHOLE at %p entered!\n",R1.p);
501 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
505 INFO_TABLE(SE_CAF_BLACKHOLE_info, SE_CAF_BLACKHOLE_entry,0,2,SE_CAF_BLACKHOLE,,EF_,0,0);
506 STGFUN(stg_SE_CAF_BLACKHOLE_entry)
509 STGCALL3(fprintf,stderr,"SE_CAF_BLACKHOLE at %p entered!\n",R1.p);
510 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
516 INFO_TABLE(stg_WHITEHOLE_info, stg_WHITEHOLE_entry,0,2,CONSTR_NOCAF_STATIC,,EF_,0,0);
517 STGFUN(stg_WHITEHOLE_entry)
520 JMP_(GET_ENTRY(R1.cl));
525 /* -----------------------------------------------------------------------------
526 Some static info tables for things that don't get entered, and
527 therefore don't need entry code (i.e. boxed but unpointed objects)
528 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
529 -------------------------------------------------------------------------- */
531 INFO_TABLE(stg_TSO_info, stg_TSO_entry, 0,0,TSO,,EF_,"TSO","TSO");
532 NON_ENTERABLE_ENTRY_CODE(TSO);
534 /* -----------------------------------------------------------------------------
535 Evacuees are left behind by the garbage collector. Any attempt to enter
537 -------------------------------------------------------------------------- */
539 INFO_TABLE(stg_EVACUATED_info,stg_EVACUATED_entry,1,0,EVACUATED,,EF_,0,0);
540 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
542 /* -----------------------------------------------------------------------------
545 Live weak pointers have a special closure type. Dead ones are just
546 nullary constructors (although they live on the heap - we overwrite
547 live weak pointers with dead ones).
548 -------------------------------------------------------------------------- */
550 INFO_TABLE(stg_WEAK_info,stg_WEAK_entry,0,4,WEAK,,EF_,"WEAK","WEAK");
551 NON_ENTERABLE_ENTRY_CODE(WEAK);
553 INFO_TABLE_CONSTR(stg_DEAD_WEAK_info,stg_DEAD_WEAK_entry,0,1,0,CONSTR,,EF_,"DEAD_WEAK","DEAD_WEAK");
554 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
556 /* -----------------------------------------------------------------------------
559 This is a static nullary constructor (like []) that we use to mark an empty
560 finalizer in a weak pointer object.
561 -------------------------------------------------------------------------- */
563 INFO_TABLE_CONSTR(stg_NO_FINALIZER_info,stg_NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
564 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
566 SET_STATIC_HDR(stg_NO_FINALIZER_closure,stg_NO_FINALIZER_info,0/*CC*/,,EI_)
569 /* -----------------------------------------------------------------------------
570 Foreign Objects are unlifted and therefore never entered.
571 -------------------------------------------------------------------------- */
573 INFO_TABLE(stg_FOREIGN_info,stg_FOREIGN_entry,0,1,FOREIGN,,EF_,"FOREIGN","FOREIGN");
574 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
576 /* -----------------------------------------------------------------------------
577 Stable Names are unlifted too.
578 -------------------------------------------------------------------------- */
580 INFO_TABLE(stg_STABLE_NAME_info,stg_STABLE_NAME_entry,0,1,STABLE_NAME,,EF_,"STABLE_NAME","STABLE_NAME");
581 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
583 /* -----------------------------------------------------------------------------
586 There are two kinds of these: full and empty. We need an info table
587 and entry code for each type.
588 -------------------------------------------------------------------------- */
590 INFO_TABLE(stg_FULL_MVAR_info,stg_FULL_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
591 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
593 INFO_TABLE(stg_EMPTY_MVAR_info,stg_EMPTY_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
594 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
596 /* -----------------------------------------------------------------------------
599 This is a static nullary constructor (like []) that we use to mark the
600 end of a linked TSO queue.
601 -------------------------------------------------------------------------- */
603 INFO_TABLE_CONSTR(stg_END_TSO_QUEUE_info,stg_END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
604 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
606 SET_STATIC_HDR(stg_END_TSO_QUEUE_closure,stg_END_TSO_QUEUE_info,0/*CC*/,,EI_)
609 /* -----------------------------------------------------------------------------
612 Mutable lists (used by the garbage collector) consist of a chain of
613 StgMutClosures connected through their mut_link fields, ending in
614 an END_MUT_LIST closure.
615 -------------------------------------------------------------------------- */
617 INFO_TABLE_CONSTR(stg_END_MUT_LIST_info,stg_END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
618 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
620 SET_STATIC_HDR(stg_END_MUT_LIST_closure,stg_END_MUT_LIST_info,0/*CC*/,,EI_)
623 INFO_TABLE(stg_MUT_CONS_info, stg_MUT_CONS_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
624 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
626 /* -----------------------------------------------------------------------------
628 -------------------------------------------------------------------------- */
630 INFO_TABLE_CONSTR(stg_END_EXCEPTION_LIST_info,stg_END_EXCEPTION_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
631 NON_ENTERABLE_ENTRY_CODE(END_EXCEPTION_LIST);
633 SET_STATIC_HDR(stg_END_EXCEPTION_LIST_closure,stg_END_EXCEPTION_LIST_info,0/*CC*/,,EI_)
636 INFO_TABLE(stg_EXCEPTION_CONS_info, stg_EXCEPTION_CONS_entry, 1, 1, CONSTR, , EF_, 0, 0);
637 NON_ENTERABLE_ENTRY_CODE(EXCEPTION_CONS);
639 /* -----------------------------------------------------------------------------
642 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
643 pointers (StgArrPtrs). They all have a similar layout:
645 ___________________________
646 | Info | No. of | data....
648 ---------------------------
650 These are *unpointed* objects: i.e. they cannot be entered.
652 -------------------------------------------------------------------------- */
654 #define ArrayInfo(type) \
655 INFO_TABLE(stg_##type##_info, stg_##type##_entry, 0, 0, type, , EF_,"" # type "","" # type "");
657 ArrayInfo(ARR_WORDS);
658 NON_ENTERABLE_ENTRY_CODE(ARR_WORDS);
659 ArrayInfo(MUT_ARR_PTRS);
660 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS);
661 ArrayInfo(MUT_ARR_PTRS_FROZEN);
662 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS_FROZEN);
666 /* -----------------------------------------------------------------------------
668 -------------------------------------------------------------------------- */
670 INFO_TABLE(stg_MUT_VAR_info, stg_MUT_VAR_entry, 1, 1, MUT_VAR, , EF_, "MUT_VAR", "MUT_VAR");
671 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
673 /* -----------------------------------------------------------------------------
674 Standard Error Entry.
676 This is used for filling in vector-table entries that can never happen,
678 -------------------------------------------------------------------------- */
679 /* No longer used; we use NULL, because a) it never happens, right? and b)
680 Windows doesn't like DLL entry points being used as static initialisers
681 STGFUN(stg_error_entry) \
684 DUMP_ERRMSG("fatal: stg_error_entry"); \
685 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
690 /* -----------------------------------------------------------------------------
693 Entering this closure will just return to the address on the top of the
694 stack. Useful for getting a thread in a canonical form where we can
695 just enter the top stack word to start the thread. (see deleteThread)
696 * -------------------------------------------------------------------------- */
698 INFO_TABLE(stg_dummy_ret_info, stg_dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, , EF_, 0, 0);
699 STGFUN(stg_dummy_ret_entry)
705 JMP_(ENTRY_CODE(ret_addr));
708 SET_STATIC_HDR(stg_dummy_ret_closure,stg_dummy_ret_info,CCS_DONT_CARE,,EI_)
711 /* -----------------------------------------------------------------------------
712 Strict IO application - performing an IO action and entering its result.
714 rts_evalIO() lets you perform Haskell IO actions from outside of Haskell-land,
715 returning back to you their result. Want this result to be evaluated to WHNF
716 by that time, so that we can easily get at the int/char/whatever using the
717 various get{Ty} functions provided by the RTS API.
719 forceIO takes care of this, performing the IO action and entering the
720 results that comes back.
722 * -------------------------------------------------------------------------- */
725 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
726 STGFUN(stg_forceIO_ret_entry)
730 Sp -= sizeofW(StgSeqFrame);
732 JMP_(GET_ENTRY(R1.cl));
735 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
736 STGFUN(forceIO_ret_entry)
740 rval = (StgClosure *)Sp[0];
742 Sp -= sizeofW(StgSeqFrame);
745 JMP_(GET_ENTRY(R1.cl));
749 INFO_TABLE(stg_forceIO_info,stg_forceIO_entry,1,0,FUN_STATIC,,EF_,0,0);
750 FN_(stg_forceIO_entry)
753 /* Sp[0] contains the IO action we want to perform */
755 /* Replace it with the return continuation that enters the result. */
756 Sp[0] = (W_)&stg_forceIO_ret_info;
758 /* Push the RealWorld# tag and enter */
759 Sp[0] =(W_)REALWORLD_TAG;
760 JMP_(GET_ENTRY(R1.cl));
763 SET_STATIC_HDR(stg_forceIO_closure,stg_forceIO_info,CCS_DONT_CARE,,EI_)
767 /* -----------------------------------------------------------------------------
768 CHARLIKE and INTLIKE closures.
770 These are static representations of Chars and small Ints, so that
771 we can remove dynamic Chars and Ints during garbage collection and
772 replace them with references to the static objects.
773 -------------------------------------------------------------------------- */
775 #if defined(INTERPRETER) || defined(ENABLE_WIN32_DLL_SUPPORT)
777 * When sticking the RTS in a DLL, we delay populating the
778 * Charlike and Intlike tables until load-time, which is only
779 * when we've got the real addresses to the C# and I# closures.
782 static INFO_TBL_CONST StgInfoTable czh_static_info;
783 static INFO_TBL_CONST StgInfoTable izh_static_info;
784 #define Char_hash_static_info czh_static_info
785 #define Int_hash_static_info izh_static_info
787 #define Char_hash_static_info PrelBase_Czh_static_info
788 #define Int_hash_static_info PrelBase_Izh_static_info
791 #define CHARLIKE_HDR(n) \
793 STATIC_HDR(Char_hash_static_info, /* C# */ \
798 #define INTLIKE_HDR(n) \
800 STATIC_HDR(Int_hash_static_info, /* I# */ \
805 /* put these in the *data* section, since the garbage collector relies
806 * on the fact that static closures live in the data section.
809 /* end the name with _closure, to convince the mangler this is a closure */
811 StgIntCharlikeClosure stg_CHARLIKE_closure[] = {
1070 StgIntCharlikeClosure stg_INTLIKE_closure[] = {
1071 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
1103 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */