Feature #14460 ยป 0001-Use-shared-substrings-in-feature-index-cache-hash.patch
| load.c | ||
|---|---|---|
|     return GET_VM()->loaded_features_index; | ||
| } | ||
| static VALUE | ||
| get_loaded_features_index_pool_raw(void) | ||
| { | ||
|     return GET_VM()->loaded_features_index_pool; | ||
| } | ||
| static st_table * | ||
| get_loading_table(void) | ||
| { | ||
| ... | ... | |
| } | ||
| static void | ||
| features_index_add_single(VALUE short_feature, VALUE offset) | ||
| features_index_add_single(const char *short_feature_cstr, VALUE offset) | ||
| { | ||
|     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(); | ||
|     st_lookup(features_index, (st_data_t)short_feature_cstr, (st_data_t *)&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); | ||
| 	st_insert(features_index, (st_data_t)short_feature_cstr, (st_data_t)offset); | ||
|     } | ||
|     else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) { | ||
| 	VALUE feature_indexes[2]; | ||
| ... | ... | |
| static void | ||
| features_index_add(VALUE feature, VALUE offset) | ||
| { | ||
|     VALUE short_feature; | ||
|     const char *feature_str, *feature_end, *ext, *p; | ||
|     VALUE short_feature_no_ext; | ||
|     const char *feature_str, *feature_end, *feature_no_ext_str, *ext, *p; | ||
|     feature_str = StringValuePtr(feature); | ||
|     feature_end = feature_str + RSTRING_LEN(feature); | ||
| ... | ... | |
|     /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is | ||
|        at the end of `feature`, or is NULL if there is no such string. */ | ||
|     p = ext ? ext : feature_end; | ||
|     if (ext) { | ||
| 	p = ext; | ||
| 	short_feature_no_ext = rb_fstring(rb_str_freeze(rb_str_subseq(feature, 0, ext - feature_str))); | ||
| 	feature_no_ext_str = StringValuePtr(short_feature_no_ext); | ||
| 	rb_ary_push(get_loaded_features_index_pool_raw(), short_feature_no_ext); | ||
|     } else { | ||
| 	p = feature_end; | ||
| 	short_feature_no_ext = Qnil; | ||
|     } | ||
|     while (1) { | ||
| 	long beg; | ||
| ... | ... | |
| 	    break; | ||
| 	/* Now *p == '/'.  We reach this point for every '/' in `feature`. */ | ||
| 	beg = p + 1 - feature_str; | ||
| 	short_feature = rb_str_subseq(feature, beg, feature_end - p - 1); | ||
| 	features_index_add_single(short_feature, offset); | ||
| 	features_index_add_single(feature_str + beg, offset); | ||
| 	if (ext) { | ||
| 	    short_feature = rb_str_subseq(feature, beg, ext - p - 1); | ||
| 	    features_index_add_single(short_feature, offset); | ||
| 	    features_index_add_single(feature_no_ext_str + beg, offset); | ||
| 	} | ||
|     } | ||
|     features_index_add_single(feature, offset); | ||
|     features_index_add_single(feature_str, offset); | ||
|     if (ext) { | ||
| 	short_feature = rb_str_subseq(feature, 0, ext - feature_str); | ||
| 	features_index_add_single(short_feature, offset); | ||
| 	features_index_add_single(feature_no_ext_str, offset); | ||
|     } | ||
| } | ||
| ... | ... | |
| 	rb_ary_free(obj); | ||
| 	xfree((void *)obj); | ||
|     } | ||
|     xfree((char *)key); | ||
|     return ST_DELETE; | ||
| } | ||
| ... | ... | |
| 	/* The sharing was broken; something (other than us in rb_provide_feature()) | ||
| 	   modified loaded_features.  Rebuild the index. */ | ||
| 	st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0); | ||
| 	rb_ary_clear(vm->loaded_features_index_pool); | ||
| 	features = vm->loaded_features; | ||
| 	for (i = 0; i < RARRAY_LEN(features); i++) { | ||
| 	    VALUE entry, as_str; | ||
| ... | ... | |
|     vm->loaded_features = rb_ary_new(); | ||
|     vm->loaded_features_snapshot = rb_ary_tmp_new(0); | ||
|     vm->loaded_features_index = st_init_strtable(); | ||
|     vm->loaded_features_index_pool = rb_ary_new(); | ||
|     rb_define_global_function("load", rb_f_load, -1); | ||
|     rb_define_global_function("require", rb_f_require, 1); | ||
| vm.c | ||
|---|---|---|
| 	rb_gc_mark(vm->expanded_load_path); | ||
| 	rb_gc_mark(vm->loaded_features); | ||
| 	rb_gc_mark(vm->loaded_features_snapshot); | ||
| 	rb_gc_mark(vm->loaded_features_index_pool); | ||
| 	rb_gc_mark(vm->top_self); | ||
| 	RUBY_MARK_UNLESS_NULL(vm->coverages); | ||
| 	rb_gc_mark(vm->defined_module_hash); | ||
| vm_core.h | ||
|---|---|---|
|     VALUE expanded_load_path; | ||
|     VALUE loaded_features; | ||
|     VALUE loaded_features_snapshot; | ||
|     VALUE loaded_features_index_pool; | ||
|     struct st_table *loaded_features_index; | ||
|     struct st_table *loading_table; | ||