Project

General

Profile

Feature #11614 ยป 0001-use-id_table-for-constant-tables.patch

normalperson (Eric Wong), 10/22/2015 08:54 PM

View differences:

class.c
274 274

  
275 275
struct clone_const_arg {
276 276
    VALUE klass;
277
    st_table *tbl;
277
    struct rb_id_table *tbl;
278 278
};
279 279

  
280 280
static int
......
285 285
    RB_OBJ_WRITTEN(arg->klass, Qundef, ce->value);
286 286
    RB_OBJ_WRITTEN(arg->klass, Qundef, ce->file);
287 287

  
288
    st_insert(arg->tbl, key, (st_data_t)nce);
289
    return ST_CONTINUE;
288
    rb_id_table_insert(arg->tbl, key, (VALUE)nce);
289
    return ID_TABLE_CONTINUE;
290 290
}
291 291

  
292
static int
293
clone_const_i(st_data_t key, st_data_t value, st_data_t data)
292
static enum rb_id_table_iterator_result
293
clone_const_i(ID key, VALUE value, void *data)
294 294
{
295
    return clone_const((ID)key, (const rb_const_entry_t *)value, (struct clone_const_arg *)data);
295
    return clone_const(key, (const rb_const_entry_t *)value, data);
296 296
}
297 297

  
298 298
static void
......
346 346
    if (RCLASS_CONST_TBL(orig)) {
347 347
	struct clone_const_arg arg;
348 348

  
349
	RCLASS_CONST_TBL(clone) = st_init_numtable();
349
	arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
350 350
	arg.klass = clone;
351
	arg.tbl = RCLASS_CONST_TBL(clone);
352
	st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
351
	rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg);
353 352
    }
354 353
    if (RCLASS_M_TBL(orig)) {
355 354
	struct clone_method_arg arg;
......
393 392
	}
394 393
	if (RCLASS_CONST_TBL(klass)) {
395 394
	    struct clone_const_arg arg;
396
	    RCLASS_CONST_TBL(clone) = st_init_numtable();
395
	    arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
397 396
	    arg.klass = clone;
398
	    arg.tbl = RCLASS_CONST_TBL(clone);
399
	    st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg);
397
	    rb_id_table_foreach(RCLASS_CONST_TBL(klass), clone_const_i, &arg);
400 398
	}
401 399
	if (attach != Qundef) {
402 400
	    rb_singleton_class_attached(clone, attach);
......
810 808
	RCLASS_IV_TBL(module) = st_init_numtable();
811 809
    }
812 810
    if (!RCLASS_CONST_TBL(module)) {
813
	RCLASS_CONST_TBL(module) = st_init_numtable();
811
	RCLASS_CONST_TBL(module) = rb_id_table_create(0);
814 812
    }
815 813
    RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
816 814
    RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
......
867 865

  
868 866
    while (module) {
869 867
	int superclass_seen = FALSE;
868
	struct rb_id_table *tbl;
870 869

  
871 870
	if (RCLASS_ORIGIN(module) != module)
872 871
	    goto skip;
......
904 903
	    rb_id_table_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (void *)refined_class);
905 904
	    FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
906 905
	}
907
	if (RMODULE_M_TBL(module) && rb_id_table_size(RMODULE_M_TBL(module))) method_changed = 1;
908
	if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries) constant_changed = 1;
906

  
907
	tbl = RMODULE_M_TBL(module);
908
	if (tbl && rb_id_table_size(tbl)) method_changed = 1;
909

  
910
	tbl = RMODULE_CONST_TBL(module);
911
	if (tbl && rb_id_table_size(tbl)) constant_changed = 1;
909 912
      skip:
910 913
	module = RCLASS_SUPER(module);
911 914
    }
constant.h
38 38
VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj);
39 39
VALUE rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj);
40 40
VALUE rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj);
41
void rb_free_const_table(st_table *tbl);
41
void rb_free_const_table(struct rb_id_table *tbl);
42 42
VALUE rb_public_const_get(VALUE klass, ID id);
43 43
VALUE rb_public_const_get_at(VALUE klass, ID id);
44 44
VALUE rb_public_const_get_from(VALUE klass, ID id);
gc.c
1966 1966
    return FALSE;
