From 2cffbb305b39ab11c9d0c3fbb399e9d8462f6b66 Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Mon, 3 Mar 2014 18:59:31 +0900 Subject: [PATCH 01/14] introduce gc-able symbols --- gc.c | 17 +++- include/ruby/ruby.h | 25 +++-- internal.h | 3 + parse.y | 241 +++++++++++++++++++++++++++++++++++++------- string.c | 22 ++-- template/id.h.tmpl | 20 ++-- 6 files changed, 267 insertions(+), 61 deletions(-) diff --git a/gc.c b/gc.c index fdc388f3a39e0c..3e66f360942c5a 100644 --- a/gc.c +++ b/gc.c @@ -354,6 +354,7 @@ typedef struct RVALUE { struct RMatch match; struct RRational rational; struct RComplex complex; + struct RSymbol symbol; struct { struct RBasic basic; VALUE v1; @@ -1652,6 +1653,12 @@ obj_free(rb_objspace_t *objspace, VALUE obj) } break; + case T_SYMBOL: + { + rb_gc_free_dsymbol(obj); + } + break; + default: rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE, BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags); @@ -2410,7 +2417,7 @@ rb_obj_id(VALUE obj) * 24 if 32-bit, double is 8-byte aligned * 40 if 64-bit */ - if (SYMBOL_P(obj)) { + if (STATIC_SYM_P(obj)) { return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG; } else if (FLONUM_P(obj)) { @@ -2516,6 +2523,7 @@ obj_memsize_of(VALUE obj, int use_tdata) break; case T_FLOAT: + case T_SYMBOL: break; case T_BIGNUM: @@ -3966,6 +3974,13 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) } break; + case T_SYMBOL: + { + ptr = obj->as.symbol.fstr; + goto again; + } + break; + default: #if GC_DEBUG rb_gcdebug_print_obj_condition((VALUE)obj); diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index abd4b4bad3cac9..ffe0bb1b5a5e9d 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -351,9 +351,14 @@ rb_long2int_inline(long n) #define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK) -#define SYMBOL_P(x) (((VALUE)(x)&~((~(VALUE)0)<= SIZEOF_DOUBLE @@ -957,6 +962,12 @@ struct RComplex { #define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->real,(r)) #define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->imag,(i)) +struct RSymbol { + struct RBasic basic; + VALUE fstr; + ID type; +}; + struct RData { struct RBasic basic; void (*dmark)(void*); @@ -1093,6 +1104,7 @@ struct RStruct { #define RFILE(obj) (R_CAST(RFile)(obj)) #define RRATIONAL(obj) (R_CAST(RRational)(obj)) #define RCOMPLEX(obj) (R_CAST(RComplex)(obj)) +#define RSYMBOL(obj) (R_CAST(RSymbol)(obj)) #define FL_SINGLETON FL_USER0 #define FL_WB_PROTECTED (((VALUE)1)<<5) @@ -1146,7 +1158,7 @@ struct RStruct { (OBJ_TAINTABLE(x) && FL_ABLE(s)) ? \ RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT : 0) -#define OBJ_FROZEN(x) (!!(FL_ABLE(x)?(RBASIC(x)->flags&(FL_FREEZE)):(FIXNUM_P(x)||FLONUM_P(x)||SYMBOL_P(x)))) +#define OBJ_FROZEN(x) (!!(FL_ABLE(x)?(RBASIC(x)->flags&(FL_FREEZE)):(FIXNUM_P(x)||FLONUM_P(x)||STATIC_SYM_P(x)))) #define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE) #if USE_RGENGC @@ -1381,6 +1393,7 @@ const char *rb_id2name(ID); ID rb_check_id(volatile VALUE *); ID rb_to_id(VALUE); VALUE rb_id2str(ID); +VALUE rb_sym2str(VALUE); #define CONST_ID_CACHE(result, str) \ { \ @@ -1597,7 +1610,7 @@ rb_class_of(VALUE obj) if (FIXNUM_P(obj)) return rb_cFixnum; if (FLONUM_P(obj)) return rb_cFloat; if (obj == Qtrue) return rb_cTrueClass; - if (SYMBOL_P(obj)) return rb_cSymbol; + if (STATIC_SYM_P(obj)) return rb_cSymbol; } else if (!RTEST(obj)) { if (obj == Qnil) return rb_cNilClass; @@ -1613,7 +1626,7 @@ rb_type(VALUE obj) if (FIXNUM_P(obj)) return T_FIXNUM; if (FLONUM_P(obj)) return T_FLOAT; if (obj == Qtrue) return T_TRUE; - if (SYMBOL_P(obj)) return T_SYMBOL; + if (STATIC_SYM_P(obj)) return T_SYMBOL; if (obj == Qundef) return T_UNDEF; } else if (!RTEST(obj)) { diff --git a/internal.h b/internal.h index 3309b65ad57c78..cb3a041e20e5cb 100644 --- a/internal.h +++ b/internal.h @@ -742,6 +742,9 @@ int rb_is_junk_name(VALUE name); void rb_gc_mark_parser(void); void rb_gc_mark_symbols(int full_mark); ID rb_make_internal_id(void); +void rb_gc_mark_dsymbol(VALUE); +void rb_gc_free_dsymbol(VALUE); +VALUE rb_str_dynamic_intern(VALUE s); /* proc.c */ VALUE rb_proc_location(VALUE self); diff --git a/parse.y b/parse.y index 492fd3da6491e7..51d8a457123e14 100644 --- a/parse.y +++ b/parse.y @@ -41,26 +41,26 @@ #define free YYFREE #ifndef RIPPER -static ID register_symid(ID, const char *, long, rb_encoding *); -static ID register_symid_str(ID, VALUE); -#define REGISTER_SYMID(id, name) register_symid((id), (name), strlen(name), enc) +static ID register_static_symid(ID, const char *, long, rb_encoding *); +static ID register_static_symid_str(ID, VALUE); +#define REGISTER_SYMID(id, name) register_static_symid((id), (name), strlen(name), enc) #include "id.c" #endif +static inline int id_type(ID); #define is_notop_id(id) ((id)>tLAST_OP_ID) -#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL) -#define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL) -#define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE) -#define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET) -#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST) -#define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS) -#define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK) -#define id_type(id) (is_notop_id(id) ? (int)((id)&ID_SCOPE_MASK) : -1) +#define is_local_id(id) (id_type(id)==ID_LOCAL) +#define is_global_id(id) (id_type(id)==ID_GLOBAL) +#define is_instance_id(id) (id_type(id)==ID_INSTANCE) +#define is_attrset_id(id) (id_type(id)==ID_ATTRSET) +#define is_const_id(id) (id_type(id)==ID_CONST) +#define is_class_id(id) (id_type(id)==ID_CLASS) +#define is_junk_id(id) (id_type(id)==ID_JUNK) #define is_asgn_or_id(id) ((is_notop_id(id)) && \ - (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \ - ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \ - ((id)&ID_SCOPE_MASK) == ID_CLASS)) + ((id_type(id)) == ID_GLOBAL || \ + (id_type(id)) == ID_INSTANCE || \ + (id_type(id)) == ID_CLASS)) enum lex_state_bits { EXPR_BEG_bit, /* ignore newline, +/- is a sign. */ @@ -8802,6 +8802,8 @@ static const char id_type_names[][9] = { "JUNK", }; +static ID rb_stick_dynamic_symbol(VALUE); + ID rb_id_attrset(ID id) { @@ -8813,7 +8815,7 @@ rb_id_attrset(ID id) rb_name_error(id, "cannot make operator ID :%s attrset", rb_id2name(id)); } else { - int scope = (int)(id & ID_SCOPE_MASK); + int scope = id_type(id); switch (scope) { case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL: case ID_CONST: case ID_CLASS: case ID_JUNK: @@ -8826,8 +8828,19 @@ rb_id_attrset(ID id) } } - id &= ~ID_SCOPE_MASK; - id |= ID_ATTRSET; + if (id&ID_STATIC_SYM) { + id &= ~ID_SCOPE_MASK; + id |= ID_ATTRSET; + } + else { + VALUE str; + + /* make new dynamic symbol */ + str = rb_str_dup(RSYMBOL((VALUE)id)->fstr); + rb_str_cat(str, "=", 1); + id = (ID)rb_str_dynamic_intern(str); + rb_stick_dynamic_symbol((VALUE)id); + } return id; } @@ -10105,12 +10118,15 @@ static struct symbols { ID last_id; st_table *sym_id; st_table *id_str; + st_table *id_dsym; + st_table *stick_dsym; #if ENABLE_SELECTOR_NAMESPACE st_table *ivar2_id; st_table *id_ivar2; #endif VALUE op_sym[tLAST_OP_ID]; int minor_marked; + int stick_dsym_minor_marked; } global_symbols = {tLAST_TOKEN}; static const struct st_hash_type symhash = { @@ -10150,6 +10166,7 @@ Init_sym(void) { global_symbols.sym_id = st_init_table_with_size(&symhash, 1000); global_symbols.id_str = st_init_numtable_with_size(1000); + global_symbols.stick_dsym = st_init_numtable_with_size(1000); #if ENABLE_SELECTOR_NAMESPACE global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000); global_symbols.id_ivar2 = st_init_numtable_with_size(1000); @@ -10169,11 +10186,17 @@ rb_gc_mark_symbols(int full_mark) { if (full_mark || global_symbols.minor_marked == 0) { rb_mark_tbl(global_symbols.id_str); + rb_mark_tbl(global_symbols.stick_dsym); rb_gc_mark_locations(global_symbols.op_sym, global_symbols.op_sym + numberof(global_symbols.op_sym)); if (!full_mark) global_symbols.minor_marked = 1; } + + if (full_mark || global_symbols.stick_dsym_minor_marked == 0) { + rb_mark_tbl(global_symbols.stick_dsym); + if (!full_mark) global_symbols.stick_dsym_minor_marked = 1; + } } #endif /* !RIPPER */ @@ -10182,7 +10205,22 @@ internal_id_gen(struct parser_params *parser) { ID id = (ID)vtable_size(lvtbl->args) + (ID)vtable_size(lvtbl->vars); id += ((tLAST_TOKEN - ID_INTERNAL) >> ID_SCOPE_SHIFT) + 1; - return ID_INTERNAL | (id << ID_SCOPE_SHIFT); + return ID_STATIC_SYM | ID_INTERNAL | (id << ID_SCOPE_SHIFT); +} + +static inline int +id_type(ID id) +{ + if (id<=tLAST_OP_ID) { + return -1; + } + if (id&ID_STATIC_SYM) { + return (int)((id)&ID_SCOPE_MASK); + } + else { + VALUE dsym = (VALUE)id; + return RSYMBOL(dsym)->type; + } } #ifndef RIPPER @@ -10342,14 +10380,14 @@ rb_str_symname_type(VALUE name, unsigned int allowed_attrset) } static ID -register_symid(ID id, const char *name, long len, rb_encoding *enc) +register_static_symid(ID id, const char *name, long len, rb_encoding *enc) { VALUE str = rb_enc_str_new(name, len, enc); - return register_symid_str(id, str); + return register_static_symid_str(id, str); } static ID -register_symid_str(ID id, VALUE str) +register_static_symid_str(ID id, VALUE str) { OBJ_FREEZE(str); str = rb_fstring(str); @@ -10395,6 +10433,32 @@ setup_fake_str(struct RString *fake_str, const char *name, long len) return (VALUE)fake_str; } +ID +rb_stick_dynamic_symbol(VALUE sym) +{ + /* stick dynamic symbol */ + if (!st_insert(global_symbols.stick_dsym, sym, (st_data_t)sym)) { + global_symbols.stick_dsym_minor_marked = 0; + } + return (ID)sym; +} + +static int +lookup_sym_id(st_data_t str, st_data_t *data) +{ + ID id; + + if (!st_lookup(global_symbols.sym_id, str, data)) { + return FALSE; + } + id = (ID)*data; + if (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) { + /* stick dynamic symbol */ + rb_stick_dynamic_symbol((VALUE)id); + } + return TRUE; +} + ID rb_intern3(const char *name, long len, rb_encoding *enc) { @@ -10404,7 +10468,7 @@ rb_intern3(const char *name, long len, rb_encoding *enc) rb_enc_associate(str, enc); OBJ_FREEZE(str); - if (st_lookup(global_symbols.sym_id, str, &data)) + if (lookup_sym_id(str, &data)) return (ID)data; str = rb_enc_str_new(name, len, enc); /* make true string */ @@ -10417,11 +10481,12 @@ next_id_base(void) if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) { return (ID)-1; } - return ++global_symbols.last_id << ID_SCOPE_SHIFT; + ++global_symbols.last_id; + return global_symbols.last_id << ID_SCOPE_SHIFT; } static ID -intern_str(VALUE str) +next_id(VALUE str) { const char *name, *m, *e; long len, last; @@ -10473,13 +10538,13 @@ intern_str(VALUE str) if (len == 1) { id = c; - goto id_register; + return id; } for (i = 0; i < op_tbl_count; i++) { if (*op_tbl[i].name == *m && strcmp(op_tbl[i].name, m) == 0) { id = op_tbl[i].token; - goto id_register; + return id; } } } @@ -10490,10 +10555,11 @@ intern_str(VALUE str) if (last > 1 && name[last-1] == '=') goto junk; id = rb_intern3(name, last, enc); + id |= ID_STATIC_SYM; if (id > tLAST_OP_ID && !is_attrset_id(id)) { enc = rb_enc_get(rb_id2str(id)); id = rb_id_attrset(id); - goto id_register; + return id; } id = ID_ATTRSET; } @@ -10530,8 +10596,14 @@ intern_str(VALUE str) } } id |= nid; - id_register: - return register_symid_str(id, str); + id |= ID_STATIC_SYM; + return id; +} + +static ID +intern_str(VALUE str) +{ + return register_static_symid_str(next_id(str), str); } ID @@ -10552,11 +10624,110 @@ rb_intern_str(VALUE str) { st_data_t id; - if (st_lookup(global_symbols.sym_id, str, &id)) + if (lookup_sym_id(str, &id)) return (ID)id; return intern_str(rb_str_dup(str)); } +void +rb_gc_free_dsymbol(VALUE ptr) +{ + st_delete(global_symbols.sym_id, (st_data_t *)&RSYMBOL(ptr)->fstr, 0); + RSYMBOL(ptr)->fstr = (VALUE)NULL; +} + +VALUE +rb_str_dynamic_intern(VALUE s) +{ + VALUE str = RB_GC_GUARD(s); + VALUE dup; + rb_encoding *enc; + VALUE dsym; + ID id, type; + + if (st_lookup(global_symbols.sym_id, str, &id)) { + return ID2SYM(id); + } + + dup = rb_str_dup(str); + enc = rb_enc_get(str); + if (rb_enc_asciicompat(enc)) { + if (sym_check_asciionly(str)) { + rb_enc_associate(dup, rb_usascii_encoding()); + } + } + + type = rb_str_symname_type(str, TRUE); + OBJ_FREEZE(dup); + str = rb_fstring(dup); + dsym = rb_newobj_of(rb_cSymbol, T_SYMBOL); + OBJ_FREEZE(dsym); + RSYMBOL(dsym)->fstr = str; + RSYMBOL(dsym)->type = type; + + if (RUBY_DTRACE_SYMBOL_CREATE_ENABLED()) { + RUBY_DTRACE_SYMBOL_CREATE(RSTRING_PTR(str), rb_sourcefile(), rb_sourceline()); + } + + st_add_direct(global_symbols.sym_id, (st_data_t)str, dsym); + global_symbols.minor_marked = 0; + return dsym; +} + +static int +lookup_id_str(ID id, st_data_t *data) +{ + if (st_lookup(global_symbols.id_str, id, data)) { + return TRUE; + } + if (!(id&ID_STATIC_SYM)) { + *data = RSYMBOL(id)->fstr; + return TRUE; + } + return FALSE; +} + +inline ID +rb_sym2id(VALUE x) +{ + if (STATIC_SYM_P(x)) { + return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT); + } + else { + return rb_stick_dynamic_symbol(x); + } +} + +inline ID +rb_sym2id_nostick(VALUE x) +{ + if (STATIC_SYM_P(x)) { + return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT); + } + else { + return (ID)x; + } +} + +inline VALUE +rb_id2sym(ID x) +{ + if (x&ID_STATIC_SYM||xklass == 0) RBASIC_SET_CLASS_RAW(str, rb_cString); @@ -10602,7 +10773,7 @@ rb_id2str(ID id) } if (is_attrset_id(id)) { - ID id_stem = (id & ~ID_SCOPE_MASK); + ID id_stem = (id & ~ID_SCOPE_MASK) | ID_STATIC_SYM; VALUE str; do { @@ -10616,7 +10787,7 @@ rb_id2str(ID id) } while (0); str = rb_str_dup(str); rb_str_cat(str, "=", 1); - register_symid_str(id, str); + register_static_symid_str(id, str); if (st_lookup(global_symbols.id_str, id, &data)) { VALUE str = (VALUE)data; if (RBASIC(str)->klass == 0) @@ -10639,7 +10810,7 @@ rb_id2name(ID id) ID rb_make_internal_id(void) { - return next_id_base() | ID_INTERNAL; + return next_id_base() | ID_INTERNAL | ID_STATIC_SYM; } static int @@ -10750,7 +10921,7 @@ rb_check_id(volatile VALUE *namep) sym_check_asciionly(name); - if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id)) + if (lookup_sym_id((st_data_t)name, &id)) return (ID)id; if (rb_is_attrset_name(name)) { diff --git a/string.c b/string.c index 075876f47ab391..2346adf4236400 100644 --- a/string.c +++ b/string.c @@ -7347,6 +7347,8 @@ rb_str_crypt(VALUE str, VALUE salt) * 'cat and dog'.to_sym #=> :"cat and dog" */ +VALUE rb_str_dynamic_intern(VALUE); + VALUE rb_str_intern(VALUE s) { @@ -8466,7 +8468,7 @@ sym_to_proc(VALUE sym) static VALUE sym_succ(VALUE sym) { - return rb_str_intern(rb_str_succ(rb_sym_to_s(sym))); + return rb_str_dynamic_intern(rb_str_succ(rb_sym_to_s(sym))); } /* @@ -8550,7 +8552,7 @@ sym_aref(int argc, VALUE *argv, VALUE sym) static VALUE sym_length(VALUE sym) { - return rb_str_length(rb_id2str(SYM2ID(sym))); + return rb_str_length(rb_sym2str(sym)); } /* @@ -8563,7 +8565,7 @@ sym_length(VALUE sym) static VALUE sym_empty(VALUE sym) { - return rb_str_empty(rb_id2str(SYM2ID(sym))); + return rb_str_empty(rb_sym2str(sym)); } /* @@ -8576,7 +8578,7 @@ sym_empty(VALUE sym) static VALUE sym_upcase(VALUE sym) { - return rb_str_intern(rb_str_upcase(rb_id2str(SYM2ID(sym)))); + return rb_str_dynamic_intern(rb_str_upcase(rb_sym2str(sym))); } /* @@ -8589,7 +8591,7 @@ sym_upcase(VALUE sym) static VALUE sym_downcase(VALUE sym) { - return rb_str_intern(rb_str_downcase(rb_id2str(SYM2ID(sym)))); + return rb_str_dynamic_intern(rb_str_downcase(rb_sym2str(sym))); } /* @@ -8602,7 +8604,7 @@ sym_downcase(VALUE sym) static VALUE sym_capitalize(VALUE sym) { - return rb_str_intern(rb_str_capitalize(rb_id2str(SYM2ID(sym)))); + return rb_str_dynamic_intern(rb_str_capitalize(rb_sym2str(sym))); } /* @@ -8615,7 +8617,7 @@ sym_capitalize(VALUE sym) static VALUE sym_swapcase(VALUE sym) { - return rb_str_intern(rb_str_swapcase(rb_id2str(SYM2ID(sym)))); + return rb_str_dynamic_intern(rb_str_swapcase(rb_sym2str(sym))); } /* @@ -8628,7 +8630,7 @@ sym_swapcase(VALUE sym) static VALUE sym_encoding(VALUE sym) { - return rb_obj_encoding(rb_id2str(SYM2ID(sym))); + return rb_obj_encoding(rb_sym2str(sym)); } ID @@ -8740,8 +8742,8 @@ Init_String(void) rb_define_method(rb_cString, "<<", rb_str_concat, 1); rb_define_method(rb_cString, "prepend", rb_str_prepend, 1); rb_define_method(rb_cString, "crypt", rb_str_crypt, 1); - rb_define_method(rb_cString, "intern", rb_str_intern, 0); - rb_define_method(rb_cString, "to_sym", rb_str_intern, 0); + rb_define_method(rb_cString, "intern", rb_str_dynamic_intern, 0); + rb_define_method(rb_cString, "to_sym", rb_str_dynamic_intern, 0); rb_define_method(rb_cString, "ord", rb_str_ord, 0); rb_define_method(rb_cString, "include?", rb_str_include, 1); diff --git a/template/id.h.tmpl b/template/id.h.tmpl index 9df794721412a5..65c94749e86dac 100644 --- a/template/id.h.tmpl +++ b/template/id.h.tmpl @@ -29,18 +29,20 @@ types = ids.keys.grep(/^[A-Z]/) #define RUBY_ID_H enum ruby_id_types { + RUBY_ID_STATIC_SYM = 0x01, RUBY_ID_LOCAL = 0x00, - RUBY_ID_INSTANCE = 0x01, - RUBY_ID_GLOBAL = 0x03, - RUBY_ID_ATTRSET = 0x04, - RUBY_ID_CONST = 0x05, - RUBY_ID_CLASS = 0x06, - RUBY_ID_JUNK = 0x07, + RUBY_ID_INSTANCE = (0x02<<1), + RUBY_ID_GLOBAL = (0x03<<1), + RUBY_ID_ATTRSET = (0x04<<1), + RUBY_ID_CONST = (0x05<<1), + RUBY_ID_CLASS = (0x06<<1), + RUBY_ID_JUNK = (0x07<<1), RUBY_ID_INTERNAL = RUBY_ID_JUNK, - RUBY_ID_SCOPE_SHIFT = 3, - RUBY_ID_SCOPE_MASK = ~(~0U<ID(n) id##n = ((t##n<) +#define TOKEN2<%=type%>ID(n) id##n = ((t##n<|ID_STATIC_SYM) % types.each do |token| TOKEN2<%=type%>ID(<%=token%>), % end From ff91bc767d217ba9d7cb17d63d4305ca9ec3ce81 Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Tue, 4 Mar 2014 10:50:11 +0900 Subject: [PATCH 02/14] stick -> pin --- include/ruby/ruby.h | 2 +- parse.y | 32 +++++++++++++++----------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index ffe0bb1b5a5e9d..147fb0bd7b45ec 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -352,7 +352,7 @@ rb_long2int_inline(long n) #define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK) ID rb_sym2id(VALUE); -ID rb_sym2id_nostick(VALUE); +ID rb_sym2id_nopin(VALUE); VALUE rb_id2sym(ID); #define STATIC_SYM_P(x) (((VALUE)(x)&~((~(VALUE)0)<fstr); rb_str_cat(str, "=", 1); id = (ID)rb_str_dynamic_intern(str); - rb_stick_dynamic_symbol((VALUE)id); + rb_pin_dynamic_symbol((VALUE)id); } return id; } @@ -10119,14 +10119,14 @@ static struct symbols { st_table *sym_id; st_table *id_str; st_table *id_dsym; - st_table *stick_dsym; + st_table *pinned_dsym; #if ENABLE_SELECTOR_NAMESPACE st_table *ivar2_id; st_table *id_ivar2; #endif VALUE op_sym[tLAST_OP_ID]; int minor_marked; - int stick_dsym_minor_marked; + int pinned_dsym_minor_marked; } global_symbols = {tLAST_TOKEN}; static const struct st_hash_type symhash = { @@ -10166,7 +10166,7 @@ Init_sym(void) { global_symbols.sym_id = st_init_table_with_size(&symhash, 1000); global_symbols.id_str = st_init_numtable_with_size(1000); - global_symbols.stick_dsym = st_init_numtable_with_size(1000); + global_symbols.pinned_dsym = st_init_numtable_with_size(1000); #if ENABLE_SELECTOR_NAMESPACE global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000); global_symbols.id_ivar2 = st_init_numtable_with_size(1000); @@ -10186,16 +10186,15 @@ rb_gc_mark_symbols(int full_mark) { if (full_mark || global_symbols.minor_marked == 0) { rb_mark_tbl(global_symbols.id_str); - rb_mark_tbl(global_symbols.stick_dsym); rb_gc_mark_locations(global_symbols.op_sym, global_symbols.op_sym + numberof(global_symbols.op_sym)); if (!full_mark) global_symbols.minor_marked = 1; } - if (full_mark || global_symbols.stick_dsym_minor_marked == 0) { - rb_mark_tbl(global_symbols.stick_dsym); - if (!full_mark) global_symbols.stick_dsym_minor_marked = 1; + if (full_mark || global_symbols.pinned_dsym_minor_marked == 0) { + rb_mark_tbl(global_symbols.pinned_dsym); + if (!full_mark) global_symbols.pinned_dsym_minor_marked = 1; } } #endif /* !RIPPER */ @@ -10434,11 +10433,11 @@ setup_fake_str(struct RString *fake_str, const char *name, long len) } ID -rb_stick_dynamic_symbol(VALUE sym) +rb_pin_dynamic_symbol(VALUE sym) { /* stick dynamic symbol */ - if (!st_insert(global_symbols.stick_dsym, sym, (st_data_t)sym)) { - global_symbols.stick_dsym_minor_marked = 0; + if (!st_insert(global_symbols.pinned_dsym, sym, (st_data_t)sym)) { + global_symbols.pinned_dsym_minor_marked = 0; } return (ID)sym; } @@ -10453,8 +10452,7 @@ lookup_sym_id(st_data_t str, st_data_t *data) } id = (ID)*data; if (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) { - /* stick dynamic symbol */ - rb_stick_dynamic_symbol((VALUE)id); + rb_pin_dynamic_symbol((VALUE)id); } return TRUE; } @@ -10694,12 +10692,12 @@ rb_sym2id(VALUE x) return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT); } else { - return rb_stick_dynamic_symbol(x); + return rb_pin_dynamic_symbol(x); } } inline ID -rb_sym2id_nostick(VALUE x) +rb_sym2id_nopin(VALUE x) { if (STATIC_SYM_P(x)) { return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT); @@ -10724,7 +10722,7 @@ rb_id2sym(ID x) VALUE rb_sym2str(VALUE sym) { - return rb_id2str(rb_sym2id_nostick(sym)); + return rb_id2str(rb_sym2id_nopin(sym)); } From 8e4a92f29916b91c24f5d07c5938ed298365caba Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Tue, 4 Mar 2014 16:13:50 +0900 Subject: [PATCH 03/14] use lookup_id_str --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 73c162ddbc9fd4..595bf111ab3914 100644 --- a/parse.y +++ b/parse.y @@ -10948,7 +10948,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) sym_check_asciionly(name); - if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id)) + if (lookup_id_str((st_data_t)name, &id)) return (ID)id; if (rb_is_attrset_name(name)) { From 5b9b11c7fa8c2aabde1d90da637c86b986552934 Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Tue, 4 Mar 2014 16:35:14 +0900 Subject: [PATCH 04/14] add rb_check_id_nopin --- internal.h | 4 ++++ parse.y | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/internal.h b/internal.h index cb3a041e20e5cb..6d78d53f19e49a 100644 --- a/internal.h +++ b/internal.h @@ -745,6 +745,10 @@ ID rb_make_internal_id(void); void rb_gc_mark_dsymbol(VALUE); void rb_gc_free_dsymbol(VALUE); VALUE rb_str_dynamic_intern(VALUE s); +ID rb_check_id_nopin(volatile VALUE *); +#ifdef RUBY_ENCODING_H +ID rb_check_id_cstr_nopin(const char *, long, rb_encoding *); +#endif /* proc.c */ VALUE rb_proc_location(VALUE self); diff --git a/parse.y b/parse.y index 595bf111ab3914..efd3a801a669b8 100644 --- a/parse.y +++ b/parse.y @@ -10898,13 +10898,39 @@ rb_is_junk_id(ID id) */ ID rb_check_id(volatile VALUE *namep) +{ + ID id; + + id = rb_check_id_nopin(namep); + if (id && !(id & ID_STATIC_SYM)) { + rb_pin_dynamic_symbol((VALUE)id); + } + + return id; +} + +ID +rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) +{ + ID id; + + id = rb_check_id_cstr_nopin(ptr, len, enc); + if (id && !(id & ID_STATIC_SYM)) { + rb_pin_dynamic_symbol((VALUE)id); + } + + return id; +} + +ID +rb_check_id_nopin(volatile VALUE *namep) { st_data_t id; VALUE tmp; VALUE name = *namep; if (SYMBOL_P(name)) { - return SYM2ID(name); + return rb_sym2id_nopin(name); } else if (!RB_TYPE_P(name, T_STRING)) { tmp = rb_check_string_type(name); @@ -10919,7 +10945,7 @@ rb_check_id(volatile VALUE *namep) sym_check_asciionly(name); - if (lookup_sym_id((st_data_t)name, &id)) + if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id)) return (ID)id; if (rb_is_attrset_name(name)) { @@ -10939,7 +10965,7 @@ rb_check_id(volatile VALUE *namep) } ID -rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) +rb_check_id_cstr_nopin(const char *ptr, long len, rb_encoding *enc) { st_data_t id; struct RString fake_str; @@ -10948,7 +10974,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) sym_check_asciionly(name); - if (lookup_id_str((st_data_t)name, &id)) + if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id)) return (ID)id; if (rb_is_attrset_name(name)) { From 242be489ac529d6a8ca6affcd21f5a7db3a19aa4 Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Tue, 4 Mar 2014 16:53:33 +0900 Subject: [PATCH 05/14] use rb_check_id(/_cstr)_nopin --- load.c | 2 +- object.c | 12 ++++++------ sprintf.c | 2 +- struct.c | 2 +- thread.c | 8 ++++---- variable.c | 8 ++++---- vm_method.c | 10 +++++----- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/load.c b/load.c index e88abfbb0c58b7..2959bd11e956cf 100644 --- a/load.c +++ b/load.c @@ -1108,7 +1108,7 @@ rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) static VALUE rb_mod_autoload_p(VALUE mod, VALUE sym) { - ID id = rb_check_id(&sym); + ID id = rb_check_id_nopin(&sym); if (!id) { return Qnil; } diff --git a/object.c b/object.c index 240b4f54d2d31c..4f6e542fcd073a 100644 --- a/object.c +++ b/object.c @@ -2122,7 +2122,7 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) if (pbeg == p) goto wrong_name; - id = rb_check_id_cstr(pbeg, len = p-pbeg, enc); + id = rb_check_id_cstr_nopin(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { @@ -2264,7 +2264,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) if (pbeg == p) goto wrong_name; - id = rb_check_id_cstr(pbeg, len = p-pbeg, enc); + id = rb_check_id_cstr_nopin(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { @@ -2335,7 +2335,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) static VALUE rb_obj_ivar_get(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = rb_check_id_nopin(&iv); if (!id) { if (rb_is_instance_name(iv)) { @@ -2406,7 +2406,7 @@ rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val) static VALUE rb_obj_ivar_defined(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = rb_check_id_nopin(&iv); if (!id) { if (rb_is_instance_name(iv)) { @@ -2443,7 +2443,7 @@ rb_obj_ivar_defined(VALUE obj, VALUE iv) static VALUE rb_mod_cvar_get(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = rb_check_id_nopin(&iv); if (!id) { if (rb_is_class_name(iv)) { @@ -2509,7 +2509,7 @@ rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val) static VALUE rb_mod_cvar_defined(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = rb_check_id_nopin(&iv); if (!id) { if (rb_is_class_name(iv)) { diff --git a/sprintf.c b/sprintf.c index 6551f8f0435e30..d4b57375b8fa00 100644 --- a/sprintf.c +++ b/sprintf.c @@ -567,7 +567,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) rb_enc_raise(enc, rb_eArgError, "named%.*s after <%s>", len, start, rb_id2name(id)); } - nextvalue = GETNAMEARG((id = rb_check_id_cstr(start + 1, + nextvalue = GETNAMEARG((id = rb_check_id_cstr_nopin(start + 1, len - 2 /* without parenthesis */, enc), ID2SYM(id)), diff --git a/struct.c b/struct.c index c3dba62962dda2..f3dcaa18a6d89b 100644 --- a/struct.c +++ b/struct.c @@ -749,7 +749,7 @@ rb_struct_aref(VALUE s, VALUE idx) return rb_struct_aref_id(s, SYM2ID(idx)); } else if (RB_TYPE_P(idx, T_STRING)) { - ID id = rb_check_id(&idx); + ID id = rb_check_id_nopin(&idx); if (!id) { rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct", QUOTE(idx)); diff --git a/thread.c b/thread.c index 0b52cbd127ba0c..20aec11d78b2f4 100644 --- a/thread.c +++ b/thread.c @@ -2776,7 +2776,7 @@ rb_thread_local_aref(VALUE thread, ID id) static VALUE rb_thread_aref(VALUE thread, VALUE key) { - ID id = rb_check_id(&key); + ID id = rb_check_id_nopin(&key); if (!id) return Qnil; return rb_thread_local_aref(thread, id); } @@ -2853,7 +2853,7 @@ static VALUE rb_thread_variable_get(VALUE thread, VALUE key) { VALUE locals; - ID id = rb_check_id(&key); + ID id = rb_check_id_nopin(&key); if (!id) return Qnil; locals = rb_ivar_get(thread, id_locals); @@ -2899,7 +2899,7 @@ static VALUE rb_thread_key_p(VALUE self, VALUE key) { rb_thread_t *th; - ID id = rb_check_id(&key); + ID id = rb_check_id_nopin(&key); GetThreadPtr(self, th); @@ -3020,7 +3020,7 @@ static VALUE rb_thread_variable_p(VALUE thread, VALUE key) { VALUE locals; - ID id = rb_check_id(&key); + ID id = rb_check_id_nopin(&key); if (!id) return Qfalse; diff --git a/variable.c b/variable.c index c97c210af12971..dba5d97b209d4b 100644 --- a/variable.c +++ b/variable.c @@ -353,7 +353,7 @@ rb_path_to_class(VALUE pathname) } while (*p) { while (*p && *p != ':') p++; - id = rb_check_id_cstr(pbeg, p-pbeg, enc); + id = rb_check_id_cstr_nopin(pbeg, p-pbeg, enc); if (p[0] == ':') { if (p[1] != ':') goto undefined_class; p += 2; @@ -1403,7 +1403,7 @@ VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name) { VALUE val = Qnil; - const ID id = rb_check_id(&name); + const ID id = rb_check_id_nopin(&name); st_data_t n, v; struct st_table *iv_index_tbl; st_data_t index; @@ -1919,7 +1919,7 @@ rb_public_const_get_at(VALUE klass, ID id) VALUE rb_mod_remove_const(VALUE mod, VALUE name) { - const ID id = rb_check_id(&name); + const ID id = rb_check_id_nopin(&name); if (!id) { if (rb_is_const_name(name)) { @@ -2566,7 +2566,7 @@ rb_mod_class_variables(int argc, VALUE *argv, VALUE mod) VALUE rb_mod_remove_cvar(VALUE mod, VALUE name) { - const ID id = rb_check_id(&name); + const ID id = rb_check_id_nopin(&name); st_data_t val, n = id; if (!id) { diff --git a/vm_method.c b/vm_method.c index 203b8b8dcef6ee..7e3def47306378 100644 --- a/vm_method.c +++ b/vm_method.c @@ -784,7 +784,7 @@ rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) for (i = 0; i < argc; i++) { VALUE v = argv[i]; - ID id = rb_check_id(&v); + ID id = rb_check_id_nopin(&v); if (!id) { rb_name_error_str(v, "method `%s' not defined in %s", RSTRING_PTR(v), rb_class2name(mod)); @@ -995,7 +995,7 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) int i; for (i = 0; i < argc; i++) { VALUE v = argv[i]; - ID id = rb_check_id(&v); + ID id = rb_check_id_nopin(&v); if (!id) { rb_method_name_error(mod, v); } @@ -1035,7 +1035,7 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) static VALUE rb_mod_method_defined(VALUE mod, VALUE mid) { - ID id = rb_check_id(&mid); + ID id = rb_check_id_nopin(&mid); if (!id || !rb_method_boundp(mod, id, 1)) { return Qfalse; } @@ -1049,7 +1049,7 @@ static VALUE check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex) { const rb_method_entry_t *me; - ID id = rb_check_id(&mid); + ID id = rb_check_id_nopin(&mid); if (!id) return Qfalse; me = rb_method_entry(mod, id, 0); if (me) { @@ -1678,7 +1678,7 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) ID id; rb_scan_args(argc, argv, "11", &mid, &priv); - if (!(id = rb_check_id(&mid))) { + if (!(id = rb_check_id_nopin(&mid))) { if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) { VALUE args[2]; args[0] = ID2SYM(rb_to_id(mid)); From ecc3548cad841ebe8e415147b3125905954ae505 Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Tue, 4 Mar 2014 17:08:25 +0900 Subject: [PATCH 06/14] check TOKEN symbol --- parse.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parse.y b/parse.y index efd3a801a669b8..39cdf65d626715 100644 --- a/parse.y +++ b/parse.y @@ -10902,7 +10902,7 @@ rb_check_id(volatile VALUE *namep) ID id; id = rb_check_id_nopin(namep); - if (id && !(id & ID_STATIC_SYM)) { + if (id && !(id & ID_STATIC_SYM || id < tLAST_TOKEN)) { rb_pin_dynamic_symbol((VALUE)id); } @@ -10915,7 +10915,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) ID id; id = rb_check_id_cstr_nopin(ptr, len, enc); - if (id && !(id & ID_STATIC_SYM)) { + if (id && !(id & ID_STATIC_SYM || id < tLAST_TOKEN)) { rb_pin_dynamic_symbol((VALUE)id); } From 67adf03a013882975f474db19648436ae4d6fd7b Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Wed, 5 Mar 2014 16:58:49 +0900 Subject: [PATCH 07/14] use rb_sym2str(sym) instead of rb_id2str(SYM2ID(sym)) --- string.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/string.c b/string.c index 2346adf4236400..79d282b60c28de 100644 --- a/string.c +++ b/string.c @@ -8345,10 +8345,9 @@ sym_inspect(VALUE sym) VALUE str; const char *ptr; long len; - ID id = SYM2ID(sym); char *dest; - sym = rb_id2str(id); + sym = rb_sym2str(sym); if (!rb_str_symname_p(sym)) { str = rb_str_inspect(sym); len = RSTRING_LEN(str); @@ -8384,9 +8383,7 @@ sym_inspect(VALUE sym) VALUE rb_sym_to_s(VALUE sym) { - ID id = SYM2ID(sym); - - return str_new_shared(rb_cString, rb_id2str(id)); + return str_new_shared(rb_cString, rb_sym2str(sym)); } From 6fa42b0f73bbb818c349beb70cd80bd6c312affc Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Fri, 7 Mar 2014 16:58:24 +0900 Subject: [PATCH 08/14] add intern_cstr_nopin() and use this in parser_yylex --- parse.y | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/parse.y b/parse.y index 39cdf65d626715..3b6771f2e25921 100644 --- a/parse.y +++ b/parse.y @@ -297,6 +297,12 @@ struct parser_params { #endif }; +#ifdef RIPPER +#define intern_cstr_nopin(n,l,en) rb_intern3(n,l,en) +#else +static ID intern_cstr_nopin(const char *, long, rb_encoding *); +#endif + #define STR_NEW(p,n) rb_enc_str_new((p),(n),current_enc) #define STR_NEW0() rb_enc_str_new(0,0,current_enc) #define STR_NEW2(p) rb_enc_str_new((p),strlen(p),current_enc) @@ -7999,7 +8005,7 @@ parser_yylex(struct parser_params *parser) return '$'; } gvar: - set_yylval_name(rb_intern3(tok(), tokidx, current_enc)); + set_yylval_name(intern_cstr_nopin(tok(), tokidx, current_enc)); return tGVAR; case '&': /* $&: last match */ @@ -10457,8 +10463,8 @@ lookup_sym_id(st_data_t str, st_data_t *data) return TRUE; } -ID -rb_intern3(const char *name, long len, rb_encoding *enc) +static ID +intern_cstr_nopin(const char *name, long len, rb_encoding *enc) { st_data_t data; struct RString fake_str; @@ -10466,13 +10472,26 @@ rb_intern3(const char *name, long len, rb_encoding *enc) rb_enc_associate(str, enc); OBJ_FREEZE(str); - if (lookup_sym_id(str, &data)) + if (st_lookup(global_symbols.sym_id, str, &data)) return (ID)data; str = rb_enc_str_new(name, len, enc); /* make true string */ return intern_str(str); } +ID +rb_intern3(const char *name, long len, rb_encoding *enc) +{ + ID id; + + id = intern_cstr_nopin(name, len, enc); + if (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) { + rb_pin_dynamic_symbol((VALUE)id); + } + + return id; +} + static ID next_id_base(void) { From d1d5ab73da3e7c1c122c3ef2e0119e0c0f624fb3 Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Fri, 7 Mar 2014 17:22:02 +0900 Subject: [PATCH 09/14] hide nopin --- include/ruby/ruby.h | 1 - internal.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 147fb0bd7b45ec..8de3a43010abb9 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -352,7 +352,6 @@ rb_long2int_inline(long n) #define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK) ID rb_sym2id(VALUE); -ID rb_sym2id_nopin(VALUE); VALUE rb_id2sym(ID); #define STATIC_SYM_P(x) (((VALUE)(x)&~((~(VALUE)0)< Date: Fri, 7 Mar 2014 17:27:23 +0900 Subject: [PATCH 10/14] add ID_DYNAMIC_SYM_P() macro --- parse.y | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/parse.y b/parse.y index 3b6771f2e25921..bc441fc959846d 100644 --- a/parse.y +++ b/parse.y @@ -10438,6 +10438,8 @@ setup_fake_str(struct RString *fake_str, const char *name, long len) return (VALUE)fake_str; } +#define ID_DYNAMIC_SYM_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) + ID rb_pin_dynamic_symbol(VALUE sym) { @@ -10457,7 +10459,7 @@ lookup_sym_id(st_data_t str, st_data_t *data) return FALSE; } id = (ID)*data; - if (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) { + if (ID_DYNAMIC_SYM_P(id)) { rb_pin_dynamic_symbol((VALUE)id); } return TRUE; @@ -10485,7 +10487,7 @@ rb_intern3(const char *name, long len, rb_encoding *enc) ID id; id = intern_cstr_nopin(name, len, enc); - if (!(id&ID_STATIC_SYM)&&id>tLAST_TOKEN) { + if (ID_DYNAMIC_SYM_P(id)) { rb_pin_dynamic_symbol((VALUE)id); } @@ -10697,7 +10699,7 @@ lookup_id_str(ID id, st_data_t *data) if (st_lookup(global_symbols.id_str, id, data)) { return TRUE; } - if (!(id&ID_STATIC_SYM)) { + if (ID_DYNAMIC_SYM_P(id)) { *data = RSYMBOL(id)->fstr; return TRUE; } @@ -10729,7 +10731,7 @@ rb_sym2id_nopin(VALUE x) inline VALUE rb_id2sym(ID x) { - if (x&ID_STATIC_SYM||x Date: Mon, 10 Mar 2014 15:39:44 +0900 Subject: [PATCH 11/14] nopin -> without_pindown --- internal.h | 6 +++--- load.c | 2 +- object.c | 12 ++++++------ parse.y | 26 +++++++++++++------------- sprintf.c | 2 +- struct.c | 2 +- thread.c | 8 ++++---- variable.c | 8 ++++---- vm_method.c | 10 +++++----- 9 files changed, 38 insertions(+), 38 deletions(-) diff --git a/internal.h b/internal.h index 2b4af7a1fbded8..e54ccab3c3492f 100644 --- a/internal.h +++ b/internal.h @@ -745,10 +745,10 @@ ID rb_make_internal_id(void); void rb_gc_mark_dsymbol(VALUE); void rb_gc_free_dsymbol(VALUE); VALUE rb_str_dynamic_intern(VALUE s); -ID rb_check_id_nopin(volatile VALUE *); -ID rb_sym2id_nopin(VALUE); +ID rb_check_id_without_pindown(volatile VALUE *); +ID rb_sym2id_without_pindown(VALUE); #ifdef RUBY_ENCODING_H -ID rb_check_id_cstr_nopin(const char *, long, rb_encoding *); +ID rb_check_id_cstr_without_pindown(const char *, long, rb_encoding *); #endif /* proc.c */ diff --git a/load.c b/load.c index 2959bd11e956cf..bb8829da057512 100644 --- a/load.c +++ b/load.c @@ -1108,7 +1108,7 @@ rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) static VALUE rb_mod_autoload_p(VALUE mod, VALUE sym) { - ID id = rb_check_id_nopin(&sym); + ID id = rb_check_id_without_pindown(&sym); if (!id) { return Qnil; } diff --git a/object.c b/object.c index 4f6e542fcd073a..7ce8a1df19ec68 100644 --- a/object.c +++ b/object.c @@ -2122,7 +2122,7 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) if (pbeg == p) goto wrong_name; - id = rb_check_id_cstr_nopin(pbeg, len = p-pbeg, enc); + id = rb_check_id_cstr_without_pindown(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { @@ -2264,7 +2264,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) if (pbeg == p) goto wrong_name; - id = rb_check_id_cstr_nopin(pbeg, len = p-pbeg, enc); + id = rb_check_id_cstr_without_pindown(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { @@ -2335,7 +2335,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) static VALUE rb_obj_ivar_get(VALUE obj, VALUE iv) { - ID id = rb_check_id_nopin(&iv); + ID id = rb_check_id_without_pindown(&iv); if (!id) { if (rb_is_instance_name(iv)) { @@ -2406,7 +2406,7 @@ rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val) static VALUE rb_obj_ivar_defined(VALUE obj, VALUE iv) { - ID id = rb_check_id_nopin(&iv); + ID id = rb_check_id_without_pindown(&iv); if (!id) { if (rb_is_instance_name(iv)) { @@ -2443,7 +2443,7 @@ rb_obj_ivar_defined(VALUE obj, VALUE iv) static VALUE rb_mod_cvar_get(VALUE obj, VALUE iv) { - ID id = rb_check_id_nopin(&iv); + ID id = rb_check_id_without_pindown(&iv); if (!id) { if (rb_is_class_name(iv)) { @@ -2509,7 +2509,7 @@ rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val) static VALUE rb_mod_cvar_defined(VALUE obj, VALUE iv) { - ID id = rb_check_id_nopin(&iv); + ID id = rb_check_id_without_pindown(&iv); if (!id) { if (rb_is_class_name(iv)) { diff --git a/parse.y b/parse.y index bc441fc959846d..d0cd6ee6306498 100644 --- a/parse.y +++ b/parse.y @@ -298,16 +298,16 @@ struct parser_params { }; #ifdef RIPPER -#define intern_cstr_nopin(n,l,en) rb_intern3(n,l,en) +#define intern_cstr_without_pindown(n,l,en) rb_intern3(n,l,en) #else -static ID intern_cstr_nopin(const char *, long, rb_encoding *); +static ID intern_cstr_without_pindown(const char *, long, rb_encoding *); #endif #define STR_NEW(p,n) rb_enc_str_new((p),(n),current_enc) #define STR_NEW0() rb_enc_str_new(0,0,current_enc) #define STR_NEW2(p) rb_enc_str_new((p),strlen(p),current_enc) #define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),current_enc) -#define TOK_INTERN() rb_intern3(tok(), toklen(), current_enc) +#define TOK_INTERN() intern_cstr_without_pindown(tok(), toklen(), current_enc) static int parser_yyerror(struct parser_params*, const char*); #define yyerror(msg) parser_yyerror(parser, (msg)) @@ -8005,7 +8005,7 @@ parser_yylex(struct parser_params *parser) return '$'; } gvar: - set_yylval_name(intern_cstr_nopin(tok(), tokidx, current_enc)); + set_yylval_name(intern_cstr_without_pindown(tok(), tokidx, current_enc)); return tGVAR; case '&': /* $&: last match */ @@ -10466,7 +10466,7 @@ lookup_sym_id(st_data_t str, st_data_t *data) } static ID -intern_cstr_nopin(const char *name, long len, rb_encoding *enc) +intern_cstr_without_pindown(const char *name, long len, rb_encoding *enc) { st_data_t data; struct RString fake_str; @@ -10486,7 +10486,7 @@ rb_intern3(const char *name, long len, rb_encoding *enc) { ID id; - id = intern_cstr_nopin(name, len, enc); + id = intern_cstr_without_pindown(name, len, enc); if (ID_DYNAMIC_SYM_P(id)) { rb_pin_dynamic_symbol((VALUE)id); } @@ -10718,7 +10718,7 @@ rb_sym2id(VALUE x) } inline ID -rb_sym2id_nopin(VALUE x) +rb_sym2id_without_pindown(VALUE x) { if (STATIC_SYM_P(x)) { return RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT); @@ -10743,7 +10743,7 @@ rb_id2sym(ID x) VALUE rb_sym2str(VALUE sym) { - return rb_id2str(rb_sym2id_nopin(sym)); + return rb_id2str(rb_sym2id_without_pindown(sym)); } @@ -10922,7 +10922,7 @@ rb_check_id(volatile VALUE *namep) { ID id; - id = rb_check_id_nopin(namep); + id = rb_check_id_without_pindown(namep); if (ID_DYNAMIC_SYM_P(id)) { rb_pin_dynamic_symbol((VALUE)id); } @@ -10935,7 +10935,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) { ID id; - id = rb_check_id_cstr_nopin(ptr, len, enc); + id = rb_check_id_cstr_without_pindown(ptr, len, enc); if (ID_DYNAMIC_SYM_P(id)) { rb_pin_dynamic_symbol((VALUE)id); } @@ -10944,14 +10944,14 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) } ID -rb_check_id_nopin(volatile VALUE *namep) +rb_check_id_without_pindown(volatile VALUE *namep) { st_data_t id; VALUE tmp; VALUE name = *namep; if (SYMBOL_P(name)) { - return rb_sym2id_nopin(name); + return rb_sym2id_without_pindown(name); } else if (!RB_TYPE_P(name, T_STRING)) { tmp = rb_check_string_type(name); @@ -10986,7 +10986,7 @@ rb_check_id_nopin(volatile VALUE *namep) } ID -rb_check_id_cstr_nopin(const char *ptr, long len, rb_encoding *enc) +rb_check_id_cstr_without_pindown(const char *ptr, long len, rb_encoding *enc) { st_data_t id; struct RString fake_str; diff --git a/sprintf.c b/sprintf.c index d4b57375b8fa00..52a7168dc97760 100644 --- a/sprintf.c +++ b/sprintf.c @@ -567,7 +567,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt) rb_enc_raise(enc, rb_eArgError, "named%.*s after <%s>", len, start, rb_id2name(id)); } - nextvalue = GETNAMEARG((id = rb_check_id_cstr_nopin(start + 1, + nextvalue = GETNAMEARG((id = rb_check_id_cstr_without_pindown(start + 1, len - 2 /* without parenthesis */, enc), ID2SYM(id)), diff --git a/struct.c b/struct.c index f3dcaa18a6d89b..1891f5d5744ef1 100644 --- a/struct.c +++ b/struct.c @@ -749,7 +749,7 @@ rb_struct_aref(VALUE s, VALUE idx) return rb_struct_aref_id(s, SYM2ID(idx)); } else if (RB_TYPE_P(idx, T_STRING)) { - ID id = rb_check_id_nopin(&idx); + ID id = rb_check_id_without_pindown(&idx); if (!id) { rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct", QUOTE(idx)); diff --git a/thread.c b/thread.c index 20aec11d78b2f4..dfa91a827bc1d3 100644 --- a/thread.c +++ b/thread.c @@ -2776,7 +2776,7 @@ rb_thread_local_aref(VALUE thread, ID id) static VALUE rb_thread_aref(VALUE thread, VALUE key) { - ID id = rb_check_id_nopin(&key); + ID id = rb_check_id_without_pindown(&key); if (!id) return Qnil; return rb_thread_local_aref(thread, id); } @@ -2853,7 +2853,7 @@ static VALUE rb_thread_variable_get(VALUE thread, VALUE key) { VALUE locals; - ID id = rb_check_id_nopin(&key); + ID id = rb_check_id_without_pindown(&key); if (!id) return Qnil; locals = rb_ivar_get(thread, id_locals); @@ -2899,7 +2899,7 @@ static VALUE rb_thread_key_p(VALUE self, VALUE key) { rb_thread_t *th; - ID id = rb_check_id_nopin(&key); + ID id = rb_check_id_without_pindown(&key); GetThreadPtr(self, th); @@ -3020,7 +3020,7 @@ static VALUE rb_thread_variable_p(VALUE thread, VALUE key) { VALUE locals; - ID id = rb_check_id_nopin(&key); + ID id = rb_check_id_without_pindown(&key); if (!id) return Qfalse; diff --git a/variable.c b/variable.c index dba5d97b209d4b..142332720dc688 100644 --- a/variable.c +++ b/variable.c @@ -353,7 +353,7 @@ rb_path_to_class(VALUE pathname) } while (*p) { while (*p && *p != ':') p++; - id = rb_check_id_cstr_nopin(pbeg, p-pbeg, enc); + id = rb_check_id_cstr_without_pindown(pbeg, p-pbeg, enc); if (p[0] == ':') { if (p[1] != ':') goto undefined_class; p += 2; @@ -1403,7 +1403,7 @@ VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name) { VALUE val = Qnil; - const ID id = rb_check_id_nopin(&name); + const ID id = rb_check_id_without_pindown(&name); st_data_t n, v; struct st_table *iv_index_tbl; st_data_t index; @@ -1919,7 +1919,7 @@ rb_public_const_get_at(VALUE klass, ID id) VALUE rb_mod_remove_const(VALUE mod, VALUE name) { - const ID id = rb_check_id_nopin(&name); + const ID id = rb_check_id_without_pindown(&name); if (!id) { if (rb_is_const_name(name)) { @@ -2566,7 +2566,7 @@ rb_mod_class_variables(int argc, VALUE *argv, VALUE mod) VALUE rb_mod_remove_cvar(VALUE mod, VALUE name) { - const ID id = rb_check_id_nopin(&name); + const ID id = rb_check_id_without_pindown(&name); st_data_t val, n = id; if (!id) { diff --git a/vm_method.c b/vm_method.c index 7e3def47306378..1d77307a720d46 100644 --- a/vm_method.c +++ b/vm_method.c @@ -784,7 +784,7 @@ rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) for (i = 0; i < argc; i++) { VALUE v = argv[i]; - ID id = rb_check_id_nopin(&v); + ID id = rb_check_id_without_pindown(&v); if (!id) { rb_name_error_str(v, "method `%s' not defined in %s", RSTRING_PTR(v), rb_class2name(mod)); @@ -995,7 +995,7 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) int i; for (i = 0; i < argc; i++) { VALUE v = argv[i]; - ID id = rb_check_id_nopin(&v); + ID id = rb_check_id_without_pindown(&v); if (!id) { rb_method_name_error(mod, v); } @@ -1035,7 +1035,7 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) static VALUE rb_mod_method_defined(VALUE mod, VALUE mid) { - ID id = rb_check_id_nopin(&mid); + ID id = rb_check_id_without_pindown(&mid); if (!id || !rb_method_boundp(mod, id, 1)) { return Qfalse; } @@ -1049,7 +1049,7 @@ static VALUE check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex) { const rb_method_entry_t *me; - ID id = rb_check_id_nopin(&mid); + ID id = rb_check_id_without_pindown(&mid); if (!id) return Qfalse; me = rb_method_entry(mod, id, 0); if (me) { @@ -1678,7 +1678,7 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) ID id; rb_scan_args(argc, argv, "11", &mid, &priv); - if (!(id = rb_check_id_nopin(&mid))) { + if (!(id = rb_check_id_without_pindown(&mid))) { if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) { VALUE args[2]; args[0] = ID2SYM(rb_to_id(mid)); From 2652b6c4de4339dc21f9da4c8688d3db6d636a0e Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Tue, 11 Mar 2014 16:12:53 +0900 Subject: [PATCH 12/14] use intern_cstr_without_pindown --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index d0cd6ee6306498..c6dc3a26055a07 100644 --- a/parse.y +++ b/parse.y @@ -9938,7 +9938,7 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end, !rb_enc_symname2_p(s, len, enc)) { return ST_CONTINUE; } - var = rb_intern3(s, len, enc); + var = intern_cstr_without_pindown(s, len, enc); if (dvar_defined(var) || local_id(var)) { rb_warningS("named capture conflicts a local variable - %s", rb_id2name(var)); From 9cd060aab6ca9cf55971b8d8881b30f0204f71be Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Fri, 14 Mar 2014 13:58:21 +0900 Subject: [PATCH 13/14] a fstr is freed up if collector sweeps it before a dsym --- gc.c | 8 +------- parse.y | 13 ++++++++----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/gc.c b/gc.c index 3e66f360942c5a..f5126acaf97da4 100644 --- a/gc.c +++ b/gc.c @@ -3943,6 +3943,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) case T_FLOAT: case T_BIGNUM: + case T_SYMBOL: break; case T_MATCH: @@ -3974,13 +3975,6 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) } break; - case T_SYMBOL: - { - ptr = obj->as.symbol.fstr; - goto again; - } - break; - default: #if GC_DEBUG rb_gcdebug_print_obj_condition((VALUE)obj); diff --git a/parse.y b/parse.y index c6dc3a26055a07..9a32553cab58d3 100644 --- a/parse.y +++ b/parse.y @@ -10652,6 +10652,7 @@ void rb_gc_free_dsymbol(VALUE ptr) { st_delete(global_symbols.sym_id, (st_data_t *)&RSYMBOL(ptr)->fstr, 0); + st_delete(global_symbols.id_str, (st_data_t *)&ptr, 0); RSYMBOL(ptr)->fstr = (VALUE)NULL; } @@ -10684,25 +10685,27 @@ rb_str_dynamic_intern(VALUE s) RSYMBOL(dsym)->fstr = str; RSYMBOL(dsym)->type = type; + st_add_direct(global_symbols.sym_id, (st_data_t)str, (ID)dsym); + st_add_direct(global_symbols.id_str, (ID)dsym, (st_data_t)str); + global_symbols.minor_marked = 0; + if (RUBY_DTRACE_SYMBOL_CREATE_ENABLED()) { RUBY_DTRACE_SYMBOL_CREATE(RSTRING_PTR(str), rb_sourcefile(), rb_sourceline()); } - st_add_direct(global_symbols.sym_id, (st_data_t)str, dsym); - global_symbols.minor_marked = 0; return dsym; } static int lookup_id_str(ID id, st_data_t *data) { - if (st_lookup(global_symbols.id_str, id, data)) { - return TRUE; - } if (ID_DYNAMIC_SYM_P(id)) { *data = RSYMBOL(id)->fstr; return TRUE; } + if (st_lookup(global_symbols.id_str, id, data)) { + return TRUE; + } return FALSE; } From 5d5f9a63cc059433aa304a4af58ca91a14715a9e Mon Sep 17 00:00:00 2001 From: Narihiro Nakamura Date: Sat, 15 Mar 2014 13:12:22 +0900 Subject: [PATCH 14/14] remove volatile declaration --- internal.h | 2 +- parse.y | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal.h b/internal.h index e54ccab3c3492f..5932eb4b362ee6 100644 --- a/internal.h +++ b/internal.h @@ -745,7 +745,7 @@ ID rb_make_internal_id(void); void rb_gc_mark_dsymbol(VALUE); void rb_gc_free_dsymbol(VALUE); VALUE rb_str_dynamic_intern(VALUE s); -ID rb_check_id_without_pindown(volatile VALUE *); +ID rb_check_id_without_pindown(VALUE *); ID rb_sym2id_without_pindown(VALUE); #ifdef RUBY_ENCODING_H ID rb_check_id_cstr_without_pindown(const char *, long, rb_encoding *); diff --git a/parse.y b/parse.y index 9a32553cab58d3..071f8151211520 100644 --- a/parse.y +++ b/parse.y @@ -10925,7 +10925,7 @@ rb_check_id(volatile VALUE *namep) { ID id; - id = rb_check_id_without_pindown(namep); + id = rb_check_id_without_pindown((VALUE *)namep); if (ID_DYNAMIC_SYM_P(id)) { rb_pin_dynamic_symbol((VALUE)id); } @@ -10947,7 +10947,7 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) } ID -rb_check_id_without_pindown(volatile VALUE *namep) +rb_check_id_without_pindown(VALUE *namep) { st_data_t id; VALUE tmp;