Project

General

Profile

Feature #5767 » cache_expanded_load_path.patch

funny_falcon (Yura Sokolov), 12/15/2011 06:18 PM

View differences:

load.c
return load_path;
}
static void rb_check_expanded_cache();
static int cached_expanded_load_path = 1;
VALUE
rb_get_expanded_load_path(void)
{
VALUE load_path = rb_get_load_path();
VALUE ary;
long i;
rb_vm_t *vm = GET_VM();
ary = rb_ary_new2(RARRAY_LEN(load_path));
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil);
rb_str_freeze(path);
rb_ary_push(ary, path);
rb_check_expanded_cache();
ary = vm->load_path_expanded;
if ( !RTEST(ary) ) {
long i;
ary = rb_ary_new2(RARRAY_LEN(load_path));
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil);
rb_str_freeze(path);
rb_ary_push(ary, path);
}
if (cached_expanded_load_path) {
char *curwd = my_getcwd();
vm->load_path_curwd = rb_str_new_cstr(curwd);
xfree(curwd);
vm->load_path_expanded = ary;
}
}
rb_obj_freeze(ary);
return ary;
}
......
return rb_mod_autoload_p(klass, sym);
}
static const char *load_path_reset_cache_methods[] = {
"[]=", "collect!", "compact!", "delete",
"delete_if", "fill", "flatten!", "insert", "keep_if",
"map!", "reject!", "replace", "select!", "shuffle!",
"sort!", "sort_by!", "uniq!", NULL
};
static const char *load_path_apply_to_cache_methods[] = {
"clear", "delete_at", "pop", "reverse!", "rotate!",
"shift", "slice!", NULL
};
static const char *load_path_apply_expanded_methods[] = {
"<<", "push", "unshift", NULL
};
static void
rb_reset_expanded_cache()
{
rb_vm_t *vm = GET_VM();
vm->load_path_curwd = 0;
vm->load_path_expanded = 0;
}
static void
rb_check_expanded_cache()
{
rb_vm_t *vm = GET_VM();
if (RTEST(vm->load_path_curwd)) {
char *cwd = my_getcwd();
if (strcmp(RSTRING_PTR(vm->load_path_curwd), cwd)) {
rb_reset_expanded_cache();
}
xfree(cwd);
}
}
static VALUE
rb_load_path_reset_cache_method(int argc, VALUE *argv, VALUE self)
{
rb_reset_expanded_cache();
return rb_call_super(argc, argv);
}
static VALUE
rb_load_path_apply_to_cache_method(int argc, VALUE *argv, VALUE self)
{
VALUE load_path_expanded;
RB_GC_GUARD(load_path_expanded) = GET_VM()->load_path_expanded;
if (RTEST(load_path_expanded)) {
ID func = rb_frame_this_func();
rb_funcall2(load_path_expanded, func, argc, argv);
}
return rb_call_super(argc, argv);
}
static VALUE
rb_load_path_apply_expanded_method(int argc, VALUE *argv, VALUE self)
{
VALUE load_path_expanded;
rb_check_expanded_cache();
RB_GC_GUARD(load_path_expanded) = GET_VM()->load_path_expanded;
if (RTEST(load_path_expanded)) {
int i;
ID func = rb_frame_this_func();
VALUE expanded = rb_ary_new2(argc);
for(i = 0; i < argc; i++) {
VALUE path = rb_file_expand_path(argv[i], Qnil);
rb_str_freeze(path);
rb_ary_push(expanded, path);
}
rb_funcall2(load_path_expanded, func, argc, RARRAY_PTR(expanded));
}
return rb_call_super(argc, argv);
}
// concat - special
static VALUE
rb_load_path_concat(VALUE self, VALUE ary)
{
ID push;
CONST_ID(push, "push");
RB_GC_GUARD(ary);
return rb_funcall2(self, push, RARRAY_LEN(ary), RARRAY_PTR(ary));
}
static VALUE
rb_load_path_init(void)
{
const char **name;
VALUE load_path = rb_ary_new();
char *cached_flag;
cached_flag = getenv("RUBY_CACHED_LOAD_PATH");
if (cached_flag != NULL) {
cached_expanded_load_path = atoi(cached_flag);
}
if (cached_expanded_load_path) {
VALUE load_path_c = rb_singleton_class(load_path);
for(name = load_path_reset_cache_methods; *name; name++ ) {
rb_define_method(load_path_c, *name, rb_load_path_reset_cache_method, -1);
}
for(name = load_path_apply_to_cache_methods; *name; name++ ) {
rb_define_method(load_path_c, *name, rb_load_path_apply_to_cache_method, -1);
}
for(name = load_path_apply_expanded_methods; *name; name++ ) {
rb_define_method(load_path_c, *name, rb_load_path_apply_expanded_method, -1);
}
rb_define_method(load_path_c, "concat", rb_load_path_concat, 1);
}
rb_reset_expanded_cache();
return load_path;
}
void
Init_load()
{
......
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);
rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
vm->load_path = rb_ary_new();
vm->load_path = rb_load_path_init();
rb_define_virtual_variable("$\"", get_loaded_features, 0);
rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
vm.c
RUBY_MARK_UNLESS_NULL(vm->thgroup_default);
RUBY_MARK_UNLESS_NULL(vm->mark_object_ary);
RUBY_MARK_UNLESS_NULL(vm->load_path);
RUBY_MARK_UNLESS_NULL(vm->load_path_expanded);
RUBY_MARK_UNLESS_NULL(vm->load_path_curwd);
RUBY_MARK_UNLESS_NULL(vm->loaded_features);
RUBY_MARK_UNLESS_NULL(vm->top_self);
RUBY_MARK_UNLESS_NULL(vm->coverages);
vm_core.h
/* load */
VALUE top_self;
VALUE load_path;
VALUE load_path_expanded;
VALUE load_path_curwd;
VALUE loaded_features;
struct st_table *loading_table;
(1-1/5)