diff --git a/ghc/includes/SchedAPI.h b/ghc/includes/SchedAPI.h index 18c48f5f9cf6c5c8155593d12cdacbfcf00947a1..05d3ca859966923383a2651ba872420b04ac3523 100644 --- a/ghc/includes/SchedAPI.h +++ b/ghc/includes/SchedAPI.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: SchedAPI.h,v 1.9 2000/01/13 14:34:01 hwloidl Exp $ + * $Id: SchedAPI.h,v 1.10 2000/04/14 15:18:05 sewardj Exp $ * * (c) The GHC Team 1998 * @@ -90,14 +90,17 @@ createStrictIOThread(nat stack_size, StgClosure *closure) { /* * Killing threads */ - -void deleteThread(StgTSO *tso); -void deleteAllThreads ( void ); +extern void deleteThread(StgTSO *tso); +extern void deleteAllThreads ( void ); +extern int howManyThreadsAvail ( void ); +/* + * Run until there are no more threads. + */ +extern void finishAllThreads ( void ); /* * Reverting CAFs */ - -void RevertCAFs(void); +extern void RevertCAFs ( void ); #endif diff --git a/ghc/includes/Updates.h b/ghc/includes/Updates.h index 5378b6c8711d0b102ed49b6b98c74d45282e08ca..0c2f38507995f63c90ac92ded17ac11ab5e25a7a 100644 --- a/ghc/includes/Updates.h +++ b/ghc/includes/Updates.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Updates.h,v 1.16 2000/01/13 14:34:01 hwloidl Exp $ + * $Id: Updates.h,v 1.17 2000/04/14 15:18:05 sewardj Exp $ * * (c) The GHC Team, 1998-1999 * @@ -212,14 +212,22 @@ extern DLL_IMPORT_DATA const StgPolyInfoTable Upd_frame_info; extern void newCAF(StgClosure*); +/* newCAF must be called before the itbl ptr is overwritten, since + newCAF records the old itbl ptr in order to do CAF reverting + (which Hugs needs to do in order that combined mode works right.) +*/ #define UPD_CAF(cafptr, bhptr) \ { \ LOCK_CLOSURE(cafptr); \ + STGCALL1(newCAF,(StgClosure *)cafptr); \ ((StgInd *)cafptr)->indirectee = (StgClosure *)(bhptr); \ SET_INFO((StgInd *)cafptr,(const StgInfoTable*)&IND_STATIC_info); \ - STGCALL1(newCAF,(StgClosure *)cafptr); \ } +#ifdef INTERPRETER +extern void newCAF_made_by_Hugs(StgCAF*); +#endif + /* ----------------------------------------------------------------------------- Update-related prototypes -------------------------------------------------------------------------- */ diff --git a/ghc/interpreter/compiler.c b/ghc/interpreter/compiler.c index c6b1cce8f0e1b1cb6d0cab12187e66e792d3df1f..20bc336014454b5f76d1dfcf50d5a3422532493c 100644 --- a/ghc/interpreter/compiler.c +++ b/ghc/interpreter/compiler.c @@ -11,8 +11,8 @@ * included in the distribution. * * $RCSfile: compiler.c,v $ - * $Revision: 1.27 $ - * $Date: 2000/04/11 16:36:53 $ + * $Revision: 1.28 $ + * $Date: 2000/04/14 15:18:06 $ * ------------------------------------------------------------------------*/ #include "hugsbasictypes.h" @@ -1528,29 +1528,44 @@ Void evalExp ( void ) { /* compile and run input expression */ switch (status) { case Deadlock: printf("{Deadlock or Blackhole}"); - if (doRevertCAFs) RevertCAFs(); break; case Interrupted: printf("{Interrupted}"); - if (doRevertCAFs) RevertCAFs(); break; case Killed: printf("{Interrupted or Killed}"); - if (doRevertCAFs) RevertCAFs(); break; case Success: - if (doRevertCAFs) RevertCAFs(); break; default: internal("evalExp: Unrecognised SchedulerStatus"); } - deleteAllThreads(); + + /* Begin heap cleanup sequence */ + do { + /* fprintf ( stderr, "finalisation loop START\n" ); */ + finishAllThreads(); + finalizeWeakPointersNow(); + /* fprintf ( stderr, "finalisation loop END %d\n", + howManyThreadsAvail() ); */ + } + while (howManyThreadsAvail() > 0); + + RevertCAFs(); + performMajorGC(); + if (combined && SPT_size != 0) { + FPrintf ( stderr, + "hugs: fatal: stable pointers are not yet allowed in combined mode" ); + internal("evalExp"); + } + /* End heap cleanup sequence */ + fflush(stdout); fflush(stderr); } -#ifdef CRUDE_PROFILING +# ifdef CRUDE_PROFILING cp_show(); -#endif +# endif } diff --git a/ghc/interpreter/interface.c b/ghc/interpreter/interface.c index b70105f554f1ed533ab142bdf3cfd667df70fb81..d4719d6deed4bebc36470b277842b8e1fd2709d9 100644 --- a/ghc/interpreter/interface.c +++ b/ghc/interpreter/interface.c @@ -7,8 +7,8 @@ * Hugs version 1.4, December 1997 * * $RCSfile: interface.c,v $ - * $Revision: 1.53 $ - * $Date: 2000/04/12 09:43:10 $ + * $Revision: 1.54 $ + * $Date: 2000/04/14 15:18:06 $ * ------------------------------------------------------------------------*/ #include "hugsbasictypes.h" @@ -19,7 +19,6 @@ #include "Assembler.h" /* for wrapping GHC objects */ - /*#define DEBUG_IFACE*/ #define VERBOSE FALSE diff --git a/ghc/interpreter/storage.c b/ghc/interpreter/storage.c index 696e117f597c4eb8d7e5a0342e116a9637823923..637c15bc6ca4b9f06eed3f66f2fa55c83a73a17b 100644 --- a/ghc/interpreter/storage.c +++ b/ghc/interpreter/storage.c @@ -9,8 +9,8 @@ * included in the distribution. * * $RCSfile: storage.c,v $ - * $Revision: 1.70 $ - * $Date: 2000/04/12 09:37:19 $ + * $Revision: 1.71 $ + * $Date: 2000/04/14 15:18:06 $ * ------------------------------------------------------------------------*/ #include "hugsbasictypes.h" @@ -1640,11 +1640,13 @@ void nukeModule ( Module m ) if (!isModule(m)) internal("nukeModule"); + /* fprintf ( stderr, "NUKE MODULE %s\n", textToStr(module(m).text) ); */ + /* see comment in compiler.c about this, and interaction with info tables */ if (nukeModule_needs_major_gc) { /* fprintf ( stderr, "doing major GC in nukeModule\n"); */ - performMajorGC(); + /* performMajorGC(); */ nukeModule_needs_major_gc = FALSE; } @@ -1663,14 +1665,20 @@ void nukeModule ( Module m ) for (i = NAME_BASE_ADDR; i < NAME_BASE_ADDR+tabNameSz; i++) if (tabName[i-NAME_BASE_ADDR].inUse && name(i).mod == m) { - if (name(i).itbl) free(name(i).itbl); + if (name(i).itbl && + module(name(i).mod).mode == FM_SOURCE) { + free(name(i).itbl); + } name(i).itbl = NULL; freeName(i); } for (i = TYCON_BASE_ADDR; i < TYCON_BASE_ADDR+tabTyconSz; i++) if (tabTycon[i-TYCON_BASE_ADDR].inUse && tycon(i).mod == m) { - if (tycon(i).itbl) free(tycon(i).itbl); + if (tycon(i).itbl && + module(tycon(i).mod).mode == FM_SOURCE) { + free(tycon(i).itbl); + } tycon(i).itbl = NULL; freeTycon(i); } diff --git a/ghc/rts/Assembler.c b/ghc/rts/Assembler.c index 5b6d9dacdad1edb919b5fd962e67020b887baf85..a382920b7784c00f76e083964416f5ba4391d73d 100644 --- a/ghc/rts/Assembler.c +++ b/ghc/rts/Assembler.c @@ -5,8 +5,8 @@ * Copyright (c) 1994-1998. * * $RCSfile: Assembler.c,v $ - * $Revision: 1.25 $ - * $Date: 2000/04/11 20:44:19 $ + * $Revision: 1.26 $ + * $Date: 2000/04/14 15:18:06 $ * * This module provides functions to construct BCOs and other closures * required by the bytecode compiler. @@ -191,7 +191,7 @@ static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference ) ap->fun = reference; } else { ASSERT(ap->payload[i-1] == NULL); - ap->payload[i-1] = reference; + ap->payload[i-1] = (StgPtr)reference; } break; } @@ -1430,7 +1430,9 @@ AsmPrim ccall_stdcall_IO = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_stdcall_IO }; #ifdef DEBUG -void checkBytecodeCount( void ) { +void checkBytecodeCount( void ); +void checkBytecodeCount( void ) +{ if (MAX_Primop1 >= 255) { printf("Too many Primop1 bytecodes (%d)\n",MAX_Primop1); } diff --git a/ghc/rts/Evaluator.c b/ghc/rts/Evaluator.c index 82603e0cd5ab982eb86675b8b6983bfef5d01725..ac0c986b3d91af8ac2031488cf42a2cb1a7417eb 100644 --- a/ghc/rts/Evaluator.c +++ b/ghc/rts/Evaluator.c @@ -5,8 +5,8 @@ * Copyright (c) 1994-1998. * * $RCSfile: Evaluator.c,v $ - * $Revision: 1.47 $ - * $Date: 2000/04/11 20:44:19 $ + * $Revision: 1.48 $ + * $Date: 2000/04/14 15:18:06 $ * ---------------------------------------------------------------------------*/ #include "Rts.h" @@ -1356,22 +1356,19 @@ StgThreadReturnCode enter( Capability* cap, StgClosure* obj0 ) xPushCPtr(obj); /* code to restart with */ RETURN(StackOverflow); } - /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME - and insert an indirection immediately */ SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL; SET_INFO(bh,&CAF_BLACKHOLE_info); bh->blocking_queue = EndTSOQueue; IF_DEBUG(gccafs, - fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p in evaluator\n",bh,caf)); + fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p" + " in evaluator\n",bh,caf)); SET_INFO(caf,&CAF_ENTERED_info); caf->value = (StgClosure*)bh; - if (caf->mut_link == NULL) { - SSS; recordOldToNewPtrs((StgMutClosure*)caf); LLL; - } + + SSS; newCAF_made_by_Hugs(caf); LLL; + xPushUpdateFrame(bh,0); xSp -= sizeofW(StgUpdateFrame); - caf->link = enteredCAFs; - enteredCAFs = caf; obj = caf->body; goto enterLoop; } diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index f4308141ae83fdc38a2a317913afe7726faa4632..d3056b67306351675ed0e3d169bc1ea07f32102b 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: GC.c,v 1.78 2000/04/11 16:36:53 sewardj Exp $ + * $Id: GC.c,v 1.79 2000/04/14 15:18:06 sewardj Exp $ * * (c) The GHC Team 1998-1999 * @@ -53,8 +53,6 @@ # endif #endif -StgCAF* enteredCAFs; - //@node STATIC OBJECT LIST, Static function declarations, Includes //@subsection STATIC OBJECT LIST @@ -486,9 +484,11 @@ void GarbageCollect ( void (*get_roots)(void), rtsBool force_major_gc ) */ gcStablePtrTable(major_gc); +#if 0 /* revert dead CAFs and update enteredCAFs list */ revert_dead_CAFs(); - +#endif + #if defined(PAR) /* Reconstruct the Global Address tables used in GUM */ rebuildGAtables(major_gc); @@ -2757,7 +2757,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end) const StgInfoTable* info; StgWord32 bitmap; - IF_DEBUG(sanity, belch(" scavenging stack between %p and %p", p, stack_end)); + //IF_DEBUG(sanity, belch(" scavenging stack between %p and %p", p, stack_end)); /* * Each time around this loop, we are looking at a chunk of stack @@ -3086,18 +3086,32 @@ zero_mutable_list( StgMutClosure *first ) void RevertCAFs(void) { - while (enteredCAFs != END_CAF_LIST) { - StgCAF* caf = enteredCAFs; - - enteredCAFs = caf->link; - ASSERT(get_itbl(caf)->type == CAF_ENTERED); - SET_INFO(caf,&CAF_UNENTERED_info); - caf->value = (StgClosure *)0xdeadbeef; - caf->link = (StgCAF *)0xdeadbeef; - } - enteredCAFs = END_CAF_LIST; +#ifdef INTERPRETER + StgInt i; + + /* Deal with CAFs created by compiled code. */ + for (i = 0; i < usedECafTable; i++) { + SET_INFO( (StgInd*)(ecafTable[i].closure), ecafTable[i].origItbl ); + ((StgInd*)(ecafTable[i].closure))->indirectee = 0; + } + + /* Deal with CAFs created by the interpreter. */ + while (ecafList != END_ECAF_LIST) { + StgCAF* caf = ecafList; + ecafList = caf->link; + ASSERT(get_itbl(caf)->type == CAF_ENTERED); + SET_INFO(caf,&CAF_UNENTERED_info); + caf->value = (StgClosure *)0xdeadbeef; + caf->link = (StgCAF *)0xdeadbeef; + } + + /* Empty out both the table and the list. */ + clearECafTable(); + ecafList = END_ECAF_LIST; +#endif } +#if 0 //@cindex revert_dead_CAFs void revert_dead_CAFs(void) @@ -3120,6 +3134,7 @@ void revert_dead_CAFs(void) caf = next; } } +#endif //@node Sanity code for CAF garbage collection, Lazy black holing, Reverting CAFs //@subsection Sanity code for CAF garbage collection diff --git a/ghc/rts/Printer.c b/ghc/rts/Printer.c index 82ce1355537e55111bf5fe306572521c26f6e254..541b7c2a7789e5bdb780ffaec014531e62829956 100644 --- a/ghc/rts/Printer.c +++ b/ghc/rts/Printer.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Printer.c,v 1.24 2000/04/12 09:37:19 sewardj Exp $ + * $Id: Printer.c,v 1.25 2000/04/14 15:18:06 sewardj Exp $ * * (c) The GHC Team, 1994-2000. * @@ -152,7 +152,7 @@ void printClosure( StgClosure *obj ) fprintf(stderr,", "); printPtr((StgPtr)caf->value); /* should be null */ fprintf(stderr,", "); - printPtr((StgPtr)caf->link); /* should be null */ + printPtr((StgPtr)caf->link); fprintf(stderr,")\n"); break; } diff --git a/ghc/rts/Sanity.c b/ghc/rts/Sanity.c index 2285c416c913a8319bc17a4c4fbf30239b898b2b..a80efb257598f2080ad1adb0a8c79fabbcd1cdd3 100644 --- a/ghc/rts/Sanity.c +++ b/ghc/rts/Sanity.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Sanity.c,v 1.20 2000/04/12 09:34:46 sewardj Exp $ + * $Id: Sanity.c,v 1.21 2000/04/14 15:18:06 sewardj Exp $ * * (c) The GHC Team, 1998-1999 * @@ -482,7 +482,7 @@ checkHeap(bdescr *bd, StgPtr start) nat xxx = 0; // tmp -- HWL if (start == NULL) { - p = bd->start; + if (bd != NULL) p = bd->start; } else { p = start; } diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index 50009f272120814e9783ff2bbcc34d9f54c6a1c3..1fde2f083978fe35b96ba5dc900001d6fc637960 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -1,5 +1,5 @@ /* --------------------------------------------------------------------------- - * $Id: Schedule.c,v 1.66 2000/04/11 16:36:53 sewardj Exp $ + * $Id: Schedule.c,v 1.67 2000/04/14 15:18:07 sewardj Exp $ * * (c) The GHC Team, 1998-2000 * @@ -1066,7 +1066,7 @@ schedule( void ) break; default: - barf("doneThread: invalid thread return code"); + barf("schedule: invalid thread return code %d", (int)ret); } #ifdef SMP @@ -1572,7 +1572,10 @@ initScheduler(void) context_switch = 0; interrupted = 0; - enteredCAFs = END_CAF_LIST; + ecafList = END_ECAF_LIST; +#ifdef INTERPRETER + clearECafTable(); +#endif /* Install the SIGHUP handler */ #ifdef SMP @@ -1702,6 +1705,33 @@ exitScheduler( void ) * will be in the main_thread struct. * -------------------------------------------------------------------------- */ +int +howManyThreadsAvail ( void ) +{ + int i = 0; + StgTSO* q; + for (q = run_queue_hd; q != END_TSO_QUEUE; q = q->link) + i++; + for (q = blocked_queue_hd; q != END_TSO_QUEUE; q = q->link) + i++; + return i; +} + +void +finishAllThreads ( void ) +{ + do { + while (run_queue_hd != END_TSO_QUEUE) { + waitThread ( run_queue_hd, NULL ); + } + while (blocked_queue_hd != END_TSO_QUEUE) { + waitThread ( blocked_queue_hd, NULL ); + } + } while + (blocked_queue_hd != END_TSO_QUEUE || + run_queue_hd != END_TSO_QUEUE); +} + SchedulerStatus waitThread(StgTSO *tso, /*out*/StgClosure **ret) { diff --git a/ghc/rts/Schedule.h b/ghc/rts/Schedule.h index 78b7a60bc79f7b9c14d82ad3c01f07b03fbf8dd1..d0c3f9923dc5d9f4e2db873205a674eda5a6cac4 100644 --- a/ghc/rts/Schedule.h +++ b/ghc/rts/Schedule.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Schedule.h,v 1.17 2000/03/31 03:09:36 hwloidl Exp $ + * $Id: Schedule.h,v 1.18 2000/04/14 15:18:07 sewardj Exp $ * * (c) The GHC Team 1998-1999 * @@ -32,6 +32,7 @@ void exitScheduler( void ); void startTasks( void ); #endif + //@cindex awakenBlockedQueue /* awakenBlockedQueue() * @@ -193,7 +194,7 @@ void print_bq (StgClosure *node); /* this is the NIL ptr for a TSO queue (e.g. runnable queue) */ #define END_TSO_QUEUE ((StgTSO *)(void*)&END_TSO_QUEUE_closure) /* this is the NIL ptr for a list CAFs */ -#define END_CAF_LIST ((StgCAF *)(void*)&END_TSO_QUEUE_closure) +#define END_ECAF_LIST ((StgCAF *)(void*)&END_TSO_QUEUE_closure) #if defined(PAR) || defined(GRAN) /* this is the NIL ptr for a blocking queue */ # define END_BQ_QUEUE ((StgBlockingQueueElement *)(void*)&END_TSO_QUEUE_closure) diff --git a/ghc/rts/Storage.c b/ghc/rts/Storage.c index 3dd36f7df506a36e69c8f4bd2dc2cbd7017184a0..39a6a5fff977e5ed60abc8df6d33872165b97e46 100644 --- a/ghc/rts/Storage.c +++ b/ghc/rts/Storage.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Storage.c,v 1.23 2000/02/14 10:58:05 sewardj Exp $ + * $Id: Storage.c,v 1.24 2000/04/14 15:18:07 sewardj Exp $ * * (c) The GHC Team, 1998-1999 * @@ -195,6 +195,11 @@ exitStorage (void) stat_exit(calcAllocated()); } + +/* ----------------------------------------------------------------------------- + CAF management. + -------------------------------------------------------------------------- */ + void newCAF(StgClosure* caf) { @@ -206,24 +211,78 @@ newCAF(StgClosure* caf) * any more and can use it as a STATIC_LINK. */ ACQUIRE_LOCK(&sm_mutex); + + ASSERT( ((StgMutClosure*)caf)->mut_link == NULL ); ((StgMutClosure *)caf)->mut_link = oldest_gen->mut_once_list; oldest_gen->mut_once_list = (StgMutClosure *)caf; -#ifdef DEBUG - { - const StgInfoTable *info; - - info = get_itbl(caf); - ASSERT(info->type == IND_STATIC); -#if 0 - STATIC_LINK2(info,caf) = caf_list; - caf_list = caf; -#endif - } +#ifdef INTERPRETER + /* If we're Hugs, we also have to put it in the CAF table, so that + the CAF can be reverted. When reverting, CAFs created by compiled + code are recorded in the CAF table, which lives outside the + heap, in mallocville. CAFs created by interpreted code are + chained together via the link fields in StgCAFs, and are not + recorded in the CAF table. + */ + ASSERT( get_itbl(caf)->type == THUNK_STATIC ); + addToECafTable ( caf, get_itbl(caf) ); #endif + RELEASE_LOCK(&sm_mutex); } +#ifdef INTERPRETER +void +newCAF_made_by_Hugs(StgCAF* caf) +{ + ACQUIRE_LOCK(&sm_mutex); + + ASSERT( get_itbl(caf)->type == CAF_ENTERED ); + recordOldToNewPtrs((StgMutClosure*)caf); + caf->link = ecafList; + ecafList = caf->link; + + RELEASE_LOCK(&sm_mutex); +} +#endif + +#ifdef INTERPRETER +/* These initialisations are critical for correct operation + on the first call of addToECafTable. +*/ +StgCAF* ecafList = END_ECAF_LIST; +StgCAFTabEntry* ecafTable = NULL; +StgInt usedECafTable = 0; +StgInt sizeECafTable = 0; + + +void clearECafTable ( void ) +{ + usedECafTable = 0; +} + +void addToECafTable ( StgClosure* closure, StgInfoTable* origItbl ) +{ + StgInt i; + StgCAFTabEntry* et2; + if (usedECafTable == sizeECafTable) { + /* Make the initial table size be 8 */ + sizeECafTable *= 2; + if (sizeECafTable == 0) sizeECafTable = 8; + et2 = stgMallocBytes ( + sizeECafTable * sizeof(StgCAFTabEntry), + "addToECafTable" ); + for (i = 0; i < usedECafTable; i++) + et2[i] = ecafTable[i]; + if (ecafTable) free(ecafTable); + ecafTable = et2; + } + ecafTable[usedECafTable].closure = closure; + ecafTable[usedECafTable].origItbl = origItbl; + usedECafTable++; +} +#endif + /* ----------------------------------------------------------------------------- Nursery management. -------------------------------------------------------------------------- */ @@ -653,8 +712,8 @@ extern void checkSanity(nat N) { nat g, s; - - if (RtsFlags.GcFlags.generations == 1) { +fprintf(stderr, "--- checkSanity %d\n", N ); + if (0&&RtsFlags.GcFlags.generations == 1) { checkHeap(g0s0->to_space, NULL); checkChain(g0s0->large_objects); } else { diff --git a/ghc/rts/Storage.h b/ghc/rts/Storage.h index 53f76f862c275723723f22432f14726086b23eb7..a9c6a095a30930a7bd0f5f977f159406f73727c2 100644 --- a/ghc/rts/Storage.h +++ b/ghc/rts/Storage.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Storage.h,v 1.15 2000/04/11 16:36:54 sewardj Exp $ + * $Id: Storage.h,v 1.16 2000/04/14 15:18:07 sewardj Exp $ * * (c) The GHC Team, 1998-1999 * @@ -172,11 +172,24 @@ updateWithPermIndirection(const StgInfoTable *info, StgClosure *p1, StgClosure * #endif /* ----------------------------------------------------------------------------- - The CAF list - used to let us revert CAFs + The CAF table - used to let us revert CAFs -------------------------------------------------------------------------- */ -extern StgCAF* enteredCAFs; +#if defined(INTERPRETER) +typedef struct StgCAFTabEntry_ { + StgClosure* closure; + StgInfoTable* origItbl; +} StgCAFTabEntry; + +extern void addToECafTable ( StgClosure* closure, StgInfoTable* origItbl ); +extern void clearECafTable ( void ); + +extern StgCAF* ecafList; +extern StgCAFTabEntry* ecafTable; +extern StgInt usedECafTable; +extern StgInt sizeECafTable; +#endif #if defined(DEBUG) void printMutOnceList(generation *gen);