summaryrefslogtreecommitdiff
path: root/rts/ForeignExports.c
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-09-11 06:16:18 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-09-18 15:56:25 -0400
commit40dc91069d15bfc1d81f1722b39e06cac8fdddd1 (patch)
tree35dddbae6594e1db99802ed08ddd2b1ee4e92afe /rts/ForeignExports.c
parentc492134912e5270180881b7345ee86dc32756bdd (diff)
downloadhaskell-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.c53
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;
}
}