void revertCAFs( void );
+ // set to disable CAF garbage collection in GHCi.
+ // (needed when dynamic libraries are used).
+extern rtsBool keepCAFs;
+
/* -----------------------------------------------------------------------------
DEBUGGING predicates for pointers
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
{
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
{
evac(&c->indirectee);
}
+ for (c = (StgIndStatic *)revertible_caf_list; c != NULL;
+ c = (StgIndStatic *)c->static_link)
+ {
+ evac(&c->indirectee);
+ }
}
/* -----------------------------------------------------------------------------
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);
#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 */
weak_ptr_list = NULL;
caf_list = NULL;
+ revertible_caf_list = NULL;
/* initialise the allocate() interface */
small_alloc_list = NULL;
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
// 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.
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;
}