1967 1967
}
1968 1968

  
1969
static int
1970
free_const_entry_i(st_data_t key, st_data_t value, st_data_t data)
1969
static enum rb_id_table_iterator_result
1970
free_const_entry_i(VALUE value, void *data)
1971 1971
{
1972 1972
    rb_const_entry_t *ce = (rb_const_entry_t *)value;
1973 1973
    xfree(ce);
1974
    return ST_CONTINUE;
1974
    return ID_TABLE_CONTINUE;
1975 1975
}
1976 1976

  
1977 1977
void
1978
rb_free_const_table(st_table *tbl)
1978
rb_free_const_table(struct rb_id_table *tbl)
1979 1979
{
1980
    st_foreach(tbl, free_const_entry_i, 0);
1981
    st_free_table(tbl);
1980
    rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
1981
    rb_id_table_free(tbl);
1982 1982
}
1983 1983

  
1984 1984
static inline void
......
3046 3046
		size += st_memsize(RCLASS(obj)->ptr->iv_tbl);
3047 3047
	    }
3048 3048
	    if (RCLASS(obj)->ptr->const_tbl) {
3049
		size += st_memsize(RCLASS(obj)->ptr->const_tbl);
3049
		size += rb_id_table_memsize(RCLASS(obj)->ptr->const_tbl);
3050 3050
	    }
3051 3051
	    size += sizeof(rb_classext_t);
3052 3052
	}
......
4013 4013
    }
4014 4014
}
4015 4015

  
4016
static int
4017
mark_const_entry_i(st_data_t key, st_data_t value, st_data_t data)
4016
static enum rb_id_table_iterator_result
4017
mark_const_entry_i(VALUE value, void *data)
4018 4018
{
4019 4019
    const rb_const_entry_t *ce = (const rb_const_entry_t *)value;
4020
    rb_objspace_t *objspace = (rb_objspace_t *)data;
4020
    rb_objspace_t *objspace = data;
4021 4021

  
4022 4022
    gc_mark(objspace, ce->value);
4023 4023
    gc_mark(objspace, ce->file);
4024
    return ST_CONTINUE;
4024
    return ID_TABLE_CONTINUE;
4025 4025
}
4026 4026

  
4027 4027
static void
4028
mark_const_tbl(rb_objspace_t *objspace, st_table *tbl)
4028
mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
4029 4029
{
4030 4030
    if (!tbl) return;
4031
    st_foreach(tbl, mark_const_entry_i, (st_data_t)objspace);
4031
    rb_id_table_foreach_values(tbl, mark_const_entry_i, objspace);
4032 4032
}
4033 4033

  
4034 4034
#if STACK_GROW_DIRECTION < 0
internal.h
463 463
struct rb_classext_struct {
464 464
    struct st_table *iv_index_tbl;
465 465
    struct st_table *iv_tbl;
466
    struct st_table *const_tbl;
466
    struct rb_id_table *const_tbl;
467 467
    struct rb_id_table *callable_m_tbl;
468 468
    rb_subclass_entry_t *subclasses;
469 469
    rb_subclass_entry_t **parent_subclasses;
object.c
2185 2185
{
2186 2186
    ID id = id_for_setter(name, const, "wrong constant name %"PRIsVALUE);
2187 2187
    rb_const_set(mod, id, value);
2188

  
2189
    /*
2190
     * Resolve and cache class name immediately to resolve ambiguity
2191
     * and avoid order-dependency on const_tbl
2192
     */
2193
    if (RB_TYPE_P(value, T_MODULE) || RB_TYPE_P(value, T_CLASS)) {
2194
	rb_class_name(value);
2195
    }
2188 2196
    return value;
2189 2197
}
2190 2198

  
variable.c
14 14
#include "internal.h"
15 15
#include "ruby/st.h"
16 16
#include "ruby/util.h"
17
#include "id_table.h"
17 18
#include "constant.h"
18 19
#include "id.h"
19 20

  
......
22 23

  
23 24
static void check_before_mod_set(VALUE, ID, VALUE, const char *);
24 25
static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
25
static int const_update(st_data_t *, st_data_t *, st_data_t, int);
26 26
static st_table *generic_iv_tbl;
27 27
static st_table *generic_iv_tbl_compat;
28 28

  
......
90 90
    return path;
91 91
}
92 92

  
93
static int
94
fc_i(st_data_t k, st_data_t v, st_data_t a)
93
static enum rb_id_table_iterator_result
94
fc_i(ID key, VALUE v, void *a)
95 95
{
96
    ID key = (ID)k;
97 96
    rb_const_entry_t *ce = (rb_const_entry_t *)v;
98
    struct fc_result *res = (struct fc_result *)a;
97
    struct fc_result *res = a;
99 98
    VALUE value = ce->value;
100
    if (!rb_is_const_id(key)) return ST_CONTINUE;
99
    if (!rb_is_const_id(key)) return ID_TABLE_CONTINUE;
101 100

  
102 101
    if (value == res->klass && (!res->preferred || key == res->preferred)) {
103 102
	res->path = fc_path(res, key);
104
	return ST_STOP;
103
	return ID_TABLE_STOP;
105 104
    }
106 105
    if (RB_TYPE_P(value, T_MODULE) || RB_TYPE_P(value, T_CLASS)) {
107
	if (!RCLASS_CONST_TBL(value)) return ST_CONTINUE;
106
	if (!RCLASS_CONST_TBL(value)) return ID_TABLE_CONTINUE;
108 107
	else {
109 108
	    struct fc_result arg;
110 109
	    struct fc_result *list;
111 110

  
112 111
	    list = res;
113 112
	    while (list) {
114
		if (list->track == value) return ST_CONTINUE;
113
		if (list->track == value) return ID_TABLE_CONTINUE;
115 114
		list = list->prev;
116 115
	    }
117 116

  
......
121 120
	    arg.klass = res->klass;
122 121
	    arg.track = value;
123 122
	    arg.prev = res;
124
	    st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg);
123
	    rb_id_table_foreach(RCLASS_CONST_TBL(value), fc_i, &arg);
125 124
	    if (arg.path) {
126 125
		res->path = arg.path;
127
		return ST_STOP;
126
		return ID_TABLE_STOP;
128 127
	    }
129 128
	}
130 129
    }
