зеркало из https://github.com/github/ruby.git
symbol.c: immortal IDs
* symbol.c (global_symbols): make IDs immortal always, instead of treating dynamic symbols as IDs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47913 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
5617e31771
Коммит
3e69b074c5
6
.gdbinit
6
.gdbinit
|
@ -378,9 +378,9 @@ define rp_id
|
|||
end
|
||||
end
|
||||
printf "(%ld): ", $id
|
||||
rb_numtable_entry global_symbols.id_str $id
|
||||
if $rb_numtable_rec
|
||||
rp_string $rb_numtable_rec
|
||||
if global_symbols.ids.size > ($id >> RUBY_ID_SCOPE_SHIFT)
|
||||
set $str = global_symbols.ids.ptr[$id >> RUBY_ID_SCOPE_SHIFT]->str
|
||||
rp_string $str
|
||||
else
|
||||
echo undef\n
|
||||
end
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
Tue Oct 14 16:22:59 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
Tue Oct 14 16:23:04 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* symbol.c (global_symbols): make IDs immortal always, instead
|
||||
of treating dynamic symbols as IDs.
|
||||
|
||||
* iseq.c, marshal.c, string.c: use rb_str_intern instead of
|
||||
rb_str_dynamic_intern.
|
||||
|
|
493
symbol.c
493
symbol.c
|
@ -18,10 +18,9 @@
|
|||
#include "gc.h"
|
||||
#include "probes.h"
|
||||
|
||||
#define SYMBOL_PINNED FL_USER1
|
||||
#define SYMBOL_PINNED_P(sym) FL_TEST((sym), SYMBOL_PINNED)
|
||||
#define SYMBOL_PINNED_P(sym) (RSYMBOL(sym)->id&~ID_SCOPE_MASK)
|
||||
|
||||
#define ID_DYNAMIC_SYM_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_OP_ID)
|
||||
#define DYNAMIC_ID_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_OP_ID)
|
||||
#define STATIC_SYM2ID(sym) RSHIFT((unsigned long)(sym), RUBY_SPECIAL_SHIFT)
|
||||
#define STATIC_ID2SYM(id) (((VALUE)(id)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
|
||||
|
||||
|
@ -77,10 +76,36 @@ static const struct {
|
|||
STATIC_ASSERT(op_tbl_name_size, sizeof(op_tbl[0].name) == 3);
|
||||
#define op_tbl_len(i) (!op_tbl[i].name[1] ? 1 : !op_tbl[i].name[2] ? 2 : 3)
|
||||
|
||||
static void
|
||||
Init_op_tbl(void)
|
||||
{
|
||||
int i;
|
||||
rb_encoding *const enc = rb_usascii_encoding();
|
||||
|
||||
for (i = '!'; i <= '~'; ++i) {
|
||||
if (!ISALNUM(i) && i != '_') {
|
||||
char c = (char)i;
|
||||
register_static_symid(i, &c, 1, enc);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < op_tbl_count; ++i) {
|
||||
register_static_symid(op_tbl[i].token, op_tbl[i].name, op_tbl_len(i), enc);
|
||||
}
|
||||
}
|
||||
|
||||
enum {ID_ENTRY_UNIT = 2048};
|
||||
|
||||
struct id_entry {
|
||||
VALUE str, sym;
|
||||
};
|
||||
|
||||
static struct symbols {
|
||||
ID last_id;
|
||||
st_table *str_id;
|
||||
st_table *id_str;
|
||||
st_table *str_sym;
|
||||
struct {
|
||||
size_t size;
|
||||
struct id_entry *ptr;
|
||||
} ids;
|
||||
VALUE dsymbol_fstr_hash;
|
||||
} global_symbols = {tNEXT_ID-1};
|
||||
|
||||
|
@ -97,24 +122,31 @@ Init_sym(void)
|
|||
rb_gc_register_mark_object(dsym_fstrs);
|
||||
rb_obj_hide(dsym_fstrs);
|
||||
|
||||
global_symbols.str_id = st_init_table_with_size(&symhash, 1000);
|
||||
global_symbols.id_str = st_init_numtable_with_size(1000);
|
||||
global_symbols.str_sym = st_init_table_with_size(&symhash, 1000);
|
||||
global_symbols.ids.size = ID_ENTRY_UNIT;
|
||||
global_symbols.ids.ptr = ALLOC_N(struct id_entry, global_symbols.ids.size);
|
||||
|
||||
Init_op_tbl();
|
||||
Init_id();
|
||||
}
|
||||
|
||||
WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type));
|
||||
WARN_UNUSED_RESULT(static VALUE dsymbol_check(const VALUE sym));
|
||||
WARN_UNUSED_RESULT(static ID dsymbol_pindown(VALUE sym));
|
||||
WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str));
|
||||
WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str));
|
||||
WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id));
|
||||
WARN_UNUSED_RESULT(static ID attrsetname_to_attr(VALUE name));
|
||||
WARN_UNUSED_RESULT(static ID attrsetname_to_attr_id(VALUE name));
|
||||
WARN_UNUSED_RESULT(static ID intern_str(VALUE str, int mutable));
|
||||
|
||||
#define id_to_serial(id) (is_notop_id(id) ? id >> ID_SCOPE_SHIFT : id)
|
||||
|
||||
ID
|
||||
rb_id_attrset(ID id)
|
||||
{
|
||||
VALUE str, sym;
|
||||
int scope;
|
||||
|
||||
if (!is_notop_id(id)) {
|
||||
switch (id) {
|
||||
case tAREF: case tASET:
|
||||
|
@ -124,7 +156,7 @@ rb_id_attrset(ID id)
|
|||
rb_id2str(id));
|
||||
}
|
||||
else {
|
||||
int scope = id_type(id);
|
||||
scope = id_type(id);
|
||||
switch (scope) {
|
||||
case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
|
||||
case ID_CONST: case ID_CLASS: case ID_JUNK:
|
||||
|
@ -133,7 +165,6 @@ rb_id_attrset(ID id)
|
|||
return id;
|
||||
default:
|
||||
{
|
||||
VALUE str;
|
||||
if ((str = lookup_id_str(id)) != 0) {
|
||||
rb_name_error(id, "cannot make unknown type ID %d:%"PRIsVALUE" attrset",
|
||||
scope, str);
|
||||
|
@ -145,18 +176,26 @@ rb_id_attrset(ID id)
|
|||
}
|
||||
}
|
||||
}
|
||||
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 = SYM2ID(rb_str_intern(str));
|
||||
/* make new symbol and ID */
|
||||
if (!(str = lookup_id_str(id))) {
|
||||
static const char id_types[][8] = {
|
||||
"local",
|
||||
"instance",
|
||||
"invalid",
|
||||
"global",
|
||||
"attrset",
|
||||
"const",
|
||||
"class",
|
||||
"junk",
|
||||
};
|
||||
rb_name_error(id, "cannot make anonymous %.*s ID %"PRIxVALUE" attrset",
|
||||
(int)sizeof(id_types[0]), id_types[scope], (VALUE)id);
|
||||
}
|
||||
str = rb_str_dup(str);
|
||||
rb_str_cat(str, "=", 1);
|
||||
sym = lookup_str_sym(str);
|
||||
id = sym ? rb_sym2id(sym) : intern_str(str, 1);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -330,35 +369,41 @@ rb_str_symname_type(VALUE name, unsigned int allowed_attrset)
|
|||
}
|
||||
|
||||
static void
|
||||
register_symid_direct(VALUE str, ID id)
|
||||
set_id_entry(ID num, VALUE str, VALUE sym)
|
||||
{
|
||||
st_add_direct(global_symbols.str_id, (st_data_t)str, (st_data_t)id);
|
||||
st_add_direct(global_symbols.id_str, (st_data_t)id, (st_data_t)str);
|
||||
struct id_entry *entry;
|
||||
if (num >= global_symbols.ids.size) {
|
||||
size_t new_size = (num / ID_ENTRY_UNIT + 1) * ID_ENTRY_UNIT;
|
||||
REALLOC_N(global_symbols.ids.ptr, struct id_entry, new_size);
|
||||
global_symbols.ids.size = new_size;
|
||||
}
|
||||
entry = &global_symbols.ids.ptr[num];
|
||||
entry->str = str;
|
||||
entry->sym = sym;
|
||||
}
|
||||
|
||||
static int
|
||||
unregister_sym_str(VALUE str)
|
||||
static struct id_entry *
|
||||
get_id_entry(ID num)
|
||||
{
|
||||
st_data_t str_data = (st_data_t)str;
|
||||
return st_delete(global_symbols.str_id, &str_data, NULL);
|
||||
if (num && num <= global_symbols.last_id) {
|
||||
return &global_symbols.ids.ptr[num];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unregister_sym_id(VALUE sym)
|
||||
static void
|
||||
register_sym(VALUE str, VALUE sym)
|
||||
{
|
||||
st_data_t sym_data = (st_data_t)sym;
|
||||
return st_delete(global_symbols.id_str, &sym_data, NULL);
|
||||
st_add_direct(global_symbols.str_sym, (st_data_t)str, (st_data_t)sym);
|
||||
}
|
||||
|
||||
static void
|
||||
unregister_sym(VALUE str, VALUE sym)
|
||||
{
|
||||
if (!unregister_sym_str(str)) {
|
||||
st_data_t str_data = (st_data_t)str;
|
||||
if (!st_delete(global_symbols.str_sym, &str_data, NULL)) {
|
||||
rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str));
|
||||
}
|
||||
if (!unregister_sym_id(sym)) {
|
||||
rb_bug("%p can't remove sym from id_str (%s)", (void *)sym, RSTRING_PTR(str));
|
||||
}
|
||||
}
|
||||
|
||||
static ID
|
||||
|
@ -371,6 +416,9 @@ register_static_symid(ID id, const char *name, long len, rb_encoding *enc)
|
|||
static ID
|
||||
register_static_symid_str(ID id, VALUE str)
|
||||
{
|
||||
ID num = id_to_serial(id);
|
||||
VALUE sym = STATIC_ID2SYM(id);
|
||||
|
||||
OBJ_FREEZE(str);
|
||||
str = rb_fstring(str);
|
||||
|
||||
|
@ -378,7 +426,8 @@ register_static_symid_str(ID id, VALUE str)
|
|||
RUBY_DTRACE_SYMBOL_CREATE(RSTRING_PTR(str), rb_sourcefile(), rb_sourceline());
|
||||
}
|
||||
|
||||
register_symid_direct(str, id);
|
||||
register_sym(str, sym);
|
||||
set_id_entry(num, str, sym);
|
||||
rb_gc_register_mark_object(str);
|
||||
|
||||
return id;
|
||||
|
@ -397,12 +446,12 @@ sym_check_asciionly(VALUE str)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* _str_ itself will be registered at the global symbol table. _str_
|
||||
* can be modified before the registration, since the encoding will be
|
||||
* set to ASCII-8BIT if it is a special global name.
|
||||
*/
|
||||
static ID intern_str(VALUE str);
|
||||
|
||||
static inline void
|
||||
must_be_dynamic_symbol(VALUE x)
|
||||
|
@ -423,6 +472,7 @@ must_be_dynamic_symbol(VALUE x)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static VALUE
|
||||
dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
|
||||
|
@ -432,9 +482,9 @@ dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const
|
|||
rb_enc_associate(dsym, enc);
|
||||
OBJ_FREEZE(dsym);
|
||||
RB_OBJ_WRITE(dsym, &RSYMBOL(dsym)->fstr, str);
|
||||
RSYMBOL(dsym)->type = type;
|
||||
RSYMBOL(dsym)->id = type;
|
||||
|
||||
register_symid_direct(str, (ID)dsym);
|
||||
register_sym(str, dsym);
|
||||
rb_hash_aset(global_symbols.dsymbol_fstr_hash, str, Qtrue);
|
||||
|
||||
if (RUBY_DTRACE_SYMBOL_CREATE_ENABLED()) {
|
||||
|
@ -449,7 +499,7 @@ dsymbol_check(const VALUE sym)
|
|||
{
|
||||
if (UNLIKELY(rb_objspace_garbage_object_p(sym))) {
|
||||
const VALUE fstr = RSYMBOL(sym)->fstr;
|
||||
const ID type = RSYMBOL(sym)->type;
|
||||
const ID type = RSYMBOL(sym)->id & ID_SCOPE_MASK;
|
||||
RSYMBOL(sym)->fstr = 0;
|
||||
|
||||
unregister_sym(fstr, sym);
|
||||
|
@ -460,34 +510,23 @@ dsymbol_check(const VALUE sym)
|
|||
}
|
||||
}
|
||||
|
||||
static ID
|
||||
dsymbol_pindown(VALUE sym)
|
||||
{
|
||||
must_be_dynamic_symbol(sym);
|
||||
|
||||
if (UNLIKELY(SYMBOL_PINNED_P(sym) == 0)) {
|
||||
VALUE fstr = RSYMBOL(sym)->fstr;
|
||||
sym = dsymbol_check(sym);
|
||||
FL_SET(sym, SYMBOL_PINNED);
|
||||
|
||||
/* make it permanent object */
|
||||
rb_gc_register_mark_object(sym);
|
||||
rb_gc_register_mark_object(fstr);
|
||||
rb_hash_delete(global_symbols.dsymbol_fstr_hash, fstr);
|
||||
}
|
||||
|
||||
return (ID)sym;
|
||||
}
|
||||
|
||||
static ID
|
||||
lookup_str_id(VALUE str)
|
||||
{
|
||||
st_data_t id_data;
|
||||
if (st_lookup(global_symbols.str_id, (st_data_t)str, &id_data)) {
|
||||
const ID id = (ID)id_data;
|
||||
st_data_t sym_data;
|
||||
if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) {
|
||||
const VALUE sym = (VALUE)sym_data;
|
||||
|
||||
if (!ID_DYNAMIC_SYM_P(id) || SYMBOL_PINNED_P(id)) {
|
||||
return id;
|
||||
if (STATIC_SYM_P(sym)) {
|
||||
return STATIC_SYM2ID(sym);
|
||||
}
|
||||
else if (DYNAMIC_SYM_P(sym)) {
|
||||
ID id = RSYMBOL(sym)->id;
|
||||
if (id & ~ID_SCOPE_MASK) return id;
|
||||
}
|
||||
else {
|
||||
rb_bug("non-symbol object %s:%"PRIxVALUE" for %"PRIsVALUE" in symbol table",
|
||||
rb_builtin_class_name(sym), sym, str);
|
||||
}
|
||||
}
|
||||
return (ID)0;
|
||||
|
@ -497,15 +536,13 @@ static VALUE
|
|||
lookup_str_sym(const VALUE str)
|
||||
{
|
||||
st_data_t sym_data;
|
||||
if (st_lookup(global_symbols.str_id, (st_data_t)str, &sym_data)) {
|
||||
const ID id = (ID)sym_data;
|
||||
if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) {
|
||||
VALUE sym = (VALUE)sym_data;
|
||||
|
||||
if (ID_DYNAMIC_SYM_P(id)) {
|
||||
return dsymbol_check(id);
|
||||
}
|
||||
else {
|
||||
return STATIC_ID2SYM(id);
|
||||
if (DYNAMIC_SYM_P(sym)) {
|
||||
sym = dsymbol_check(sym);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
else {
|
||||
return (VALUE)0;
|
||||
|
@ -515,46 +552,26 @@ lookup_str_sym(const VALUE str)
|
|||
static VALUE
|
||||
lookup_id_str(ID id)
|
||||
{
|
||||
st_data_t data;
|
||||
if (ID_DYNAMIC_SYM_P(id)) {
|
||||
return RSYMBOL(id)->fstr;
|
||||
}
|
||||
if (st_lookup(global_symbols.id_str, id, &data)) {
|
||||
return (VALUE)data;
|
||||
const struct id_entry *entry;
|
||||
|
||||
if ((entry = get_id_entry(id_to_serial(id))) != 0) {
|
||||
return entry->str;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ID
|
||||
rb_intern_cstr_without_pindown(const char *name, long len, rb_encoding *enc)
|
||||
rb_intern3(const char *name, long len, rb_encoding *enc)
|
||||
{
|
||||
st_data_t id;
|
||||
VALUE sym;
|
||||
struct RString fake_str;
|
||||
VALUE str = rb_setup_fake_str(&fake_str, name, len, enc);
|
||||
OBJ_FREEZE(str);
|
||||
|
||||
if (st_lookup(global_symbols.str_id, str, &id)) {
|
||||
if (ID_DYNAMIC_SYM_P((ID)id)) {
|
||||
return (ID)dsymbol_check((VALUE)id);
|
||||
}
|
||||
return (ID)id;
|
||||
}
|
||||
|
||||
sym = lookup_str_sym(str);
|
||||
if (sym) return rb_sym2id(sym);
|
||||
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 = rb_intern_cstr_without_pindown(name, len, enc);
|
||||
if (ID_DYNAMIC_SYM_P(id)) {
|
||||
id = dsymbol_pindown((VALUE)id);
|
||||
}
|
||||
|
||||
return id;
|
||||
return intern_str(str, 1);
|
||||
}
|
||||
|
||||
static ID
|
||||
|
@ -563,109 +580,24 @@ next_id_base(void)
|
|||
if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) {
|
||||
return (ID)-1;
|
||||
}
|
||||
++global_symbols.last_id;
|
||||
return global_symbols.last_id << ID_SCOPE_SHIFT;
|
||||
else {
|
||||
const size_t num = ++global_symbols.last_id;
|
||||
return num << ID_SCOPE_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
static ID
|
||||
next_id(VALUE str)
|
||||
intern_str(VALUE str, int mutable)
|
||||
{
|
||||
const char *name, *m, *e;
|
||||
long len, last;
|
||||
rb_encoding *enc, *symenc;
|
||||
unsigned char c;
|
||||
ID id;
|
||||
ID nid;
|
||||
int mb;
|
||||
|
||||
RSTRING_GETMEM(str, name, len);
|
||||
m = name;
|
||||
e = m + len;
|
||||
enc = rb_enc_get(str);
|
||||
symenc = enc;
|
||||
|
||||
if (!len || (rb_cString && !rb_enc_asciicompat(enc))) {
|
||||
junk:
|
||||
id = ID_JUNK;
|
||||
goto new_id;
|
||||
id = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
|
||||
if (id == (ID)-1) id = ID_JUNK;
|
||||
if (sym_check_asciionly(str)) {
|
||||
if (!mutable) str = rb_str_dup(str);
|
||||
rb_enc_associate(str, rb_usascii_encoding());
|
||||
}
|
||||
last = len-1;
|
||||
id = 0;
|
||||
switch (*m) {
|
||||
case '$':
|
||||
if (len < 2) goto junk;
|
||||
id |= ID_GLOBAL;
|
||||
if ((mb = is_special_global_name(++m, e, enc)) != 0) {
|
||||
if (!--mb) symenc = rb_usascii_encoding();
|
||||
goto new_id;
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
if (m[1] == '@') {
|
||||
if (len < 3) goto junk;
|
||||
m++;
|
||||
id |= ID_CLASS;
|
||||
}
|
||||
else {
|
||||
if (len < 2) goto junk;
|
||||
id |= ID_INSTANCE;
|
||||
}
|
||||
m++;
|
||||
break;
|
||||
default:
|
||||
c = m[0];
|
||||
if (c != '_' && rb_enc_isascii(c, enc) && rb_enc_ispunct(c, enc)) {
|
||||
/* operators */
|
||||
int i;
|
||||
|
||||
if (len == 1) {
|
||||
id = c;
|
||||
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;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (name[last] == '=') {
|
||||
/* attribute assignment */
|
||||
if (last > 1 && name[last-1] == '=')
|
||||
goto junk;
|
||||
id = rb_intern3(name, last, enc);
|
||||
if (id > tLAST_OP_ID && !is_attrset_id(id)) {
|
||||
enc = rb_enc_get(rb_id2str(id));
|
||||
id = rb_id_attrset(id);
|
||||
return id;
|
||||
}
|
||||
id = ID_ATTRSET;
|
||||
}
|
||||
else if (id == 0) {
|
||||
if (rb_enc_isupper(m[0], enc)) {
|
||||
id = ID_CONST;
|
||||
}
|
||||
else {
|
||||
id = ID_LOCAL;
|
||||
}
|
||||
}
|
||||
if (!rb_enc_isdigit(*m, enc)) {
|
||||
while (m <= name + last && is_identchar(m, e, enc)) {
|
||||
if (ISASCII(*m)) {
|
||||
m++;
|
||||
}
|
||||
else {
|
||||
m += rb_enc_mbclen(m, e, enc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id != ID_ATTRSET && m - name < len) id = ID_JUNK;
|
||||
if (sym_check_asciionly(str)) symenc = rb_usascii_encoding();
|
||||
new_id:
|
||||
if (symenc != enc) rb_enc_associate(str, symenc);
|
||||
if ((nid = next_id_base()) == (ID)-1) {
|
||||
str = rb_str_ellipsize(str, 20);
|
||||
rb_raise(rb_eRuntimeError, "symbol table overflow (symbol %"PRIsVALUE")",
|
||||
|
@ -673,14 +605,6 @@ next_id(VALUE str)
|
|||
}
|
||||
id |= nid;
|
||||
id |= ID_STATIC_SYM;
|
||||
return id;
|
||||
}
|
||||
|
||||
static ID
|
||||
intern_str(VALUE str)
|
||||
{
|
||||
ID id = next_id(str);
|
||||
if (ID_DYNAMIC_SYM_P(id) && is_attrset_id(id)) return id;
|
||||
return register_static_symid_str(id, str);
|
||||
}
|
||||
|
||||
|
@ -706,7 +630,7 @@ rb_intern_str(VALUE str)
|
|||
return SYM2ID(sym);
|
||||
}
|
||||
|
||||
return intern_str(rb_str_dup(str));
|
||||
return intern_str(str, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -745,13 +669,17 @@ rb_str_intern(VALUE str)
|
|||
{
|
||||
#if USE_SYMBOL_GC
|
||||
rb_encoding *enc, *ascii;
|
||||
int type;
|
||||
#else
|
||||
ID id;
|
||||
#endif
|
||||
VALUE sym = lookup_str_sym(str);
|
||||
ID type;
|
||||
|
||||
if (sym) {
|
||||
return sym;
|
||||
}
|
||||
|
||||
#if USE_SYMBOL_GC
|
||||
enc = rb_enc_get(str);
|
||||
ascii = rb_usascii_encoding();
|
||||
if (enc != ascii) {
|
||||
|
@ -762,45 +690,56 @@ rb_str_intern(VALUE str)
|
|||
enc = ascii;
|
||||
}
|
||||
}
|
||||
|
||||
str = rb_fstring(str);
|
||||
type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
|
||||
if (type == ID_ATTRSET) {
|
||||
ID attr_id = attrsetname_to_attr_id(str);
|
||||
if (attr_id && !ID_DYNAMIC_SYM_P(attr_id)) {
|
||||
attr_id = rb_id_attrset(attr_id);
|
||||
return ID2SYM(attr_id);
|
||||
}
|
||||
}
|
||||
|
||||
return dsymbol_alloc(rb_cSymbol, rb_fstring(str), enc, type);
|
||||
if (type < 0) type = ID_JUNK;
|
||||
return dsymbol_alloc(rb_cSymbol, str, enc, type);
|
||||
#else
|
||||
return rb_str_intern(str);
|
||||
id = intern_str(str, 0);
|
||||
return ID2SYM(id);
|
||||
#endif
|
||||
}
|
||||
|
||||
ID
|
||||
rb_sym2id(VALUE sym)
|
||||
{
|
||||
ID id;
|
||||
if (STATIC_SYM_P(sym)) {
|
||||
return STATIC_SYM2ID(sym);
|
||||
id = STATIC_SYM2ID(sym);
|
||||
}
|
||||
else if (DYNAMIC_SYM_P(sym)) {
|
||||
sym = dsymbol_check(sym);
|
||||
id = RSYMBOL(sym)->id;
|
||||
if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) {
|
||||
VALUE fstr = RSYMBOL(sym)->fstr;
|
||||
ID num = next_id_base();
|
||||
|
||||
RSYMBOL(sym)->id = id |= num;
|
||||
/* make it permanent object */
|
||||
set_id_entry(num >>= ID_SCOPE_SHIFT, fstr, sym);
|
||||
rb_gc_register_mark_object(sym);
|
||||
rb_gc_register_mark_object(fstr);
|
||||
rb_hash_delete(global_symbols.dsymbol_fstr_hash, fstr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!SYMBOL_PINNED_P(sym)) {
|
||||
return dsymbol_pindown(sym);
|
||||
}
|
||||
return (ID)sym;
|
||||
rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)",
|
||||
rb_builtin_class_name(sym));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_id2sym(ID x)
|
||||
{
|
||||
if (!ID_DYNAMIC_SYM_P(x)) {
|
||||
return STATIC_ID2SYM(x);
|
||||
}
|
||||
else {
|
||||
return (VALUE)x;
|
||||
const struct id_entry *entry;
|
||||
|
||||
if (!DYNAMIC_ID_P(x)) return STATIC_ID2SYM(x);
|
||||
|
||||
if ((entry = get_id_entry(id_to_serial(x))) != 0) {
|
||||
return entry->sym;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -820,49 +759,12 @@ rb_id2str(ID id)
|
|||
{
|
||||
VALUE str;
|
||||
|
||||
if (id < tLAST_OP_ID) {
|
||||
int i = 0;
|
||||
|
||||
if (id < INT_MAX && rb_ispunct((int)id)) {
|
||||
char name[1];
|
||||
name[0] = (char)id;
|
||||
return rb_fstring_new(name, 1);
|
||||
}
|
||||
for (i = 0; i < op_tbl_count; i++) {
|
||||
if (op_tbl[i].token == id) {
|
||||
const char *name = op_tbl[i].name;
|
||||
return rb_fstring_new(name, op_tbl_len(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((str = lookup_id_str(id)) != 0) {
|
||||
if (RBASIC(str)->klass == 0)
|
||||
RBASIC_SET_CLASS_RAW(str, rb_cString);
|
||||
return str;
|
||||
}
|
||||
|
||||
if (is_attrset_id(id)) {
|
||||
ID id_stem = (id & ~ID_SCOPE_MASK) | ID_STATIC_SYM;
|
||||
|
||||
do {
|
||||
if (!!(str = rb_id2str(id_stem | ID_LOCAL))) break;
|
||||
if (!!(str = rb_id2str(id_stem | ID_CONST))) break;
|
||||
if (!!(str = rb_id2str(id_stem | ID_INSTANCE))) break;
|
||||
if (!!(str = rb_id2str(id_stem | ID_GLOBAL))) break;
|
||||
if (!!(str = rb_id2str(id_stem | ID_CLASS))) break;
|
||||
if (!!(str = rb_id2str(id_stem | ID_JUNK))) break;
|
||||
return 0;
|
||||
} while (0);
|
||||
str = rb_str_dup(str);
|
||||
rb_str_cat(str, "=", 1);
|
||||
register_static_symid_str(id, str);
|
||||
if ((str = lookup_id_str(id)) != 0) {
|
||||
if (RBASIC(str)->klass == 0)
|
||||
RBASIC_SET_CLASS_RAW(str, rb_cString);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -885,11 +787,17 @@ static int
|
|||
symbols_i(st_data_t key, st_data_t value, st_data_t arg)
|
||||
{
|
||||
VALUE ary = (VALUE)arg;
|
||||
VALUE sym = ID2SYM((ID)value);
|
||||
VALUE sym = (VALUE)value;
|
||||
|
||||
if (DYNAMIC_SYM_P(sym) && !SYMBOL_PINNED_P(sym) && rb_objspace_garbage_object_p(sym)) {
|
||||
if (STATIC_SYM_P(sym)) {
|
||||
rb_ary_push(ary, sym);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
else if (!DYNAMIC_SYM_P(sym)) {
|
||||
rb_bug("invalid symbol: %s", RSTRING_PTR((VALUE)key));
|
||||
}
|
||||
else if (!SYMBOL_PINNED_P(sym) && rb_objspace_garbage_object_p(sym)) {
|
||||
RSYMBOL(sym)->fstr = 0;
|
||||
unregister_sym_id(sym);
|
||||
return ST_DELETE;
|
||||
}
|
||||
else {
|
||||
|
@ -918,8 +826,8 @@ symbols_i(st_data_t key, st_data_t value, st_data_t arg)
|
|||
VALUE
|
||||
rb_sym_all_symbols(void)
|
||||
{
|
||||
VALUE ary = rb_ary_new2(global_symbols.str_id->num_entries);
|
||||
st_foreach(global_symbols.str_id, symbols_i, ary);
|
||||
VALUE ary = rb_ary_new2(global_symbols.str_sym->num_entries);
|
||||
st_foreach(global_symbols.str_sym, symbols_i, ary);
|
||||
return ary;
|
||||
}
|
||||
|
||||
|
@ -979,7 +887,6 @@ rb_is_junk_id(ID id)
|
|||
ID
|
||||
rb_check_id(volatile VALUE *namep)
|
||||
{
|
||||
ID id;
|
||||
VALUE tmp;
|
||||
VALUE name = *namep;
|
||||
|
||||
|
@ -988,7 +895,7 @@ rb_check_id(volatile VALUE *namep)
|
|||
}
|
||||
else if (DYNAMIC_SYM_P(name)) {
|
||||
if (SYMBOL_PINNED_P(name)) {
|
||||
return (ID)name;
|
||||
return RSYMBOL(name)->id;
|
||||
}
|
||||
else {
|
||||
*namep = RSYMBOL(name)->fstr;
|
||||
|
@ -1008,16 +915,7 @@ rb_check_id(volatile VALUE *namep)
|
|||
|
||||
sym_check_asciionly(name);
|
||||
|
||||
if ((id = lookup_str_id(name)) != 0) {
|
||||
return id;
|
||||
}
|
||||
|
||||
{
|
||||
ID gid = attrsetname_to_attr(name);
|
||||
if (gid) return rb_id_attrset(gid);
|
||||
}
|
||||
|
||||
return (ID)0;
|
||||
return lookup_str_id(name);
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -1027,7 +925,14 @@ rb_check_symbol(volatile VALUE *namep)
|
|||
VALUE tmp;
|
||||
VALUE name = *namep;
|
||||
|
||||
if (SYMBOL_P(name)) {
|
||||
if (STATIC_SYM_P(name)) {
|
||||
return name;
|
||||
}
|
||||
else if (DYNAMIC_SYM_P(name)) {
|
||||
if (!SYMBOL_PINNED_P(name)) {
|
||||
name = dsymbol_check(name);
|
||||
*namep = name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
else if (!RB_TYPE_P(name, T_STRING)) {
|
||||
|
@ -1047,35 +952,18 @@ rb_check_symbol(volatile VALUE *namep)
|
|||
return sym;
|
||||
}
|
||||
|
||||
{
|
||||
ID gid = attrsetname_to_attr(name);
|
||||
if (gid) return ID2SYM(rb_id_attrset(gid));
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
ID
|
||||
rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
|
||||
{
|
||||
ID id;
|
||||
struct RString fake_str;
|
||||
const VALUE name = rb_setup_fake_str(&fake_str, ptr, len, enc);
|
||||
|
||||
sym_check_asciionly(name);
|
||||
|
||||
if ((id = lookup_str_id(name)) != 0) {
|
||||
return id;
|
||||
}
|
||||
|
||||
if (rb_is_attrset_name(name)) {
|
||||
fake_str.as.heap.len = len - 1;
|
||||
if ((id = lookup_str_id(name)) != 0) {
|
||||
return rb_id_attrset(id);
|
||||
}
|
||||
}
|
||||
|
||||
return (ID)0;
|
||||
return lookup_str_id(name);
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -1091,13 +979,6 @@ rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
|
|||
return sym;
|
||||
}
|
||||
|
||||
if (rb_is_attrset_name(name)) {
|
||||
fake_str.as.heap.len = len - 1;
|
||||
if ((sym = lookup_str_sym(name)) != 0) {
|
||||
return ID2SYM(rb_id_attrset(SYM2ID(sym)));
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
|
34
symbol.h
34
symbol.h
|
@ -17,7 +17,7 @@
|
|||
struct RSymbol {
|
||||
struct RBasic basic;
|
||||
VALUE fstr;
|
||||
ID type;
|
||||
ID id;
|
||||
};
|
||||
|
||||
#define RSYMBOL(obj) (R_CAST(RSymbol)(obj))
|
||||
|
@ -28,13 +28,7 @@ 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 (int)(RSYMBOL(dsym)->type);
|
||||
}
|
||||
return (int)(id&ID_SCOPE_MASK);
|
||||
}
|
||||
|
||||
#define is_notop_id(id) ((id)>tLAST_OP_ID)
|
||||
|
@ -46,6 +40,30 @@ id_type(ID id)
|
|||
#define is_class_id(id) (id_type(id)==ID_CLASS)
|
||||
#define is_junk_id(id) (id_type(id)==ID_JUNK)
|
||||
|
||||
static inline int
|
||||
sym_type(VALUE sym)
|
||||
{
|
||||
ID id;
|
||||
if (STATIC_SYM_P(sym)) {
|
||||
id = RSHIFT(sym, RUBY_SPECIAL_SHIFT);
|
||||
if (id<=tLAST_OP_ID) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
id = RSYMBOL(sym)->id;
|
||||
}
|
||||
return (int)(id&ID_SCOPE_MASK);
|
||||
}
|
||||
|
||||
#define is_local_sym(sym) (sym_type(sym)==SYM_LOCAL)
|
||||
#define is_global_sym(sym) (sym_type(sym)==SYM_GLOBAL)
|
||||
#define is_instance_sym(sym) (sym_type(sym)==SYM_INSTANCE)
|
||||
#define is_attrset_sym(sym) (sym_type(sym)==SYM_ATTRSET)
|
||||
#define is_const_sym(sym) (sym_type(sym)==SYM_CONST)
|
||||
#define is_class_sym(sym) (sym_type(sym)==SYM_CLASS)
|
||||
#define is_junk_sym(sym) (sym_type(sym)==SYM_JUNK)
|
||||
|
||||
RUBY_FUNC_EXPORTED const unsigned int ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];
|
||||
|
||||
static inline int
|
||||
|
|
Загрузка…
Ссылка в новой задаче