Commit c9fe903f authored by Yukihiro Matsumoto's avatar Yukihiro Matsumoto

now segmented list can be used as instance variable tables by...

now segmented list can be used as instance variable tables by -DMRB_USE_IV_SEGLIST; we still need to measure the performance and memory consumption
parent 3fe4b641
......@@ -19,7 +19,10 @@
/* number of object per heap page */
//#define MRB_HEAP_PAGE_SIZE 1024
/* initial size for IV khash */
/* use segmented list for IV table */
//#define MRB_USE_IV_SEGLIST
/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */
//#define MRB_IV_INITIAL_SIZE 8
/* default size of khash table bucket */
......
......@@ -233,7 +233,7 @@ typedef struct mrb_state {
int esize;
struct RObject *exc;
struct kh_iv *globals;
struct iv_tbl *globals;
struct mrb_irep **irep;
size_t irep_len, irep_capa;
......
......@@ -13,7 +13,7 @@ extern "C" {
struct RClass {
MRUBY_OBJECT_HEADER;
struct kh_iv *iv;
struct iv_tbl *iv;
struct kh_mt *mt;
struct RClass *super;
};
......
......@@ -18,7 +18,7 @@ struct mrb_data_type {
struct RData {
MRUBY_OBJECT_HEADER;
struct kh_iv *iv;
struct iv_tbl *iv;
struct mrb_data_type *type;
void *data;
};
......
......@@ -13,7 +13,7 @@ extern "C" {
struct RHash {
MRUBY_OBJECT_HEADER;
struct kh_iv *iv;
struct iv_tbl *iv;
struct kh_ht *ht;
};
......
......@@ -44,7 +44,7 @@ struct RBasic {
struct RObject {
MRUBY_OBJECT_HEADER;
struct kh_iv *iv;
struct iv_tbl *iv;
};
#define mrb_obj_ptr(v) ((struct RObject*)((v).value.p))
......
......@@ -38,17 +38,21 @@ mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym);
void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value);
int mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
mrb_value mrb_obj_iv_get(mrb_state*, struct RObject*, mrb_sym);
void mrb_obj_iv_set(mrb_state*, struct RObject*, mrb_sym, mrb_value);
const char * mrb_class2name(mrb_state *mrb, struct RClass* klass);
mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
int mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
int mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym);
void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src);
int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id);
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym);
void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer);
/* GC functions */
void mrb_gc_mark_gv(mrb_state*);
......@@ -57,9 +61,6 @@ void mrb_gc_mark_iv(mrb_state*, struct RObject*);
size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
void mrb_gc_free_iv(mrb_state*, struct RObject*);
#include "mruby/khash.h"
KHASH_DECLARE(iv, mrb_sym, mrb_value, 1)
#if defined(__cplusplus)
} /* extern "C" { */
#endif
......
......@@ -15,7 +15,6 @@
#include "mruby/array.h"
#include "error.h"
KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal);
KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal);
typedef struct fc_result {
......@@ -65,30 +64,6 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mrb_intern(mrb, "__classid__"), mrb_symbol_value(name));
}
static mrb_sym
class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
{
mrb_value name;
name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__"));
if (mrb_nil_p(name)) {
khash_t(iv)* h;
khiter_t k;
mrb_value v;
if (!outer) outer = mrb->object_class;
h = outer->iv;
for (k = kh_begin(h); k != kh_end(h); k++) {
if (!kh_exist(h,k)) continue;
v = kh_value(h,k);
if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
return kh_key(h,k);
}
}
}
return SYM2ID(name);
}
static void
make_metaclass(mrb_state *mrb, struct RClass *c)
{
......@@ -1114,16 +1089,16 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"));
if (mrb_nil_p(path)) {
struct RClass *outer = mrb_class_outer_module(mrb, c);
mrb_sym sym = class_sym(mrb, c, outer);
if (outer && outer != mrb->object_class) {
mrb_sym sym = mrb_class_sym(mrb, c, outer);
if (sym == 0) {
return mrb_nil_value();
}
else if (outer && outer != mrb->object_class) {
mrb_value base = mrb_class_path(mrb, outer);
path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2));
name = mrb_sym2name_len(mrb, sym, &len);
mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len));
}
else if (sym == 0) {
return mrb_nil_value();
}
else {
name = mrb_sym2name_len(mrb, sym, &len);
path = mrb_str_new(mrb, name, len);
......
......@@ -8,6 +8,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include "error.h"
#include "mruby/variable.h"
#include "mruby/string.h"
......
......@@ -32,43 +32,6 @@ struct obj_ivar_tag {
void * arg;
};
static mrb_value
inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur)
{
if (recur) {
mrb_str_cat2(mrb, str, " ...");
}
else {
khiter_t k;
kh_iv_t *h = RCLASS_IV_TBL(obj);
if (h) {
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)){
mrb_sym id = kh_key(h, k);
mrb_value value = kh_value(h, k);
/* need not to show internal data */
if (RSTRING_PTR(str)[0] == '-') { /* first element */
RSTRING_PTR(str)[0] = '#';
mrb_str_cat2(mrb, str, " ");
}
else {
mrb_str_cat2(mrb, str, ", ");
}
mrb_str_cat2(mrb, str, mrb_sym2name(mrb, id));
mrb_str_cat2(mrb, str, "=");
mrb_str_append(mrb, str, mrb_inspect(mrb, value));
}
}
}
}
mrb_str_cat2(mrb, str, ">");
RSTRING_PTR(str)[0] = '#';
return str;
}
int
mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
{
......@@ -96,16 +59,7 @@ mrb_value
mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
{
if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
long len = ROBJECT_NUMIV(obj);
if (len > 0) {
mrb_value str;
const char *c = mrb_obj_classname(mrb, obj);
str = mrb_sprintf(mrb, "-<%s:%p", c, (void*)&obj);
return inspect_obj(mrb, obj, str, 0);
}
return mrb_any_to_s(mrb, obj);
return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
}
else if (mrb_nil_p(obj)) {
return mrb_str_new(mrb, "nil", 3);
......@@ -347,13 +301,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
case MRB_TT_OBJECT:
case MRB_TT_CLASS:
case MRB_TT_MODULE:
if (ROBJECT(dest)->iv) {
kh_destroy(iv, ROBJECT(dest)->iv);
ROBJECT(dest)->iv = 0;
}
if (ROBJECT(obj)->iv) {
ROBJECT(dest)->iv = kh_copy(iv, mrb, ROBJECT(obj)->iv);
}
mrb_iv_copy(mrb, dest, obj);
break;
default:
......@@ -630,19 +578,12 @@ check_iv_name(mrb_state *mrb, mrb_sym id)
mrb_value
mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
{
khiter_t k;
kh_iv_t *h = RCLASS_IV_TBL(self);
mrb_sym mid;
mrb_get_args(mrb, "n", &mid);
check_iv_name(mrb, mid);
if (h) {
k = kh_get(iv, h, mid);
if (k != kh_end(h)) {
return mrb_true_value();
}
}
if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid))
return mrb_true_value();
return mrb_false_value();
}
......
......@@ -6,29 +6,374 @@
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/khash.h"
#include "mruby/variable.h"
#include "error.h"
#include "mruby/array.h"
#include "mruby/string.h"
#include "mruby/proc.h"
#ifndef MRB_USE_IV_SEGLIST
#include "mruby/khash.h"
#endif
#ifdef ENABLE_REGEXP
#include "re.h"
#endif
typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
#ifdef MRB_USE_IV_SEGLIST
#ifndef MRB_SEGMENT_SIZE
#define MRB_SEGMENT_SIZE 4
#endif
typedef struct segment
{
mrb_sym key[MRB_SEGMENT_SIZE];
mrb_value val[MRB_SEGMENT_SIZE];
struct segment *next;
} segment;
typedef struct iv_tbl {
segment *rootseg;
int size;
int last_len;
} iv_tbl;
static iv_tbl*
iv_new(mrb_state *mrb)
{
iv_tbl *t;
t = mrb_malloc(mrb, sizeof(iv_tbl));
if (t) {
t->size = 0;
t->rootseg = NULL;
t->last_len = 0;
}
return t;
}
static void
iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
{
segment *seg = t->rootseg;
segment *prev = NULL;
segment *matched_seg = NULL;
int matched_idx = 0;
int i;
while (seg) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
/* found room in last segment after last_len */
if (!seg->next && i >= t->last_len) {
seg->key[i] = sym;
seg->val[i] = val;
t->last_len = i+1;
t->size++;
return;
}
if (key == 0 && !matched_seg) {
matched_seg = seg;
matched_idx = i;
}
else if (key == sym) {
seg->val[i] = val;
return;
}
}
prev = seg;
seg = seg->next;
}
/* not found */
t->size++;
if (matched_seg) {
matched_seg->key[matched_idx] = sym;
matched_seg->val[matched_idx] = val;
return;
}
seg = mrb_malloc(mrb, sizeof(segment));
if (!seg) return;
seg->next = NULL;
seg->key[0] = sym;
seg->val[0] = val;
t->last_len = 1;
if (prev) {
prev->next = seg;
}
else {
t->rootseg = seg;
}
return;
}
static int
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
segment *seg;
int i;
seg = t->rootseg;
while (seg) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
if (!seg->next && i >= t->last_len) {
return 0;
}
if (key == sym) {
if (vp) *vp = seg->val[i];
return 1;
}
}
seg = seg->next;
}
return 0;
}
static int
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
segment *seg;
int i;
seg = t->rootseg;
while (seg) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
if (!seg->next && i >= t->last_len) {
return 0;
}
if (key == sym) {
t->size--;
seg->key[i] = 0;
if (vp) *vp = seg->val[i];
return 1;
}
}
seg = seg->next;
}
return 0;
}
static int
iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
{
segment *seg;
int i, n;
seg = t->rootseg;
while (seg) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
/* no value in last segment after last_len */
if (!seg->next && i >= t->last_len) {
return 0;
}
if (key != 0) {
n =(*func)(mrb, key, seg->val[i], p);
if (n > 0) return 0;
if (n < 0) {
t->size--;
seg->key[i] = 0;
}
}
}
seg = seg->next;
}
return 1;
}
static int
iv_size(mrb_state *mrb, iv_tbl *t)
{
segment *seg;
int size = 0;
if (!t) return 0;
if (t->size > 0) return t->size;
seg = t->rootseg;
while (seg) {
if (seg->next == NULL) {
size += t->last_len;
return size;
}
seg = seg->next;
size += MRB_SEGMENT_SIZE;
}
/* empty iv_tbl */
return 0;
}
static iv_tbl*
iv_copy(mrb_state *mrb, iv_tbl *t)
{
segment *seg;
iv_tbl *t2;
int i;
seg = t->rootseg;
t2 = iv_new(mrb);
while (seg != NULL) {
for (i=0; i<MRB_SEGMENT_SIZE; i++) {
mrb_sym key = seg->key[i];
mrb_value val = seg->val[i];
iv_put(mrb, t2, key, val);
if ((seg->next == NULL) && (i >= t->last_len)) {
return t2;
}
}
seg = seg->next;
}
return t2;
}
static void
iv_free(mrb_state *mrb, iv_tbl *t)
{
segment *seg;
seg = t->rootseg;
while (seg) {
segment *p = seg;
seg = seg->next;
mrb_free(mrb, p);
}
mrb_free(mrb, t);
}
#else
#include "mruby/khash.h"
#ifndef MRB_IV_INITIAL_SIZE
#define MRB_IV_INITIAL_SIZE 8
#endif
KHASH_DECLARE(iv, mrb_sym, mrb_value, 1)
KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal);
typedef struct iv_tbl {
khash_t(iv) h;
} iv_tbl;
static iv_tbl*
iv_new(mrb_state *mrb)
{
return (iv_tbl*)kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE);
}
static void
mark_tbl(mrb_state *mrb, struct kh_iv *h)
iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
{
khash_t(iv) *h = &t->h;
khiter_t k;
k = kh_put(iv, h, sym);
kh_value(h, k) = val;
}
static int
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
khash_t(iv) *h = &t->h;
khiter_t k;
if (!h) return;
for (k = kh_begin(h); k != kh_end(h); k++)
if (kh_exist(h, k))
mrb_gc_mark_value(mrb, kh_value(h, k));
k = kh_get(iv, h, sym);
if (k != kh_end(h)) {
if (vp) *vp = kh_value(h, k);
return 1;
}
return 0;
}
static int
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
khash_t(iv) *h = &t->h;
khiter_t k;
if (h) {
k = kh_get(iv, h, sym);
if (k != kh_end(h)) {
mrb_value val = kh_value(h, k);
kh_del(iv, h, k);
if (vp) *vp = val;
return 1;
}
}
return 0;
}
static int
iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
{
khash_t(iv) *h = &t->h;
khiter_t k;
int n;
if (h) {
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)){
n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
if (n > 0) return 0;
if (n < 0) {
kh_del(iv, h, k);
}
}
}
}
return 1;
}
static int
iv_size(mrb_state *mrb, iv_tbl *t)
{
khash_t(iv) *h = &t->h;
if (!h) return 0;
return kh_size(h);
}
static iv_tbl*
iv_copy(mrb_state *mrb, iv_tbl *t)
{
return (iv_tbl*)kh_copy(iv, mrb, &t->h);
}
static void
iv_free(mrb_state *mrb, iv_tbl *t)
{
kh_destroy(iv, &t->h);
}
#endif
#ifndef MRB_IV_INITIAL_SIZE
#define MRB_IV_INITIAL_SIZE 8
#endif
static int
iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_gc_mark_value(mrb, v);
return 0;
}
static void
mark_tbl(mrb_state *mrb, iv_tbl *t)
{
if (t) {
iv_foreach(mrb, t, iv_mark_i, 0);
}
}
void
......@@ -40,7 +385,8 @@ mrb_gc_mark_gv(mrb_state *mrb)
void
mrb_gc_free_gv(mrb_state *mrb)
{
kh_destroy(iv, mrb->globals);
if (mrb->globals)
iv_free(mrb, mrb->globals);
}
void
......@@ -52,16 +398,15 @@ mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj)
size_t
mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj)
{
struct kh_iv *h = obj->iv;
if (!h) return 0;
return kh_size(h);
return iv_size(mrb, obj->iv);
}
void
mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj)
{
kh_destroy(iv, obj->iv);
if (obj->iv) {
iv_free(mrb, obj->iv);
}
}
mrb_value
......@@ -75,26 +420,6 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v)
{
}
static mrb_value
ivget(mrb_state *mrb, struct kh_iv *h, mrb_sym sym)
{
khiter_t k;
k = kh_get(iv, h, sym);
if (k != kh_end(h))
return kh_value(h, k);
return mrb_nil_value();
}
mrb_value
mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
if (!obj->iv) {
return mrb_nil_value();
}
return ivget(mrb, obj->iv, sym);
}
static int
obj_iv_p(mrb_value obj)
{
......@@ -110,6 +435,16 @@ obj_iv_p(mrb_value obj)
}
}
mrb_value
mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
mrb_value v;
if (obj->iv && iv_get(mrb, obj->iv, sym, &v))
return v;
return mrb_nil_value();
}
mrb_value
mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
......@@ -119,54 +454,110 @@ mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
return mrb_nil_value();
}
static void
ivset(mrb_state *mrb, struct kh_iv *h, mrb_sym sym, mrb_value v)
void
mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
{
khiter_t k;
iv_tbl *t = obj->iv;
k = kh_put(iv, h, sym);
kh_value(h, k) = v;
if (!t) {
t = obj->iv = iv_new(mrb);
}
mrb_write_barrier(mrb, (struct RBasic*)obj);
iv_put(mrb, t, sym, v);
}
void
mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
{
khash_t(iv) *h;
if (!obj->iv) {
h = obj->iv = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE);
if (obj_iv_p(obj)) {
mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
}
else {
h = obj->iv;
mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable");
}
mrb_write_barrier(mrb, (struct RBasic*)obj);
ivset(mrb, h, sym, v);
}
int
mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
{
iv_tbl *t;
t = obj->iv;
if (t) {
return iv_get(mrb, t, sym, NULL);
}
return 0;
}
int
mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (!obj_iv_p(obj)) return 0;
return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
}
void
mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) /* mrb_ivar_set */
mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
{
if (obj_iv_p(obj)) {
mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
struct RObject *d = mrb_obj_ptr(dest);
struct RObject *s = mrb_obj_ptr(src);
if (d->iv) {
iv_free(mrb, d->iv);
d->iv = 0;
}
if (s->iv) {
d->iv = iv_copy(mrb, s->iv);
}
}
static int
inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value str = *(mrb_value*)p;
const char *s;
int len;
/* need not to show internal data */
if (RSTRING_PTR(str)[0] == '-') { /* first element */
RSTRING_PTR(str)[0] = '#';
mrb_str_cat2(mrb, str, " ");
}
else {
mrb_str_cat2(mrb, str, ", ");
}
s = mrb_sym2name_len(mrb, sym, &len);
mrb_str_cat(mrb, str, s, len);
mrb_str_cat(mrb, str, "=", 1);
mrb_str_append(mrb, str, mrb_inspect(mrb, v));
return 0;
}
mrb_value
mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
{
mrb_value val;
iv_tbl *t = obj->iv;
int len = iv_size(mrb, t);
if (len > 0) {
const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj);
iv_foreach(mrb, t, inspect_i, &str);
return str;
}
return mrb_any_to_s(mrb, mrb_obj_value(obj));
}
mrb_value
mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
{
if (obj_iv_p(obj)) {
khash_t(iv) *h = mrb_obj_ptr(obj)->iv;
khiter_t k;
if (h) {
k = kh_get(iv, h, sym);
if (k != kh_end(h)) {
val = kh_value(h, k);
kh_del(iv, h, k);
return val;
}
iv_tbl *t = mrb_obj_ptr(obj)->iv;
mrb_value val;
if (iv_del(mrb, t, sym, &val)) {
return val;
}
}
return mrb_undef_value();
......@@ -186,6 +577,21 @@ mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
mrb_iv_set(mrb, mrb->stack[0], sym, v);
}
static int
iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value ary;
const char* s;
int len;
ary = *(mrb_value*)p;
s = mrb_sym2name_len(mrb, sym, &len);
if (len > 1 && s[0] == '@') {
mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
}
return 0;
}
/* 15.3.1.3.23 */
/*
* call-seq:
......@@ -207,25 +613,10 @@ mrb_value
mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
{
mrb_value ary;
kh_iv_t *h;
khint_t i;
int len;
const char* p;
ary = mrb_ary_new(mrb);
if (obj_iv_p(self)) {
h = ROBJECT_IVPTR(self);
if (h) {
for (i=0;i<kh_end(h);i++) {
if (kh_exist(h, i)) {
p = mrb_sym2name_len(mrb, kh_key(h,i), &len);
if (len > 1 && *p == '@') {
if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF)
mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, len));
}
}
}
}
iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary);
}
return ary;
}
......@@ -238,11 +629,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
if (!c) c = mrb->ci->target_class;
while (c) {
if (c->iv) {
khash_t(iv) *h = c->iv;
khiter_t k = kh_get(iv, h, sym);
iv_tbl *t = c->iv;
mrb_value v;
if (k != kh_end(h))
return kh_value(h, k);
if (iv_get(mrb, t, sym, &v))
return v;
}
c = c->super;
}
......@@ -253,43 +644,34 @@ void
mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
struct RClass *c = mrb->ci->proc->target_class;
khash_t(iv) *h;
khiter_t k;
if (!c) c = mrb->ci->target_class;
while (c) {
if (c->iv) {
h = c->iv;
k = kh_get(iv, h, sym);
if (k != kh_end(h)) {
k = kh_put(iv, h, sym);
kh_value(h, k) = v;
iv_tbl *t = c->iv;
if (iv_get(mrb, t, sym, NULL)) {
iv_put(mrb, t, sym, v);
return;
}
}
c = c->super;
}
c = mrb->ci->target_class;
h = c->iv;
if (!h) {
c->iv = h = kh_init_size(iv, mrb, MRB_IV_INITIAL_SIZE);
if (!c->iv) {
c->iv = iv_new(mrb);
}
k = kh_put(iv, h, sym);
kh_value(h, k) = v;
iv_put(mrb, c->iv, sym, v);
}
int
mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
{
khiter_t k;
struct RClass *m = mrb_class_ptr(mod);
struct kh_iv *h = m->iv;
iv_tbl *t = m->iv;
if (!h) return 0;
k = kh_get(iv, h, sym);
if (k != kh_end(h))
return 1;
return 0;
if (!t) return 0;
return iv_get(mrb, t, sym, NULL);
}
static void
......@@ -309,19 +691,17 @@ static mrb_value
const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
{
struct RClass *c = base;
khash_t(iv) *h;
khiter_t k;
mrb_value v;
iv_tbl *t;
int retry = 0;
mrb_sym cm;
L_RETRY:
while (c) {
if (c->iv) {
h = c->iv;
k = kh_get(iv, h, sym);
if (k != kh_end(h)) {
return kh_value(h, k);
}
t = c->iv;
if (iv_get(mrb, t, sym, &v))
return v;
}
c = c->super;
}
......@@ -374,13 +754,13 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
struct RClass *c = mrb->ci->proc->target_class;
if (!c) c = mrb->ci->target_class;
mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
mrb_iv_set(mrb, mrb_obj_value(c), sym, v);
}
void
mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v)
{
mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern(mrb, name), v);
mrb_iv_set(mrb, mrb_obj_value(mod), mrb_intern(mrb, name), v);
}
void
......@@ -392,24 +772,38 @@ mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val)
mrb_value
mrb_gv_get(mrb_state *mrb, mrb_sym sym)
{
mrb_value v;
if (!mrb->globals) {
return mrb_nil_value();
}
return ivget(mrb, mrb->globals, sym);
if (iv_get(mrb, mrb->globals, sym, &v))
return v;
return mrb_nil_value();
}
void
mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
khash_t(iv) *h;
iv_tbl *t;
if (!mrb->globals) {
h = mrb->globals = kh_init(iv, mrb);
t = mrb->globals = iv_new(mrb);
}
else {
h = mrb->globals;
t = mrb->globals;
}
ivset(mrb, h, sym, v);
iv_put(mrb, t, sym, v);
}
static int
gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
mrb_value ary;
ary = *(mrb_value*)p;
mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
return 0;
}
/* 15.3.1.2.4 */
......@@ -425,73 +819,34 @@ mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
mrb_value
mrb_f_global_variables(mrb_state *mrb, mrb_value self)
{
char buf[3];
khint_t i;
struct kh_iv *h = mrb->globals;
iv_tbl *t = mrb->globals;
mrb_value ary = mrb_ary_new(mrb);
int i;
char buf[3];
if (h) {
for (i=0;i < kh_end(h);i++) {
if (kh_exist(h, i)) {
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(h,i)));
}
}
if (t) {
iv_foreach(mrb, t, gv_i, &ary);
}
buf[0] = '$';
buf[2] = 0;
for (i = 1; i <= 9; ++i) {
buf[1] = (char)(i + '0');
mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf)));
buf[1] = (char)(i + '0');
mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern2(mrb, buf, 2)));
}
return ary;
}
int
mrb_st_lookup(struct kh_iv *table, mrb_sym id, khiter_t *value)
{
khash_t(iv) *h;
khiter_t k;
if (table) {
h = (khash_t(iv)*)table;
k = kh_get(iv, h, id);
if (k != kh_end(h)) {
if (value != 0) *value = k;//kh_value(h, k);
return 1;/* TRUE */
}
return 0;/* FALSE */
}
else {
return 0;/* FALSE */
}
}
static int
kiv_lookup(khash_t(iv)* table, mrb_sym key, mrb_value *value)
{
khash_t(iv) *h=table;
khiter_t k;
k = kh_get(iv, h, key);
if (k != kh_end(h)) {
*value = kh_value(h, k);
return 1;
}
return 0;
}
static int
mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse)
{
mrb_value value;
struct RClass * tmp;
int mod_retry = 0;
tmp = klass;
retry:
while (tmp) {
if (tmp->iv && kiv_lookup(tmp->iv, id, &value)) {
return (int)1/*Qtrue*/;
if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) {
return 1;
}
if (!recurse && (klass != mrb->object_class)) break;
tmp = tmp->super;
......@@ -525,3 +880,38 @@ mrb_class_obj_get(mrb_state *mrb, const char *name)
return mrb_class_ptr(mrb_const_get(mrb, mod, sym));
}
struct csym_arg {
struct RClass *c;
mrb_sym sym;
};
static int
csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
struct csym_arg *a = (struct csym_arg*)p;
struct RClass *c = a->c;
if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
a->sym = sym;
return 1; /* stop iteration*/
}
return 0;
}
mrb_sym
mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
{
mrb_value name;
name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__"));
if (mrb_nil_p(name)) {
struct csym_arg arg;
arg.c = c;
arg.sym = 0;
iv_foreach(mrb, outer->iv, csym_i, &arg);
return arg.sym;
}
return SYM2ID(name);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment