Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View load.c.patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
Index: load.c
===================================================================
--- load.c (revision 34564)
+++ load.c (working copy)
@@ -8,6 +8,96 @@
#include "dln.h"
#include "eval_intern.h"
+struct expander {
+ VALUE hash;
+};
+
+struct expander_alive_values {
+ VALUE *ptr;
+ long len;
+};
+
+static struct expander *expander;
+
+static int
+expander_collect_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ struct expander_alive_values *alive_values = (void*)arg;
+ long i;
+
+ /* delete dead values using information in the alive_values */
+ for (i = 0; i < alive_values->len; i++) {
+ if (alive_values->ptr[i] == (VALUE)value) {
+ /* value is alive */
+ return ST_CONTINUE;
+ }
+ }
+ /* value is dead */
+ return ST_DELETE;
+}
+
+static void
+expander_collect(struct expander *e)
+{
+ st_table *st = RHASH(e->hash)->ntbl;
+ VALUE load_path = rb_get_load_path();
+ struct expander_alive_values alive_values;
+ VALUE *ptr = ALLOCA_N(VALUE, RARRAY_LEN(load_path));
+ long i, len = 0;
+
+ /* remember alive values */
+ for (i = 0; i < RARRAY_LEN(load_path); i++) {
+ /* alive values can be found by rb_hash_lookup2 */
+ VALUE key = RARRAY_PTR(load_path)[i];
+ VALUE value = rb_hash_lookup2(e->hash, key, Qfalse);
+ if (RTEST(value)) {
+ ptr[len] = value;
+ len++;
+ }
+ }
+ alive_values.ptr = ptr;
+ alive_values.len = len;
+ st_foreach(st, expander_collect_i, (st_data_t)&alive_values);
+}
+
+#define EXPANDER_COLLECTION_SPAN 10
+static void
+expander_mark(void *ptr)
+{
+ struct expander *e = ptr;
+ static int count = 0;
+
+ if (!e) return;
+ rb_gc_mark(e->hash);
+ if (++count < EXPANDER_COLLECTION_SPAN) return;
+ count = 0;
+ /* do collection in EXPANDER_COLLECTION_SPAN times once */
+ expander_collect(e);
+}
+
+static void
+expander_free(void *p)
+{
+ if (p) xfree(p);
+}
+
+static const rb_data_type_t expander_data_type = {
+ "expander",
+ {expander_mark, expander_free, NULL,},
+};
+
+static VALUE
+expander_alloc(VALUE klass)
+{
+ VALUE obj;
+ struct expander *e;
+
+ obj = TypedData_Make_Struct(klass, struct expander, &expander_data_type, e);
+ e->hash = rb_hash_new();
+
+ return obj;
+}
+
VALUE ruby_dln_librefs;
#define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
@@ -43,8 +133,18 @@
ary = rb_ary_new2(RARRAY_LEN(load_path));
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
+#if 0
VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil);
rb_str_freeze(path);
+#else
+ VALUE orig = RARRAY_PTR(load_path)[i];
+ VALUE path = rb_hash_lookup2(expander->hash, orig, Qfalse);
+ if (!RTEST(path)) {
+ path = rb_file_expand_path(orig, Qnil);
+ rb_str_freeze(path);
+ rb_hash_aset(expander->hash, orig, path);
+ }
+#endif
rb_ary_push(ary, path);
}
rb_obj_freeze(ary);
@@ -784,6 +884,9 @@
rb_vm_t *vm = GET_VM();
static const char var_load_path[] = "$:";
ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
+ VALUE expander_parent = rb_class_new(rb_cObject);
+ VALUE rb_cLoadPathExpander = rb_define_class_under(expander_parent, "Expander", rb_cObject);
+ VALUE expander_value;
rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter);
rb_alias_variable(rb_intern("$-I"), id_load_path);
@@ -804,4 +907,10 @@
ruby_dln_librefs = rb_ary_new();
rb_gc_register_mark_object(ruby_dln_librefs);
+
+ rb_define_alloc_func(rb_cLoadPathExpander, expander_alloc);
+ expander_value = rb_obj_alloc(rb_cLoadPathExpander);
+ rb_gc_register_mark_object(expander_parent);
+ rb_gc_register_mark_object(expander_value);
+ expander = DATA_PTR(expander_value);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.