Commit abde5fdf authored by wolfgang's avatar wolfgang
Browse files

[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
parent f733edf2
......@@ -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
......@@ -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);
}
}
/* -----------------------------------------------------------------------------
......
......@@ -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);
......
......@@ -28,6 +28,8 @@
#include <string.h>
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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment