summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2022-05-17 23:44:14 +1200
committerGitHub <noreply@github.com>2022-05-17 23:44:14 +1200
commit11af23ee923858fbcec18f2d1365296fdfe24dc2 (patch)
tree0316f389a366b781aa015f108f710383a9e18921
parent60d45b2ee86a80e248c3bff0c90c981ed2168ac3 (diff)
Move feature deletion from GC mark to `autoload_delete`. (#5912)
Notes
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
-rw-r--r--variable.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/variable.c b/variable.c
index 37359fe55a..6360dd5476 100644
--- a/variable.c
+++ b/variable.c
@@ -2176,11 +2176,6 @@ autoload_data_mark(void *ptr)
rb_gc_mark_movable(p->feature);
rb_gc_mark_movable(p->mutex);
-
- // Allow GC to free us if no modules refer to this via autoload_const.autoload_data
- if (ccan_list_empty(&p->constants)) {
- rb_hash_delete(autoload_features, p->feature);
- }
}
static void
@@ -2422,7 +2417,10 @@ autoload_delete(VALUE module, ID name)
/* Qfalse can indicate already deleted */
if (load != Qfalse) {
struct autoload_const *autoload_const;
- get_autoload_data((VALUE)load, &autoload_const);
+ struct autoload_data *autoload_data = get_autoload_data((VALUE)load, &autoload_const);
+
+ VM_ASSERT(autoload_data);
+ VM_ASSERT(!ccan_list_empty(&autoload_data->constants));
/*
* we must delete here to avoid "already initialized" warnings
@@ -2431,6 +2429,10 @@ autoload_delete(VALUE module, ID name)
*/
ccan_list_del_init(&autoload_const->cnode);
+ if (ccan_list_empty(&autoload_data->constants)) {
+ rb_hash_delete(autoload_features, autoload_data->feature);
+ }
+
// If the autoload table is empty, we can delete it.
if (table->num_entries == 0) {
name = autoload;
@@ -2650,6 +2652,8 @@ autoload_apply_constants(VALUE _arguments)
struct autoload_const *autoload_const;
struct autoload_const *next;
+ // We use safe iteration here because `autoload_const_set` will eventually invoke `autoload_delete` which will remove the constant from the linked list. In theory, once the `autoload_data->constants` linked list is empty, we can remove it.
+
// Iterate over all constants and assign them:
ccan_list_for_each_safe(&arguments->autoload_data->constants, autoload_const, next, cnode) {
if (autoload_const->value != Qundef) {