1 /* -----------------------------------------------------------------------------
2 * $Id: StgMiscClosures.hc,v 1.55 2000/12/14 16:32:40 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 ... */
140 /* When the returned value is in D1 ... */
144 /* The other way round: when the interpreter returns a value to
145 compiled code. The stack looks like this:
147 return info table (pushed by compiled code)
148 return value (pushed by interpreter)
150 If the value is ptr-rep'd, the interpreter simply returns to the
151 scheduler, instructing it to ThreadEnterGHC.
153 Otherwise (unboxed return value), we replace the top stack word,
154 which must be the tag, with stg_gc_unbx_r1_info (or f1_info or d1_info),
155 and return to the scheduler, instructing it to ThreadRunGHC.
157 No supporting code needed!
161 /* Entering a BCO. Heave it on the stack and defer to the
163 INFO_TABLE(stg_BCO_info,stg_BCO_entry,3,0,BCO,,EF_,"BCO","BCO");
164 STGFUN(stg_BCO_entry) {
168 JMP_(stg_yield_to_interpreter);
175 /* -----------------------------------------------------------------------------
176 Entry code for an indirection.
177 -------------------------------------------------------------------------- */
179 INFO_TABLE(stg_IND_info,stg_IND_entry,1,0,IND,,EF_,0,0);
180 STGFUN(stg_IND_entry)
183 TICK_ENT_IND(Node); /* tick */
185 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
187 JMP_(ENTRY_CODE(*R1.p));
191 INFO_TABLE(stg_IND_STATIC_info,stg_IND_STATIC_entry,1,0,IND_STATIC,,EF_,0,0);
192 STGFUN(stg_IND_STATIC_entry)
195 TICK_ENT_IND(Node); /* tick */
196 R1.p = (P_) ((StgIndStatic*)R1.p)->indirectee;
198 JMP_(ENTRY_CODE(*R1.p));
202 INFO_TABLE(stg_IND_PERM_info,stg_IND_PERM_entry,1,1,IND_PERM,,EF_,"IND_PERM","IND_PERM");
203 STGFUN(stg_IND_PERM_entry)
206 /* Don't add INDs to granularity cost */
207 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
209 #if defined(TICKY_TICKY) && !defined(PROFILING)
210 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
211 TICK_ENT_PERM_IND(R1.p); /* tick */
214 /* Enter PAP cost centre -- lexical scoping only */
215 ENTER_CCS_PAP_CL(R1.cl);
217 /* For ticky-ticky, change the perm_ind to a normal ind on first
218 * entry, so the number of ent_perm_inds is the number of *thunks*
219 * entered again, not the number of subsequent entries.
221 * Since this screws up cost centres, we die if profiling and
222 * ticky_ticky are on at the same time. KSW 1999-01.
227 # error Profiling and ticky-ticky do not mix at present!
228 # endif /* PROFILING */
229 SET_INFO((StgInd*)R1.p,&IND_info);
230 #endif /* TICKY_TICKY */
232 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
234 /* Dont: TICK_ENT_VIA_NODE(); for ticky-ticky; as above */
236 #if defined(TICKY_TICKY) && !defined(PROFILING)
240 JMP_(ENTRY_CODE(*R1.p));
244 INFO_TABLE(stg_IND_OLDGEN_info,stg_IND_OLDGEN_entry,1,1,IND_OLDGEN,,EF_,0,0);
245 STGFUN(stg_IND_OLDGEN_entry)
248 TICK_ENT_IND(Node); /* tick */
250 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
252 JMP_(ENTRY_CODE(*R1.p));
256 INFO_TABLE(stg_IND_OLDGEN_PERM_info,stg_IND_OLDGEN_PERM_entry,1,1,IND_OLDGEN_PERM,,EF_,0,0);
257 STGFUN(stg_IND_OLDGEN_PERM_entry)
260 /* Dont: TICK_ENT_IND(Node); for ticky-ticky; this ind is here only to help profiling */
262 #if defined(TICKY_TICKY) && !defined(PROFILING)
263 /* TICKY_TICKY && !PROFILING means PERM_IND *replaces* an IND, rather than being extra */
264 TICK_ENT_PERM_IND(R1.p); /* tick */
267 /* Enter PAP cost centre -- lexical scoping only */
268 ENTER_CCS_PAP_CL(R1.cl);
270 /* see comment in IND_PERM */
273 # error Profiling and ticky-ticky do not mix at present!
274 # endif /* PROFILING */
275 SET_INFO((StgInd*)R1.p,&IND_OLDGEN_info);
276 #endif /* TICKY_TICKY */
278 R1.p = (P_) ((StgInd*)R1.p)->indirectee;
280 JMP_(ENTRY_CODE(*R1.p));
284 /* -----------------------------------------------------------------------------
287 This code assumes R1 is in a register for now.
288 -------------------------------------------------------------------------- */
290 INFO_TABLE(stg_CAF_UNENTERED_info,stg_CAF_UNENTERED_entry,1,3,CAF_UNENTERED,,EF_,0,0);
291 STGFUN(stg_CAF_UNENTERED_entry)
294 /* ToDo: implement directly in GHC */
297 JMP_(stg_yield_to_interpreter);
301 /* 0,4 is entirely bogus; _do not_ rely on this info */
302 INFO_TABLE(stg_CAF_ENTERED_info,stg_CAF_ENTERED_entry,0,4,CAF_ENTERED,,EF_,0,0);
303 STGFUN(stg_CAF_ENTERED_entry)
306 R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */
308 JMP_(GET_ENTRY(R1.cl));
312 /* -----------------------------------------------------------------------------
313 Entry code for a black hole.
315 Entering a black hole normally causes a cyclic data dependency, but
316 in the concurrent world, black holes are synchronization points,
317 and they are turned into blocking queues when there are threads
318 waiting for the evaluation of the closure to finish.
319 -------------------------------------------------------------------------- */
321 /* Note: a BLACKHOLE and BLACKHOLE_BQ must be big enough to be
322 * overwritten with an indirection/evacuee/catch. Thus we claim it
323 * has 1 non-pointer word of payload (in addition to the pointer word
324 * for the blocking queue in a BQ), which should be big enough for an
325 * old-generation indirection.
328 INFO_TABLE(stg_BLACKHOLE_info, stg_BLACKHOLE_entry,0,2,BLACKHOLE,,EF_,"BLACKHOLE","BLACKHOLE");
329 STGFUN(stg_BLACKHOLE_entry)
333 /* Before overwriting TSO_LINK */
334 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
339 bdescr *bd = Bdescr(R1.p);
340 if (bd->back != (bdescr *)BaseReg) {
341 if (bd->gen->no >= 1 || bd->step->no >= 1) {
342 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
344 EXTFUN_RTS(stg_gc_enter_1_hponly);
345 JMP_(stg_gc_enter_1_hponly);
352 /* Put ourselves on the blocking queue for this black hole */
353 #if defined(GRAN) || defined(PAR)
354 /* in fact, only difference is the type of the end-of-queue marker! */
355 CurrentTSO->link = END_BQ_QUEUE;
356 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
358 CurrentTSO->link = END_TSO_QUEUE;
359 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
361 /* jot down why and on what closure we are blocked */
362 CurrentTSO->why_blocked = BlockedOnBlackHole;
363 CurrentTSO->block_info.closure = R1.cl;
364 /* closure is mutable since something has just been added to its BQ */
365 recordMutable((StgMutClosure *)R1.cl);
366 /* Change the BLACKHOLE into a BLACKHOLE_BQ */
367 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
369 /* PAR: dumping of event now done in blockThread -- HWL */
371 /* stg_gen_block is too heavyweight, use a specialised one */
377 INFO_TABLE(stg_BLACKHOLE_BQ_info, stg_BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,,EF_,"BLACKHOLE","BLACKHOLE");
378 STGFUN(stg_BLACKHOLE_BQ_entry)
382 /* Before overwriting TSO_LINK */
383 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
388 bdescr *bd = Bdescr(R1.p);
389 if (bd->back != (bdescr *)BaseReg) {
390 if (bd->gen->no >= 1 || bd->step->no >= 1) {
391 CMPXCHG(R1.cl->header.info, &BLACKHOLE_info, &WHITEHOLE_info);
393 EXTFUN_RTS(stg_gc_enter_1_hponly);
394 JMP_(stg_gc_enter_1_hponly);
402 /* Put ourselves on the blocking queue for this black hole */
403 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
404 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
405 /* jot down why and on what closure we are blocked */
406 CurrentTSO->why_blocked = BlockedOnBlackHole;
407 CurrentTSO->block_info.closure = R1.cl;
409 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
412 /* PAR: dumping of event now done in blockThread -- HWL */
414 /* stg_gen_block is too heavyweight, use a specialised one */
420 Revertible black holes are needed in the parallel world, to handle
421 negative acknowledgements of messages containing updatable closures.
422 The idea is that when the original message is transmitted, the closure
423 is turned into a revertible black hole...an object which acts like a
424 black hole when local threads try to enter it, but which can be reverted
425 back to the original closure if necessary.
427 It's actually a lot like a blocking queue (BQ) entry, because revertible
428 black holes are initially set up with an empty blocking queue.
431 #if defined(PAR) || defined(GRAN)
433 INFO_TABLE(stg_RBH_info, stg_RBH_entry,1,1,RBH,,EF_,0,0);
434 STGFUN(stg_RBH_entry)
438 /* mainly statistics gathering for GranSim simulation */
439 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
442 /* exactly the same as a BLACKHOLE_BQ_entry -- HWL */
443 /* Put ourselves on the blocking queue for this black hole */
444 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
445 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
446 /* jot down why and on what closure we are blocked */
447 CurrentTSO->why_blocked = BlockedOnBlackHole;
448 CurrentTSO->block_info.closure = R1.cl;
450 /* PAR: dumping of event now done in blockThread -- HWL */
452 /* stg_gen_block is too heavyweight, use a specialised one */
457 INFO_TABLE(stg_RBH_Save_0_info, stg_RBH_Save_0_entry,0,2,CONSTR,,EF_,0,0);
458 NON_ENTERABLE_ENTRY_CODE(RBH_Save_0);
460 INFO_TABLE(stg_RBH_Save_1_info, stg_RBH_Save_1_entry,1,1,CONSTR,,EF_,0,0);
461 NON_ENTERABLE_ENTRY_CODE(RBH_Save_1);
463 INFO_TABLE(stg_RBH_Save_2_info, stg_RBH_Save_2_entry,2,0,CONSTR,,EF_,0,0);
464 NON_ENTERABLE_ENTRY_CODE(RBH_Save_2);
465 #endif /* defined(PAR) || defined(GRAN) */
467 /* identical to BLACKHOLEs except for the infotag */
468 INFO_TABLE(stg_CAF_BLACKHOLE_info, stg_CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,,EF_,"CAF_BLACKHOLE","CAF_BLACKHOLE");
469 STGFUN(stg_CAF_BLACKHOLE_entry)
473 /* mainly statistics gathering for GranSim simulation */
474 STGCALL3(GranSimBlock,CurrentTSO,CurrentProc,(StgClosure *)R1.p /*Node*/);
479 bdescr *bd = Bdescr(R1.p);
480 if (bd->back != (bdescr *)BaseReg) {
481 if (bd->gen->no >= 1 || bd->step->no >= 1) {
482 CMPXCHG(R1.cl->header.info, &CAF_BLACKHOLE_info, &WHITEHOLE_info);
484 EXTFUN_RTS(stg_gc_enter_1_hponly);
485 JMP_(stg_gc_enter_1_hponly);
493 /* Put ourselves on the blocking queue for this black hole */
494 #if defined(GRAN) || defined(PAR)
495 /* in fact, only difference is the type of the end-of-queue marker! */
496 CurrentTSO->link = END_BQ_QUEUE;
497 ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
499 CurrentTSO->link = END_TSO_QUEUE;
500 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
502 /* jot down why and on what closure we are blocked */
503 CurrentTSO->why_blocked = BlockedOnBlackHole;
504 CurrentTSO->block_info.closure = R1.cl;
505 /* closure is mutable since something has just been added to its BQ */
506 recordMutable((StgMutClosure *)R1.cl);
507 /* Change the CAF_BLACKHOLE into a BLACKHOLE_BQ */
508 ((StgBlockingQueue *)R1.p)->header.info = &stg_BLACKHOLE_BQ_info;
510 /* PAR: dumping of event now done in blockThread -- HWL */
512 /* stg_gen_block is too heavyweight, use a specialised one */
518 INFO_TABLE(stg_SE_BLACKHOLE_info, stg_SE_BLACKHOLE_entry,0,2,SE_BLACKHOLE,,EF_,0,0);
519 STGFUN(stg_SE_BLACKHOLE_entry)
522 STGCALL3(fprintf,stderr,"SE_BLACKHOLE at %p entered!\n",R1.p);
523 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
527 INFO_TABLE(SE_CAF_BLACKHOLE_info, SE_CAF_BLACKHOLE_entry,0,2,SE_CAF_BLACKHOLE,,EF_,0,0);
528 STGFUN(stg_SE_CAF_BLACKHOLE_entry)
531 STGCALL3(fprintf,stderr,"SE_CAF_BLACKHOLE at %p entered!\n",R1.p);
532 STGCALL1(shutdownHaskellAndExit,EXIT_FAILURE);
538 INFO_TABLE(stg_WHITEHOLE_info, stg_WHITEHOLE_entry,0,2,CONSTR_NOCAF_STATIC,,EF_,0,0);
539 STGFUN(stg_WHITEHOLE_entry)
542 JMP_(GET_ENTRY(R1.cl));
547 /* -----------------------------------------------------------------------------
548 Some static info tables for things that don't get entered, and
549 therefore don't need entry code (i.e. boxed but unpointed objects)
550 NON_ENTERABLE_ENTRY_CODE now defined at the beginning of the file
551 -------------------------------------------------------------------------- */
553 INFO_TABLE(stg_TSO_info, stg_TSO_entry, 0,0,TSO,,EF_,"TSO","TSO");
554 NON_ENTERABLE_ENTRY_CODE(TSO);
556 /* -----------------------------------------------------------------------------
557 Evacuees are left behind by the garbage collector. Any attempt to enter
559 -------------------------------------------------------------------------- */
561 INFO_TABLE(stg_EVACUATED_info,stg_EVACUATED_entry,1,0,EVACUATED,,EF_,0,0);
562 NON_ENTERABLE_ENTRY_CODE(EVACUATED);
564 /* -----------------------------------------------------------------------------
567 Live weak pointers have a special closure type. Dead ones are just
568 nullary constructors (although they live on the heap - we overwrite
569 live weak pointers with dead ones).
570 -------------------------------------------------------------------------- */
572 INFO_TABLE(stg_WEAK_info,stg_WEAK_entry,0,4,WEAK,,EF_,"WEAK","WEAK");
573 NON_ENTERABLE_ENTRY_CODE(WEAK);
575 INFO_TABLE_CONSTR(stg_DEAD_WEAK_info,stg_DEAD_WEAK_entry,0,1,0,CONSTR,,EF_,"DEAD_WEAK","DEAD_WEAK");
576 NON_ENTERABLE_ENTRY_CODE(DEAD_WEAK);
578 /* -----------------------------------------------------------------------------
581 This is a static nullary constructor (like []) that we use to mark an empty
582 finalizer in a weak pointer object.
583 -------------------------------------------------------------------------- */
585 INFO_TABLE_CONSTR(stg_NO_FINALIZER_info,stg_NO_FINALIZER_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
586 NON_ENTERABLE_ENTRY_CODE(NO_FINALIZER);
588 SET_STATIC_HDR(stg_NO_FINALIZER_closure,stg_NO_FINALIZER_info,0/*CC*/,,EI_)
591 /* -----------------------------------------------------------------------------
592 Foreign Objects are unlifted and therefore never entered.
593 -------------------------------------------------------------------------- */
595 INFO_TABLE(stg_FOREIGN_info,stg_FOREIGN_entry,0,1,FOREIGN,,EF_,"FOREIGN","FOREIGN");
596 NON_ENTERABLE_ENTRY_CODE(FOREIGN);
598 /* -----------------------------------------------------------------------------
599 Stable Names are unlifted too.
600 -------------------------------------------------------------------------- */
602 INFO_TABLE(stg_STABLE_NAME_info,stg_STABLE_NAME_entry,0,1,STABLE_NAME,,EF_,"STABLE_NAME","STABLE_NAME");
603 NON_ENTERABLE_ENTRY_CODE(STABLE_NAME);
605 /* -----------------------------------------------------------------------------
608 There are two kinds of these: full and empty. We need an info table
609 and entry code for each type.
610 -------------------------------------------------------------------------- */
612 INFO_TABLE(stg_FULL_MVAR_info,stg_FULL_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
613 NON_ENTERABLE_ENTRY_CODE(FULL_MVAR);
615 INFO_TABLE(stg_EMPTY_MVAR_info,stg_EMPTY_MVAR_entry,4,0,MVAR,,EF_,"MVAR","MVAR");
616 NON_ENTERABLE_ENTRY_CODE(EMPTY_MVAR);
618 /* -----------------------------------------------------------------------------
621 This is a static nullary constructor (like []) that we use to mark the
622 end of a linked TSO queue.
623 -------------------------------------------------------------------------- */
625 INFO_TABLE_CONSTR(stg_END_TSO_QUEUE_info,stg_END_TSO_QUEUE_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
626 NON_ENTERABLE_ENTRY_CODE(END_TSO_QUEUE);
628 SET_STATIC_HDR(stg_END_TSO_QUEUE_closure,stg_END_TSO_QUEUE_info,0/*CC*/,,EI_)
631 /* -----------------------------------------------------------------------------
634 Mutable lists (used by the garbage collector) consist of a chain of
635 StgMutClosures connected through their mut_link fields, ending in
636 an END_MUT_LIST closure.
637 -------------------------------------------------------------------------- */
639 INFO_TABLE_CONSTR(stg_END_MUT_LIST_info,stg_END_MUT_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
640 NON_ENTERABLE_ENTRY_CODE(END_MUT_LIST);
642 SET_STATIC_HDR(stg_END_MUT_LIST_closure,stg_END_MUT_LIST_info,0/*CC*/,,EI_)
645 INFO_TABLE(stg_MUT_CONS_info, stg_MUT_CONS_entry, 1, 1, MUT_VAR, , EF_, 0, 0);
646 NON_ENTERABLE_ENTRY_CODE(MUT_CONS);
648 /* -----------------------------------------------------------------------------
650 -------------------------------------------------------------------------- */
652 INFO_TABLE_CONSTR(stg_END_EXCEPTION_LIST_info,stg_END_EXCEPTION_LIST_entry,0,0,0,CONSTR_NOCAF_STATIC,,EF_,0,0);
653 NON_ENTERABLE_ENTRY_CODE(END_EXCEPTION_LIST);
655 SET_STATIC_HDR(stg_END_EXCEPTION_LIST_closure,stg_END_EXCEPTION_LIST_info,0/*CC*/,,EI_)
658 INFO_TABLE(stg_EXCEPTION_CONS_info, stg_EXCEPTION_CONS_entry, 1, 1, CONSTR, , EF_, 0, 0);
659 NON_ENTERABLE_ENTRY_CODE(EXCEPTION_CONS);
661 /* -----------------------------------------------------------------------------
664 These come in two basic flavours: arrays of data (StgArrWords) and arrays of
665 pointers (StgArrPtrs). They all have a similar layout:
667 ___________________________
668 | Info | No. of | data....
670 ---------------------------
672 These are *unpointed* objects: i.e. they cannot be entered.
674 -------------------------------------------------------------------------- */
676 #define ArrayInfo(type) \
677 INFO_TABLE(stg_##type##_info, stg_##type##_entry, 0, 0, type, , EF_,"" # type "","" # type "");
679 ArrayInfo(ARR_WORDS);
680 NON_ENTERABLE_ENTRY_CODE(ARR_WORDS);
681 ArrayInfo(MUT_ARR_PTRS);
682 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS);
683 ArrayInfo(MUT_ARR_PTRS_FROZEN);
684 NON_ENTERABLE_ENTRY_CODE(MUT_ARR_PTRS_FROZEN);
688 /* -----------------------------------------------------------------------------
690 -------------------------------------------------------------------------- */
692 INFO_TABLE(stg_MUT_VAR_info, stg_MUT_VAR_entry, 1, 1, MUT_VAR, , EF_, "MUT_VAR", "MUT_VAR");
693 NON_ENTERABLE_ENTRY_CODE(MUT_VAR);
695 /* -----------------------------------------------------------------------------
696 Standard Error Entry.
698 This is used for filling in vector-table entries that can never happen,
700 -------------------------------------------------------------------------- */
701 /* No longer used; we use NULL, because a) it never happens, right? and b)
702 Windows doesn't like DLL entry points being used as static initialisers
703 STGFUN(stg_error_entry) \
706 DUMP_ERRMSG("fatal: stg_error_entry"); \
707 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE); \
712 /* -----------------------------------------------------------------------------
715 Entering this closure will just return to the address on the top of the
716 stack. Useful for getting a thread in a canonical form where we can
717 just enter the top stack word to start the thread. (see deleteThread)
718 * -------------------------------------------------------------------------- */
720 INFO_TABLE(stg_dummy_ret_info, stg_dummy_ret_entry, 0, 0, CONSTR_NOCAF_STATIC, , EF_, 0, 0);
721 STGFUN(stg_dummy_ret_entry)
727 JMP_(ENTRY_CODE(ret_addr));
730 SET_STATIC_HDR(stg_dummy_ret_closure,stg_dummy_ret_info,CCS_DONT_CARE,,EI_)
733 /* -----------------------------------------------------------------------------
734 Strict IO application - performing an IO action and entering its result.
736 rts_evalIO() lets you perform Haskell IO actions from outside of Haskell-land,
737 returning back to you their result. Want this result to be evaluated to WHNF
738 by that time, so that we can easily get at the int/char/whatever using the
739 various get{Ty} functions provided by the RTS API.
741 forceIO takes care of this, performing the IO action and entering the
742 results that comes back.
744 * -------------------------------------------------------------------------- */
747 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
748 STGFUN(stg_forceIO_ret_entry)
752 Sp -= sizeofW(StgSeqFrame);
754 JMP_(GET_ENTRY(R1.cl));
757 INFO_TABLE_SRT_BITMAP(stg_forceIO_ret_info,stg_forceIO_ret_entry,0,0,0,0,RET_SMALL,,EF_,0,0);
758 STGFUN(forceIO_ret_entry)
762 rval = (StgClosure *)Sp[0];
764 Sp -= sizeofW(StgSeqFrame);
767 JMP_(GET_ENTRY(R1.cl));
771 INFO_TABLE(stg_forceIO_info,stg_forceIO_entry,1,0,FUN_STATIC,,EF_,0,0);
772 FN_(stg_forceIO_entry)
775 /* Sp[0] contains the IO action we want to perform */
777 /* Replace it with the return continuation that enters the result. */
778 Sp[0] = (W_)&stg_forceIO_ret_info;
780 /* Push the RealWorld# tag and enter */
781 Sp[0] =(W_)REALWORLD_TAG;
782 JMP_(GET_ENTRY(R1.cl));
785 SET_STATIC_HDR(stg_forceIO_closure,stg_forceIO_info,CCS_DONT_CARE,,EI_)
789 /* -----------------------------------------------------------------------------
790 CHARLIKE and INTLIKE closures.
792 These are static representations of Chars and small Ints, so that
793 we can remove dynamic Chars and Ints during garbage collection and
794 replace them with references to the static objects.
795 -------------------------------------------------------------------------- */
797 #if defined(INTERPRETER) || defined(ENABLE_WIN32_DLL_SUPPORT)
799 * When sticking the RTS in a DLL, we delay populating the
800 * Charlike and Intlike tables until load-time, which is only
801 * when we've got the real addresses to the C# and I# closures.
804 static INFO_TBL_CONST StgInfoTable czh_static_info;
805 static INFO_TBL_CONST StgInfoTable izh_static_info;
806 #define Char_hash_static_info czh_static_info
807 #define Int_hash_static_info izh_static_info
809 #define Char_hash_static_info PrelBase_Czh_static_info
810 #define Int_hash_static_info PrelBase_Izh_static_info
813 #define CHARLIKE_HDR(n) \
815 STATIC_HDR(Char_hash_static_info, /* C# */ \
820 #define INTLIKE_HDR(n) \
822 STATIC_HDR(Int_hash_static_info, /* I# */ \
827 /* put these in the *data* section, since the garbage collector relies
828 * on the fact that static closures live in the data section.
831 /* end the name with _closure, to convince the mangler this is a closure */
833 StgIntCharlikeClosure stg_CHARLIKE_closure[] = {
1092 StgIntCharlikeClosure stg_INTLIKE_closure[] = {
1093 INTLIKE_HDR(-16), /* MIN_INTLIKE == -16 */
1125 INTLIKE_HDR(16) /* MAX_INTLIKE == 16 */