diff options
author | Ben Gamari <ben@smart-cactus.org> | 2020-09-11 06:16:18 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-09-18 15:56:25 -0400 |
commit | 40dc91069d15bfc1d81f1722b39e06cac8fdddd1 (patch) | |
tree | 35dddbae6594e1db99802ed08ddd2b1ee4e92afe /rts/ForeignExports.c | |
parent | c492134912e5270180881b7345ee86dc32756bdd (diff) | |
download | haskell-40dc91069d15bfc1d81f1722b39e06cac8fdddd1.tar.gz |
rts: Refactor unloading of foreign export StablePtrs
Previously we would allocate a linked list cell for each foreign export.
Now we can avoid this by taking advantage of the fact that they are
already broken into groups.
Diffstat (limited to 'rts/ForeignExports.c')
-rw-r--r-- | rts/ForeignExports.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/rts/ForeignExports.c b/rts/ForeignExports.c index 3195b6e779..e218281b51 100644 --- a/rts/ForeignExports.c +++ b/rts/ForeignExports.c @@ -48,12 +48,14 @@ static ObjectCode *loading_obj = NULL; * For instance, doing exactly this resulted in #18548. * * Another consideration here is that the linker needs to know which - * `StablePtr`s belong to each `ObjectCode` it loads for the sake of unloading. - * For this reason, the linker informs us when it is loading an object by calling - * `foreignExportsLoadingObject` and `foreignExportsFinishedLoadingObject`. We - * take note of the `ObjectCode*` we are loading in `loading_obj` such that we - * can associate the `StablePtr` with the `ObjectCode` in - * `processForeignExports`. + * `StablePtr`s belong to each `ObjectCode` so it can free them when the module is + * unloaded. For this reason, the linker informs us when it is loading an + * object by calling `foreignExportsLoadingObject` and + * `foreignExportsFinishedLoadingObject`. We take note of the `ObjectCode*` we + * are loading in `loading_obj` such that we can associate the `ForeignExportsList` with + * the `ObjectCode` in `processForeignExports`. We then record each of the + * StablePtrs we create in the ->stable_ptrs array of ForeignExportsList so + * they can be enumerated during unloading. * */ @@ -94,20 +96,35 @@ void foreignExportsFinishedLoadingObject() void processForeignExports() { while (pending) { - for (int i=0; i < pending->n_entries; i++) { - StgPtr p = pending->exports[i]; - StgStablePtr *sptr = getStablePtr(p); + struct ForeignExportsList *cur = pending; + pending = cur->next; - if (loading_obj != NULL) { - ForeignExportStablePtr *fe_sptr = (ForeignExportStablePtr *) - stgMallocBytes(sizeof(ForeignExportStablePtr), - "foreignExportStablePtr"); - fe_sptr->stable_ptr = sptr; - fe_sptr->next = loading_obj->stable_ptrs; - pending->oc->stable_ptrs = fe_sptr; + /* sanity check */ + ASSERT(cur->stable_ptrs == NULL); + + /* N.B. We only need to populate the ->stable_ptrs + * array if the object might later be unloaded. + */ + if (cur->oc != NULL) { + cur->stable_ptrs = + stgMallocBytes(sizeof(StgStablePtr*) * cur->n_entries, + "foreignExportStablePtr"); + + for (int i=0; i < cur->n_entries; i++) { + StgStablePtr *sptr = getStablePtr(cur->exports[i]); + + if (cur->oc != NULL) { + cur->stable_ptrs[i] = sptr; + } + } + cur->next = cur->oc->foreign_exports; + cur->oc->foreign_exports = cur; + } else { + /* can't be unloaded, don't bother populating + * ->stable_ptrs array. */ + for (int i=0; i < cur->n_entries; i++) { + getStablePtr(cur->exports[i]); } } - - pending = pending->next; } } |