diff options
author | Simon Marlow <marlowsd@gmail.com> | 2014-09-29 12:49:21 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2014-11-28 14:10:32 +0000 |
commit | 9e6e4796437a7fc23e83605a45db9b2663570123 (patch) | |
tree | b78db2642aed0c47bcbca124f99031fcb52d6d9d /rts | |
parent | b5e8b3b162b3ff15ae6caf1afc659565365f54a8 (diff) | |
download | haskell-9e6e4796437a7fc23e83605a45db9b2663570123.tar.gz |
Add purgeObj() to remove the symbol table entries for an object
This allows us to replace an object without actually unloading the old
object, which is necessary when we know we have references to the old
object so it can't be completely unloaded. Using unloadObj() would
cause the GC (CheckUnload) to repeatedly and fruitlessly try to unload
the old object.
Diffstat (limited to 'rts')
-rw-r--r-- | rts/Linker.c | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index 6d9abfe695..0c390ae46c 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -2255,20 +2255,45 @@ mmap_again: } #endif // USE_MMAP +/* + * Remove symbols from the symbol table, and free oc->symbols. + * This operation is idempotent. + */ static void removeOcSymbols (ObjectCode *oc) { if (oc->symbols == NULL) return; - /* Remove all the mappings for the symbols within this object.. - */ + // Remove all the mappings for the symbols within this object.. int i; for (i = 0; i < oc->n_symbols; i++) { if (oc->symbols[i] != NULL) { ghciRemoveSymbolTable(symhash, oc->symbols[i], oc); } } + + stgFree(oc->symbols); + oc->symbols = NULL; +} + +/* + * Release StablePtrs and free oc->stable_ptrs. + * This operation is idempotent. + */ +static void freeOcStablePtrs (ObjectCode *oc) +{ + // Release any StablePtrs that were created when this + // object module was initialized. + ForeignExportStablePtr *fe_ptr, *next; + + for (fe_ptr = oc->stable_ptrs; fe_ptr != NULL; fe_ptr = next) { + next = fe_ptr->next; + freeStablePtr(fe_ptr->stable_ptr); + stgFree(fe_ptr); + } + oc->stable_ptrs = NULL; } + /* * freeObjectCode() releases all the pieces of an ObjectCode. It is called by * the GC when a previously unloaded ObjectCode has been determined to be @@ -3015,6 +3040,7 @@ static HsInt loadObj_ (pathchar *path) if (! loadOc(oc)) { // failed; free everything we've allocated removeOcSymbols(oc); + // no need to freeOcStablePtrs, they aren't created until resolveObjs() freeObjectCode(oc); return 0; } @@ -3150,7 +3176,7 @@ HsInt resolveObjs (void) /* ----------------------------------------------------------------------------- * delete an object from the pool */ -static HsInt unloadObj_ (pathchar *path) +static HsInt unloadObj_ (pathchar *path, rtsBool just_purge) { ObjectCode *oc, *prev, *next; HsBool unloadedAnyObj = HS_BOOL_FALSE; @@ -3166,30 +3192,24 @@ static HsInt unloadObj_ (pathchar *path) if (!pathcmp(oc->fileName,path)) { + // these are both idempotent, so in just_purge mode we can + // later call unloadObj() to really unload the object. removeOcSymbols(oc); + freeOcStablePtrs(oc); - if (prev == NULL) { - objects = oc->next; - } else { - prev->next = oc->next; - } - oc->next = unloaded_objects; - unloaded_objects = oc; - - // Release any StablePtrs that were created when this - // object module was initialized. - { - ForeignExportStablePtr *fe_ptr, *next; - - for (fe_ptr = oc->stable_ptrs; fe_ptr != NULL; fe_ptr = next) { - next = fe_ptr->next; - freeStablePtr(fe_ptr->stable_ptr); - stgFree(fe_ptr); + if (!just_purge) { + if (prev == NULL) { + objects = oc->next; + } else { + prev->next = oc->next; } + oc->next = unloaded_objects; + unloaded_objects = oc; + oc->status = OBJECT_UNLOADED; + } else { + prev = oc; } - oc->status = OBJECT_UNLOADED; - /* This could be a member of an archive so continue * unloading other members. */ unloadedAnyObj = HS_BOOL_TRUE; @@ -3210,7 +3230,15 @@ static HsInt unloadObj_ (pathchar *path) HsInt unloadObj (pathchar *path) { ACQUIRE_LOCK(&linker_mutex); - HsInt r = unloadObj_(path); + HsInt r = unloadObj_(path, rtsFalse); + RELEASE_LOCK(&linker_mutex); + return r; +} + +HsInt purgeObj (pathchar *path) +{ + ACQUIRE_LOCK(&linker_mutex); + HsInt r = unloadObj_(path, rtsTrue); RELEASE_LOCK(&linker_mutex); return r; } |