Feature #9614 » 0003-parse.y-switch-to-ihash-saves-200K-out-of-the-box.patch
parse.y | ||
---|---|---|
#include "ruby/st.h"
|
||
#include "ruby/encoding.h"
|
||
#include "internal.h"
|
||
#include "ihash.h"
|
||
#include "node.h"
|
||
#include "parse.h"
|
||
#include "id.h"
|
||
... | ... | |
static struct symbols {
|
||
ID last_id;
|
||
st_table *sym_id;
|
||
st_table *id_str;
|
||
struct rb_ihash_tbl *sym_id;
|
||
struct rb_ihash_tbl *id_str;
|
||
#if ENABLE_SELECTOR_NAMESPACE
|
||
st_table *ivar2_id;
|
||
st_table *id_ivar2;
|
||
... | ... | |
int minor_marked;
|
||
} global_symbols = {tLAST_TOKEN};
|
||
static const struct st_hash_type symhash = {
|
||
rb_str_hash_cmp,
|
||
rb_str_hash,
|
||
/* this struct is stored in both sym_id and id_str tables */
|
||
struct rb_idsym {
|
||
struct rb_ihash_node id_str_node;
|
||
ID id;
|
||
struct rb_ihash_node sym_id_node;
|
||
VALUE symstr;
|
||
st_index_t hashval;
|
||
};
|
||
static inline struct rb_idsym *
|
||
rb_idsym_of_s(const struct rb_ihash_node *node)
|
||
{
|
||
return RB_CONTAINER_OF(node, struct rb_idsym, sym_id_node);
|
||
}
|
||
static int
|
||
sym_id_cmp(const struct rb_ihash_node *n1, const struct rb_ihash_node *n2)
|
||
{
|
||
struct rb_idsym *is1 = rb_idsym_of_s(n1);
|
||
struct rb_idsym *is2 = rb_idsym_of_s(n2);
|
||
if (is1->hashval == is2->hashval) {
|
||
return rb_str_hash_cmp(is1->symstr, is2->symstr);
|
||
}
|
||
return 1;
|
||
}
|
||
static st_index_t
|
||
sym_id_hash(const struct rb_ihash_node *node)
|
||
{
|
||
struct rb_idsym *is = rb_idsym_of_s(node);
|
||
return is->hashval; /* needs to be precomputed */
|
||
}
|
||
static inline struct rb_idsym *
|
||
rb_idsym_of_i(const struct rb_ihash_node *node)
|
||
{
|
||
return RB_CONTAINER_OF(node, struct rb_idsym, id_str_node);
|
||
}
|
||
static int
|
||
id_str_cmp(const struct rb_ihash_node *n1, const struct rb_ihash_node *n2)
|
||
{
|
||
return rb_idsym_of_i(n1)->id != rb_idsym_of_i(n2)->id;
|
||
}
|
||
static st_index_t
|
||
id_str_hash(const struct rb_ihash_node *node)
|
||
{
|
||
return rb_idsym_of_i(node)->id;
|
||
}
|
||
static int
|
||
id_str_lookup(ID id, VALUE *str)
|
||
{
|
||
struct rb_idsym finder;
|
||
struct rb_ihash_node *node;
|
||
finder.id = id;
|
||
node = rb_ihash_lookup(global_symbols.id_str, &finder.id_str_node);
|
||
if (node) {
|
||
*str = rb_idsym_of_i(node)->symstr;
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
static int
|
||
sym_id_lookup(VALUE str, ID *id)
|
||
{
|
||
struct rb_idsym finder;
|
||
struct rb_ihash_node *node;
|
||
finder.symstr = str;
|
||
finder.hashval = rb_str_hash(str);
|
||
node = rb_ihash_lookup(global_symbols.sym_id, &finder.sym_id_node);
|
||
if (node) {
|
||
*id = rb_idsym_of_s(node)->id;
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
static const struct rb_ihash_type sym_id_hash_type = {
|
||
sym_id_cmp,
|
||
sym_id_hash,
|
||
};
|
||
static const struct rb_ihash_type id_str_hash_type = {
|
||
id_str_cmp,
|
||
id_str_hash,
|
||
};
|
||
#if ENABLE_SELECTOR_NAMESPACE
|
||
... | ... | |
void
|
||
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.sym_id = rb_ihash_new(&sym_id_hash_type, 10);
|
||
global_symbols.id_str = rb_ihash_new(&id_str_hash_type, 10);
|
||
#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);
|
||
... | ... | |
Init_id();
|
||
}
|
||
static enum rb_ihash_next
|
||
mark_symstr(struct rb_ihash_node *id_str_node, void *unused)
|
||
{
|
||
struct rb_idsym *is = rb_idsym_of_i(id_str_node);
|
||
rb_gc_mark(is->symstr);
|
||
return RB_IHASH_CONTINUE;
|
||
}
|
||
void
|
||
rb_gc_mark_symbols(int full_mark)
|
||
{
|
||
if (full_mark || global_symbols.minor_marked == 0) {
|
||
rb_mark_tbl(global_symbols.id_str);
|
||
if (global_symbols.id_str) {
|
||
rb_ihash_foreach(&global_symbols.id_str, mark_symstr, 0);
|
||
}
|
||
rb_gc_mark_locations(global_symbols.op_sym,
|
||
global_symbols.op_sym + numberof(global_symbols.op_sym));
|
||
... | ... | |
static ID
|
||
register_symid_str(ID id, VALUE str)
|
||
{
|
||
struct rb_idsym *is = ALLOC(struct rb_idsym);
|
||
OBJ_FREEZE(str);
|
||
str = rb_fstring(str);
|
||
... | ... | |
RUBY_DTRACE_SYMBOL_CREATE(RSTRING_PTR(str), rb_sourcefile(), rb_sourceline());
|
||
}
|
||
st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
|
||
st_add_direct(global_symbols.id_str, id, (st_data_t)str);
|
||
is->hashval = rb_str_hash(str);
|
||
is->symstr = str;
|
||
is->id = id;
|
||
rb_ihash_add_direct(&global_symbols.sym_id, &is->sym_id_node);
|
||
rb_ihash_add_direct(&global_symbols.id_str, &is->id_str_node);
|
||
global_symbols.minor_marked = 0;
|
||
return id;
|
||
}
|
||
... | ... | |
ID
|
||
rb_intern3(const char *name, long len, rb_encoding *enc)
|
||
{
|
||
st_data_t data;
|
||
ID id;
|
||
struct RString fake_str;
|
||
VALUE str = setup_fake_str(&fake_str, name, len);
|
||
rb_enc_associate(str, enc);
|
||
OBJ_FREEZE(str);
|
||
if (st_lookup(global_symbols.sym_id, str, &data))
|
||
return (ID)data;
|
||
if (sym_id_lookup(str, &id))
|
||
return id;
|
||
str = rb_enc_str_new(name, len, enc); /* make true string */
|
||
return intern_str(str);
|
||
... | ... | |
ID
|
||
rb_intern_str(VALUE str)
|
||
{
|
||
st_data_t id;
|
||
ID id;
|
||
if (st_lookup(global_symbols.sym_id, str, &id))
|
||
return (ID)id;
|
||
if (sym_id_lookup(str, &id))
|
||
return id;
|
||
return intern_str(rb_str_dup(str));
|
||
}
|
||
VALUE
|
||
rb_id2str(ID id)
|
||
{
|
||
st_data_t data;
|
||
VALUE str;
|
||
if (id < tLAST_TOKEN) {
|
||
int i = 0;
|
||
if (id < INT_MAX && rb_ispunct((int)id)) {
|
||
VALUE str = global_symbols.op_sym[i = (int)id];
|
||
str = global_symbols.op_sym[i = (int)id];
|
||
if (!str) {
|
||
char name[2];
|
||
name[0] = (char)id;
|
||
... | ... | |
}
|
||
for (i = 0; i < op_tbl_count; i++) {
|
||
if (op_tbl[i].token == id) {
|
||
VALUE str = global_symbols.op_sym[i];
|
||
str = global_symbols.op_sym[i];
|
||
if (!str) {
|
||
str = rb_usascii_str_new2(op_tbl[i].name);
|
||
OBJ_FREEZE(str);
|
||
... | ... | |
}
|
||
}
|
||
if (st_lookup(global_symbols.id_str, id, &data)) {
|
||
VALUE str = (VALUE)data;
|
||
if (id_str_lookup(id, &str)) {
|
||
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);
|
||
VALUE str;
|
||
do {
|
||
if (!!(str = rb_id2str(id_stem | ID_LOCAL))) break;
|
||
... | ... | |
str = rb_str_dup(str);
|
||
rb_str_cat(str, "=", 1);
|
||
register_symid_str(id, str);
|
||
if (st_lookup(global_symbols.id_str, id, &data)) {
|
||
VALUE str = (VALUE)data;
|
||
if (id_str_lookup(id, &str)) {
|
||
if (RBASIC(str)->klass == 0)
|
||
RBASIC_SET_CLASS_RAW(str, rb_cString);
|
||
return str;
|
||
... | ... | |
return next_id_base() | ID_INTERNAL;
|
||
}
|
||
static int
|
||
symbols_i(VALUE sym, ID value, VALUE ary)
|
||
static enum rb_ihash_next
|
||
symbols_i(struct rb_ihash_node *sym_id_node, void *arg)
|
||
{
|
||
rb_ary_push(ary, ID2SYM(value));
|
||
return ST_CONTINUE;
|
||
VALUE ary = (VALUE)arg;
|
||
struct rb_idsym *is = rb_idsym_of_s(sym_id_node);
|
||
rb_ary_push(ary, ID2SYM(is->id));
|
||
return RB_IHASH_CONTINUE;
|
||
}
|
||
/*
|
||
... | ... | |
{
|
||
VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
|
||
st_foreach(global_symbols.sym_id, symbols_i, ary);
|
||
rb_ihash_foreach(&global_symbols.sym_id, symbols_i, (void *)ary);
|
||
return ary;
|
||
}
|
||
... | ... | |
ID
|
||
rb_check_id(volatile VALUE *namep)
|
||
{
|
||
st_data_t id;
|
||
ID id;
|
||
VALUE tmp;
|
||
VALUE name = *namep;
|
||
... | ... | |
sym_check_asciionly(name);
|
||
if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id))
|
||
return (ID)id;
|
||
if (sym_id_lookup(name, &id))
|
||
return id;
|
||
if (rb_is_attrset_name(name)) {
|
||
struct RString fake_str;
|
||
... | ... | |
rb_enc_copy(localname, name);
|
||
OBJ_FREEZE(localname);
|
||
if (st_lookup(global_symbols.sym_id, (st_data_t)localname, &id)) {
|
||
if (sym_id_lookup(localname, &id)) {
|
||
return rb_id_attrset((ID)id);
|
||
}
|
||
RB_GC_GUARD(name);
|
||
... | ... | |
ID
|
||
rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
|
||
{
|
||
st_data_t id;
|
||
ID id;
|
||
struct RString fake_str;
|
||
const VALUE name = setup_fake_str(&fake_str, ptr, len);
|
||
rb_enc_associate(name, enc);
|
||
sym_check_asciionly(name);
|
||
if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id))
|
||
return (ID)id;
|
||
if (sym_id_lookup(name, &id))
|
||
return id;
|
||
if (rb_is_attrset_name(name)) {
|
||
fake_str.as.heap.len = len - 1;
|
||
if (st_lookup(global_symbols.sym_id, (st_data_t)name, &id)) {
|
||
return rb_id_attrset((ID)id);
|
||
if (sym_id_lookup(name, &id)) {
|
||
return rb_id_attrset(id);
|
||
}
|
||
}
|
||
- « Previous
- 1
- 2
- 3
- 4
- Next »