131
    return ST_CONTINUE;
130
    return ID_TABLE_CONTINUE;
132 131
}
133 132

  
134 133
/**
......
150 149
    arg.track = rb_cObject;
151 150
    arg.prev = 0;
152 151
    if (RCLASS_CONST_TBL(rb_cObject)) {
153
	st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg);
152
	rb_id_table_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, &arg);
154 153
    }
155 154
    if (arg.path) {
156 155
	st_data_t tmp = tmp_classpath;
......
2053 2052
    VALUE value;
2054 2053
};
2055 2054

  
2055
static void const_tbl_update(struct autoload_const_set_args *);
2056

  
2056 2057
static VALUE
2057 2058
autoload_const_set(VALUE arg)
2058 2059
{
......
2060 2061
    VALUE klass = args->mod;
2061 2062
    ID id = args->id;
2062 2063
    check_before_mod_set(klass, id, args->value, "constant");
2063
    st_update(RCLASS_CONST_TBL(klass), (st_data_t)id,
2064
	      const_update, (st_data_t)args);
2064
    const_tbl_update(args);
2065 2065
    return 0;			/* ignored */
2066 2066
}
2067 2067

  
......
2262 2262
rb_const_remove(VALUE mod, ID id)
2263 2263
{
2264 2264
    VALUE val;
2265
    st_data_t v, n = id;
2265
    rb_const_entry_t *ce;
2266 2266

  
2267 2267
    rb_check_frozen(mod);
2268
    if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) {
2268
    ce = rb_const_lookup(mod, id);
2269
    if (!ce || !rb_id_table_delete(RCLASS_CONST_TBL(mod), id)) {
2269 2270
	if (rb_const_defined_at(mod, id)) {
2270 2271
	    rb_name_error(id, "cannot remove %"PRIsVALUE"::%"PRIsVALUE"",
2271 2272
			  rb_class_name(mod), QUOTE_ID(id));
......
2276 2277

  
2277 2278
    rb_clear_constant_cache();
2278 2279

  
2279
    val = ((rb_const_entry_t*)v)->value;
2280
    val = ce->value;
2280 2281
    if (val == Qundef) {
2281 2282
	autoload_delete(mod, id);
2282 2283
	val = Qnil;
2283 2284
    }
2284
    xfree((rb_const_entry_t*)v);
2285
    xfree(ce);
2285 2286
    return val;
2286 2287
}
2287 2288

  
......
2293 2294
    return ST_CONTINUE;
2294 2295
}
2295 2296

  
2296
static int
2297
sv_i(st_data_t k, st_data_t v, st_data_t a)
2297
static enum rb_id_table_iterator_result
2298
sv_i(ID key, VALUE v, void *a)
2298 2299
{
2299
    ID key = (ID)k;
2300 2300
    rb_const_entry_t *ce = (rb_const_entry_t *)v;
2301
    st_table *tbl = (st_table *)a;
2301
    st_table *tbl = a;
2302 2302

  
2303 2303
    if (rb_is_const_id(key)) {
2304 2304
	st_update(tbl, (st_data_t)key, cv_i_update, (st_data_t)ce);
2305 2305
    }
2306
    return ST_CONTINUE;
2306
    return ID_TABLE_CONTINUE;
2307 2307
}
2308 2308

  
2309
static int
2310
rb_local_constants_i(st_data_t const_name, st_data_t const_value, st_data_t ary)
2309
static enum rb_id_table_iterator_result
2310
rb_local_constants_i(ID const_name, VALUE const_value, void *ary)
2311 2311
{
2312
    rb_ary_push((VALUE)ary, ID2SYM((ID)const_name));
2313
    return ST_CONTINUE;
2312
    rb_ary_push((VALUE)ary, ID2SYM(const_name));
2313
    return ID_TABLE_CONTINUE;
2314 2314
}
2315 2315

  
2316 2316
static VALUE
2317 2317
rb_local_constants(VALUE mod)
2318 2318
{
2319
    st_table *tbl = RCLASS_CONST_TBL(mod);
2319
    struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
2320 2320
    VALUE ary;
2321 2321

  
2322 2322
    if (!tbl) return rb_ary_new2(0);
2323 2323

  
2324
    ary = rb_ary_new2(tbl->num_entries);
2325
    st_foreach(tbl, rb_local_constants_i, ary);
2324
    ary = rb_ary_new2(rb_id_table_size(tbl));
2325
    rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
2326 2326
    return ary;
2327 2327
}
2328 2328

  
......
2334 2334
	tbl = st_init_numtable();
2335 2335
    }
