зеркало из https://github.com/github/ruby.git
* id_table.h: introduce ID key table.
[Feature #11420] This table only manage ID->VALUE table to reduce overhead of st. Some functions prefixed rb_id_table_* are provided. * id_table.c: implement rb_id_table_*. There are several algorithms to implement it. Now, there are roughly 4 types: * st * array * hash (implemented by Yura Sokolov) * mix of array and hash The macro ID_TABLE_IMPL can choose implementation. You can see detailes about them at the head of id_table.c. At the default, I choose 34 (mix of list and hash). This is not final decision. Please report your suitable parameters or your data structure. * symbol.c: introduce rb_id_serial_t and rb_id_to_serial() to represent ID by serial number. * internal.h: use id_table for method tables. * class.c, gc.c, marshal.c, vm.c, vm_method.c: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51541 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
ce5196b228
Коммит
c35ff11ae5
35
ChangeLog
35
ChangeLog
|
@ -1,3 +1,38 @@
|
|||
Wed Aug 12 17:05:36 2015 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* id_table.h: introduce ID key table.
|
||||
[Feature #11420]
|
||||
|
||||
This table only manage ID->VALUE table to reduce overhead of st.
|
||||
|
||||
Some functions prefixed rb_id_table_* are provided.
|
||||
|
||||
* id_table.c: implement rb_id_table_*.
|
||||
|
||||
There are several algorithms to implement it.
|
||||
|
||||
Now, there are roughly 4 types:
|
||||
|
||||
* st
|
||||
* array
|
||||
* hash (implemented by Yura Sokolov)
|
||||
* mix of array and hash
|
||||
|
||||
The macro ID_TABLE_IMPL can choose implementation.
|
||||
You can see detailes about them at the head of id_table.c.
|
||||
|
||||
At the default, I choose 34 (mix of list and hash).
|
||||
This is not final decision.
|
||||
Please report your suitable parameters or
|
||||
your data structure.
|
||||
|
||||
* symbol.c: introduce rb_id_serial_t and rb_id_to_serial()
|
||||
to represent ID by serial number.
|
||||
|
||||
* internal.h: use id_table for method tables.
|
||||
|
||||
* class.c, gc.c, marshal.c, vm.c, vm_method.c: ditto.
|
||||
|
||||
Wed Aug 12 05:19:11 2015 Eric Wong <e@80x24.org>
|
||||
|
||||
* parse.y (rb_parser_compile_cstr): remove volatile arg
|
||||
|
|
63
class.c
63
class.c
|
@ -27,6 +27,7 @@
|
|||
#include "ruby/st.h"
|
||||
#include "constant.h"
|
||||
#include "vm_core.h"
|
||||
#include "id_table.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define id_attached id__attached__
|
||||
|
@ -181,6 +182,11 @@ class_alloc(VALUE flags, VALUE klass)
|
|||
return (VALUE)obj;
|
||||
}
|
||||
|
||||
static void
|
||||
RCLASS_M_TBL_INIT(VALUE c)
|
||||
{
|
||||
RCLASS_M_TBL(c) = rb_id_table_create(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* A utility function that wraps class_alloc.
|
||||
|
@ -258,11 +264,11 @@ struct clone_method_arg {
|
|||
VALUE old_klass;
|
||||
};
|
||||
|
||||
static int
|
||||
clone_method_i(st_data_t key, st_data_t value, st_data_t data)
|
||||
static enum rb_id_table_iterator_result
|
||||
clone_method_i(ID key, VALUE value, void *data)
|
||||
{
|
||||
const struct clone_method_arg *arg = (struct clone_method_arg *)data;
|
||||
clone_method(arg->old_klass, arg->new_klass, (ID)key, (const rb_method_entry_t *)value);
|
||||
clone_method(arg->old_klass, arg->new_klass, key, (const rb_method_entry_t *)value);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -350,7 +356,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
|
|||
arg.old_klass = orig;
|
||||
arg.new_klass = clone;
|
||||
RCLASS_M_TBL_INIT(clone);
|
||||
st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)&arg);
|
||||
rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
|
||||
}
|
||||
|
||||
return clone;
|
||||
|
@ -400,7 +406,7 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
|
|||
struct clone_method_arg arg;
|
||||
arg.old_klass = klass;
|
||||
arg.new_klass = clone;
|
||||
st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)&arg);
|
||||
rb_id_table_foreach(RCLASS_M_TBL(klass), clone_method_i, &arg);
|
||||
}
|
||||
rb_singleton_class_attached(RBASIC(clone)->klass, clone);
|
||||
FL_SET(clone, FL_SINGLETON);
|
||||
|
@ -836,10 +842,10 @@ rb_include_module(VALUE klass, VALUE module)
|
|||
rb_raise(rb_eArgError, "cyclic include detected");
|
||||
}
|
||||
|
||||
static int
|
||||
add_refined_method_entry_i(st_data_t key, st_data_t value, st_data_t data)
|
||||
static enum rb_id_table_iterator_result
|
||||
add_refined_method_entry_i(ID key, VALUE value, void *data)
|
||||
{
|
||||
rb_add_refined_method_entry((VALUE) data, (ID) key);
|
||||
rb_add_refined_method_entry((VALUE)data, key);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -848,7 +854,7 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
|
|||
{
|
||||
VALUE p, iclass;
|
||||
int method_changed = 0, constant_changed = 0;
|
||||
const st_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
|
||||
struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
|
||||
|
||||
while (module) {
|
||||
int superclass_seen = FALSE;
|
||||
|
@ -886,14 +892,11 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
|
|||
VALUE refined_class =
|
||||
rb_refinement_module_get_refined_class(klass);
|
||||
|
||||
st_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i,
|
||||
(st_data_t) refined_class);
|
||||
rb_id_table_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (void *)refined_class);
|
||||
FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
|
||||
}
|
||||
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
|
||||
method_changed = 1;
|
||||
if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries)
|
||||
constant_changed = 1;
|
||||
if (RMODULE_M_TBL(module) && rb_id_table_size(RMODULE_M_TBL(module))) method_changed = 1;
|
||||
if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries) constant_changed = 1;
|
||||
skip:
|
||||
module = RCLASS_SUPER(module);
|
||||
}
|
||||
|
@ -904,23 +907,23 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
|
|||
return method_changed;
|
||||
}
|
||||
|
||||
static int
|
||||
move_refined_method(st_data_t key, st_data_t value, st_data_t data)
|
||||
static enum rb_id_table_iterator_result
|
||||
move_refined_method(ID key, VALUE value, void *data)
|
||||
{
|
||||
rb_method_entry_t *me = (rb_method_entry_t *) value;
|
||||
st_table *tbl = (st_table *) data;
|
||||
struct rb_id_table *tbl = (struct rb_id_table *) data;
|
||||
|
||||
if (me->def->type == VM_METHOD_TYPE_REFINED) {
|
||||
if (me->def->body.refined.orig_me) {
|
||||
const rb_method_entry_t *orig_me = me->def->body.refined.orig_me, *new_me;
|
||||
RB_OBJ_WRITE(me, &me->def->body.refined.orig_me, NULL);
|
||||
new_me = rb_method_entry_clone(me);
|
||||
st_add_direct(tbl, key, (st_data_t) new_me);
|
||||
rb_id_table_insert(tbl, key, (VALUE)new_me);
|
||||
rb_method_entry_copy(me, orig_me);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
else {
|
||||
st_add_direct(tbl, key, (st_data_t) me);
|
||||
rb_id_table_insert(tbl, key, (VALUE)me);
|
||||
return ST_DELETE;
|
||||
}
|
||||
}
|
||||
|
@ -950,8 +953,7 @@ rb_prepend_module(VALUE klass, VALUE module)
|
|||
RCLASS_SET_ORIGIN(klass, origin);
|
||||
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
|
||||
RCLASS_M_TBL_INIT(klass);
|
||||
st_foreach(RCLASS_M_TBL(origin), move_refined_method,
|
||||
(st_data_t) RCLASS_M_TBL(klass));
|
||||
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)RCLASS_M_TBL(klass));
|
||||
}
|
||||
changed = include_modules_at(klass, klass, module, FALSE);
|
||||
if (changed < 0)
|
||||
|
@ -1109,8 +1111,8 @@ struct method_entry_arg {
|
|||
int recur;
|
||||
};
|
||||
|
||||
static int
|
||||
method_entry_i(st_data_t key, st_data_t value, st_data_t data)
|
||||
static enum rb_id_table_iterator_result
|
||||
method_entry_i(ID key, VALUE value, void *data)
|
||||
{
|
||||
const rb_method_entry_t *me = (const rb_method_entry_t *)value;
|
||||
struct method_entry_arg *arg = (struct method_entry_arg *)data;
|
||||
|
@ -1158,7 +1160,7 @@ class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int
|
|||
me_arg.list = st_init_numtable();
|
||||
me_arg.recur = recur;
|
||||
for (; mod; mod = RCLASS_SUPER(mod)) {
|
||||
if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&me_arg);
|
||||
if (RCLASS_M_TBL(mod)) rb_id_table_foreach(RCLASS_M_TBL(mod), method_entry_i, &me_arg);
|
||||
if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
|
||||
if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
|
||||
if (!recur) break;
|
||||
|
@ -1379,7 +1381,7 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
|
|||
{
|
||||
VALUE recur, ary, klass, origin;
|
||||
struct method_entry_arg me_arg;
|
||||
st_table *mtbl;
|
||||
struct rb_id_table *mtbl;
|
||||
|
||||
if (argc == 0) {
|
||||
recur = Qtrue;
|
||||
|
@ -1392,14 +1394,12 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj)
|
|||
me_arg.list = st_init_numtable();
|
||||
me_arg.recur = RTEST(recur);
|
||||
if (klass && FL_TEST(klass, FL_SINGLETON)) {
|
||||
if ((mtbl = RCLASS_M_TBL(origin)) != 0)
|
||||
st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
|
||||
if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
|
||||
klass = RCLASS_SUPER(klass);
|
||||
}
|
||||
if (RTEST(recur)) {
|
||||
while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
|
||||
if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0)
|
||||
st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
|
||||
if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg);
|
||||
klass = RCLASS_SUPER(klass);
|
||||
}
|
||||
}
|
||||
|
@ -1989,8 +1989,7 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V
|
|||
int
|
||||
rb_class_has_methods(VALUE c)
|
||||
{
|
||||
st_table *mtbl = RCLASS_M_TBL(c);
|
||||
return mtbl && mtbl->num_entries ? TRUE : FALSE;
|
||||
return rb_id_table_size(RCLASS_M_TBL(c)) == 0 ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -1117,6 +1117,7 @@ class.$(OBJEXT): {$(VPATH)}constant.h
|
|||
class.$(OBJEXT): {$(VPATH)}defines.h
|
||||
class.$(OBJEXT): {$(VPATH)}encoding.h
|
||||
class.$(OBJEXT): {$(VPATH)}id.h
|
||||
class.$(OBJEXT): {$(VPATH)}id_table.h
|
||||
class.$(OBJEXT): {$(VPATH)}intern.h
|
||||
class.$(OBJEXT): {$(VPATH)}internal.h
|
||||
class.$(OBJEXT): {$(VPATH)}io.h
|
||||
|
@ -1456,6 +1457,7 @@ gc.$(OBJEXT): {$(VPATH)}eval_intern.h
|
|||
gc.$(OBJEXT): {$(VPATH)}gc.c
|
||||
gc.$(OBJEXT): {$(VPATH)}gc.h
|
||||
gc.$(OBJEXT): {$(VPATH)}id.h
|
||||
gc.$(OBJEXT): {$(VPATH)}id_table.h
|
||||
gc.$(OBJEXT): {$(VPATH)}intern.h
|
||||
gc.$(OBJEXT): {$(VPATH)}internal.h
|
||||
gc.$(OBJEXT): {$(VPATH)}io.h
|
||||
|
@ -1668,7 +1670,8 @@ marshal.$(OBJEXT): $(top_srcdir)/include/ruby.h
|
|||
marshal.$(OBJEXT): {$(VPATH)}config.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}defines.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}encoding.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}intern.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}id_table.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}intern.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}internal.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}io.h
|
||||
marshal.$(OBJEXT): {$(VPATH)}marshal.c
|
||||
|
@ -2215,6 +2218,8 @@ symbol.$(OBJEXT): {$(VPATH)}probes.h
|
|||
symbol.$(OBJEXT): {$(VPATH)}st.h
|
||||
symbol.$(OBJEXT): {$(VPATH)}subst.h
|
||||
symbol.$(OBJEXT): {$(VPATH)}symbol.c
|
||||
symbol.$(OBJEXT): {$(VPATH)}id_table.c
|
||||
symbol.$(OBJEXT): {$(VPATH)}id_table.h
|
||||
symbol.$(OBJEXT): {$(VPATH)}symbol.h
|
||||
symbol.$(OBJEXT): {$(VPATH)}vm_opts.h
|
||||
thread.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
|
||||
|
@ -2330,6 +2335,7 @@ vm.$(OBJEXT): {$(VPATH)}encoding.h
|
|||
vm.$(OBJEXT): {$(VPATH)}eval_intern.h
|
||||
vm.$(OBJEXT): {$(VPATH)}gc.h
|
||||
vm.$(OBJEXT): {$(VPATH)}id.h
|
||||
vm.$(OBJEXT): {$(VPATH)}id_table.h
|
||||
vm.$(OBJEXT): {$(VPATH)}insns.def
|
||||
vm.$(OBJEXT): {$(VPATH)}insns.inc
|
||||
vm.$(OBJEXT): {$(VPATH)}intern.h
|
||||
|
|
30
gc.c
30
gc.c
|
@ -27,6 +27,7 @@
|
|||
#include "constant.h"
|
||||
#include "ruby_atomic.h"
|
||||
#include "probes.h"
|
||||
#include "id_table.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <setjmp.h>
|
||||
|
@ -1928,14 +1929,6 @@ is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_free_m_tbl(st_table *tbl)
|
||||
{
|
||||
if (tbl) {
|
||||
st_free_table(tbl);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
free_const_entry_i(st_data_t key, st_data_t value, st_data_t data)
|
||||
{
|
||||
|
@ -2010,7 +2003,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
|
|||
break;
|
||||
case T_MODULE:
|
||||
case T_CLASS:
|
||||
rb_free_m_tbl(RCLASS_M_TBL(obj));
|
||||
rb_id_table_free(RCLASS_M_TBL(obj));
|
||||
if (RCLASS_IV_TBL(obj)) {
|
||||
st_free_table(RCLASS_IV_TBL(obj));
|
||||
}
|
||||
|
@ -2104,9 +2097,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
|
|||
case T_ICLASS:
|
||||
/* Basically , T_ICLASS shares table with the module */
|
||||
if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
|
||||
rb_free_m_tbl(RCLASS_M_TBL(obj));
|
||||
rb_id_table_free(RCLASS_M_TBL(obj));
|
||||
}
|
||||
if (RCLASS_CALLABLE_M_TBL(obj) != NULL) {
|
||||
rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
|
||||
}
|
||||
rb_free_m_tbl(RCLASS_CALLABLE_M_TBL(obj));
|
||||
if (RCLASS_EXT(obj)->subclasses) {
|
||||
rb_class_detach_subclasses(obj);
|
||||
RCLASS_EXT(obj)->subclasses = NULL;
|
||||
|
@ -3001,7 +2996,7 @@ obj_memsize_of(VALUE obj, int use_all_types)
|
|||
case T_MODULE:
|
||||
case T_CLASS:
|
||||
if (RCLASS_M_TBL(obj)) {
|
||||
size += st_memsize(RCLASS_M_TBL(obj));
|
||||
size += rb_id_table_memsize(RCLASS_M_TBL(obj));
|
||||
}
|
||||
if (RCLASS_EXT(obj)) {
|
||||
if (RCLASS_IV_TBL(obj)) {
|
||||
|
@ -3022,7 +3017,7 @@ obj_memsize_of(VALUE obj, int use_all_types)
|
|||
case T_ICLASS:
|
||||
if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
|
||||
if (RCLASS_M_TBL(obj)) {
|
||||
size += st_memsize(RCLASS_M_TBL(obj));
|
||||
size += rb_id_table_memsize(RCLASS_M_TBL(obj));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -3966,10 +3961,9 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mark_method_entry_i(st_data_t key, st_data_t value, st_data_t data)
|
||||
static enum rb_id_table_iterator_result
|
||||
mark_method_entry_i(VALUE me, void *data)
|
||||
{
|
||||
VALUE me = (VALUE)value;
|
||||
rb_objspace_t *objspace = (rb_objspace_t *)data;
|
||||
|
||||
gc_mark(objspace, me);
|
||||
|
@ -3977,10 +3971,10 @@ mark_method_entry_i(st_data_t key, st_data_t value, st_data_t data)
|
|||
}
|
||||
|
||||
static void
|
||||
mark_m_tbl(rb_objspace_t *objspace, struct st_table *tbl)
|
||||
mark_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
|
||||
{
|
||||
if (tbl) {
|
||||
st_foreach(tbl, mark_method_entry_i, (st_data_t)objspace);
|
||||
rb_id_table_foreach_values(tbl, mark_method_entry_i, objspace);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,23 @@
|
|||
#include "ruby/ruby.h"
|
||||
|
||||
struct rb_id_table;
|
||||
|
||||
/* compatible with ST_* */
|
||||
enum rb_id_table_iterator_result {
|
||||
ID_TABLE_CONTINUE = ST_CONTINUE,
|
||||
ID_TABLE_STOP = ST_STOP,
|
||||
ID_TABLE_DELETE = ST_DELETE,
|
||||
};
|
||||
|
||||
struct rb_id_table *rb_id_table_create(size_t size);
|
||||
void rb_id_table_free(struct rb_id_table *tbl);
|
||||
void rb_id_table_clear(struct rb_id_table *tbl);
|
||||
|
||||
size_t rb_id_table_size(struct rb_id_table *tbl);
|
||||
size_t rb_id_table_memsize(struct rb_id_table *tbl);
|
||||
|
||||
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val);
|
||||
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp);
|
||||
int rb_id_table_delete(struct rb_id_table *tbl, ID id);
|
||||
void rb_id_table_foreach(struct rb_id_table *tbl, enum rb_id_table_iterator_result (*func)(ID id, VALUE val, void *data), void *data);
|
||||
void rb_id_table_foreach_values(struct rb_id_table *tbl, enum rb_id_table_iterator_result (*func)(VALUE val, void *data), void *data);
|
10
internal.h
10
internal.h
|
@ -464,7 +464,7 @@ struct rb_classext_struct {
|
|||
struct st_table *iv_index_tbl;
|
||||
struct st_table *iv_tbl;
|
||||
struct st_table *const_tbl;
|
||||
struct st_table *callable_m_tbl;
|
||||
struct rb_id_table *callable_m_tbl;
|
||||
rb_subclass_entry_t *subclasses;
|
||||
rb_subclass_entry_t **parent_subclasses;
|
||||
/**
|
||||
|
@ -486,7 +486,7 @@ struct RClass {
|
|||
struct RBasic basic;
|
||||
VALUE super;
|
||||
rb_classext_t *ptr;
|
||||
struct st_table *m_tbl;
|
||||
struct rb_id_table *m_tbl;
|
||||
};
|
||||
|
||||
void rb_class_subclass_add(VALUE super, VALUE klass);
|
||||
|
@ -511,12 +511,6 @@ RCLASS_SET_ORIGIN(VALUE klass, VALUE origin)
|
|||
if (klass != origin) FL_SET(origin, RICLASS_IS_ORIGIN);
|
||||
}
|
||||
|
||||
static inline void
|
||||
RCLASS_M_TBL_INIT(VALUE c)
|
||||
{
|
||||
RCLASS_M_TBL(c) = st_init_numtable();
|
||||
}
|
||||
|
||||
#undef RCLASS_SUPER
|
||||
static inline VALUE
|
||||
RCLASS_SUPER(VALUE klass)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "ruby/io.h"
|
||||
#include "ruby/st.h"
|
||||
#include "ruby/util.h"
|
||||
#include "id_table.h"
|
||||
|
||||
#include <math.h>
|
||||
#ifdef HAVE_FLOAT_H
|
||||
|
@ -474,7 +475,7 @@ hash_each(VALUE key, VALUE value, struct dump_call_arg *arg)
|
|||
}
|
||||
|
||||
#define SINGLETON_DUMP_UNABLE_P(klass) \
|
||||
(RCLASS_M_TBL(klass)->num_entries || \
|
||||
(rb_id_table_size(RCLASS_M_TBL(klass)) > 0 || \
|
||||
(RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1))
|
||||
|
||||
static void
|
||||
|
|
34
symbol.c
34
symbol.c
|
@ -107,7 +107,7 @@ enum id_entry_type {
|
|||
};
|
||||
|
||||
static struct symbols {
|
||||
ID last_id;
|
||||
rb_id_serial_t last_id;
|
||||
st_table *str_sym;
|
||||
VALUE ids;
|
||||
VALUE dsymbol_fstr_hash;
|
||||
|
@ -143,8 +143,6 @@ 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)
|
||||
{
|
||||
|
@ -373,7 +371,7 @@ rb_str_symname_type(VALUE name, unsigned int allowed_attrset)
|
|||
}
|
||||
|
||||
static void
|
||||
set_id_entry(ID num, VALUE str, VALUE sym)
|
||||
set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym)
|
||||
{
|
||||
size_t idx = num / ID_ENTRY_UNIT;
|
||||
VALUE ary, ids = global_symbols.ids;
|
||||
|
@ -387,7 +385,7 @@ set_id_entry(ID num, VALUE str, VALUE sym)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
get_id_entry(ID num, const enum id_entry_type t)
|
||||
get_id_entry(rb_id_serial_t num, const enum id_entry_type t)
|
||||
{
|
||||
if (num && num <= global_symbols.last_id) {
|
||||
size_t idx = num / ID_ENTRY_UNIT;
|
||||
|
@ -401,6 +399,18 @@ get_id_entry(ID num, const enum id_entry_type t)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline ID
|
||||
rb_id_serial_to_id(rb_id_serial_t num)
|
||||
{
|
||||
if (is_notop_id((ID)num)) {
|
||||
VALUE sym = get_id_entry(num, ID_ENTRY_SYM);
|
||||
return SYM2ID(sym);
|
||||
}
|
||||
else {
|
||||
return (ID)num;
|
||||
}
|
||||
}
|
||||
|
||||
#if SYMBOL_DEBUG
|
||||
static int
|
||||
register_sym_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
|
||||
|
@ -444,7 +454,7 @@ 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);
|
||||
rb_id_serial_t num = rb_id_to_serial(id);
|
||||
VALUE sym = STATIC_ID2SYM(id);
|
||||
|
||||
OBJ_FREEZE(str);
|
||||
|
@ -584,7 +594,7 @@ lookup_str_sym(const VALUE str)
|
|||
static VALUE
|
||||
lookup_id_str(ID id)
|
||||
{
|
||||
return get_id_entry(id_to_serial(id), ID_ENTRY_STR);
|
||||
return get_id_entry(rb_id_to_serial(id), ID_ENTRY_STR);
|
||||
}
|
||||
|
||||
ID
|
||||
|
@ -604,7 +614,9 @@ rb_intern3(const char *name, long len, rb_encoding *enc)
|
|||
static ID
|
||||
next_id_base(void)
|
||||
{
|
||||
if (global_symbols.last_id >= ~(ID)0 >> (ID_SCOPE_SHIFT+RUBY_SPECIAL_SHIFT)) {
|
||||
rb_id_serial_t next_serial = global_symbols.last_id + 1;
|
||||
|
||||
if (next_serial == 0) {
|
||||
return (ID)-1;
|
||||
}
|
||||
else {
|
||||
|
@ -744,7 +756,7 @@ rb_sym2id(VALUE sym)
|
|||
|
||||
RSYMBOL(sym)->id = id |= num;
|
||||
/* make it permanent object */
|
||||
set_id_entry(num >>= ID_SCOPE_SHIFT, fstr, sym);
|
||||
set_id_entry(rb_id_to_serial(num), fstr, sym);
|
||||
rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, fstr);
|
||||
}
|
||||
}
|
||||
|
@ -760,7 +772,7 @@ VALUE
|
|||
rb_id2sym(ID x)
|
||||
{
|
||||
if (!DYNAMIC_ID_P(x)) return STATIC_ID2SYM(x);
|
||||
return get_id_entry(id_to_serial(x), ID_ENTRY_SYM);
|
||||
return get_id_entry(rb_id_to_serial(x), ID_ENTRY_SYM);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1122,3 +1134,5 @@ rb_is_junk_name(VALUE name)
|
|||
{
|
||||
return rb_str_symname_type(name, IDSET_ATTRSET_FOR_SYNTAX) == -1;
|
||||
}
|
||||
|
||||
#include "id_table.c"
|
||||
|
|
33
symbol.h
33
symbol.h
|
@ -32,15 +32,6 @@ struct RSymbol {
|
|||
|
||||
#define RSYMBOL(obj) (R_CAST(RSymbol)(obj))
|
||||
|
||||
static inline int
|
||||
id_type(ID id)
|
||||
{
|
||||
if (id<=tLAST_OP_ID) {
|
||||
return -1;
|
||||
}
|
||||
return (int)(id&ID_SCOPE_MASK);
|
||||
}
|
||||
|
||||
#define is_notop_id(id) ((id)>tLAST_OP_ID)
|
||||
#define is_local_id(id) (id_type(id)==ID_LOCAL)
|
||||
#define is_global_id(id) (id_type(id)==ID_GLOBAL)
|
||||
|
@ -50,6 +41,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
|
||||
id_type(ID id)
|
||||
{
|
||||
if (is_notop_id(id)) {
|
||||
return (int)(id&ID_SCOPE_MASK);
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
typedef uint32_t rb_id_serial_t;
|
||||
|
||||
static inline rb_id_serial_t
|
||||
rb_id_to_serial(ID id)
|
||||
{
|
||||
if (is_notop_id(id)) {
|
||||
return (rb_id_serial_t)(id >> ID_SCOPE_SHIFT);
|
||||
}
|
||||
else {
|
||||
return (rb_id_serial_t)id;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
sym_type(VALUE sym)
|
||||
{
|
||||
|
|
8
vm.c
8
vm.c
|
@ -1242,10 +1242,9 @@ rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
check_redefined_method(st_data_t key, st_data_t value, st_data_t data)
|
||||
static enum rb_id_table_iterator_result
|
||||
check_redefined_method(ID mid, VALUE value, void *data)
|
||||
{
|
||||
ID mid = (ID)key;
|
||||
VALUE klass = (VALUE)data;
|
||||
const rb_method_entry_t *me = (rb_method_entry_t *)value;
|
||||
const rb_method_entry_t *newme = rb_method_entry(klass, mid);
|
||||
|
@ -1259,8 +1258,7 @@ void
|
|||
rb_vm_check_redefinition_by_prepend(VALUE klass)
|
||||
{
|
||||
if (!vm_redefinition_check_flag(klass)) return;
|
||||
st_foreach(RCLASS_M_TBL(RCLASS_ORIGIN(klass)), check_redefined_method,
|
||||
(st_data_t)klass);
|
||||
rb_id_table_foreach(RCLASS_M_TBL(RCLASS_ORIGIN(klass)), check_redefined_method, (void *)klass);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
32
vm_method.c
32
vm_method.c
|
@ -2,6 +2,8 @@
|
|||
* This file is included by vm.c
|
||||
*/
|
||||
|
||||
#include "id_table.h"
|
||||
|
||||
#define METHOD_DEBUG 0
|
||||
|
||||
#if OPT_GLOBAL_METHOD_CACHE
|
||||
|
@ -98,8 +100,8 @@ rb_clear_method_cache_by_class(VALUE klass)
|
|||
rb_subclass_entry_t *entry = RCLASS_EXT(klass)->subclasses;
|
||||
|
||||
for (; entry != NULL; entry = entry->next) {
|
||||
struct st_table *table = RCLASS_CALLABLE_M_TBL(entry->klass);
|
||||
if (table) st_clear(table);
|
||||
struct rb_id_table *table = RCLASS_CALLABLE_M_TBL(entry->klass);
|
||||
if (table)rb_id_table_clear(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,8 +167,9 @@ static inline rb_method_entry_t *
|
|||
lookup_method_table(VALUE klass, ID id)
|
||||
{
|
||||
st_data_t body;
|
||||
st_table *m_tbl = RCLASS_M_TBL(klass);
|
||||
if (st_lookup(m_tbl, id, &body)) {
|
||||
struct rb_id_table *m_tbl = RCLASS_M_TBL(klass);
|
||||
|
||||
if (rb_id_table_lookup(m_tbl, id, &body)) {
|
||||
return (rb_method_entry_t *) body;
|
||||
}
|
||||
else {
|
||||
|
@ -448,7 +451,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
|
|||
{
|
||||
rb_method_entry_t *me;
|
||||
|
||||
st_table *mtbl;
|
||||
struct rb_id_table *mtbl;
|
||||
st_data_t data;
|
||||
int make_refined = 0;
|
||||
|
||||
|
@ -484,7 +487,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
|
|||
mtbl = RCLASS_M_TBL(klass);
|
||||
|
||||
/* check re-definition */
|
||||
if (st_lookup(mtbl, mid, &data)) {
|
||||
if (rb_id_table_lookup(mtbl, mid, &data)) {
|
||||
rb_method_entry_t *old_me = (rb_method_entry_t *)data;
|
||||
rb_method_definition_t *old_def = old_me->def;
|
||||
|
||||
|
@ -543,7 +546,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
|
|||
make_method_entry_refined(klass, me);
|
||||
}
|
||||
|
||||
st_insert(mtbl, mid, (st_data_t) me);
|
||||
rb_id_table_insert(mtbl, mid, (VALUE)me);
|
||||
RB_OBJ_WRITTEN(klass, Qundef, (VALUE)me);
|
||||
|
||||
VM_ASSERT(me->def != NULL);
|
||||
|
@ -743,7 +746,7 @@ rb_method_entry(VALUE klass, ID id)
|
|||
static const rb_callable_method_entry_t *
|
||||
prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_t *me)
|
||||
{
|
||||
struct st_table *mtbl;
|
||||
struct rb_id_table *mtbl;
|
||||
const rb_callable_method_entry_t *cme;
|
||||
|
||||
if (me && me->defined_class == 0) {
|
||||
|
@ -751,16 +754,16 @@ prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_
|
|||
VM_ASSERT(me->defined_class == 0);
|
||||
|
||||
if ((mtbl = RCLASS_EXT(defined_class)->callable_m_tbl) == NULL) {
|
||||
mtbl = RCLASS_EXT(defined_class)->callable_m_tbl = st_init_numtable();
|
||||
mtbl = RCLASS_EXT(defined_class)->callable_m_tbl = rb_id_table_create(0);
|
||||
}
|
||||
|
||||
if (st_lookup(mtbl, id, (st_data_t *)&me)) {
|
||||
if (rb_id_table_lookup(mtbl, id, (VALUE *)&me)) {
|
||||
cme = (rb_callable_method_entry_t *)me;
|
||||
VM_ASSERT(callable_method_entry_p(cme));
|
||||
}
|
||||
else {
|
||||
cme = rb_method_entry_complement_defined_class(me, defined_class);
|
||||
st_insert(mtbl, id, (st_data_t)cme);
|
||||
rb_id_table_insert(mtbl, id, (VALUE)cme);
|
||||
VM_ASSERT(callable_method_entry_p(cme));
|
||||
}
|
||||
}
|
||||
|
@ -902,7 +905,7 @@ rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_e
|
|||
static void
|
||||
remove_method(VALUE klass, ID mid)
|
||||
{
|
||||
st_data_t key, data;
|
||||
VALUE data;
|
||||
rb_method_entry_t *me = 0;
|
||||
VALUE self = klass;
|
||||
|
||||
|
@ -912,7 +915,7 @@ remove_method(VALUE klass, ID mid)
|
|||
rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
|
||||
}
|
||||
|
||||
if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
|
||||
if (!rb_id_table_lookup(RCLASS_M_TBL(klass), mid, &data) ||
|
||||
!(me = (rb_method_entry_t *)data) ||
|
||||
(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) ||
|
||||
UNDEFINED_REFINED_METHOD_P(me->def)) {
|
||||
|
@ -920,8 +923,7 @@ remove_method(VALUE klass, ID mid)
|
|||
rb_id2str(mid), rb_class_path(klass));
|
||||
}
|
||||
|
||||
key = (st_data_t)mid;
|
||||
st_delete(RCLASS_M_TBL(klass), &key, &data);
|
||||
rb_id_table_delete(RCLASS_M_TBL(klass), mid);
|
||||
|
||||
rb_vm_check_redefinition_opt_method(me, klass);
|
||||
rb_clear_method_cache_by_class(klass);
|
||||
|
|
Загрузка…
Ссылка в новой задаче