diff options
Diffstat (limited to 'symbol.c')
| -rw-r--r-- | symbol.c | 207 |
1 files changed, 113 insertions, 94 deletions
@@ -9,6 +9,7 @@ **********************************************************************/ +#include "darray.h" #include "internal.h" #include "internal/concurrent_set.h" #include "internal/error.h" @@ -19,19 +20,13 @@ #include "internal/vm.h" #include "probes.h" #include "ruby/encoding.h" +#include "ruby/ractor.h" #include "ruby/st.h" #include "symbol.h" #include "vm_sync.h" #include "builtin.h" #include "ruby/internal/attr/nonstring.h" -#if defined(USE_SYMBOL_GC) && !(USE_SYMBOL_GC+0) -# undef USE_SYMBOL_GC -# define USE_SYMBOL_GC 0 -#else -# undef USE_SYMBOL_GC -# define USE_SYMBOL_GC 1 -#endif #if defined(SYMBOL_DEBUG) && (SYMBOL_DEBUG+0) # undef SYMBOL_DEBUG # define SYMBOL_DEBUG 1 @@ -86,12 +81,6 @@ Init_op_tbl(void) static const int ID_ENTRY_UNIT = 512; -enum id_entry_type { - ID_ENTRY_STR, - ID_ENTRY_SYM, - ID_ENTRY_SIZE -}; - typedef struct { rb_atomic_t next_id; VALUE sym_set; @@ -168,6 +157,60 @@ sym_set_cmp(VALUE a, VALUE b) return rb_str_hash_cmp(sym_set_sym_get_str(a), sym_set_sym_get_str(b)) == false; } +struct sym_id_entry { + VALUE sym; + VALUE str; +}; + +static void +sym_id_entry_list_mark(void *ptr) +{ + rb_darray(struct sym_id_entry) ary = ptr; + + struct sym_id_entry *entry; + rb_darray_foreach(ary, i, entry) { + // sym must be pinned because it may be used in places that don't + // support compaction + rb_gc_mark(entry->sym); + rb_gc_mark_movable(entry->str); + } +} + +static void +sym_id_entry_list_free(void *ptr) +{ + rb_darray_free_sized(ptr, struct sym_id_entry); +} + +static size_t +sym_id_entry_list_memsize(const void *ptr) +{ + const rb_darray(struct sym_id_entry) ary = ptr; + + return rb_darray_memsize(ary); +} + +static void +sym_id_entry_list_compact(void *ptr) +{ + rb_darray(struct sym_id_entry) ary = ptr; + + struct sym_id_entry *entry; + rb_darray_foreach(ary, i, entry) { + entry->str = rb_gc_location(entry->str); + } +} + +static const rb_data_type_t sym_id_entry_list_type = { + "symbol_id_entry_list", + { + sym_id_entry_list_mark, + sym_id_entry_list_free, + sym_id_entry_list_memsize, + sym_id_entry_list_compact, + }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED +}; static int sym_check_asciionly(VALUE str, bool fake_str) @@ -200,7 +243,6 @@ dup_string_for_create(VALUE str) OBJ_FREEZE(str); str = rb_fstring(str); - return str; } @@ -231,14 +273,24 @@ set_id_entry(rb_symbols_t *symbols, rb_id_serial_t num, VALUE str, VALUE sym) size_t idx = num / ID_ENTRY_UNIT; - VALUE ary, ids = symbols->ids; - if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(ary = rb_ary_entry(ids, (long)idx))) { - ary = rb_ary_hidden_new(ID_ENTRY_UNIT * ID_ENTRY_SIZE); - rb_ary_store(ids, (long)idx, ary); + VALUE id_entry_list, ids = symbols->ids; + rb_darray(struct sym_id_entry) entries; + if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(id_entry_list = rb_ary_entry(ids, (long)idx))) { + rb_darray_make(&entries, ID_ENTRY_UNIT); + id_entry_list = TypedData_Wrap_Struct(0, &sym_id_entry_list_type, entries); + rb_ary_store(ids, (long)idx, id_entry_list); + } + else { + entries = RTYPEDDATA_GET_DATA(id_entry_list); } - idx = (num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE; - rb_ary_store(ary, (long)idx + ID_ENTRY_STR, str); - rb_ary_store(ary, (long)idx + ID_ENTRY_SYM, sym); + + idx = num % ID_ENTRY_UNIT; + struct sym_id_entry *entry = rb_darray_ref(entries, idx); + RUBY_ASSERT(entry->str == 0); + RUBY_ASSERT(entry->sym == 0); + + RB_OBJ_WRITE(id_entry_list, &entry->str, str); + RB_OBJ_WRITE(id_entry_list, &entry->sym, sym); } static VALUE @@ -251,12 +303,12 @@ sym_set_create(VALUE sym, void *data) VALUE str = dup_string_for_create(static_sym_entry->str); if (create_dynamic_symbol) { - NEWOBJ_OF(obj, struct RSymbol, rb_cSymbol, T_SYMBOL | FL_WB_PROTECTED, sizeof(struct RSymbol), 0); + NEWOBJ_OF(obj, struct RSymbol, rb_cSymbol, T_SYMBOL, sizeof(struct RSymbol)); rb_encoding *enc = rb_enc_get(str); rb_enc_set_index((VALUE)obj, rb_enc_to_index(enc)); - OBJ_FREEZE((VALUE)obj); RB_OBJ_WRITE((VALUE)obj, &obj->fstr, str); + RB_OBJ_SET_FROZEN_SHAREABLE((VALUE)obj); int id = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN); if (id < 0) id = ID_INTERNAL; @@ -394,7 +446,7 @@ rb_free_global_symbol_table(void) } WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str)); -WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id)); +WARN_UNUSED_RESULT(static VALUE get_id_str(ID id)); ID rb_id_attrset(ID id) @@ -419,7 +471,7 @@ rb_id_attrset(ID id) return id; default: { - VALUE str = lookup_id_str(id); + VALUE str = get_id_str(id); if (str != 0) { rb_name_error(id, "cannot make unknown type ID %d:%"PRIsVALUE" attrset", scope, str); @@ -434,7 +486,7 @@ rb_id_attrset(ID id) bool error = false; /* make new symbol and ID */ - VALUE str = lookup_id_str(id); + VALUE str = get_id_str(id); if (str) { str = rb_str_dup(str); rb_str_cat(str, "=", 1); @@ -705,75 +757,60 @@ rb_enc_symname2_p(const char *name, long len, rb_encoding *enc) return rb_enc_symname_type(name, len, enc, IDSET_ATTRSET_FOR_SYNTAX) != -1; } -static VALUE -get_id_serial_entry(rb_id_serial_t num, ID id, const enum id_entry_type t) +static struct sym_id_entry * +get_id_serial_entry(rb_id_serial_t num) { - VALUE result = 0; + struct sym_id_entry *entry = NULL; GLOBAL_SYMBOLS_LOCKING(symbols) { if (num && num < RUBY_ATOMIC_LOAD(symbols->next_id)) { size_t idx = num / ID_ENTRY_UNIT; VALUE ids = symbols->ids; - VALUE ary; - if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) { - long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE; - result = rb_ary_entry(ary, pos + t); + VALUE id_entry_list; + if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(id_entry_list = rb_ary_entry(ids, (long)idx))) { + rb_darray(struct sym_id_entry) entries = RTYPEDDATA_GET_DATA(id_entry_list); - if (NIL_P(result)) { - result = 0; - } - else if (CHECK_ID_SERIAL) { - if (id) { - VALUE sym = result; - if (t != ID_ENTRY_SYM) - sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM); - if (STATIC_SYM_P(sym)) { - if (STATIC_SYM2ID(sym) != id) result = 0; - } - else { - if (RSYMBOL(sym)->id != id) result = 0; - } - } - } + size_t pos = (size_t)(num % ID_ENTRY_UNIT); + RUBY_ASSERT(pos < rb_darray_size(entries)); + entry = rb_darray_ref(entries, pos); } } } - if (result) { - switch (t) { - case ID_ENTRY_STR: - RUBY_ASSERT_BUILTIN_TYPE(result, T_STRING); - break; - case ID_ENTRY_SYM: - RUBY_ASSERT_BUILTIN_TYPE(result, T_SYMBOL); - break; - default: - break; - } - } + return entry; +} - return result; +static VALUE +get_id_sym(ID id) +{ + struct sym_id_entry *entry = get_id_serial_entry(rb_id_to_serial(id)); + return entry ? entry->sym : 0; } static VALUE -get_id_entry(ID id, const enum id_entry_type t) +get_id_str(ID id) { - return get_id_serial_entry(rb_id_to_serial(id), id, t); + struct sym_id_entry *entry = get_id_serial_entry(rb_id_to_serial(id)); + return entry ? entry->str : 0; } int rb_static_id_valid_p(ID id) { - return STATIC_ID2SYM(id) == get_id_entry(id, ID_ENTRY_SYM); + return STATIC_ID2SYM(id) == get_id_sym(id); } static inline ID rb_id_serial_to_id(rb_id_serial_t num) { if (is_notop_id((ID)num)) { - VALUE sym = get_id_serial_entry(num, 0, ID_ENTRY_SYM); - if (sym) return SYM2ID(sym); - return ((ID)num << ID_SCOPE_SHIFT) | ID_INTERNAL | ID_STATIC_SYM; + struct sym_id_entry *entry = get_id_serial_entry(num); + if (entry && entry->sym != 0) { + return SYM2ID(entry->sym); + } + else { + return ((ID)num << ID_SCOPE_SHIFT) | ID_INTERNAL | ID_STATIC_SYM; + } } else { return (ID)num; @@ -836,16 +873,10 @@ lookup_str_id(VALUE str) return (ID)0; } -static VALUE -lookup_id_str(ID id) -{ - return get_id_entry(id, ID_ENTRY_STR); -} - ID rb_intern3(const char *name, long len, rb_encoding *enc) { - struct RString fake_str; + struct RString fake_str = {RBASIC_INIT}; VALUE str = rb_setup_fake_str(&fake_str, name, len, enc); OBJ_FREEZE(str); @@ -927,22 +958,10 @@ rb_gc_free_dsymbol(VALUE sym) /* * call-seq: - * str.intern -> symbol - * str.to_sym -> symbol - * - * Returns the +Symbol+ corresponding to <i>str</i>, creating the - * symbol if it did not previously exist. See Symbol#id2name. - * - * "Koala".intern #=> :Koala - * s = 'cat'.to_sym #=> :cat - * s == :cat #=> true - * s = '@cat'.to_sym #=> :@cat - * s == :@cat #=> true + * intern -> symbol * - * This can also be used to create symbols that cannot be represented using the - * <code>:xxx</code> notation. + * :include: doc/string/intern.rdoc * - * 'cat and dog'.to_sym #=> :"cat and dog" */ VALUE @@ -986,7 +1005,7 @@ VALUE rb_id2sym(ID x) { if (!DYNAMIC_ID_P(x)) return STATIC_ID2SYM(x); - return get_id_entry(x, ID_ENTRY_SYM); + return get_id_sym(x); } /* @@ -1020,7 +1039,7 @@ rb_sym2str(VALUE sym) VALUE rb_id2str(ID id) { - return lookup_id_str(id); + return get_id_str(id); } const char * @@ -1234,7 +1253,7 @@ rb_check_symbol(volatile VALUE *namep) ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc) { - struct RString fake_str; + struct RString fake_str = {RBASIC_INIT}; const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc); sym_check_asciionly(name, true); @@ -1246,7 +1265,7 @@ VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc) { VALUE sym; - struct RString fake_str; + struct RString fake_str = {RBASIC_INIT}; const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc); sym_check_asciionly(name, true); @@ -1270,7 +1289,7 @@ FUNC_MINIMIZED(VALUE rb_sym_intern_ascii_cstr(const char *ptr)); VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc) { - struct RString fake_str; + struct RString fake_str = {RBASIC_INIT}; const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc); return rb_str_intern(name); } |
