merge revision(s) 39644,39646,39647,39874,39898: [Backport #8048]

* load.c (features_index_add_single, rb_feature_p): store single index
	  as Fixnum to reduce the number of arrays for the indexes.  based on
	  the patch by tmm1 (Aman Gupta) in [ruby-core:53216] [Bug #8048].

	* load.c (rb_feature_p), vm_core.h (rb_vm_struct): turn
	  loaded_features_index into st_table.  patches by tmm1 (Aman Gupta)
	  in [ruby-core:53251] and [ruby-core:53274] [Bug #8048]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@40397 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagachika 2013-04-20 15:13:50 +00:00
parent 80ecaa1777
commit c1ca05af16
5 changed files with 77 additions and 25 deletions

View file

@ -1,3 +1,15 @@
Sun Apr 21 00:13:24 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* load.c (rb_feature_p), vm_core.h (rb_vm_struct): turn
loaded_features_index into st_table. patches by tmm1 (Aman Gupta)
in [ruby-core:53251] and [ruby-core:53274] [Bug #8048]
Sun Apr 21 00:13:24 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* load.c (features_index_add_single, rb_feature_p): store single index
as Fixnum to reduce the number of arrays for the indexes. based on
the patch by tmm1 (Aman Gupta) in [ruby-core:53216] [Bug #8048].
Sat Apr 20 23:32:06 2013 Nobuyoshi Nakada <nobu@ruby-lang.org> Sat Apr 20 23:32:06 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* dir.c (glob_helper): should skip dot directories only for recursion, * dir.c (glob_helper): should skip dot directories only for recursion,

76
load.c
View file

@ -11,6 +11,8 @@
VALUE ruby_dln_librefs; VALUE ruby_dln_librefs;
#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
#define IS_RBEXT(e) (strcmp((e), ".rb") == 0) #define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0) #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
#ifdef DLEXT2 #ifdef DLEXT2
@ -56,7 +58,7 @@ rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache)
long i; long i;
int level = rb_safe_level(); int level = rb_safe_level();
ary = rb_ary_new2(RARRAY_LEN(load_path)); ary = rb_ary_tmp_new(RARRAY_LEN(load_path));
for (i = 0; i < RARRAY_LEN(load_path); ++i) { for (i = 0; i < RARRAY_LEN(load_path); ++i) {
VALUE path, as_str, expanded_path; VALUE path, as_str, expanded_path;
int is_string, non_cache; int is_string, non_cache;
@ -169,7 +171,7 @@ reset_loaded_features_snapshot(void)
rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
} }
static VALUE static struct st_table *
get_loaded_features_index_raw(void) get_loaded_features_index_raw(void)
{ {
return GET_VM()->loaded_features_index; return GET_VM()->loaded_features_index;
@ -184,13 +186,32 @@ get_loading_table(void)
static void static void
features_index_add_single(VALUE short_feature, VALUE offset) features_index_add_single(VALUE short_feature, VALUE offset)
{ {
VALUE features_index, this_feature_index; struct st_table *features_index;
VALUE this_feature_index = Qnil;
char *short_feature_cstr;
Check_Type(offset, T_FIXNUM);
Check_Type(short_feature, T_STRING);
short_feature_cstr = StringValueCStr(short_feature);
features_index = get_loaded_features_index_raw(); features_index = get_loaded_features_index_raw();
if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { st_lookup(features_index, (st_data_t)short_feature_cstr, (st_data_t *)&this_feature_index);
this_feature_index = rb_ary_new();
rb_hash_aset(features_index, short_feature, this_feature_index); if (NIL_P(this_feature_index)) {
st_insert(features_index, (st_data_t)ruby_strdup(short_feature_cstr), (st_data_t)offset);
} }
else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
VALUE feature_indexes[2];
feature_indexes[0] = this_feature_index;
feature_indexes[1] = offset;
this_feature_index = rb_ary_tmp_new(numberof(feature_indexes));
rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
st_insert(features_index, (st_data_t)short_feature_cstr, (st_data_t)this_feature_index);
}
else {
Check_Type(this_feature_index, T_ARRAY);
rb_ary_push(this_feature_index, offset); rb_ary_push(this_feature_index, offset);
}
} }
/* Add to the loaded-features index all the required entries for /* Add to the loaded-features index all the required entries for
@ -240,7 +261,14 @@ features_index_add(VALUE feature, VALUE offset)
} }
} }
static VALUE static int
loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
{
xfree((char *)key);
return ST_DELETE;
}
static st_table *
get_loaded_features_index(void) get_loaded_features_index(void)
{ {
VALUE features; VALUE features;
@ -250,7 +278,7 @@ get_loaded_features_index(void)
if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) {
/* The sharing was broken; something (other than us in rb_provide_feature()) /* The sharing was broken; something (other than us in rb_provide_feature())
modified loaded_features. Rebuild the index. */ modified loaded_features. Rebuild the index. */
rb_hash_clear(vm->loaded_features_index); st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
features = vm->loaded_features; features = vm->loaded_features;
for (i = 0; i < RARRAY_LEN(features); i++) { for (i = 0; i < RARRAY_LEN(features); i++) {
VALUE entry, as_str; VALUE entry, as_str;
@ -340,10 +368,10 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
static int static int
rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
{ {
VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; VALUE features, this_feature_index = Qnil, v, p, load_path = 0;
const char *f, *e; const char *f, *e;
long i, len, elen, n; long i, len, elen, n;
st_table *loading_tbl; st_table *loading_tbl, *features_index;
st_data_t data; st_data_t data;
int type; int type;
@ -361,8 +389,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
features = get_loaded_features(); features = get_loaded_features();
features_index = get_loaded_features_index(); features_index = get_loaded_features_index();
feature_val = rb_str_new(feature, len); st_lookup(features_index, (st_data_t)feature, (st_data_t *)&this_feature_index);
this_feature_index = rb_hash_lookup(features_index, feature_val);
/* We search `features` for an entry such that either /* We search `features` for an entry such that either
"#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
for some j, or for some j, or
@ -389,8 +416,19 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
or ends in '/'. This includes both match forms above, as well or ends in '/'. This includes both match forms above, as well
as any distractors, so we may ignore all other entries in `features`. as any distractors, so we may ignore all other entries in `features`.
*/ */
for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { for (i = 0; !NIL_P(this_feature_index); i++) {
long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); VALUE entry;
long index;
if (RB_TYPE_P(this_feature_index, T_ARRAY)) {
if (i >= RARRAY_LEN(this_feature_index)) break;
entry = RARRAY_PTR(this_feature_index)[i];
}
else {
if (i > 0) break;
entry = this_feature_index;
}
index = FIX2LONG(entry);
v = RARRAY_PTR(features)[index]; v = RARRAY_PTR(features)[index];
f = StringValuePtr(v); f = StringValuePtr(v);
if ((n = RSTRING_LEN(v)) < len) continue; if ((n = RSTRING_LEN(v)) < len) continue;
@ -1082,15 +1120,15 @@ Init_load()
rb_alias_variable(rb_intern("$-I"), id_load_path); rb_alias_variable(rb_intern("$-I"), id_load_path);
rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
vm->load_path = rb_ary_new(); vm->load_path = rb_ary_new();
vm->expanded_load_path = rb_ary_new(); vm->expanded_load_path = rb_ary_tmp_new(0);
vm->load_path_snapshot = rb_ary_new(); vm->load_path_snapshot = rb_ary_tmp_new(0);
vm->load_path_check_cache = 0; vm->load_path_check_cache = 0;
rb_define_virtual_variable("$\"", get_loaded_features, 0); rb_define_virtual_variable("$\"", get_loaded_features, 0);
rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
vm->loaded_features = rb_ary_new(); vm->loaded_features = rb_ary_new();
vm->loaded_features_snapshot = rb_ary_new(); vm->loaded_features_snapshot = rb_ary_tmp_new(0);
vm->loaded_features_index = rb_hash_new(); vm->loaded_features_index = st_init_strtable();
rb_define_global_function("load", rb_f_load, -1); rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1); rb_define_global_function("require", rb_f_require, 1);
@ -1100,6 +1138,6 @@ Init_load()
rb_define_global_function("autoload", rb_f_autoload, 2); rb_define_global_function("autoload", rb_f_autoload, 2);
rb_define_global_function("autoload?", rb_f_autoload_p, 1); rb_define_global_function("autoload?", rb_f_autoload_p, 1);
ruby_dln_librefs = rb_ary_new(); ruby_dln_librefs = rb_ary_tmp_new(0);
rb_gc_register_mark_object(ruby_dln_librefs); rb_gc_register_mark_object(ruby_dln_librefs);
} }

View file

@ -1,10 +1,10 @@
#define RUBY_VERSION "2.0.0" #define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2013-04-20" #define RUBY_RELEASE_DATE "2013-04-21"
#define RUBY_PATCHLEVEL 156 #define RUBY_PATCHLEVEL 157
#define RUBY_RELEASE_YEAR 2013 #define RUBY_RELEASE_YEAR 2013
#define RUBY_RELEASE_MONTH 4 #define RUBY_RELEASE_MONTH 4
#define RUBY_RELEASE_DAY 20 #define RUBY_RELEASE_DAY 21
#include "ruby/version.h" #include "ruby/version.h"

4
vm.c
View file

@ -1565,7 +1565,6 @@ rb_vm_mark(void *ptr)
RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); RUBY_MARK_UNLESS_NULL(vm->expanded_load_path);
RUBY_MARK_UNLESS_NULL(vm->loaded_features); RUBY_MARK_UNLESS_NULL(vm->loaded_features);
RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot);
RUBY_MARK_UNLESS_NULL(vm->loaded_features_index);
RUBY_MARK_UNLESS_NULL(vm->top_self); RUBY_MARK_UNLESS_NULL(vm->top_self);
RUBY_MARK_UNLESS_NULL(vm->coverages); RUBY_MARK_UNLESS_NULL(vm->coverages);
rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count);
@ -1573,6 +1572,9 @@ rb_vm_mark(void *ptr)
if (vm->loading_table) { if (vm->loading_table) {
rb_mark_tbl(vm->loading_table); rb_mark_tbl(vm->loading_table);
} }
if (vm->loaded_features_index) {
rb_mark_tbl(vm->loaded_features_index);
}
vm_trace_mark_event_hooks(&vm->event_hooks); vm_trace_mark_event_hooks(&vm->event_hooks);

View file

@ -364,7 +364,7 @@ typedef struct rb_vm_struct {
VALUE expanded_load_path; VALUE expanded_load_path;
VALUE loaded_features; VALUE loaded_features;
VALUE loaded_features_snapshot; VALUE loaded_features_snapshot;
VALUE loaded_features_index; struct st_table *loaded_features_index;
struct st_table *loading_table; struct st_table *loading_table;
/* signal */ /* signal */