summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/gc.c b/gc.c
index b6115abb93..e95f38e6b3 100644
--- a/gc.c
+++ b/gc.c
@@ -428,6 +428,48 @@ init_mark_stack()
static void rb_gc_mark_children(VALUE ptr);
+static st_table *source_filenames;
+
+char *
+rb_source_filename(f)
+ const char *f;
+{
+ char *name;
+
+ if (!st_lookup(source_filenames, f, &name)) {
+ long len = strlen(f) + 1;
+ char *ptr = name = ALLOC_N(char, len + 1);
+ *ptr++ = 0;
+ MEMCPY(ptr, f, char, len);
+ st_add_direct(source_filenames, ptr, name);
+ return ptr;
+ }
+ return name + 1;
+}
+
+static void
+mark_source_filename(f)
+ char *f;
+{
+ if (f) {
+ f[-1] = 1;
+ }
+}
+
+static enum st_retval
+sweep_source_filename(key, value)
+ char *key, *value;
+{
+ if (*value) {
+ *value = 0;
+ return ST_CONTINUE;
+ }
+ else {
+ free(value);
+ return ST_DELETE;
+ }
+}
+
static void
gc_mark_all()
{
@@ -604,6 +646,7 @@ rb_gc_mark_children(ptr)
break;
case T_NODE:
+ mark_source_filename(obj->as.node.nd_file);
switch (nd_type(obj)) {
case NODE_IF: /* 1,2,3 */
case NODE_FOR:
@@ -846,6 +889,9 @@ gc_sweep()
}
}
+ mark_source_filename(ruby_sourcefile);
+ st_foreach(source_filenames, sweep_source_filename, 0);
+
freelist = 0;
final_list = deferred_final_list;
deferred_final_list = 0;
@@ -1510,4 +1556,6 @@ Init_GC()
rb_global_variable(&finalizers);
rb_gc_unregister_address(&rb_mObSpace);
finalizers = rb_ary_new();
+
+ source_filenames = st_init_strtable();
}