From abde5fdfcaa5f363d9cf8cf0a10aa281c40887fe Mon Sep 17 00:00:00 2001 From: wolfgang Date: Wed, 9 Mar 2005 08:51:43 +0000 Subject: [PATCH] [project @ 2005-03-09 08:51:31 by wolfgang] Retain all CAFs when dynamic Haskell libraries are used from GHCi. The Linker usually replaces references to newCAF with references to newDynCAF, but the system dynamic linker won't do that for us. Also, the situation is slightly different - we never want CAFs from dylibs to be reverted, because the dylibs might be used both by the interpreted program and by GHCi itself. So instead of just caf_list, there's now both caf_list and revertible_caf_list. newDynCAF adds a CAF to revertible_caf_list, and newCAF either adds the CAF to caf_list or to the mutable list, depending on whether we are in GHCi. This hack is only active when Linker.c has loaded libHSbase_dyn.[so|dylib], but for now, it applies to all CAFs, not just dynamically-linked ones. If that is worth fixing, we could do that by checking whether the the CAF closure or it's info pointer is in the main executable's address range. MERGE TO STABLE --- ghc/includes/Storage.h | 5 +++++ ghc/rts/GC.c | 9 +++++++-- ghc/rts/Linker.c | 18 ++++++++++++++++++ ghc/rts/Storage.c | 49 +++++++++++++++++++++++++++++++++++------------- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/ghc/includes/Storage.h b/ghc/includes/Storage.h index 7d6fa00..7108bc6 100644 --- a/ghc/includes/Storage.h +++ b/ghc/includes/Storage.h @@ -234,6 +234,10 @@ recordMutable(StgClosure *p) void revertCAFs( void ); + // set to disable CAF garbage collection in GHCi. + // (needed when dynamic libraries are used). +extern rtsBool keepCAFs; + /* ----------------------------------------------------------------------------- DEBUGGING predicates for pointers @@ -393,6 +397,7 @@ extern StgClosure * RTS_VAR(scavenged_static_objects); extern StgWeak * RTS_VAR(old_weak_ptr_list); extern StgWeak * RTS_VAR(weak_ptr_list); extern StgClosure * RTS_VAR(caf_list); +extern StgClosure * RTS_VAR(revertible_caf_list); extern StgTSO * RTS_VAR(resurrected_threads); #endif // STORAGE_H diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index a470f32..1f67fd4 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -3849,14 +3849,14 @@ revertCAFs( void ) { StgIndStatic *c; - for (c = (StgIndStatic *)caf_list; c != NULL; + for (c = (StgIndStatic *)revertible_caf_list; c != NULL; c = (StgIndStatic *)c->static_link) { SET_INFO(c, c->saved_info); c->saved_info = NULL; // could, but not necessary: c->static_link = NULL; } - caf_list = NULL; + revertible_caf_list = NULL; } void @@ -3869,6 +3869,11 @@ markCAFs( evac_fn evac ) { evac(&c->indirectee); } + for (c = (StgIndStatic *)revertible_caf_list; c != NULL; + c = (StgIndStatic *)c->static_link) + { + evac(&c->indirectee); + } } /* ----------------------------------------------------------------------------- diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 9ee1858..41e80a9 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -803,6 +803,24 @@ addDLL( char *dll_name ) void *hdl; char *errmsg; + // *** HACK + // If we load libHSbase_cbits_dyn.[so|dylib], + // then we know that we need to activate another newCAF + // related hack in Storage.c because we can't redirect + // newCAF to newDynCAF with the system dynamic linker. +#ifdef OBJFORMAT_MACHO + const char *hsbase = "/libHSbase_cbits_dyn.dylib"; +#else + const char *hsbase = "/libHSbase_cbits_dyn.so"; +#endif + int namelen = strlen(dll_name); + int baselen = strlen(hsbase); + if(namelen > baselen && !strcmp(dll_name + namelen - baselen, hsbase)) + { + keepCAFs = rtsTrue; + } + // *** END HACK. + initLinker(); hdl= dlopen(dll_name, RTLD_NOW | RTLD_GLOBAL); diff --git a/ghc/rts/Storage.c b/ghc/rts/Storage.c index 974c075..45d94ae 100644 --- a/ghc/rts/Storage.c +++ b/ghc/rts/Storage.c @@ -28,6 +28,8 @@ #include StgClosure *caf_list = NULL; +StgClosure *revertible_caf_list = NULL; +rtsBool keepCAFs; bdescr *small_alloc_list; /* allocate()d small objects */ bdescr *pinned_object_block; /* allocate pinned objects into this block */ @@ -197,6 +199,7 @@ initStorage( void ) weak_ptr_list = NULL; caf_list = NULL; + revertible_caf_list = NULL; /* initialise the allocate() interface */ small_alloc_list = NULL; @@ -259,19 +262,37 @@ exitStorage (void) void newCAF(StgClosure* caf) { - /* Put this CAF on the mutable list for the old generation. - * This is a HACK - the IND_STATIC closure doesn't really have - * a mut_link field, but we pretend it has - in fact we re-use - * the STATIC_LINK field for the time being, because when we - * come to do a major GC we won't need the mut_link field - * any more and can use it as a STATIC_LINK. - */ ACQUIRE_SM_LOCK; - ((StgIndStatic *)caf)->saved_info = NULL; - - recordMutableGen(caf, oldest_gen); - + if(keepCAFs) + { + // HACK: + // If we are in GHCi _and_ we are using dynamic libraries, + // then we can't redirect newCAF calls to newDynCAF (see below), + // so we make newCAF behave almost like newDynCAF. + // The dynamic libraries might be used by both the interpreted + // program and GHCi itself, so they must not be reverted. + // This also means that in GHCi with dynamic libraries, CAFs are not + // garbage collected. If this turns out to be a problem, we could + // do another hack here and do an address range test on caf to figure + // out whether it is from a dynamic library. + ((StgIndStatic *)caf)->saved_info = (StgInfoTable *)caf->header.info; + ((StgIndStatic *)caf)->static_link = caf_list; + caf_list = caf; + } + else + { + /* Put this CAF on the mutable list for the old generation. + * This is a HACK - the IND_STATIC closure doesn't really have + * a mut_link field, but we pretend it has - in fact we re-use + * the STATIC_LINK field for the time being, because when we + * come to do a major GC we won't need the mut_link field + * any more and can use it as a STATIC_LINK. + */ + ((StgIndStatic *)caf)->saved_info = NULL; + recordMutableGen(caf, oldest_gen); + } + RELEASE_SM_LOCK; #ifdef PAR @@ -288,6 +309,8 @@ newCAF(StgClosure* caf) // object code in GHCi. In this case we want to retain *all* CAFs in // the object code, because they might be demanded at any time from an // expression evaluated on the command line. +// Also, GHCi might want to revert CAFs, so we add these to the +// revertible_caf_list. // // The linker hackily arranges that references to newCaf from dynamic // code end up pointing to newDynCAF. @@ -297,8 +320,8 @@ newDynCAF(StgClosure *caf) ACQUIRE_SM_LOCK; ((StgIndStatic *)caf)->saved_info = (StgInfoTable *)caf->header.info; - ((StgIndStatic *)caf)->static_link = caf_list; - caf_list = caf; + ((StgIndStatic *)caf)->static_link = revertible_caf_list; + revertible_caf_list = caf; RELEASE_SM_LOCK; } -- 1.7.10.4