Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
2468 lines (2315 sloc) 73.7 KB
diff --git a/class.c b/class.c
index 4fbdf18..f5cb4a1 100644
--- a/class.c
+++ b/class.c
@@ -31,7 +31,7 @@
#include "internal.h"
#include <ctype.h>
-extern st_table *rb_class_tbl;
+extern sa_table rb_class_tbl;
static ID id_attached;
/**
@@ -53,11 +53,15 @@ class_alloc(VALUE flags, VALUE klass)
NEWOBJ(obj, struct RClass);
OBJSETUP(obj, klass, flags);
obj->ptr = ext;
- RCLASS_IV_TBL(obj) = 0;
- RCLASS_CONST_TBL(obj) = 0;
- RCLASS_M_TBL(obj) = 0;
- RCLASS_SUPER(obj) = 0;
- RCLASS_IV_INDEX_TBL(obj) = 0;
+ MEMZERO(ext, struct rb_classext_struct, 1);
+ return (VALUE)obj;
+}
+
+static VALUE
+iclass_alloc()
+{
+ NEWOBJ(obj, struct RClass);
+ OBJSETUP(obj, rb_cClass, T_ICLASS);
return (VALUE)obj;
}
@@ -77,7 +81,6 @@ rb_class_boot(VALUE super)
VALUE klass = class_alloc(T_CLASS, rb_cClass);
RCLASS_SUPER(klass) = super;
- RCLASS_M_TBL(klass) = st_init_numtable();
OBJ_INFECT(klass, super);
return (VALUE)klass;
@@ -120,43 +123,30 @@ rb_class_new(VALUE super)
return rb_class_boot(super);
}
-struct clone_method_data {
- st_table *tbl;
- VALUE klass;
-};
-
VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
-static int
-clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data)
+static void
+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass)
{
VALUE newiseqval;
if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
rb_iseq_t *iseq;
- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass);
+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass);
GetISeqPtr(newiseqval, iseq);
- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
RB_GC_GUARD(newiseqval);
}
else {
- rb_method_entry_set(data->klass, mid, me, me->flag);
+ rb_method_entry_set(klass, mid, me, me->flag);
}
- return ST_CONTINUE;
}
-static int
-clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl)
+static void
+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl)
{
rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
- *nce = *ce;
- st_insert(tbl, key, (st_data_t)nce);
- return ST_CONTINUE;
-}
-
-static int
-clone_const_i(st_data_t key, st_data_t value, st_data_t data)
-{
- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data);
+ *nce = *(const rb_const_entry_t*)ce;
+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce);
}
static void
@@ -177,6 +167,7 @@ class_init_copy_check(VALUE clone, VALUE orig)
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
+ ID id;
if (RB_TYPE_P(clone, T_CLASS)) {
class_init_copy_check(clone, orig);
}
@@ -186,36 +177,22 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
}
RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
- if (RCLASS_IV_TBL(orig)) {
- st_data_t id;
- if (RCLASS_IV_TBL(clone)) {
- st_free_table(RCLASS_IV_TBL(clone));
- }
- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig));
- CONST_ID(id, "__classpath__");
- st_delete(RCLASS_IV_TBL(clone), &id, 0);
- CONST_ID(id, "__classid__");
- st_delete(RCLASS_IV_TBL(clone), &id, 0);
- }
- if (RCLASS_CONST_TBL(orig)) {
- if (RCLASS_CONST_TBL(clone)) {
- rb_free_const_table(RCLASS_CONST_TBL(clone));
- }
- RCLASS_CONST_TBL(clone) = st_init_numtable();
- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
- }
- if (RCLASS_M_TBL(orig)) {
- struct clone_method_data data;
+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone));
+ CONST_ID(id, "__classpath__");
+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0);
+ CONST_ID(id, "__classid__");
+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0);
- if (RCLASS_M_TBL(clone)) {
- rb_free_m_table(RCLASS_M_TBL(clone));
- }
- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable();
- data.klass = clone;
- st_foreach(RCLASS_M_TBL(orig), clone_method,
- (st_data_t)&data);
- }
+ sa_clear(RCLASS_CONST_TBL(clone));
+ SA_FOREACH_START(RCLASS_CONST_TBL(orig));
+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone));
+ SA_FOREACH_END();
+
+ rb_free_m_table(RCLASS_M_TBL(clone));
+ SA_FOREACH_START(RCLASS_M_TBL(orig));
+ clone_method(entry->key, (const rb_method_entry_t *)value, clone);
+ SA_FOREACH_END();
return clone;
}
@@ -228,7 +205,6 @@ rb_singleton_class_clone(VALUE obj)
if (!FL_TEST(klass, FL_SINGLETON))
return klass;
else {
- struct clone_method_data data;
/* copy singleton(unnamed) class */
VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0);
@@ -240,18 +216,16 @@ rb_singleton_class_clone(VALUE obj)
}
RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
- if (RCLASS_IV_TBL(klass)) {
- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
- }
- if (RCLASS_CONST_TBL(klass)) {
- RCLASS_CONST_TBL(clone) = st_init_numtable();
- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
- }
- RCLASS_M_TBL(clone) = st_init_numtable();
- data.tbl = RCLASS_M_TBL(clone);
- data.klass = (VALUE)clone;
- st_foreach(RCLASS_M_TBL(klass), clone_method,
- (st_data_t)&data);
+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone));
+
+ SA_FOREACH_START(RCLASS_CONST_TBL(klass));
+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone));
+ SA_FOREACH_END();
+
+ SA_FOREACH_START(RCLASS_M_TBL(klass));
+ clone_method(entry->key, (const rb_method_entry_t*)value, clone);
+ SA_FOREACH_END();
+
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
FL_SET(clone, FL_SINGLETON);
return (VALUE)clone;
@@ -266,10 +240,7 @@ void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
if (FL_TEST(klass, FL_SINGLETON)) {
- if (!RCLASS_IV_TBL(klass)) {
- RCLASS_IV_TBL(klass) = st_init_numtable();
- }
- st_insert(RCLASS_IV_TBL(klass), id_attached, obj);
+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj);
}
}
@@ -356,12 +327,12 @@ make_singleton_class(VALUE obj)
static VALUE
boot_defclass(const char *name, VALUE super)
{
- extern st_table *rb_class_tbl;
+ extern sa_table rb_class_tbl;
VALUE obj = rb_class_boot(super);
ID id = rb_intern(name);
rb_name_class(obj, id);
- st_add_direct(rb_class_tbl, id, obj);
+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj);
rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
return obj;
}
@@ -485,7 +456,7 @@ rb_define_class(const char *name, VALUE super)
rb_warn("no super class for `%s', Object assumed", name);
}
klass = rb_define_class_id(id, super);
- st_add_direct(rb_class_tbl, id, klass);
+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass);
rb_name_class(klass, id);
rb_const_set(rb_cObject, id, klass);
rb_class_inherited(super, klass);
@@ -566,8 +537,6 @@ rb_module_new(void)
{
VALUE mdl = class_alloc(T_MODULE, rb_cModule);
- RCLASS_M_TBL(mdl) = st_init_numtable();
-
return (VALUE)mdl;
}
@@ -596,7 +565,7 @@ rb_define_module(const char *name)
rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
}
module = rb_define_module_id(id);
- st_add_direct(rb_class_tbl, id, module);
+ sa_insert(&rb_class_tbl, (sa_index_t)id, module);
rb_const_set(rb_cObject, id, module);
return module;
@@ -631,27 +600,15 @@ rb_define_module_id_under(VALUE outer, ID id)
static VALUE
include_class_new(VALUE module, VALUE super)
{
- VALUE klass = class_alloc(T_ICLASS, rb_cClass);
+ VALUE klass;
if (BUILTIN_TYPE(module) == T_ICLASS) {
module = RBASIC(module)->klass;
}
- if (!RCLASS_IV_TBL(module)) {
- RCLASS_IV_TBL(module) = st_init_numtable();
- }
- if (!RCLASS_CONST_TBL(module)) {
- RCLASS_CONST_TBL(module) = st_init_numtable();
- }
- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
+ klass = iclass_alloc();
+ RBASIC(klass)->klass = module;
+ RCLASS_EXT(klass) = RCLASS_EXT(module);
RCLASS_SUPER(klass) = super;
- if (TYPE(module) == T_ICLASS) {
- RBASIC(klass)->klass = RBASIC(module)->klass;
- }
- else {
- RBASIC(klass)->klass = module;
- }
OBJ_INFECT(klass, module);
OBJ_INFECT(klass, super);
@@ -678,13 +635,13 @@ rb_include_module(VALUE klass, VALUE module)
while (module) {
int superclass_seen = FALSE;
- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
+ if (RCLASS_EXT(klass) == RCLASS_EXT(module))
rb_raise(rb_eArgError, "cyclic include detected");
/* ignore if the module included already in superclasses */
for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
switch (BUILTIN_TYPE(p)) {
case T_ICLASS:
- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) {
if (!superclass_seen) {
c = p; /* move insertion point */
}
@@ -697,7 +654,7 @@ rb_include_module(VALUE klass, VALUE module)
}
}
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
+ if (RMODULE_M_TBL(module)->num_entries)
changed = 1;
skip:
module = RCLASS_SUPER(module);
@@ -828,58 +785,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi)
}
static int
-ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */
}
static int
-ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary)
+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED);
}
static int
-ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary)
+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE);
}
static int
-ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary)
{
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
}
static int
-method_entry_i(st_data_t key, st_data_t value, st_data_t data)
+method_entry_i(sa_index_t key, st_data_t value, st_data_t data)
{
const rb_method_entry_t *me = (const rb_method_entry_t *)value;
- st_table *list = (st_table *)data;
+ sa_table *list = (sa_table *)data;
long type;
if ((ID)key == ID_ALLOCATOR) {
return ST_CONTINUE;
}
- if (!st_lookup(list, key, 0)) {
+ if (!sa_lookup(list, key, 0)) {
if (UNDEFINED_METHOD_ENTRY_P(me)) {
type = -1; /* none */
}
else {
type = VISI(me->flag);
}
- st_add_direct(list, key, type);
+ sa_insert(list, key, type);
}
return ST_CONTINUE;
}
static VALUE
-class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t))
{
VALUE ary;
int recur;
- st_table *list;
+ sa_table list = SA_EMPTY_TABLE;
if (argc == 0) {
recur = TRUE;
@@ -890,16 +847,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func
recur = RTEST(r);
}
- list = st_init_numtable();
for (; mod; mod = RCLASS_SUPER(mod)) {
- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list);
+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list);
if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
if (!recur) break;
}
ary = rb_ary_new();
- st_foreach(list, func, ary);
- st_free_table(list);
+ sa_foreach(&list, func, ary);
+ sa_clear(&list);
return ary;
}
@@ -1113,7 +1069,7 @@ VALUE
rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
{
VALUE recur, ary, klass;
- st_table *list;
+ sa_table list = SA_EMPTY_TABLE;
if (argc == 0) {
recur = Qtrue;
@@ -1122,20 +1078,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "01", &recur);
}
klass = CLASS_OF(obj);
- list = st_init_numtable();
if (klass && FL_TEST(klass, FL_SINGLETON)) {
- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list);
klass = RCLASS_SUPER(klass);
}
if (RTEST(recur)) {
while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list);
klass = RCLASS_SUPER(klass);
}
}
ary = rb_ary_new();
- st_foreach(list, ins_methods_i, ary);
- st_free_table(list);
+ sa_foreach(&list, ins_methods_i, ary);
+ sa_clear(&list);
return ary;
}
diff --git a/common.mk b/common.mk
index 1d8e442..0d767ab 100644
--- a/common.mk
+++ b/common.mk
@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \
safe.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
+ sp_ar.$(OBJEXT) \
st.$(OBJEXT) \
strftime.$(OBJEXT) \
string.$(OBJEXT) \
@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
{$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES)
+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES)
st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h
strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \
{$(VPATH)}timev.h
diff --git a/constant.h b/constant.h
index 8232910..9106847 100644
--- a/constant.h
+++ b/constant.h
@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct {
VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj);
VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj);
-void rb_free_const_table(st_table *tbl);
+void rb_free_const_table(sa_table *tbl);
VALUE rb_public_const_get(VALUE klass, ID id);
VALUE rb_public_const_get_at(VALUE klass, ID id);
VALUE rb_public_const_get_from(VALUE klass, ID id);
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 66e33a3..4b31f92 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -60,20 +60,10 @@ memsize_of(VALUE obj)
break;
case T_MODULE:
case T_CLASS:
- size += st_memsize(RCLASS_M_TBL(obj));
- if (RCLASS_IV_TBL(obj)) {
- size += st_memsize(RCLASS_IV_TBL(obj));
- }
- if (RCLASS_IV_INDEX_TBL(obj)) {
- size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
- }
- if (RCLASS(obj)->ptr->iv_tbl) {
- size += st_memsize(RCLASS(obj)->ptr->iv_tbl);
- }
- if (RCLASS(obj)->ptr->const_tbl) {
- size += st_memsize(RCLASS(obj)->ptr->const_tbl);
- }
- size += sizeof(rb_classext_t);
+ size += sa_memsize(RCLASS_M_TBL(obj));
+ size += sa_memsize(RCLASS_IV_TBL(obj));
+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj));
+ size += sa_memsize(RCLASS_CONST_TBL(obj));
break;
case T_STRING:
size += rb_str_memsize(obj);
diff --git a/gc.c b/gc.c
index 3110059..56f0217 100644
--- a/gc.c
+++ b/gc.c
@@ -688,7 +688,7 @@ rb_objspace_free(rb_objspace_t *objspace)
#define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE))
-extern st_table *rb_class_tbl;
+extern sa_table rb_class_tbl;
int ruby_disable_gc_stress = 0;
@@ -2358,6 +2358,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl)
st_foreach(tbl, mark_entry, (st_data_t)&arg);
}
+static void
+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl)
+{
+ if (!tbl) return;
+ SA_FOREACH_START(tbl);
+ gc_mark(objspace, (VALUE)value);
+ SA_FOREACH_END();
+}
+
static int
mark_key(VALUE key, VALUE value, st_data_t data)
{
@@ -2434,74 +2443,52 @@ rb_mark_method_entry(const rb_method_entry_t *me)
mark_method_entry(&rb_objspace, me);
}
-static int
-mark_method_entry_i(ID key, const rb_method_entry_t *me, st_data_t data)
-{
- struct mark_tbl_arg *arg = (void*)data;
- mark_method_entry(arg->objspace, me);
- return ST_CONTINUE;
-}
-
static void
-mark_m_tbl(rb_objspace_t *objspace, st_table *tbl)
-{
- struct mark_tbl_arg arg;
- if (!tbl) return;
- arg.objspace = objspace;
- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg);
-}
-
-static int
-free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data)
+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl)
{
- if (!me->mark) {
- rb_free_method_entry(me);
- }
- return ST_CONTINUE;
+ SA_FOREACH_START(tbl);
+ mark_method_entry(objspace, (const rb_method_entry_t*)value);
+ SA_FOREACH_END();
}
void
-rb_free_m_table(st_table *tbl)
+rb_free_m_table(sa_table *tbl)
{
- st_foreach(tbl, free_method_entry_i, 0);
- st_free_table(tbl);
-}
-
-static int
-mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data)
-{
- struct mark_tbl_arg *arg = (void*)data;
- gc_mark(arg->objspace, ce->value);
- return ST_CONTINUE;
+ SA_FOREACH_START(tbl);
+ if (!((rb_method_entry_t*)value)->mark) {
+ rb_free_method_entry((rb_method_entry_t*)value);
+ }
+ SA_FOREACH_END();
+ sa_clear(tbl);
}
static void
-mark_const_tbl(rb_objspace_t *objspace, st_table *tbl)
+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl)
{
- struct mark_tbl_arg arg;
- if (!tbl) return;
- arg.objspace = objspace;
- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg);
+ SA_FOREACH_START(tbl);
+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value);
+ SA_FOREACH_END();
}
-static int
-free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data)
+void
+rb_free_const_table(sa_table *tbl)
{
- xfree(ce);
- return ST_CONTINUE;
+ SA_FOREACH_START(tbl);
+ xfree((rb_const_entry_t*)value);
+ SA_FOREACH_END();
+ sa_clear(tbl);
}
void
-rb_free_const_table(st_table *tbl)
+rb_mark_tbl(st_table *tbl)
{
- st_foreach(tbl, free_const_entry_i, 0);
- st_free_table(tbl);
+ mark_tbl(&rb_objspace, tbl);
}
void
-rb_mark_tbl(st_table *tbl)
+rb_mark_sa_tbl(sa_table *tbl)
{
- mark_tbl(&rb_objspace, tbl);
+ mark_sa_tbl(&rb_objspace, tbl);
}
void
@@ -2709,7 +2696,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
case T_CLASS:
case T_MODULE:
mark_m_tbl(objspace, RCLASS_M_TBL(obj));
- mark_tbl(objspace, RCLASS_IV_TBL(obj));
+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj));
mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
ptr = RCLASS_SUPER(obj);
goto again;
@@ -3284,15 +3271,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_CLASS:
rb_clear_cache_by_class((VALUE)obj);
rb_free_m_table(RCLASS_M_TBL(obj));
- if (RCLASS_IV_TBL(obj)) {
- st_free_table(RCLASS_IV_TBL(obj));
- }
- if (RCLASS_CONST_TBL(obj)) {
- rb_free_const_table(RCLASS_CONST_TBL(obj));
- }
- if (RCLASS_IV_INDEX_TBL(obj)) {
- st_free_table(RCLASS_IV_INDEX_TBL(obj));
- }
+ sa_clear(RCLASS_IV_TBL(obj));
+ rb_free_const_table(RCLASS_CONST_TBL(obj));
+ sa_clear(RCLASS_IV_INDEX_TBL(obj));
xfree(RANY(obj)->as.klass.ptr);
break;
case T_STRING:
@@ -3345,7 +3326,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_ICLASS:
/* iClass shares table with the module */
- xfree(RANY(obj)->as.klass.ptr);
break;
case T_FLOAT:
@@ -3460,7 +3440,7 @@ gc_marks(rb_objspace_t *objspace)
rb_mark_end_proc();
rb_gc_mark_global_tbl();
- mark_tbl(objspace, rb_class_tbl);
+ mark_sa_tbl(objspace, &rb_class_tbl);
/* mark generic instance variables for special constants */
rb_mark_generic_ivar_tbl();
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index ab1cc94..53ca8b0 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -415,6 +415,7 @@ size_t ruby_stack_length(VALUE**);
int rb_during_gc(void);
void rb_gc_mark_locations(VALUE*, VALUE*);
void rb_mark_tbl(struct st_table*);
+void rb_mark_sa_tbl(sa_table*);
void rb_mark_set(struct st_table*);
void rb_mark_hash(struct st_table*);
void rb_gc_mark_maybe(VALUE);
@@ -848,7 +849,7 @@ VALUE rb_f_trace_var(int, VALUE*);
VALUE rb_f_untrace_var(int, VALUE*);
VALUE rb_f_global_variables(void);
void rb_alias_variable(ID, ID);
-struct st_table* rb_generic_ivar_table(VALUE);
+sa_table* rb_generic_ivar_table(VALUE);
void rb_copy_generic_ivar(VALUE,VALUE);
void rb_mark_generic_ivar(VALUE);
void rb_mark_generic_ivar_tbl(void);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 2f97b33..78a2286 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -605,7 +605,7 @@ struct RObject {
struct {
long numiv;
VALUE *ivptr;
- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
} heap;
VALUE ary[ROBJECT_EMBED_LEN_MAX];
} as;
@@ -629,9 +629,8 @@ typedef struct rb_classext_struct rb_classext_t;
struct RClass {
struct RBasic basic;
+ VALUE super;
rb_classext_t *ptr;
- struct st_table *m_tbl;
- struct st_table *iv_index_tbl;
};
#define RCLASS_SUPER(c) rb_class_get_superclass(c)
#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m)
diff --git a/include/ruby/st.h b/include/ruby/st.h
index 119dfde..aff94fc 100644
--- a/include/ruby/st.h
+++ b/include/ruby/st.h
@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h);
#pragma GCC visibility pop
#endif
+typedef unsigned int sa_index_t;
+#define SA_STOP ST_STOP
+#define SA_CONTINUE ST_CONTINUE
+
+#define SA_EMPTY 0
+
+typedef struct sa_entry {
+ sa_index_t next;
+ sa_index_t key;
+ st_data_t value;
+} sa_entry;
+
+typedef struct sa_table {
+ sa_index_t num_bins;
+ sa_index_t num_entries;
+ sa_index_t free_pos;
+ sa_entry *entries;
+} sa_table;
+
+#define SA_EMPTY_TABLE {0, 0, 0, 0};
+void sa_init_table(sa_table *, sa_index_t);
+sa_table *sa_new_table();
+int sa_insert(sa_table *, sa_index_t, st_data_t);
+int sa_lookup(sa_table *, sa_index_t, st_data_t *);
+int sa_delete(sa_table *, sa_index_t, st_data_t *);
+void sa_clear(sa_table *);
+void sa_clear_no_free(sa_table *);
+void sa_free_table(sa_table *);
+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t);
+size_t sa_memsize(const sa_table *);
+sa_table *sa_copy(sa_table*);
+void sa_copy_to(sa_table*, sa_table*);
+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg);
+
+#define SA_FOREACH_START_I(table, entry) do { \
+ sa_table *T##entry = (table); \
+ sa_index_t K##entry; \
+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \
+ sa_entry *entry = T##entry->entries + K##entry; \
+ if (entry->next != SA_EMPTY) { \
+ st_data_t value = entry->value
+#define SA_FOREACH_END() } } } while(0)
+
+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry)
+
#if defined(__cplusplus)
#if 0
{ /* satisfy cc-mode */
diff --git a/internal.h b/internal.h
index f5af903..5927d93 100644
--- a/internal.h
+++ b/internal.h
@@ -24,18 +24,19 @@ struct rb_deprecated_classext_struct {
};
struct rb_classext_struct {
- VALUE super;
- struct st_table *iv_tbl;
- struct st_table *const_tbl;
+ sa_table m_tbl;
+ sa_table iv_tbl;
+ sa_table const_tbl;
+ sa_table iv_index_tbl;
};
#undef RCLASS_SUPER
#define RCLASS_EXT(c) (RCLASS(c)->ptr)
-#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super)
-#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl)
-#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
-#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
-#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
+#define RCLASS_SUPER(c) (RCLASS(c)->super)
+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl)
+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl)
+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl)
+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl)
struct vtm; /* defined by timev.h */
diff --git a/marshal.c b/marshal.c
index 6ae3a55..48d9d9b 100644
--- a/marshal.c
+++ b/marshal.c
@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
}
static int
-w_obj_each(ID id, VALUE value, struct dump_call_arg *arg)
+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg)
{
if (id == rb_id_encoding()) return ST_CONTINUE;
if (id == rb_intern("E")) return ST_CONTINUE;
@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
}
static void
-w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg)
{
long num = tbl ? tbl->num_entries : 0;
w_encoding(obj, num, arg);
if (tbl) {
- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg);
+ sa_foreach(tbl, w_obj_each, (st_data_t)arg);
}
}
@@ -586,7 +586,7 @@ static void
w_object(VALUE obj, struct dump_arg *arg, int limit)
{
struct dump_call_arg c_arg;
- st_table *ivtbl = 0;
+ sa_table *ivtbl = 0;
st_data_t num;
int hasiv = 0;
#define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \
@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
}
if (rb_respond_to(obj, s_dump)) {
VALUE v;
- st_table *ivtbl2 = 0;
+ sa_table *ivtbl2 = 0;
int hasiv2;
v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
diff --git a/method.h b/method.h
index 9229896..2fecd57 100644
--- a/method.h
+++ b/method.h
@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2)
void rb_mark_method_entry(const rb_method_entry_t *me);
void rb_free_method_entry(rb_method_entry_t *me);
void rb_sweep_method_entry(void *vm);
-void rb_free_m_table(st_table *tbl);
+void rb_free_m_table(sa_table *tbl);
#endif /* METHOD_H */
diff --git a/object.c b/object.c
index 59611fd..4522d08 100644
--- a/object.c
+++ b/object.c
@@ -236,17 +236,8 @@ init_copy(VALUE dest, VALUE obj)
break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(dest)) {
- st_free_table(RCLASS_IV_TBL(dest));
- RCLASS_IV_TBL(dest) = 0;
- }
- if (RCLASS_CONST_TBL(dest)) {
- rb_free_const_table(RCLASS_CONST_TBL(dest));
- RCLASS_CONST_TBL(dest) = 0;
- }
- if (RCLASS_IV_TBL(obj)) {
- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj));
- }
+ rb_free_const_table(RCLASS_CONST_TBL(dest));
+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest));
break;
}
}
@@ -537,7 +528,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c)
}
while (cl) {
- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c))
return Qtrue;
cl = RCLASS_SUPER(cl);
}
@@ -1362,13 +1353,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg)
rb_raise(rb_eTypeError, "compared with non class/module");
}
while (mod) {
- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg))
+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg))
return Qtrue;
mod = RCLASS_SUPER(mod);
}
/* not mod < arg; check if mod > arg */
while (arg) {
- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start))
+ if (RCLASS_EXT(arg) == RCLASS_EXT(start))
return Qfalse;
arg = RCLASS_SUPER(arg);
}
diff --git a/sp_ar.c b/sp_ar.c
new file mode 100644
index 0000000..2ed69bf
--- /dev/null
+++ b/sp_ar.c
@@ -0,0 +1,374 @@
+/*
+ * sparse array lib
+ * inspired by Lua table
+ * written by Sokolov Yura aka funny_falcon
+ */
+#ifdef NOT_RUBY
+#include "regint.h"
+#include "st.h"
+#else
+#include "ruby/ruby.h"
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#ifdef RUBY
+#define malloc xmalloc
+#define calloc xcalloc
+#define realloc xrealloc
+#define free xfree
+#endif
+
+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table))
+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table))
+#define sa_table_dealloc(table) free(table)
+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry))
+#define sa_entry_dealloc(entries) free(entries)
+
+#define SA_LAST 1
+#define SA_OFFSET 2
+
+#define SA_MIN_SIZE 4
+
+void
+sa_init_table(register sa_table *table, sa_index_t num_bins)
+{
+ if (num_bins) {
+ table->num_entries = 0;
+ table->entries = sa_entry_alloc(num_bins);
+ table->num_bins = num_bins;
+ table->free_pos = num_bins;
+ }
+ else {
+ memset(table, 0, sizeof(sa_table));
+ }
+}
+
+sa_table*
+sa_new_table()
+{
+ sa_table* table = sa_table_alloc();
+ sa_init_table(table, 0);
+ return table;
+}
+
+static inline sa_index_t
+calc_pos(register sa_table* table, sa_index_t key)
+{
+ /* this formula is empirical */
+ /* it has no good avalance, but works well in our case */
+ key ^= key >> 16;
+ key *= 0x445229;
+ return (key + (key >> 16)) % table->num_bins;
+}
+
+static void
+fix_empty(register sa_table* table)
+{
+ while(--table->free_pos &&
+ table->entries[table->free_pos-1].next != SA_EMPTY);
+}
+
+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2)
+static sa_index_t
+find_empty(register sa_table* table, register sa_index_t pos)
+{
+ sa_index_t new_pos = table->free_pos-1;
+ sa_entry *entry;
+ pos &= FLOOR_TO_4;
+ entry = table->entries+pos;
+
+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; }
+ pos++; entry++;
+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; }
+ pos++; entry++;
+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; }
+ pos++; entry++;
+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; }
+
+check:
+ if (new_pos+1 == table->free_pos) fix_empty(table);
+ return new_pos;
+}
+
+static void resize(register sa_table* table);
+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos);
+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos);
+
+int
+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value)
+{
+ sa_index_t pos, main_pos;
+ register sa_entry *entry;
+
+ if (table->num_bins == 0) {
+ sa_init_table(table, SA_MIN_SIZE);
+ }
+
+ pos = calc_pos(table, key);
+ entry = table->entries + pos;
+
+ if (entry->next == SA_EMPTY) {
+ entry->next = SA_LAST;
+ entry->key = key;
+ entry->value = value;
+ table->num_entries++;
+ if (pos+1 == table->free_pos) fix_empty(table);
+ return 0;
+ }
+
+ if (entry->key == key) {
+ entry->value = value;
+ return 1;
+ }
+
+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) {
+ resize(table);
+ return sa_insert(table, key, value);
+ }
+
+ main_pos = calc_pos(table, entry->key);
+ if (main_pos == pos) {
+ return insert_into_chain(table, key, value, pos);
+ }
+ else {
+ if (!table->free_pos) {
+ resize(table);
+ return sa_insert(table, key, value);
+ }
+ return insert_into_main(table, key, value, pos, main_pos);
+ }
+}
+
+static int
+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos)
+{
+ sa_entry *entry = table->entries + pos, *new_entry;
+ sa_index_t new_pos;
+
+ while (entry->next != SA_LAST) {
+ pos = entry->next - SA_OFFSET;
+ entry = table->entries + pos;
+ if (entry->key == key) {
+ entry->value = value;
+ return 1;
+ }
+ }
+
+ if (!table->free_pos) {
+ resize(table);
+ return sa_insert(table, key, value);
+ }
+
+ new_pos = find_empty(table, pos);
+ new_entry = table->entries + new_pos;
+ entry->next = new_pos + SA_OFFSET;
+
+ new_entry->next = SA_LAST;
+ new_entry->key = key;
+ new_entry->value = value;
+ table->num_entries++;
+ return 0;
+}
+
+static int
+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos)
+{
+ sa_entry *entry = table->entries + pos;
+ sa_index_t new_pos = find_empty(table, pos);
+ sa_entry *new_entry = table->entries + new_pos;
+ sa_index_t npos;
+
+ *new_entry = *entry;
+
+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) {
+ prev_pos = npos;
+ }
+ table->entries[prev_pos].next = new_pos + SA_OFFSET;
+
+ entry->next = SA_LAST;
+ entry->key = key;
+ entry->value = value;
+ table->num_entries++;
+ return 0;
+}
+
+static sa_index_t
+new_size(sa_index_t num_entries)
+{
+ sa_index_t msb = num_entries;
+ msb |= msb >> 1;
+ msb |= msb >> 2;
+ msb |= msb >> 4;
+ msb |= msb >> 8;
+ msb |= msb >> 16;
+ msb = ((msb >> 4) + 1) << 3;
+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1);
+}
+
+static void
+resize(register sa_table *table)
+{
+ sa_table tmp_table;
+ sa_entry *entry;
+ sa_index_t i;
+
+ if (table->num_entries == 0) {
+ sa_entry_dealloc(table->entries);
+ memset(table, 0, sizeof(sa_table));
+ return;
+ }
+
+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2)));
+ entry = table->entries;
+
+ for(i = 0; i < table->num_bins; i++, entry++) {
+ if (entry->next != SA_EMPTY) {
+ sa_insert(&tmp_table, entry->key, entry->value);
+ }
+ }
+ sa_entry_dealloc(table->entries);
+ *table = tmp_table;
+}
+
+int
+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value)
+{
+ register sa_entry *entry;
+
+ if (table->num_entries == 0) return 0;
+
+ entry = table->entries + calc_pos(table, key);
+ if (entry->next == SA_EMPTY) return 0;
+
+ if (entry->key == key) goto found;
+ if (entry->next == SA_LAST) return 0;
+
+ entry = table->entries + (entry->next - SA_OFFSET);
+ if (entry->key == key) goto found;
+
+ while(entry->next != SA_LAST) {
+ entry = table->entries + (entry->next - SA_OFFSET);
+ if (entry->key == key) goto found;
+ }
+ return 0;
+found:
+ if (value) *value = entry->value;
+ return 1;
+}
+
+void
+sa_clear(sa_table *table)
+{
+ sa_entry_dealloc(table->entries);
+ memset(table, 0, sizeof(sa_table));
+}
+
+void
+sa_clear_no_free(sa_table *table)
+{
+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins);
+ table->num_entries = 0;
+ table->free_pos = table->num_bins;
+}
+
+void
+sa_free_table(sa_table *table)
+{
+ sa_entry_dealloc(table->entries);
+ sa_table_dealloc(table);
+}
+
+int
+sa_delete(sa_table *table, sa_index_t key, st_data_t *value)
+{
+ sa_index_t pos, prev_pos = ~0;
+ sa_entry *entry;
+
+ if (table->num_entries == 0) goto not_found;
+
+ pos = calc_pos(table, key);
+ entry = table->entries + pos;
+
+ if (entry->next == SA_EMPTY) goto not_found;
+
+ do {
+ if (entry->key == key) {
+ if (value) *value = entry->value;
+ if (entry->next != SA_LAST) {
+ sa_index_t npos = entry->next - SA_OFFSET;
+ *entry = table->entries[npos];
+ memset(table->entries + npos, 0, sizeof(sa_entry));
+ }
+ else {
+ memset(table->entries + pos, 0, sizeof(sa_entry));
+ if (~prev_pos) {
+ table->entries[prev_pos].next = SA_LAST;
+ }
+ }
+ table->num_entries--;
+ if (table->num_entries < table->num_bins / 4) {
+ resize(table);
+ }
+ return 1;
+ }
+ if (entry->next == SA_LAST) break;
+ prev_pos = pos;
+ pos = entry->next - SA_OFFSET;
+ entry = table->entries + pos;
+ } while(1);
+
+not_found:
+ if (value) *value = 0;
+ return 0;
+}
+
+int
+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg)
+{
+ sa_index_t i;
+ if (table->num_bins == 0) {
+ return 0;
+ }
+ for(i = 0; i < table->num_bins ; i++) {
+ if (table->entries[i].next != SA_EMPTY) {
+ sa_index_t key = table->entries[i].key;
+ st_data_t val = table->entries[i].value;
+ if ((*func)(key, val, arg) == SA_STOP) break;
+ }
+ }
+ return 0;
+}
+
+size_t
+sa_memsize(const sa_table *table)
+{
+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry);
+}
+
+sa_table*
+sa_copy(sa_table *table)
+{
+ sa_table *new_table = sa_table_alloc();
+ *new_table = *table;
+ if (table->num_bins) {
+ new_table->entries = sa_entry_alloc(table->num_bins);
+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry));
+ }
+ return new_table;
+}
+
+void
+sa_copy_to(sa_table *from, sa_table *to)
+{
+ sa_entry_dealloc(to->entries);
+ *to = *from;
+ if (to->num_bins) {
+ to->entries = sa_entry_alloc(to->num_bins);
+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry));
+ }
+}
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 0f3f794..5c2e502 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase
assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932)
end
end
- a.__send__(a.methods(true).grep(/=\z/)[0], a)
+ a.__send__(a.methods(true).grep(/r.*=\z/)[0], a)
assert_nothing_raised(bug1932) do
b = Marshal.load(Marshal.dump(a))
assert_equal(ClassISO8859_1, b.class, bug1932)
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index ea6c5f2..6ccd37c 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase
obj = a.new
assert_equal([:a], obj.public_methods(false), bug)
obj.extend(m)
- assert_equal([:m1, :a], obj.public_methods(false), bug)
+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug)
end
def test_visibility
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 6176f48..a67d845 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase
(class << self ; self ; end).class_eval do
define_method :method_added do |sym|
memo << sym
- memo << mod.instance_methods(false)
+ memo << mod.instance_methods(false).sort
memo << (mod.instance_method(sym) rescue nil)
end
end
@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase
assert_equal [:f, :g], memo.shift
assert_equal mod.instance_method(:f), memo.shift
assert_equal :a, memo.shift
- assert_equal [:f, :g, :a], memo.shift
+ assert_equal [:a, :f, :g], memo.shift
assert_equal mod.instance_method(:a), memo.shift
assert_equal :a=, memo.shift
- assert_equal [:f, :g, :a, :a=], memo.shift
+ assert_equal [:a, :a=, :f, :g], memo.shift
assert_equal mod.instance_method(:a=), memo.shift
end
diff --git a/time.c b/time.c
index 755812f..83edc83 100644
--- a/time.c
+++ b/time.c
@@ -4712,16 +4712,14 @@ time_mload(VALUE time, VALUE str)
long nsec;
VALUE submicro, nano_num, nano_den, offset;
wideval_t timew;
- st_data_t data;
time_modify(time);
#define get_attr(attr, iffound) \
attr = rb_attr_get(str, id_##attr); \
if (!NIL_P(attr)) { \
- data = id_##attr; \
iffound; \
- st_delete(rb_generic_ivar_table(str), &data, 0); \
+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \
}
get_attr(nano_num, {});
diff --git a/variable.c b/variable.c
index 3da500e..4a61453 100644
--- a/variable.c
+++ b/variable.c
@@ -19,15 +19,15 @@
#include "constant.h"
#include "internal.h"
-st_table *rb_global_tbl;
-st_table *rb_class_tbl;
+sa_table rb_global_tbl;
+sa_table rb_class_tbl;
static ID autoload, classpath, tmp_classpath, classid;
void
Init_var_tables(void)
{
- rb_global_tbl = st_init_numtable();
- rb_class_tbl = st_init_numtable();
+ sa_init_table(&rb_global_tbl, 0);
+ sa_init_table(&rb_class_tbl, 0);
CONST_ID(autoload, "__autoload__");
CONST_ID(classpath, "__classpath__");
CONST_ID(tmp_classpath, "__tmp_classpath__");
@@ -43,7 +43,7 @@ struct fc_result {
};
static VALUE
-fc_path(struct fc_result *fc, ID name)
+fc_path(struct fc_result *fc, sa_index_t name)
{
VALUE path, tmp;
@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name)
while (fc) {
st_data_t n;
if (fc->track == rb_cObject) break;
- if (RCLASS_IV_TBL(fc->track) &&
- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) {
+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) {
tmp = rb_str_dup((VALUE)n);
rb_str_cat2(tmp, "::");
rb_str_append(tmp, path);
@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name)
}
static int
-fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res)
+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res)
{
VALUE value = ce->value;
if (!rb_is_const_id(key)) return ST_CONTINUE;
@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res)
arg.klass = res->klass;
arg.track = value;
arg.prev = res;
- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg);
+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg);
if (arg.path) {
res->path = arg.path;
return ST_STOP;
@@ -123,18 +122,14 @@ find_class_path(VALUE klass)
arg.track = rb_cObject;
arg.prev = 0;
if (RCLASS_CONST_TBL(rb_cObject)) {
- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg);
+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg);
}
if (arg.path == 0) {
- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg);
}
if (arg.path) {
- st_data_t tmp = tmp_classpath;
- if (!RCLASS_IV_TBL(klass)) {
- RCLASS_IV_TBL(klass) = st_init_numtable();
- }
- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path);
- st_delete(RCLASS_IV_TBL(klass), &tmp, 0);
+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path);
+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0);
return arg.path;
}
return Qnil;
@@ -147,16 +142,15 @@ classname(VALUE klass)
st_data_t n;
if (!klass) klass = rb_cObject;
- if (RCLASS_IV_TBL(klass)) {
- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) {
- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) {
+ if (RCLASS_IV_TBL(klass)->num_entries) {
+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) {
+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) {
return find_class_path(klass);
}
path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n)));
OBJ_FREEZE(path);
- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path);
- n = classid;
- st_delete(RCLASS_IV_TBL(klass), &n, 0);
+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path);
+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0);
}
else {
path = (VALUE)n;
@@ -192,8 +186,7 @@ rb_class_path(VALUE klass)
st_data_t n = (st_data_t)path;
if (!NIL_P(path)) return path;
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
- (st_data_t)tmp_classpath, &n)) {
+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) {
return (VALUE)n;
}
else {
@@ -364,7 +357,7 @@ rb_global_entry(ID id)
struct global_entry *entry;
st_data_t data;
- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) {
struct global_variable *var;
entry = ALLOC(struct global_entry);
var = ALLOC(struct global_variable);
@@ -378,7 +371,7 @@ rb_global_entry(ID id)
var->block_trace = 0;
var->trace = 0;
- st_add_direct(rb_global_tbl, id, (st_data_t)entry);
+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry);
}
else {
entry = (struct global_entry *)data;
@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar)
rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
}
-static int
-mark_global_entry(ID key, struct global_entry *entry)
+static void
+mark_global_entry(struct global_entry *entry)
{
struct trace_var *trace;
struct global_variable *var = entry->var;
@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry)
if (trace->data) rb_gc_mark_maybe(trace->data);
trace = trace->next;
}
- return ST_CONTINUE;
}
void
rb_gc_mark_global_tbl(void)
{
- if (rb_global_tbl)
- st_foreach_safe(rb_global_tbl, mark_global_entry, 0);
+ SA_FOREACH_START(&rb_global_tbl);
+ mark_global_entry((struct global_entry*) value);
+ SA_FOREACH_END();
}
static ID
@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv)
rb_secure(4);
rb_scan_args(argc, argv, "11", &var, &cmd);
id = rb_to_id(var);
- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) {
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
}
@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry)
return Qtrue;
}
-static int
-gvar_i(ID key, struct global_entry *entry, VALUE ary)
-{
- rb_ary_push(ary, ID2SYM(key));
- return ST_CONTINUE;
-}
-
/*
* call-seq:
* global_variables -> array
@@ -765,7 +751,9 @@ rb_f_global_variables(void)
char buf[2];
int i;
- st_foreach_safe(rb_global_tbl, gvar_i, ary);
+ SA_FOREACH_START(&rb_global_tbl);
+ rb_ary_push(ary, ID2SYM(entry->key));
+ SA_FOREACH_END();
buf[0] = '$';
for (i = 1; i <= 9; ++i) {
buf[1] = (char)(i + '0');
@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2)
rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
entry2 = rb_global_entry(name2);
- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) {
+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) {
entry1 = ALLOC(struct global_entry);
entry1->id = name1;
- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1);
+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1);
}
else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) {
struct global_variable *var = entry1->var;
@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2)
static int special_generic_ivar = 0;
static st_table *generic_iv_tbl;
-st_table*
+sa_table*
rb_generic_ivar_table(VALUE obj)
{
st_data_t tbl;
@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj)
if (!FL_TEST(obj, FL_EXIVAR)) return 0;
if (!generic_iv_tbl) return 0;
if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0;
- return (st_table *)tbl;
+ return (sa_table *)tbl;
}
static VALUE
@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn)
if (generic_iv_tbl) {
if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) {
- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) {
+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) {
return (VALUE)val;
}
}
@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn)
static void
generic_ivar_set(VALUE obj, ID id, VALUE val)
{
- st_table *tbl;
st_data_t data;
if (rb_special_const_p(obj)) {
@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val)
}
if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) {
FL_SET(obj, FL_EXIVAR);
- tbl = st_init_numtable();
- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl);
- st_add_direct(tbl, (st_data_t)id, (st_data_t)val);
- return;
+ data = (st_data_t)sa_new_table();
+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data);
}
- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val);
+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val);
}
static VALUE
generic_ivar_defined(VALUE obj, ID id)
{
- st_table *tbl;
+ sa_table *tbl;
st_data_t data;
if (!generic_iv_tbl) return Qfalse;
if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse;
- tbl = (st_table *)data;
- if (st_lookup(tbl, (st_data_t)id, &data)) {
+ tbl = (sa_table *)data;
+ if (sa_lookup(tbl, (sa_index_t)id, &data)) {
return Qtrue;
}
return Qfalse;
@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id)
static int
generic_ivar_remove(VALUE obj, ID id, st_data_t *valp)
{
- st_table *tbl;
+ sa_table *tbl;
st_data_t data, key = (st_data_t)id;
int status;
if (!generic_iv_tbl) return 0;
if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0;
- tbl = (st_table *)data;
- status = st_delete(tbl, &key, valp);
+ tbl = (sa_table *)data;
+ status = sa_delete(tbl, (sa_index_t)id, valp);
if (tbl->num_entries == 0) {
key = (st_data_t)obj;
st_delete(generic_iv_tbl, &key, &data);
- st_free_table((st_table *)data);
+ sa_free_table(tbl);
}
return status;
}
@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj)
if (!generic_iv_tbl) return;
if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) {
- rb_mark_tbl((st_table *)tbl);
+ rb_mark_sa_tbl((sa_table *)tbl);
}
}
static int
-givar_mark_i(ID key, VALUE value)
-{
- rb_gc_mark(value);
- return ST_CONTINUE;
-}
-
-static int
-givar_i(VALUE obj, st_table *tbl)
+givar_i(VALUE obj, sa_table *tbl)
{
if (rb_special_const_p(obj)) {
- st_foreach_safe(tbl, givar_mark_i, 0);
+ SA_FOREACH_START(tbl);
+ rb_gc_mark((VALUE)value);
+ SA_FOREACH_END();
}
return ST_CONTINUE;
}
@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj)
if (!generic_iv_tbl) return;
if (st_delete(generic_iv_tbl, &key, &tbl))
- st_free_table((st_table *)tbl);
+ sa_free_table((sa_table *)tbl);
}
RUBY_FUNC_EXPORTED size_t
@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj)
{
st_data_t tbl;
if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl))
- return st_memsize((st_table *)tbl);
+ return sa_memsize((sa_table *)tbl);
return 0;
}
@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj)
return;
}
if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) {
- st_table *tbl = (st_table *)data;
+ sa_table *tbl = (sa_table *)data;
if (tbl->num_entries == 0)
goto clear;
if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) {
- st_free_table((st_table *)data);
- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl));
+ sa_free_table((sa_table *)data);
+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl));
}
else {
- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl));
+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl));
FL_SET(clone, FL_EXIVAR);
}
}
@@ -990,7 +970,7 @@ static VALUE
ivar_get(VALUE obj, ID id, int warn)
{
VALUE val, *ptr;
- struct st_table *iv_index_tbl;
+ sa_table *iv_index_tbl;
long len;
st_data_t index;
@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn)
ptr = ROBJECT_IVPTR(obj);
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break;
if (len <= (long)index) break;
val = ptr[index];
if (val != Qundef)
@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn)
break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index))
+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index))
return (VALUE)index;
break;
default:
@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id)
VALUE
rb_ivar_set(VALUE obj, ID id, VALUE val)
{
- struct st_table *iv_index_tbl;
+ struct sa_table *iv_index_tbl;
st_data_t index;
long i, len;
int ivar_extended;
@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val)
if (!iv_index_tbl) {
VALUE klass = rb_obj_class(obj);
iv_index_tbl = RCLASS_IV_INDEX_TBL(klass);
- if (!iv_index_tbl) {
- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
- }
}
ivar_extended = 0;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) {
index = iv_index_tbl->num_entries;
- st_add_direct(iv_index_tbl, (st_data_t)id, index);
+ sa_insert(iv_index_tbl, (sa_index_t)id, index);
ivar_extended = 1;
}
len = ROBJECT_NUMIV(obj);
@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val)
break;
case T_CLASS:
case T_MODULE:
- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable();
- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val);
+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val);
break;
default:
generic_ivar_set(obj, id, val);
@@ -1112,13 +1088,13 @@ VALUE
rb_ivar_defined(VALUE obj, ID id)
{
VALUE val;
- struct st_table *iv_index_tbl;
+ struct sa_table *iv_index_tbl;
st_data_t index;
switch (TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break;
if (ROBJECT_NUMIV(obj) <= (long)index) break;
val = ROBJECT_IVPTR(obj)[index];
if (val != Qundef)
@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id)
break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0))
+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0))
return Qtrue;
break;
default:
@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id)
return Qfalse;
}
-struct obj_ivar_tag {
- VALUE obj;
- int (*func)(ID key, VALUE val, st_data_t arg);
- st_data_t arg;
-};
-
-static int
-obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg)
-{
- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg;
- if ((long)index < ROBJECT_NUMIV(data->obj)) {
- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index];
- if (val != Qundef) {
- return (data->func)((ID)key, val, data->arg);
- }
- }
- return ST_CONTINUE;
-}
-
static void
obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
{
- st_table *tbl;
- struct obj_ivar_tag data;
+ sa_table *tbl;
+ long numiv = ROBJECT_NUMIV(obj);
+ VALUE *vars = ROBJECT_IVPTR(obj);
tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (!tbl)
+ if (!tbl || !numiv)
return;
- data.obj = obj;
- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
- data.arg = arg;
-
- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
+ SA_FOREACH_START(tbl);
+ if ((long)value < numiv) {
+ VALUE val = vars[value];
+ if (val != Qundef) {
+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP)
+ break;
+ }
+ }
+ SA_FOREACH_END();
}
void
@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(obj)) {
- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
- }
+ sa_foreach(RCLASS_IV_TBL(obj), func, arg);
break;
default:
if (!generic_iv_tbl) break;
@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
st_data_t tbl;
if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) {
- st_foreach_safe((st_table *)tbl, func, arg);
+ sa_foreach((sa_table *)tbl, func, arg);
}
}
break;
@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
st_index_t
rb_ivar_count(VALUE obj)
{
- st_table *tbl;
+ sa_table *tbl;
switch (TYPE(obj)) {
case T_OBJECT:
if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) {
- st_index_t i, count, num = tbl->num_entries;
+ sa_index_t i, count, num = tbl->num_entries;
const VALUE *const ivptr = ROBJECT_IVPTR(obj);
for (i = count = 0; i < num; ++i) {
if (ivptr[i] != Qundef) {
@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj)
st_data_t data;
if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) &&
- (tbl = (st_table *)data) != 0) {
+ (tbl = (sa_table *)data) != 0) {
return tbl->num_entries;
}
}
@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj)
}
static int
-ivar_i(ID key, VALUE val, VALUE ary)
+ivar_i(sa_index_t key, VALUE val, VALUE ary)
{
if (rb_is_instance_id(key)) {
rb_ary_push(ary, ID2SYM(key));
@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
VALUE val = Qnil;
const ID id = rb_to_id(name);
st_data_t n, v;
- struct st_table *iv_index_tbl;
+ struct sa_table *iv_index_tbl;
st_data_t index;
if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break;
if (ROBJECT_NUMIV(obj) <= (long)index) break;
val = ROBJECT_IVPTR(obj)[index];
if (val != Qundef) {
@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
case T_CLASS:
case T_MODULE:
n = id;
- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) {
return (VALUE)v;
}
break;
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
v = val;
- if (generic_ivar_remove(obj, (st_data_t)id, &v)) {
+ if (generic_ivar_remove(obj, id, &v)) {
return (VALUE)v;
}
}
@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name)
static void
autoload_mark(void *ptr)
{
- rb_mark_tbl((st_table *)ptr);
+ rb_mark_sa_tbl((sa_table *)ptr);
}
static void
autoload_free(void *ptr)
{
- st_free_table((st_table *)ptr);
+ sa_free_table((sa_table *)ptr);
}
static size_t
autoload_memsize(const void *ptr)
{
- const st_table *tbl = ptr;
- return st_memsize(tbl);
+ const sa_table *tbl = ptr;
+ return sa_memsize(tbl);
}
static const rb_data_type_t autoload_data_type = {
@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = {
};
#define check_autoload_table(av) \
- (struct st_table *)rb_check_typeddata((av), &autoload_data_type)
+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type)
void
rb_autoload(VALUE mod, ID id, const char *file)
{
st_data_t av;
VALUE fn;
- struct st_table *tbl;
+ struct sa_table *tbl;
if (!rb_is_const_id(id)) {
rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id));
@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file)
rb_raise(rb_eArgError, "empty file name");
}
- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef)
+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef)
return;
rb_const_set(mod, id, Qundef);
tbl = RCLASS_IV_TBL(mod);
- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) {
tbl = check_autoload_table((VALUE)av);
}
else {
- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0);
- st_add_direct(tbl, (st_data_t)autoload, av);
- DATA_PTR(av) = tbl = st_init_numtable();
+ sa_insert(tbl, (sa_index_t)autoload, av);
+ DATA_PTR(av) = tbl = sa_new_table();
}
fn = rb_str_new2(file);
FL_UNSET(fn, FL_TAINT);
OBJ_FREEZE(fn);
- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0));
+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0));
}
static NODE*
autoload_delete(VALUE mod, ID id)
{
- st_data_t val, load = 0, n = id;
+ st_data_t val, load = 0;
rb_const_entry_t *ce;
- st_delete(RCLASS_CONST_TBL(mod), &n, &val);
+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val);
ce = (rb_const_entry_t*)val;
if (ce) xfree(ce);
- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
- struct st_table *tbl = check_autoload_table((VALUE)val);
+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) {
+ struct sa_table *tbl = check_autoload_table((VALUE)val);
- st_delete(tbl, &n, &load);
+ sa_delete(tbl, (sa_index_t)id, &load);
if (tbl->num_entries == 0) {
- n = autoload;
- st_delete(RCLASS_IV_TBL(mod), &n, &val);
+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val);
}
}
@@ -1509,14 +1467,14 @@ static NODE *
autoload_node(VALUE mod, ID id, const char **loadingpath)
{
VALUE file;
- struct st_table *tbl;
+ struct sa_table *tbl;
st_data_t val;
NODE *load;
const char *loading;
int safe;
- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) {
+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) ||
+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) {
return 0;
}
load = (NODE *)val;
@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath)
static int
autoload_node_id(VALUE mod, ID id)
{
- struct st_table *tbl = RCLASS_CONST_TBL(mod);
+ struct sa_table *tbl = RCLASS_CONST_TBL(mod);
st_data_t val;
- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) {
+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) {
return 0;
}
return 1;
@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
while (RTEST(tmp)) {
VALUE am = 0;
st_data_t data;
- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) {
+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) {
rb_const_entry_t *ce = (rb_const_entry_t *)data;
if (visibility && ce->flag == CONST_PRIVATE) {
rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id));
@@ -1686,12 +1644,12 @@ VALUE
rb_const_remove(VALUE mod, ID id)
{
VALUE val;
- st_data_t v, n = id;
+ st_data_t v;
if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
rb_check_frozen(mod);
- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) {
+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) {
if (rb_const_defined_at(mod, id)) {
rb_name_error(id, "cannot remove %s::%s",
rb_class2name(mod), rb_id2name(id));
@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id)
return val;
}
-static int
-sv_i(ID key, rb_const_entry_t *ce, st_table *tbl)
-{
- if (rb_is_const_id(key)) {
- if (!st_lookup(tbl, (st_data_t)key, 0)) {
- st_insert(tbl, (st_data_t)key, (st_data_t)ce);
- }
- }
- return ST_CONTINUE;
-}
-
void*
rb_mod_const_at(VALUE mod, void *data)
{
- st_table *tbl = data;
+ sa_table *tbl = data;
if (!tbl) {
- tbl = st_init_numtable();
+ tbl = sa_new_table();
}
- if (RCLASS_CONST_TBL(mod)) {
- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl);
+ SA_FOREACH_START(RCLASS_CONST_TBL(mod));
+ if (rb_is_const_id(entry->key)) {
+ if (!sa_lookup(tbl, entry->key, 0)) {
+ sa_insert(tbl, entry->key, value);
+ }
}
+ SA_FOREACH_END();
return tbl;
}
@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data)
return data;
}
-static int
-list_i(st_data_t key, st_data_t value, VALUE ary)
-{
- ID sym = (ID)key;
- rb_const_entry_t *ce = (rb_const_entry_t *)value;
- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym));
- return ST_CONTINUE;
-}
-
VALUE
rb_const_list(void *data)
{
- st_table *tbl = data;
+ sa_table *tbl = data;
VALUE ary;
if (!tbl) return rb_ary_new2(0);
ary = rb_ary_new2(tbl->num_entries);
- st_foreach_safe(tbl, list_i, ary);
- st_free_table(tbl);
+
+ SA_FOREACH_START(tbl);
+ rb_const_entry_t *ce = (rb_const_entry_t *)value;
+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key));
+ SA_FOREACH_END();
+
+ sa_free_table(tbl);
return ary;
}
@@ -1790,7 +1737,7 @@ VALUE
rb_mod_constants(int argc, VALUE *argv, VALUE mod)
{
VALUE inherit;
- st_table *tbl;
+ sa_table *tbl;
if (argc == 0) {
inherit = Qtrue;
@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
tmp = klass;
retry:
while (tmp) {
- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) {
+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) {
rb_const_entry_t *ce = (rb_const_entry_t *)value;
if (visibility && ce->flag == CONST_PRIVATE) {
return (int)Qfalse;
@@ -1885,6 +1832,7 @@ void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
+ st_data_t value;
VALUE visibility = CONST_PUBLIC;
if (NIL_P(klass)) {
@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val)
}
check_before_mod_set(klass, id, val, "constant");
- if (!RCLASS_CONST_TBL(klass)) {
- RCLASS_CONST_TBL(klass) = st_init_numtable();
- }
- else {
- st_data_t value;
-
- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) {
- rb_const_entry_t *ce = (rb_const_entry_t*)value;
- if (ce->value == Qundef)
- autoload_delete(klass, id);
- else {
- visibility = ce->flag;
- rb_warn("already initialized constant %s", rb_id2name(id));
- }
- }
+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) {
+ rb_const_entry_t *ce = (rb_const_entry_t*)value;
+ if (ce->value == Qundef)
+ autoload_delete(klass, id);
+ else {
+ visibility = ce->flag;
+ rb_warn("already initialized constant %s", rb_id2name(id));
+ }
}
rb_vm_change_state();
@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
ce->flag = (rb_const_flag_t)visibility;
ce->value = val;
- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce);
}
void
@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag)
for (i = 0; i < argc; i++) {
VALUE val = argv[i];
id = rb_to_id(val);
- if (RCLASS_CONST_TBL(mod) &&
- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) {
+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) {
((rb_const_entry_t*)v)->flag = flag;
}
else {
@@ -2008,7 +1948,7 @@ original_module(VALUE c)
}
#define CVAR_LOOKUP(v,r) do {\
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\
+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\
r;\
}\
if (FL_TEST(klass, FL_SINGLETON) ) {\
@@ -2027,7 +1967,7 @@ original_module(VALUE c)
klass = RCLASS_SUPER(klass);\
}\
while (klass) {\
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\
+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\
r;\
}\
klass = RCLASS_SUPER(klass);\
@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
if (target) {
if (front && target != front) {
- st_data_t did = id;
-
if (RTEST(ruby_verbose)) {
rb_warning("class variable %s of %s is overtaken by %s",
rb_id2name(id), rb_class2name(original_module(front)),
rb_class2name(original_module(target)));
}
if (BUILTIN_TYPE(front) == T_CLASS) {
- st_delete(RCLASS_IV_TBL(front),&did,0);
+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0);
}
}
}
@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
}
check_before_mod_set(target, id, val, "class variable");
- if (!RCLASS_IV_TBL(target)) {
- RCLASS_IV_TBL(target) = st_init_numtable();
- }
-
- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val);
+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val);
}
VALUE
@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id)
rb_id2name(id), rb_class2name(tmp));
}
if (front && target != front) {
- st_data_t did = id;
-
if (RTEST(ruby_verbose)) {
rb_warning("class variable %s of %s is overtaken by %s",
rb_id2name(id), rb_class2name(original_module(front)),
rb_class2name(original_module(target)));
}
if (BUILTIN_TYPE(front) == T_CLASS) {
- st_delete(RCLASS_IV_TBL(front),&did,0);
+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0);
}
}
return (VALUE)value;
@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val)
}
static int
-cv_i(ID key, VALUE value, VALUE ary)
+cv_i(sa_index_t key, VALUE value, VALUE ary)
{
if (rb_is_class_id(key)) {
VALUE kval = ID2SYM(key);
@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj)
VALUE ary = rb_ary_new();
if (RCLASS_IV_TBL(obj)) {
- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary);
+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary);
}
return ary;
}
@@ -2196,7 +2128,7 @@ VALUE
rb_mod_remove_cvar(VALUE mod, VALUE name)
{
const ID id = rb_to_id(name);
- st_data_t val, n = id;
+ st_data_t val;
if (!rb_is_class_id(id)) {
rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name)
if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
rb_check_frozen(mod);
- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) {
return (VALUE)val;
}
if (rb_cvar_defined(mod, id)) {
diff --git a/vm.c b/vm.c
index 5a721d0..7bc007a 100644
--- a/vm.c
+++ b/vm.c
@@ -1055,7 +1055,7 @@ static void
add_opt_method(VALUE klass, ID mid, VALUE bop)
{
rb_method_entry_t *me;
- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def &&
+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def &&
me->def->type == VM_METHOD_TYPE_CFUNC) {
st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 5f7d1ee..ade417e 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1179,7 +1179,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
st_data_t data;
search_continue:
if (RCLASS_CONST_TBL(klass) &&
- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) {
+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) {
val = ((rb_const_entry_t*)data)->value;
if (val == Qundef) {
if (am == klass) break;
@@ -1289,10 +1289,10 @@ vm_getivar(VALUE obj, ID id, IC ic)
st_data_t index;
long len = ROBJECT_NUMIV(obj);
VALUE *ptr = ROBJECT_IVPTR(obj);
- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (iv_index_tbl) {
- if (st_lookup(iv_index_tbl, id, &index)) {
+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) {
if ((long)index < len) {
val = ptr[index];
}
@@ -1342,9 +1342,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic)
}
}
else {
- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) {
ic->ic_class = klass;
ic->ic_value.index = index;
ic->ic_vmstat = GET_VM_STATE_VERSION();
diff --git a/vm_method.c b/vm_method.c
index 85cb30c..d45df81 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -162,7 +162,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
rb_method_definition_t *def, rb_method_flag_t noex)
{
rb_method_entry_t *me;
- st_table *mtbl;
+ sa_table *mtbl;
st_data_t data;
if (NIL_P(klass)) {
@@ -190,7 +190,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
mtbl = RCLASS_M_TBL(klass);
/* check re-definition */
- if (st_lookup(mtbl, mid, &data)) {
+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) {
rb_method_entry_t *old_me = (rb_method_entry_t *)data;
rb_method_definition_t *old_def = old_me->def;
@@ -248,7 +248,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
}
}
- st_insert(mtbl, mid, (st_data_t) me);
+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me);
return me;
}
@@ -371,7 +371,7 @@ search_method(VALUE klass, ID id)
return 0;
}
- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) {
klass = RCLASS_SUPER(klass);
if (!klass) {
return 0;
@@ -429,7 +429,7 @@ rb_method_entry(VALUE klass, ID id)
static void
remove_method(VALUE klass, ID mid)
{
- st_data_t key, data;
+ st_data_t data;
rb_method_entry_t *me = 0;
if (klass == rb_cObject) {
@@ -443,14 +443,13 @@ 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 (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) ||
!(me = (rb_method_entry_t *)data) ||
(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
}
- key = (st_data_t)mid;
- st_delete(RCLASS_M_TBL(klass), &key, &data);
+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data);
rb_vm_check_redefinition_opt_method(me);
rb_clear_cache_for_undef(klass, mid);