2336 2336
    if (RCLASS_CONST_TBL(mod)) {
2337
	st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl);
2337
	rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
2338 2338
    }
2339 2339
    return tbl;
2340 2340
}
......
2486 2486
rb_const_set(VALUE klass, ID id, VALUE val)
2487 2487
{
2488 2488
    rb_const_entry_t *ce;
2489
    st_table *tbl = RCLASS_CONST_TBL(klass);
2489
    struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2490 2490

  
2491 2491
    if (NIL_P(klass)) {
2492 2492
	rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
......
2495 2495

  
2496 2496
    check_before_mod_set(klass, id, val, "constant");
2497 2497
    if (!tbl) {
2498
	RCLASS_CONST_TBL(klass) = tbl = st_init_numtable();
2498
	RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
2499 2499
	rb_clear_constant_cache();
2500 2500
	ce = ZALLOC(rb_const_entry_t);
2501
	st_insert(tbl, (st_data_t)id, (st_data_t)ce);
2501
	rb_id_table_insert(tbl, id, (VALUE)ce);
2502 2502
	setup_const_entry(ce, klass, val, CONST_PUBLIC);
2503 2503
    }
2504 2504
    else {
......
2506 2506
	args.mod = klass;
2507 2507
	args.id = id;
2508 2508
	args.value = val;
2509
	st_update(tbl, (st_data_t)id, const_update, (st_data_t)&args);
2509
	const_tbl_update(&args);
2510 2510
    }
2511 2511
}
2512 2512

  
2513
static int
2514
const_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
2513
static void
2514
const_tbl_update(struct autoload_const_set_args *args)
2515 2515
{
2516
    struct autoload_const_set_args *args = (struct autoload_const_set_args *)arg;
2516
    VALUE value;
2517 2517
    VALUE klass = args->mod;
2518 2518
    VALUE val = args->value;
2519 2519
    ID id = args->id;
2520
    struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
2520 2521
    rb_const_flag_t visibility = CONST_PUBLIC;
2521 2522
    rb_const_entry_t *ce;
2522 2523

  
2523
    if (existing) {
2524
	ce = (rb_const_entry_t *)*value;
2525
	if (ce) {
2526
	    if (ce->value == Qundef) {
2527
		VALUE load;
2528
		struct autoload_data_i *ele;
2529

  
2530
		load = autoload_data(klass, id);
2531
		/* for autoloading thread, keep the defined value to autoloading storage */
2532
		if (load && (ele = check_autoload_data(load)) &&
2533
			    (ele->thread == rb_thread_current())) {
2534
		    rb_clear_constant_cache();
2535

  
2536
		    ele->value = val; /* autoload_i is non-WB-protected */
2537
		    return ST_STOP;
2538
		}
2539
		/* otherwise, allow to override */
2540
		autoload_delete(klass, id);
2524
    if (rb_id_table_lookup(tbl, id, &value)) {
2525
	ce = (rb_const_entry_t *)value;
2526
	if (ce->value == Qundef) {
2527
	    VALUE load;
2528
	    struct autoload_data_i *ele;
2529

  
2530
	    load = autoload_data(klass, id);
2531
	    /* for autoloading thread, keep the defined value to autoloading storage */
2532
	    if (load && (ele = check_autoload_data(load)) &&
2533
			(ele->thread == rb_thread_current())) {
2534
		rb_clear_constant_cache();
2535

  
2536
		ele->value = val; /* autoload_i is non-WB-protected */
2537
		return;
2541 2538
	    }
2542
	    else {
2543
		VALUE name = QUOTE_ID(id);
2544
		visibility = ce->flag;
2545
		if (klass == rb_cObject)
2546
		    rb_warn("already initialized constant %"PRIsVALUE"", name);
2547
		else
2548
		    rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
2549
			    rb_class_name(klass), name);
2550
		if (!NIL_P(ce->file) && ce->line) {
2551
		    rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
2552
				    "previous definition of %"PRIsVALUE" was here", name);
2553
		}
2539
	    /* otherwise, allow to override */
2540
	    autoload_delete(klass, id);
2541
	}
2542
	else {
2543
	    VALUE name = QUOTE_ID(id);
2544
	    visibility = ce->flag;
2545
	    if (klass == rb_cObject)
2546
		rb_warn("already initialized constant %"PRIsVALUE"", name);
2547
	    else
2548
		rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
2549
			rb_class_name(klass), name);
2550
	    if (!NIL_P(ce->file) && ce->line) {
2551
		rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
2552
				"previous definition of %"PRIsVALUE" was here", name);
2554 2553
	    }
2555
	    rb_clear_constant_cache();
2556
	    setup_const_entry(ce, klass, val, visibility);
2557
	    return ST_STOP;
2558 2554
	}
2559
    }
2560

  
2561
    rb_clear_constant_cache();
2555
	rb_clear_constant_cache();
2556
	setup_const_entry(ce, klass, val, visibility);
2557
    } else {
2558
	rb_clear_constant_cache();
2562 2559

  
2563
    ce = ZALLOC(rb_const_entry_t);
2564
    *value = (st_data_t)ce;
2565
    setup_const_entry(ce, klass, val, visibility);
2566
    return ST_CONTINUE;
2560
	ce = ZALLOC(rb_const_entry_t);
2561
	rb_id_table_insert(tbl, id, (VALUE)ce);
2562
	setup_const_entry(ce, klass, val, visibility);
2563
    }
2567 2564
}
2568 2565

  
2569 2566
static void
......
3003 3000
rb_const_entry_t *
3004 3001
rb_const_lookup(VALUE klass, ID id)
3005 3002
{
3006
    st_table *tbl = RCLASS_CONST_TBL(klass);
3007
    st_data_t val;
3003
    struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
3004
    VALUE val;
3008 3005

  
3009
    if (tbl && st_lookup(tbl, (st_data_t)id, &val)) {
3006
    if (tbl && rb_id_table_lookup(tbl, id, &val)) {
3010 3007
	return (rb_const_entry_t *)val;
3011 3008
    }
3012 3009
    return 0;
3013
-