diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-10-15 18:31:06 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-10-15 18:31:06 +0900 |
| commit | 9cebddf9fe83ae0acde6f64f291fa3c9fc22880f (patch) | |
| tree | 6f9ca4f2941c3da48a504c937719adca36e4cdfe /src | |
| parent | 8c276f95be2f4e9deed73f08125a23a6746cb517 (diff) | |
| parent | 21e07d61138a87891dc780efaa28e6c76a39378f (diff) | |
| download | mruby-9cebddf9fe83ae0acde6f64f291fa3c9fc22880f.tar.gz mruby-9cebddf9fe83ae0acde6f64f291fa3c9fc22880f.zip | |
Merge pull request #5084 from mruby/mruby3
Mruby3
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 83 | ||||
| -rw-r--r-- | src/backtrace.c | 8 | ||||
| -rw-r--r-- | src/class.c | 757 | ||||
| -rw-r--r-- | src/codedump.c | 344 | ||||
| -rw-r--r-- | src/debug.c | 2 | ||||
| -rw-r--r-- | src/dump.c | 454 | ||||
| -rw-r--r-- | src/enum.c | 2 | ||||
| -rw-r--r-- | src/error.c | 22 | ||||
| -rw-r--r-- | src/etc.c | 70 | ||||
| -rw-r--r-- | src/fmt_fp.c | 2 | ||||
| -rw-r--r-- | src/gc.c | 48 | ||||
| -rw-r--r-- | src/hash.c | 72 | ||||
| -rw-r--r-- | src/kernel.c | 211 | ||||
| -rw-r--r-- | src/load.c | 191 | ||||
| -rw-r--r-- | src/numeric.c | 646 | ||||
| -rw-r--r-- | src/object.c | 185 | ||||
| -rw-r--r-- | src/print.c | 4 | ||||
| -rw-r--r-- | src/proc.c | 64 | ||||
| -rw-r--r-- | src/range.c | 14 | ||||
| -rw-r--r-- | src/state.c | 37 | ||||
| -rw-r--r-- | src/string.c | 94 | ||||
| -rw-r--r-- | src/symbol.c | 158 | ||||
| -rw-r--r-- | src/value_array.h | 1 | ||||
| -rw-r--r-- | src/variable.c | 314 | ||||
| -rw-r--r-- | src/vm.c | 798 |
25 files changed, 2675 insertions, 1906 deletions
diff --git a/src/array.c b/src/array.c index c33641264..c4bc554ef 100644 --- a/src/array.c +++ b/src/array.c @@ -508,21 +508,23 @@ mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) static mrb_value mrb_ary_push_m(mrb_state *mrb, mrb_value self) { + mrb_int argc; mrb_value *argv; - mrb_int len, len2, alen; + mrb_int len, len2; struct RArray *a; - mrb_get_args(mrb, "*!", &argv, &alen); + argc = mrb_get_argc(mrb); + argv = mrb_get_argv(mrb); a = mrb_ary_ptr(self); ary_modify(mrb, a); len = ARY_LEN(a); - len2 = len + alen; + len2 = len + argc; if (ARY_CAPA(a) < len2) { ary_expand_capa(mrb, a, len2); } - array_copy(ARY_PTR(a)+len, argv, alen); + array_copy(ARY_PTR(a)+len, argv, argc); ARY_SET_LEN(a, len2); - while (alen--) { + while (argc--) { mrb_field_write_barrier_value(mrb, (struct RBasic*)a, *argv); argv++; } @@ -820,10 +822,10 @@ mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len) static mrb_int aget_index(mrb_state *mrb, mrb_value index) { - if (mrb_fixnum_p(index)) { - return mrb_fixnum(index); + if (mrb_integer_p(index)) { + return mrb_integer(index); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT else if (mrb_float_p(index)) { return (mrb_int)mrb_float(index); } @@ -883,8 +885,8 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) else { return mrb_nil_value(); } - case MRB_TT_FIXNUM: - return mrb_ary_ref(mrb, self, mrb_fixnum(index)); + case MRB_TT_INTEGER: + return mrb_ary_ref(mrb, self, mrb_integer(index)); default: return mrb_ary_ref(mrb, self, aget_index(mrb, index)); } @@ -1086,11 +1088,11 @@ mrb_ary_splat(mrb_state *mrb, mrb_value v) return mrb_obj_value(a); } - if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { + if (!mrb_respond_to(mrb, v, MRB_SYM(to_a))) { return mrb_ary_new_from_values(mrb, 1, &v); } - ary = mrb_funcall(mrb, v, "to_a", 0); + ary = mrb_funcall_id(mrb, v, MRB_SYM(to_a), 0); if (mrb_nil_p(ary)) { return mrb_ary_new_from_values(mrb, 1, &v); } @@ -1121,8 +1123,14 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self) else if (!ARY_EMBED_P(a)){ mrb_free(mrb, a->as.heap.ptr); } - ARY_SET_EMBED_LEN(a, 0); - + if (MRB_ARY_EMBED_LEN_MAX > 0) { + ARY_SET_EMBED_LEN(a, 0); + } + else { + a->as.heap.ptr = NULL; + a->as.heap.aux.capa = 0; + ARY_SET_LEN(a, 0); + } return self; } @@ -1302,31 +1310,42 @@ static const mrb_code each_iseq[] = { OP_RETURN, 0x0 /* OP_RETURN R3 */ }; +static const mrb_sym each_syms[] = { + MRB_SYM(each), + MRB_SYM(to_enum), + MRB_QSYM(aref), + MRB_SYM(call), + MRB_SYM(length), +}; + +static const mrb_irep each_irep = { + 3, /* nlocals */ + 7, /* nregs */ + 0, /* clen */ + MRB_ISEQ_NO_FREE | MRB_IREP_NO_FREE, /* flags */ + each_iseq, /* iseq */ + NULL, /* pool */ + each_syms, /* syms */ + NULL, /* reps */ + NULL, /* lv */ + NULL, /* debug_info */ + sizeof(each_iseq), /* ilen */ + 0, /* plen */ + sizeof(each_syms), /* slen */ + 1, /* rlen */ + 0, /* refcnt */ +}; + static void init_ary_each(mrb_state *mrb, struct RClass *ary) { struct RProc *p; mrb_method_t m; - mrb_irep *each_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep)); - static const mrb_irep mrb_irep_zero = { 0 }; - - *each_irep = mrb_irep_zero; - each_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*5); - each_irep->syms[0] = mrb_intern_lit(mrb, "each"); - each_irep->syms[1] = mrb_intern_lit(mrb, "to_enum"); - each_irep->syms[2] = mrb_intern_lit(mrb, "[]"); - each_irep->syms[3] = mrb_intern_lit(mrb, "call"); - each_irep->syms[4] = mrb_intern_lit(mrb, "length"); - each_irep->slen = 5; - each_irep->flags = MRB_ISEQ_NO_FREE; - each_irep->iseq = each_iseq; - each_irep->ilen = sizeof(each_iseq); - each_irep->nregs = 7; - each_irep->nlocals = 3; - p = mrb_proc_new(mrb, each_irep); + + p = mrb_proc_new(mrb, &each_irep); p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT; MRB_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, ary, mrb_intern_lit(mrb, "each"), m); + mrb_define_method_raw(mrb, ary, MRB_SYM(each), m); } void diff --git a/src/backtrace.c b/src/backtrace.c index 591f4ea4b..bcc188796 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -39,7 +39,7 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr for (i=ciidx; i >= 0; i--) { struct backtrace_location loc; mrb_callinfo *ci; - mrb_irep *irep; + const mrb_irep *irep; const mrb_code *pc; ci = &mrb->c->cibase[i]; @@ -114,7 +114,7 @@ mrb_print_backtrace(mrb_state *mrb) return; } - backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace")); + backtrace = mrb_obj_iv_get(mrb, mrb->exc, MRB_SYM(backtrace)); if (mrb_nil_p(backtrace)) return; if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace); print_backtrace(mrb, mrb->exc, backtrace); @@ -171,7 +171,7 @@ packed_backtrace(mrb_state *mrb) void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc) { - mrb_sym sym = mrb_intern_lit(mrb, "backtrace"); + mrb_sym sym = MRB_SYM(backtrace); mrb_value backtrace; int ai; @@ -221,7 +221,7 @@ mrb_exc_backtrace(mrb_state *mrb, mrb_value exc) mrb_sym attr_name; mrb_value backtrace; - attr_name = mrb_intern_lit(mrb, "backtrace"); + attr_name = MRB_SYM(backtrace); backtrace = mrb_iv_get(mrb, exc, attr_name); if (mrb_nil_p(backtrace) || mrb_array_p(backtrace)) { return backtrace; diff --git a/src/class.c b/src/class.c index fcbdadea8..bbf64e8ea 100644 --- a/src/class.c +++ b/src/class.c @@ -18,47 +18,266 @@ #include <mruby/istruct.h> #include <mruby/opcode.h> -KHASH_DEFINE(mt, mrb_sym, mrb_method_t, TRUE, kh_int_hash_func, kh_int_hash_equal) +union mt_ptr { + struct RProc *proc; + mrb_func_t func; +}; + +struct mt_elem { + union mt_ptr ptr; + size_t func_p:1; + mrb_sym key:sizeof(mrb_sym)*8-1; +}; + +/* method table structure */ +typedef struct mt_tbl { + size_t size; + size_t alloc; + struct mt_elem *table; +} mt_tbl; + +/* Creates the method table. */ +static mt_tbl* +mt_new(mrb_state *mrb) +{ + mt_tbl *t; + + t = (mt_tbl*)mrb_malloc(mrb, sizeof(mt_tbl)); + t->size = 0; + t->alloc = 0; + t->table = NULL; + + return t; +} + +static struct mt_elem *mt_put(mrb_state *mrb, mt_tbl *t, mrb_sym sym, size_t func_p, union mt_ptr ptr); + +static void +mt_rehash(mrb_state *mrb, mt_tbl *t) +{ + size_t old_alloc = t->alloc; + size_t new_alloc = old_alloc+1; + struct mt_elem *old_table = t->table; + + khash_power2(new_alloc); + if (old_alloc == new_alloc) return; + + t->alloc = new_alloc; + t->size = 0; + t->table = (struct mt_elem*)mrb_calloc(mrb, sizeof(struct mt_elem), new_alloc); + + for (size_t i = 0; i < old_alloc; i++) { + struct mt_elem *slot = &old_table[i]; + + /* key = 0 means empty or deleted */ + if (slot->key != 0) { + mt_put(mrb, t, slot->key, slot->func_p, slot->ptr); + } + } + mrb_free(mrb, old_table); +} + +#define slot_empty_p(slot) ((slot)->key == 0 && (slot)->func_p == 0) + +/* Set the value for the symbol in the method table. */ +static struct mt_elem* +mt_put(mrb_state *mrb, mt_tbl *t, mrb_sym sym, size_t func_p, union mt_ptr ptr) +{ + size_t hash, pos, start; + struct mt_elem *dslot = NULL; + + if (t->alloc == 0) { + mt_rehash(mrb, t); + } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct mt_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + slot->func_p = func_p; + slot->ptr = ptr; + return slot; + } + else if (slot->key == 0) { /* empty or deleted */ + if (slot->func_p == 0) { /* empty */ + t->size++; + slot->key = sym; + slot->func_p = func_p; + slot->ptr = ptr; + return slot; + } + else if (!dslot) { /* deleted */ + dslot = slot; + } + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + if (dslot) { + t->size++; + dslot->key = sym; + dslot->func_p = func_p; + dslot->ptr = ptr; + return dslot; + } + /* no room */ + mt_rehash(mrb, t); + start = pos = hash & (t->alloc-1); + } + } +} + +/* Get a value for a symbol from the method table. */ +static struct mt_elem* +mt_get(mrb_state *mrb, mt_tbl *t, mrb_sym sym) +{ + size_t hash, pos, start; + + if (t == NULL) return NULL; + if (t->alloc == 0) return NULL; + if (t->size == 0) return NULL; + + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct mt_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + return slot; + } + else if (slot_empty_p(slot)) { + return NULL; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + return NULL; + } + } +} + +/* Deletes the value for the symbol from the method table. */ +static mrb_bool +mt_del(mrb_state *mrb, mt_tbl *t, mrb_sym sym) +{ + size_t hash, pos, start; + + if (t == NULL) return FALSE; + if (t->alloc == 0) return FALSE; + if (t->size == 0) return FALSE; + + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct mt_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + t->size--; + slot->key = 0; + slot->func_p = 1; + return TRUE; + } + else if (slot_empty_p(slot)) { + return FALSE; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + return FALSE; + } + } +} + +/* Copy the method table. */ +static struct mt_tbl* +mt_copy(mrb_state *mrb, mt_tbl *t) +{ + mt_tbl *t2; + size_t i; + + if (t == NULL) return NULL; + if (t->alloc == 0) return NULL; + if (t->size == 0) return NULL; + + t2 = mt_new(mrb); + for (i=0; i<t->alloc; i++) { + struct mt_elem *slot = &t->table[i]; + + if (slot->key) { + mt_put(mrb, t2, slot->key, slot->func_p, slot->ptr); + } + } + return t2; +} + +/* Free memory of the method table. */ +static void +mt_free(mrb_state *mrb, mt_tbl *t) +{ + mrb_free(mrb, t->table); + mrb_free(mrb, t); +} + +MRB_API void +mrb_mt_foreach(mrb_state *mrb, struct RClass *c, mrb_mt_foreach_func *fn, void *p) +{ + mt_tbl *t = c->mt; + size_t i; + + if (t == NULL) return; + if (t->alloc == 0) return; + if (t->size == 0) return; + + for (i=0; i<t->alloc; i++) { + struct mt_elem *slot = &t->table[i]; + + if (slot->key) { + if (fn(mrb, slot->key, slot, p) != 0) + return; + } + } + return; +} void mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c) { - khiter_t k; - khash_t(mt) *h = c->mt; + mt_tbl *t = c->mt; + size_t i; - if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - mrb_method_t m = kh_value(h, k); + if (t == NULL) return; + if (t->alloc == 0) return; + if (t->size == 0) return; - if (MRB_METHOD_PROC_P(m)) { - struct RProc *p = MRB_METHOD_PROC(m); - mrb_gc_mark(mrb, (struct RBasic*)p); - } + for (i=0; i<t->alloc; i++) { + struct mt_elem *slot = &t->table[i]; + + if (slot->key && !slot->func_p) { /* Proc pointer */ + struct RProc *p = slot->ptr.proc; + mrb_gc_mark(mrb, (struct RBasic*)p); } } + return; } size_t mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c) { - khash_t(mt) *h = c->mt; + struct mt_tbl *h = c->mt; if (!h) return 0; - return kh_size(h); + return h->size; } void mrb_gc_free_mt(mrb_state *mrb, struct RClass *c) { - kh_destroy(mt, mrb, c->mt); + if (c->mt) mt_free(mrb, c->mt); } void mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id) { mrb_value name; - mrb_sym nsym = mrb_intern_lit(mrb, "__classname__"); + mrb_sym nsym = MRB_SYM(__classname__); if (mrb_obj_iv_defined(mrb, (struct RObject*)c, nsym)) return; if (outer == NULL || outer == mrb->object_class) { @@ -68,7 +287,7 @@ mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb name = mrb_class_path(mrb, outer); if (mrb_nil_p(name)) { /* unnamed outer class */ if (outer != mrb->object_class && outer != c) { - mrb_obj_iv_set_force(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"), + mrb_obj_iv_set_force(mrb, (struct RObject*)c, MRB_SYM(__outer__), mrb_obj_value(outer)); } return; @@ -107,7 +326,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) if (o->c->tt == MRB_TT_SCLASS) return; sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); sc->flags |= MRB_FL_CLASS_IS_INHERITED; - sc->mt = kh_init(mt, mrb); + sc->mt = mt_new(mrb); sc->iv = 0; if (o->tt == MRB_TT_CLASS) { c = (struct RClass*)o; @@ -132,7 +351,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) o->c = sc; mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc); mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o); - mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o)); + mrb_obj_iv_set(mrb, (struct RObject*)sc, MRB_SYM(__attached__), mrb_obj_value(o)); sc->flags |= o->flags & MRB_FL_OBJ_IS_FROZEN; } @@ -230,6 +449,15 @@ mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) } MRB_API struct RClass* +mrb_define_module_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name) +{ + struct RClass * c = define_module(mrb, name, outer); + + setup_class(mrb, outer, c, name); + return c; +} + +MRB_API struct RClass* mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) { mrb_sym id = mrb_intern_cstr(mrb, name); @@ -283,12 +511,10 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) } static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value); -#ifdef MRB_METHOD_CACHE -static void mc_clear_all(mrb_state *mrb); -static void mc_clear_by_id(mrb_state *mrb, struct RClass*, mrb_sym); +#ifndef MRB_NO_METHOD_CACHE +static void mc_clear(mrb_state *mrb); #else -#define mc_clear_all(mrb) -#define mc_clear_by_id(mrb,c,s) +#define mc_clear(mrb) #endif static void @@ -302,7 +528,7 @@ mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass) super->flags |= MRB_FL_CLASS_IS_INHERITED; s = mrb_obj_value(super); mrb_mc_clear_by_class(mrb, klass); - mid = mrb_intern_lit(mrb, "inherited"); + mid = MRB_SYM(inherited); if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) { mrb_value c = mrb_obj_value(klass); mrb_funcall_argv(mrb, s, mid, 1, &c); @@ -349,21 +575,29 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name) { - mrb_value sym = mrb_check_intern_cstr(mrb, name); - if (mrb_nil_p(sym)) { - return FALSE; - } - return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym)); + mrb_sym sym = mrb_intern_check_cstr(mrb, name); + if (!sym) return FALSE; + return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), sym); +} + +MRB_API mrb_bool +mrb_class_defined_id(mrb_state *mrb, mrb_sym name) +{ + return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), name); } MRB_API mrb_bool mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name) { - mrb_value sym = mrb_check_intern_cstr(mrb, name); - if (mrb_nil_p(sym)) { - return FALSE; - } - return mrb_const_defined_at(mrb, mrb_obj_value(outer), mrb_symbol(sym)); + mrb_sym sym = mrb_intern_check_cstr(mrb, name); + if (!sym) return FALSE; + return mrb_const_defined_at(mrb, mrb_obj_value(outer), sym); +} + +MRB_API mrb_bool +mrb_class_defined_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name) +{ + return mrb_const_defined_at(mrb, mrb_obj_value(outer), name); } MRB_API struct RClass* @@ -373,17 +607,28 @@ mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name) } MRB_API struct RClass* +mrb_class_get_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name) +{ + return class_from_sym(mrb, outer, name); +} + +MRB_API struct RClass* mrb_class_get(mrb_state *mrb, const char *name) { return mrb_class_get_under(mrb, mrb->object_class, name); } MRB_API struct RClass* -mrb_exc_get(mrb_state *mrb, const char *name) +mrb_class_get_id(mrb_state *mrb, mrb_sym name) +{ + return mrb_class_get_under_id(mrb, mrb->object_class, name); +} + +MRB_API struct RClass* +mrb_exc_get_id(mrb_state *mrb, mrb_sym name) { struct RClass *exc, *e; - mrb_value c = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), - mrb_intern_cstr(mrb, name)); + mrb_value c = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), name); if (!mrb_class_p(c)) { mrb_raise(mrb, mrb->eException_class, "exception corrupted"); @@ -405,11 +650,23 @@ mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name) } MRB_API struct RClass* +mrb_module_get_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name) +{ + return module_from_sym(mrb, outer, name); +} + +MRB_API struct RClass* mrb_module_get(mrb_state *mrb, const char *name) { return mrb_module_get_under(mrb, mrb->object_class, name); } +MRB_API struct RClass* +mrb_module_get_id(mrb_state *mrb, mrb_sym name) +{ + return mrb_module_get_under_id(mrb, mrb->object_class, name); +} + /*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. @@ -427,9 +684,8 @@ mrb_module_get(mrb_state *mrb, const char *name) * \a super, the function just returns the defined class. */ MRB_API struct RClass* -mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) +mrb_define_class_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name, struct RClass *super) { - mrb_sym id = mrb_intern_cstr(mrb, name); struct RClass * c; #if 0 @@ -437,34 +693,45 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s mrb_warn(mrb, "no super class for '%C::%n', Object assumed", outer, id); } #endif - c = define_class(mrb, id, super, outer); - setup_class(mrb, outer, c, id); + c = define_class(mrb, name, super, outer); + setup_class(mrb, outer, c, name); return c; } +MRB_API struct RClass* +mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) +{ + return mrb_define_class_under_id(mrb, outer, mrb_intern_cstr(mrb, name), super); +} + MRB_API void mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_t m) { - khash_t(mt) *h; - khiter_t k; + mt_tbl *h; + union mt_ptr ptr; + MRB_CLASS_ORIGIN(c); h = c->mt; - mrb_check_frozen(mrb, c); - if (!h) h = c->mt = kh_init(mt, mrb); - k = kh_put(mt, mrb, h, mid); - kh_value(h, k) = m; - if (MRB_METHOD_PROC_P(m) && !MRB_METHOD_UNDEF_P(m)) { + if (!h) h = c->mt = mt_new(mrb); + if (MRB_METHOD_PROC_P(m)) { struct RProc *p = MRB_METHOD_PROC(m); - p->flags |= MRB_PROC_SCOPE; - p->c = NULL; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p); - if (!MRB_PROC_ENV_P(p)) { - MRB_PROC_SET_TARGET_CLASS(p, c); + ptr.proc = p; + if (p) { + p->flags |= MRB_PROC_SCOPE; + p->c = NULL; + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p); + if (!MRB_PROC_ENV_P(p)) { + MRB_PROC_SET_TARGET_CLASS(p, c); + } } } - mc_clear_by_id(mrb, c, mid); + else { + ptr.func = MRB_METHOD_FUNC(m); + } + mt_put(mrb, h, mid, MRB_METHOD_FUNC_P(m), ptr); + mc_clear(mrb); } MRB_API void @@ -474,6 +741,9 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f int ai = mrb_gc_arena_save(mrb); MRB_METHOD_FROM_FUNC(m, func); +#ifndef MRB_USE_METHOD_T_STRUCT + mrb_assert(MRB_METHOD_FUNC(m) == func); +#endif if (aspec == MRB_ARGS_NONE()) { MRB_METHOD_NOARG_SET(m); } @@ -588,8 +858,8 @@ void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); z: String [const char*] NUL terminated string; z! gives NULL for nil a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil c: Class/Module [strcut RClass*] - f: Fixnum/Float [mrb_float] - i: Fixnum/Float [mrb_int] + f: Integer/Float [mrb_float] + i: Integer/Float [mrb_int] b: boolean [mrb_bool] n: String/Symbol [mrb_sym] d: data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil @@ -849,7 +1119,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case 'f': { mrb_float *p; @@ -867,7 +1137,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_int*); if (i < argc) { - *p = mrb_fixnum(mrb_to_int(mrb, argv[i++])); + *p = mrb_integer(mrb_to_int(mrb, argv[i++])); } } break; @@ -984,7 +1254,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) else { uint32_t kwnum = kwargs->num; uint32_t required = kwargs->required; - const char *const *kname = kwargs->table; + const mrb_sym *kname = kwargs->table; mrb_value *values = kwargs->values; uint32_t j; const uint32_t keyword_max = 40; @@ -994,16 +1264,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } for (j = required; j > 0; j --, kname ++, values ++) { - mrb_value k = mrb_symbol_value(mrb_intern_cstr(mrb, *kname)); + mrb_value k = mrb_symbol_value(*kname); if (!mrb_hash_key_p(mrb, ksrc, k)) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "missing keyword: %s", *kname); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "missing keyword: %n", *kname); } *values = mrb_hash_delete_key(mrb, ksrc, k); mrb_gc_protect(mrb, *values); } for (j = kwnum - required; j > 0; j --, kname ++, values ++) { - mrb_value k = mrb_symbol_value(mrb_intern_cstr(mrb, *kname)); + mrb_value k = mrb_symbol_value(*kname); if (mrb_hash_key_p(mrb, ksrc, k)) { *values = mrb_hash_delete_key(mrb, ksrc, k); mrb_gc_protect(mrb, *values); @@ -1057,7 +1327,7 @@ boot_defclass(mrb_state *mrb, struct RClass *super) else { c->super = mrb->object_class; } - c->mt = kh_init(mt, mrb); + c->mt = mt_new(mrb); return c; } @@ -1065,7 +1335,7 @@ static void boot_initmod(mrb_state *mrb, struct RClass *mod) { if (!mod->mt) { - mod->mt = kh_init(mt, mrb); + mod->mt = mt_new(mrb); } } @@ -1129,7 +1399,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru skip: m = m->super; } - mc_clear_all(mrb); + mc_clear(mrb); return 0; } @@ -1155,7 +1425,7 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) origin->super = c->super; c->super = origin; origin->mt = c->mt; - c->mt = kh_init(mt, mrb); + c->mt = mt_new(mrb); mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin); c->flags |= MRB_FL_CLASS_IS_PREPENDED; } @@ -1292,8 +1562,8 @@ mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v) case MRB_TT_CPTR: return mrb->object_class; case MRB_TT_SYMBOL: - case MRB_TT_FIXNUM: -#ifndef MRB_WITHOUT_FLOAT + case MRB_TT_INTEGER: +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: #endif return NULL; @@ -1324,28 +1594,42 @@ mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, } MRB_API void +mrb_define_singleton_method_id(mrb_state *mrb, struct RObject *o, mrb_sym name, mrb_func_t func, mrb_aspec aspec) +{ + prepare_singleton_class(mrb, (struct RBasic*)o); + mrb_define_method_id(mrb, o->c, name, func, aspec); +} + +MRB_API void mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec); } MRB_API void +mrb_define_class_method_id(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_func_t func, mrb_aspec aspec) +{ + mrb_define_singleton_method_id(mrb, (struct RObject*)c, name, func, aspec); +} + +MRB_API void +mrb_define_module_function_id(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_func_t func, mrb_aspec aspec) +{ + mrb_define_class_method_id(mrb, c, name, func, aspec); + mrb_define_method_id(mrb, c, name, func, aspec); +} + +MRB_API void mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { - mrb_define_class_method(mrb, c, name, func, aspec); - mrb_define_method(mrb, c, name, func, aspec); + mrb_define_module_function_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec); } -#ifdef MRB_METHOD_CACHE +#ifndef MRB_NO_METHOD_CACHE static void -mc_clear_all(mrb_state *mrb) +mc_clear(mrb_state *mrb) { - struct mrb_cache_entry *mc = mrb->cache; - int i; - - for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) { - mc[i].c = 0; - } + memset(mrb->cache, 0, MRB_METHOD_CACHE_SIZE*sizeof(mrb->cache[0])); } void @@ -1355,7 +1639,7 @@ mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c) int i; if (c->flags & MRB_FL_CLASS_IS_INHERITED) { - mc_clear_all(mrb); + mc_clear(mrb); c->flags &= ~MRB_FL_CLASS_IS_INHERITED; return; } @@ -1363,32 +1647,14 @@ mrb_mc_clear_by_class(mrb_state *mrb, struct RClass *c) if (mc[i].c == c) mc[i].c = 0; } } - -static void -mc_clear_by_id(mrb_state *mrb, struct RClass *c, mrb_sym mid) -{ - struct mrb_cache_entry *mc = mrb->cache; - int i; - - if (c->flags & MRB_FL_CLASS_IS_INHERITED) { - mc_clear_all(mrb); - c->flags &= ~MRB_FL_CLASS_IS_INHERITED; - return; - } - for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) { - if (mc[i].c == c || mc[i].mid == mid) - mc[i].c = 0; - } -} #endif MRB_API mrb_method_t mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) { - khiter_t k; mrb_method_t m; struct RClass *c = *cp; -#ifdef MRB_METHOD_CACHE +#ifndef MRB_NO_METHOD_CACHE struct RClass *oc = c; int h = kh_int_hash_func(mrb, ((intptr_t)oc) ^ mid) & (MRB_METHOD_CACHE_SIZE-1); struct mrb_cache_entry *mc = &mrb->cache[h]; @@ -1400,15 +1666,20 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) #endif while (c) { - khash_t(mt) *h = c->mt; + mt_tbl *h = c->mt; if (h) { - k = kh_get(mt, mrb, h, mid); - if (k != kh_end(h)) { - m = kh_value(h, k); - if (MRB_METHOD_UNDEF_P(m)) break; + struct mt_elem *e = mt_get(mrb, h, mid); + if (e) { + if (e->ptr.proc == 0) break; *cp = c; -#ifdef MRB_METHOD_CACHE + if (e->func_p) { + MRB_METHOD_FROM_FUNC(m, e->ptr.func); + } + else { + MRB_METHOD_FROM_PROC(m, e->ptr.proc); + } +#ifndef MRB_NO_METHOD_CACHE mc->c = oc; mc->c0 = c; mc->mid = mid; @@ -1578,7 +1849,7 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv) mrb_get_args(mrb, "*!&", &argv, &argc, &blk); obj = mrb_instance_alloc(mrb, cv); - init = mrb_intern_lit(mrb, "initialize"); + init = MRB_SYM(initialize); if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) { mrb_funcall_with_block(mrb, obj, init, argc, argv, blk); } @@ -1592,7 +1863,7 @@ mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *arg mrb_sym mid; obj = mrb_instance_alloc(mrb, mrb_obj_value(c)); - mid = mrb_intern_lit(mrb, "initialize"); + mid = MRB_SYM(initialize); if (!mrb_func_basic_p(mrb, obj, mid, mrb_bob_init)) { mrb_funcall_argv(mrb, obj, mid, argc, argv); } @@ -1624,7 +1895,7 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv) super = mrb_obj_value(mrb->object_class); } new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super))); - mid = mrb_intern_lit(mrb, "initialize"); + mid = MRB_SYM(initialize); if (mrb_func_basic_p(mrb, new_class, mid, mrb_class_initialize)) { mrb_class_initialize(mrb, new_class); } @@ -1722,7 +1993,7 @@ MRB_API mrb_value mrb_class_path(mrb_state *mrb, struct RClass *c) { mrb_value path; - mrb_sym nsym = mrb_intern_lit(mrb, "__classname__"); + mrb_sym nsym = MRB_SYM(__classname__); path = mrb_obj_iv_get(mrb, (struct RObject*)c, nsym); if (mrb_nil_p(path)) { @@ -1827,7 +2098,7 @@ mrb_module_new(mrb_state *mrb) * called with an explicit receiver, as <code>class</code> is also a * reserved word in Ruby. * - * 1.class #=> Fixnum + * 1.class #=> Integer * self.class #=> Object */ @@ -1877,6 +2148,12 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2)); } +MRB_API void +mrb_define_alias_id(mrb_state *mrb, struct RClass *klass, mrb_sym a, mrb_sym b) +{ + mrb_alias_method(mrb, klass, a, b); +} + /* * call-seq: * mod.to_s -> string @@ -1891,7 +2168,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) { if (mrb_sclass_p(klass)) { - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__")); + mrb_value v = mrb_iv_get(mrb, klass, MRB_SYM(__attached__)); mrb_value str = mrb_str_new_lit(mrb, "#<Class:"); if (class_ptr_p(v)) { @@ -1927,7 +2204,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) mrb_define_method_raw(mrb, c, a, m); } -void +MRB_API void mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a) { if (!mrb_obj_respond_to(mrb, c, a)) { @@ -1943,11 +2220,29 @@ mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) } MRB_API void +mrb_undef_class_method_id(mrb_state *mrb, struct RClass *c, mrb_sym name) +{ + mrb_undef_method_id(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name); +} + +MRB_API void mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name) { mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name); } +MRB_API void +mrb_remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid) +{ + mt_tbl *h; + + MRB_CLASS_ORIGIN(c); + h = c->mt; + + if (h && mt_del(mrb, h, mid)) return; + mrb_name_error(mrb, mid, "method '%n' not defined in %C", mid, c); +} + static mrb_value mrb_mod_undef(mrb_state *mrb, mrb_value mod) { @@ -2207,6 +2502,202 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) return mod; } +static struct RClass* +mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) +{ + struct RClass *klass = mrb_basic_ptr(obj)->c; + + if (klass->tt != MRB_TT_SCLASS) + return klass; + else { + /* copy singleton(unnamed) class */ + struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); + + switch (mrb_type(obj)) { + case MRB_TT_CLASS: + case MRB_TT_SCLASS: + break; + default: + clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); + break; + } + clone->super = klass->super; + if (klass->iv) { + mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); + mrb_obj_iv_set(mrb, (struct RObject*)clone, MRB_SYM(__attached__), obj); + } + if (klass->mt) { + clone->mt = mt_copy(mrb, klass->mt); + } + else { + clone->mt = mt_new(mrb); + } + clone->tt = MRB_TT_SCLASS; + return clone; + } +} + +static void +copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) +{ + struct RClass *dc = mrb_class_ptr(dst); + struct RClass *sc = mrb_class_ptr(src); + /* if the origin is not the same as the class, then the origin and + the current class need to be copied */ + if (sc->flags & MRB_FL_CLASS_IS_PREPENDED) { + struct RClass *c0 = sc->super; + struct RClass *c1 = dc; + + /* copy prepended iclasses */ + while (!(c0->flags & MRB_FL_CLASS_IS_ORIGIN)) { + c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); + c1 = c1->super; + c0 = c0->super; + } + c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); + c1->super->flags |= MRB_FL_CLASS_IS_ORIGIN; + } + if (sc->mt) { + dc->mt = mt_copy(mrb, sc->mt); + } + else { + dc->mt = mt_new(mrb); + } + dc->super = sc->super; + MRB_SET_INSTANCE_TT(dc, MRB_INSTANCE_TT(sc)); +} + +/* 15.3.1.3.16 */ +static mrb_value +mrb_obj_init_copy(mrb_state *mrb, mrb_value self) +{ + mrb_value orig = mrb_get_arg1(mrb); + + if (mrb_obj_equal(mrb, self, orig)) return self; + if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) { + mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object"); + } + return self; +} + +static void +init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) +{ + switch (mrb_type(obj)) { + case MRB_TT_ICLASS: + copy_class(mrb, dest, obj); + return; + case MRB_TT_CLASS: + case MRB_TT_MODULE: + copy_class(mrb, dest, obj); + mrb_iv_copy(mrb, dest, obj); + mrb_iv_remove(mrb, dest, MRB_SYM(__classname__)); + break; + case MRB_TT_OBJECT: + case MRB_TT_SCLASS: + case MRB_TT_HASH: + case MRB_TT_DATA: + case MRB_TT_EXCEPTION: + mrb_iv_copy(mrb, dest, obj); + break; + case MRB_TT_ISTRUCT: + mrb_istruct_copy(dest, obj); + break; + + default: + break; + } + if (!mrb_func_basic_p(mrb, dest, MRB_SYM(initialize_copy), mrb_obj_init_copy)) { + mrb_funcall_id(mrb, dest, MRB_SYM(initialize_copy), 1, obj); + } +} + +/* 15.3.1.3.8 */ +/* + * call-seq: + * obj.clone -> an_object + * + * Produces a shallow copy of <i>obj</i>---the instance variables of + * <i>obj</i> are copied, but not the objects they reference. Copies + * the frozen state of <i>obj</i>. See also the discussion + * under <code>Object#dup</code>. + * + * class Klass + * attr_accessor :str + * end + * s1 = Klass.new #=> #<Klass:0x401b3a38> + * s1.str = "Hello" #=> "Hello" + * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> + * s2.str[1,4] = "i" #=> "i" + * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" + * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">" + * + * This method may have class-specific behavior. If so, that + * behavior will be documented under the #+initialize_copy+ method of + * the class. + * + * Some Class(True False Nil Symbol Integer Float) Object cannot clone. + */ +MRB_API mrb_value +mrb_obj_clone(mrb_state *mrb, mrb_value self) +{ + struct RObject *p; + mrb_value clone; + + if (mrb_immediate_p(self)) { + return self; + } + if (mrb_sclass_p(self)) { + mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class"); + } + p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self)); + p->c = mrb_singleton_class_clone(mrb, self); + mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c); + clone = mrb_obj_value(p); + init_copy(mrb, clone, self); + p->flags |= mrb_obj_ptr(self)->flags & MRB_FL_OBJ_IS_FROZEN; + + return clone; +} + +/* 15.3.1.3.9 */ +/* + * call-seq: + * obj.dup -> an_object + * + * Produces a shallow copy of <i>obj</i>---the instance variables of + * <i>obj</i> are copied, but not the objects they reference. + * <code>dup</code> copies the frozen state of <i>obj</i>. See also + * the discussion under <code>Object#clone</code>. In general, + * <code>clone</code> and <code>dup</code> may have different semantics + * in descendant classes. While <code>clone</code> is used to duplicate + * an object, including its internal state, <code>dup</code> typically + * uses the class of the descendant object to create the new instance. + * + * This method may have class-specific behavior. If so, that + * behavior will be documented under the #+initialize_copy+ method of + * the class. + */ + +MRB_API mrb_value +mrb_obj_dup(mrb_state *mrb, mrb_value obj) +{ + struct RBasic *p; + mrb_value dup; + + if (mrb_immediate_p(obj)) { + return obj; + } + if (mrb_sclass_p(obj)) { + mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class"); + } + p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj)); + dup = mrb_obj_value(p); + init_copy(mrb, dup, obj); + + return dup; +} + /* implementation of __id__ */ mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self); /* implementation of instance_eval */ @@ -2229,29 +2720,27 @@ static const mrb_code new_iseq[] = { OP_RETURN, 0x0 /* OP_RETURN R0 */ }; +const mrb_sym new_syms[] = { MRB_SYM(allocate), MRB_SYM(initialize) }; +static const mrb_irep new_irep = { + 3, 6, 0, MRB_IREP_STATIC, + new_iseq, NULL, new_syms, NULL, NULL, NULL, + sizeof(new_iseq), 0, 2, 0, 0, +}; + static void init_class_new(mrb_state *mrb, struct RClass *cls) { struct RProc *p; mrb_method_t m; - mrb_irep *new_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep)); - static const mrb_irep mrb_irep_zero = { 0 }; - - *new_irep = mrb_irep_zero; - new_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*2); - new_irep->syms[0] = mrb_intern_lit(mrb, "allocate"); - new_irep->syms[1] = mrb_intern_lit(mrb, "initialize"); - new_irep->slen = 2; - new_irep->flags = MRB_ISEQ_NO_FREE; - new_irep->iseq = new_iseq; - new_irep->ilen = sizeof(new_iseq); - new_irep->nregs = 6; - new_irep->nlocals = 3; - p = mrb_proc_new(mrb, new_irep); + + p = mrb_proc_new(mrb, &new_irep); MRB_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, cls, mrb_intern_lit(mrb, "new"), m); + mrb_define_method_raw(mrb, cls, MRB_SYM(new), m); } +/* implementation of #send method */ +mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); + void mrb_init_class(mrb_state *mrb) { @@ -2273,16 +2762,16 @@ mrb_init_class(mrb_state *mrb) make_metaclass(mrb, cls); /* name basic classes */ - mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob)); - mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj)); - mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod)); - mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls)); + mrb_define_const_id(mrb, bob, MRB_SYM(BasicObject), mrb_obj_value(bob)); + mrb_define_const_id(mrb, obj, MRB_SYM(Object), mrb_obj_value(obj)); + mrb_define_const_id(mrb, obj, MRB_SYM(Module), mrb_obj_value(mod)); + mrb_define_const_id(mrb, obj, MRB_SYM(Class), mrb_obj_value(cls)); /* name each classes */ - mrb_class_name_class(mrb, NULL, bob, mrb_intern_lit(mrb, "BasicObject")); - mrb_class_name_class(mrb, NULL, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */ - mrb_class_name_class(mrb, NULL, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */ - mrb_class_name_class(mrb, NULL, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */ + mrb_class_name_class(mrb, NULL, bob, MRB_SYM(BasicObject)); + mrb_class_name_class(mrb, NULL, obj, MRB_SYM(Object)); /* 15.2.1 */ + mrb_class_name_class(mrb, NULL, mod, MRB_SYM(Module)); /* 15.2.2 */ + mrb_class_name_class(mrb, NULL, cls, MRB_SYM(Class)); /* 15.2.3 */ mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */ MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC); diff --git a/src/codedump.c b/src/codedump.c index 649be176b..3f0801929 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -4,26 +4,20 @@ #include <mruby/opcode.h> #include <mruby/string.h> #include <mruby/proc.h> +#include <mruby/dump.h> #ifndef MRB_DISABLE_STDIO static void -print_r(mrb_state *mrb, mrb_irep *irep, size_t n) +print_r(mrb_state *mrb, const mrb_irep *irep, size_t n) { - size_t i; - if (n == 0) return; - - for (i=0; i+1<irep->nlocals; i++) { - if (irep->lv[i].r == n) { - mrb_sym sym = irep->lv[i].name; - printf(" R%d:%s", (int)n, mrb_sym_dump(mrb, sym)); - break; - } - } + if (n > irep->nlocals) return; + if (!irep->lv[n-1]) return; + printf(" R%d:%s", (int)n, mrb_sym_dump(mrb, irep->lv[n-1])); } static void -print_lv_a(mrb_state *mrb, mrb_irep *irep, uint16_t a) +print_lv_a(mrb_state *mrb, const mrb_irep *irep, uint16_t a) { if (!irep->lv || a >= irep->nlocals || a == 0) { printf("\n"); @@ -35,7 +29,7 @@ print_lv_a(mrb_state *mrb, mrb_irep *irep, uint16_t a) } static void -print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b) +print_lv_ab(mrb_state *mrb, const mrb_irep *irep, uint16_t a, uint16_t b) { if (!irep->lv || (a >= irep->nlocals && b >= irep->nlocals) || a+b == 0) { printf("\n"); @@ -48,7 +42,7 @@ print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b) } static void -print_header(mrb_state *mrb, mrb_irep *irep, ptrdiff_t i) +print_header(mrb_state *mrb, const mrb_irep *irep, ptrdiff_t i) { int32_t line; @@ -63,10 +57,10 @@ print_header(mrb_state *mrb, mrb_irep *irep, ptrdiff_t i) printf("%03d ", (int)i); } -#define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn +#define CASE(insn,ops) case insn: FETCH_ ## ops (); static void -codedump(mrb_state *mrb, mrb_irep *irep) +codedump(mrb_state *mrb, const mrb_irep *irep) { int ai; const mrb_code *pc, *pcend; @@ -82,9 +76,36 @@ codedump(mrb_state *mrb, mrb_irep *irep) printf("local variable names:\n"); for (i = 1; i < irep->nlocals; ++i) { - char const *s = mrb_sym_dump(mrb, irep->lv[i - 1].name); - int n = irep->lv[i - 1].r ? irep->lv[i - 1].r : i; - printf(" R%d:%s\n", n, s ? s : ""); + char const *s = mrb_sym_dump(mrb, irep->lv[i - 1]); + printf(" R%d:%s\n", i, s ? s : ""); + } + } + + if (irep->clen > 0) { + int i = irep->clen; + const struct mrb_irep_catch_handler *e = mrb_irep_catch_handler_table(irep); + + for (; i > 0; i --, e ++) { + int begin = bin_to_uint16(e->begin); + int end = bin_to_uint16(e->end); + int target = bin_to_uint16(e->target); + char buf[20]; + const char *type; + + switch (e->type) { + case MRB_CATCH_RESCUE: + type = "rescue"; + break; + case MRB_CATCH_ENSURE: + type = "ensure"; + break; + default: + buf[0] = '\0'; + snprintf(buf, sizeof(buf), "0x%02x <unknown>", (int)e->type); + type = buf; + break; + } + printf("catch type: %-8s begin: %04d end: %04d target: %04d\n", type, begin, end, target); } } @@ -107,159 +128,173 @@ codedump(mrb_state *mrb, mrb_irep *irep) print_header(mrb, irep, i); ins = READ_B(); switch (ins) { - CASE(OP_NOP, Z): + CASE(OP_NOP, Z); printf("OP_NOP\n"); break; - CASE(OP_MOVE, BB): + CASE(OP_MOVE, BB); printf("OP_MOVE\tR%d\tR%d\t", a, b); print_lv_ab(mrb, irep, a, b); break; - CASE(OP_LOADL, BB): - { - mrb_value v = irep->pool[b]; - mrb_value s = mrb_inspect(mrb, v); - printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s)); + CASE(OP_LOADL, BB); + switch (irep->pool[b].tt) { + case IREP_TT_FLOAT: + printf("OP_LOADL\tR%d\tL(%d)\t; %f", a, b, (double)irep->pool[b].u.f); + break; + case IREP_TT_INT32: + printf("OP_LOADL\tR%d\tL(%d)\t; %" PRId32, a, b, irep->pool[b].u.i32); + break; +#ifdef MRB_64BIT + case IREP_TT_INT64: + printf("OP_LOADL\tR%d\tL(%d)\t; %" PRId64, a, b, irep->pool[b].u.i64); + break; +#endif + default: + printf("OP_LOADL\tR%d\tL(%d)\t", a, b); + break; } print_lv_a(mrb, irep, a); break; - CASE(OP_LOADI, BB): + CASE(OP_LOADI, BB); printf("OP_LOADI\tR%d\t%d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADINEG, BB): + CASE(OP_LOADINEG, BB); printf("OP_LOADI\tR%d\t-%d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADI16, BS): + CASE(OP_LOADI16, BS); printf("OP_LOADI16\tR%d\t%d\t", a, (int)(int16_t)b); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADI__1, B): + CASE(OP_LOADI__1, B); printf("OP_LOADI__1\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADI_0, B): goto L_LOADI; - CASE(OP_LOADI_1, B): goto L_LOADI; - CASE(OP_LOADI_2, B): goto L_LOADI; - CASE(OP_LOADI_3, B): goto L_LOADI; - CASE(OP_LOADI_4, B): goto L_LOADI; - CASE(OP_LOADI_5, B): goto L_LOADI; - CASE(OP_LOADI_6, B): goto L_LOADI; - CASE(OP_LOADI_7, B): + CASE(OP_LOADI_0, B); goto L_LOADI; + CASE(OP_LOADI_1, B); goto L_LOADI; + CASE(OP_LOADI_2, B); goto L_LOADI; + CASE(OP_LOADI_3, B); goto L_LOADI; + CASE(OP_LOADI_4, B); goto L_LOADI; + CASE(OP_LOADI_5, B); goto L_LOADI; + CASE(OP_LOADI_6, B); goto L_LOADI; + CASE(OP_LOADI_7, B); L_LOADI: printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADSYM, BB): + CASE(OP_LOADSYM, BB); printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADNIL, B): + CASE(OP_LOADNIL, B); printf("OP_LOADNIL\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADSELF, B): + CASE(OP_LOADSELF, B); printf("OP_LOADSELF\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADT, B): + CASE(OP_LOADT, B); printf("OP_LOADT\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_LOADF, B): + CASE(OP_LOADF, B); printf("OP_LOADF\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_GETGV, BB): + CASE(OP_GETGV, BB); printf("OP_GETGV\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_SETGV, BB): - printf("OP_SETGV\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a); + CASE(OP_SETGV, BB); + printf("OP_SETGV\t;%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a); print_lv_a(mrb, irep, a); break; - CASE(OP_GETSV, BB): + CASE(OP_GETSV, BB); printf("OP_GETSV\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_SETSV, BB): + CASE(OP_SETSV, BB); printf("OP_SETSV\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a); print_lv_a(mrb, irep, a); break; - CASE(OP_GETCONST, BB): + CASE(OP_GETCONST, BB); printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_SETCONST, BB): + CASE(OP_SETCONST, BB); printf("OP_SETCONST\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a); print_lv_a(mrb, irep, a); break; - CASE(OP_GETMCNST, BB): + CASE(OP_GETMCNST, BB); printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_SETMCNST, BB): + CASE(OP_SETMCNST, BB); printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym_dump(mrb, irep->syms[b]), a); print_lv_a(mrb, irep, a); break; - CASE(OP_GETIV, BB): + CASE(OP_GETIV, BB); printf("OP_GETIV\tR%d\t%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_SETIV, BB): + CASE(OP_SETIV, BB); printf("OP_SETIV\t%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a); print_lv_a(mrb, irep, a); break; - CASE(OP_GETUPVAR, BBB): + CASE(OP_GETUPVAR, BBB); printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c); print_lv_a(mrb, irep, a); break; - CASE(OP_SETUPVAR, BBB): + CASE(OP_SETUPVAR, BBB); printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c); print_lv_a(mrb, irep, a); break; - CASE(OP_GETCV, BB): + CASE(OP_GETCV, BB); printf("OP_GETCV\tR%d\t%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_SETCV, BB): + CASE(OP_SETCV, BB); printf("OP_SETCV\t%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a); print_lv_a(mrb, irep, a); break; - CASE(OP_JMP, S): + CASE(OP_JMP, S); printf("OP_JMP\t\t%03d\n", a); break; - CASE(OP_JMPIF, BS): + CASE(OP_JMPUW, S); + printf("OP_JMPUW\t\t%03d\n", a); + break; + CASE(OP_JMPIF, BS); printf("OP_JMPIF\tR%d\t%03d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_JMPNOT, BS): + CASE(OP_JMPNOT, BS); printf("OP_JMPNOT\tR%d\t%03d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_JMPNIL, BS): + CASE(OP_JMPNIL, BS); printf("OP_JMPNIL\tR%d\t%03d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_SENDV, BB): + CASE(OP_SENDV, BB); printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b])); break; - CASE(OP_SENDVB, BB): + CASE(OP_SENDVB, BB); printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b])); break; - CASE(OP_SEND, BBB): + CASE(OP_SEND, BBB); printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym_dump(mrb, irep->syms[b]), c); break; - CASE(OP_SENDB, BBB): + CASE(OP_SENDB, BBB); printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym_dump(mrb, irep->syms[b]), c); break; - CASE(OP_CALL, Z): + CASE(OP_CALL, Z); printf("OP_CALL\n"); break; - CASE(OP_SUPER, BB): + CASE(OP_SUPER, BB); printf("OP_SUPER\tR%d\t%d\n", a, b); break; - CASE(OP_ARGARY, BS): + CASE(OP_ARGARY, BS); printf("OP_ARGARY\tR%d\t%d:%d:%d:%d (%d)", a, (b>>11)&0x3f, (b>>10)&0x1, @@ -268,7 +303,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) (b>>0)&0xf); print_lv_a(mrb, irep, a); break; - CASE(OP_ENTER, W): + CASE(OP_ENTER, W); printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n", MRB_ASPEC_REQ(a), MRB_ASPEC_OPT(a), @@ -278,30 +313,30 @@ codedump(mrb_state *mrb, mrb_irep *irep) MRB_ASPEC_KDICT(a), MRB_ASPEC_BLOCK(a)); break; - CASE(OP_KEY_P, BB): + CASE(OP_KEY_P, BB); printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_KEYEND, Z): + CASE(OP_KEYEND, Z); printf("OP_KEYEND\n"); break; - CASE(OP_KARG, BB): + CASE(OP_KARG, BB); printf("OP_KARG\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_RETURN, B): + CASE(OP_RETURN, B); printf("OP_RETURN\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_RETURN_BLK, B): + CASE(OP_RETURN_BLK, B); printf("OP_RETURN_BLK\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_BREAK, B): + CASE(OP_BREAK, B); printf("OP_BREAK\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_BLKPUSH, BS): + CASE(OP_BLKPUSH, BS); printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d (%d)", a, (b>>11)&0x3f, (b>>10)&0x1, @@ -310,219 +345,178 @@ codedump(mrb_state *mrb, mrb_irep *irep) (b>>0)&0xf); print_lv_a(mrb, irep, a); break; - CASE(OP_LAMBDA, BB): + CASE(OP_LAMBDA, BB); printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); break; - CASE(OP_BLOCK, BB): + CASE(OP_BLOCK, BB); printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); break; - CASE(OP_METHOD, BB): + CASE(OP_METHOD, BB); printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); break; - CASE(OP_RANGE_INC, B): + CASE(OP_RANGE_INC, B); printf("OP_RANGE_INC\tR%d\n", a); break; - CASE(OP_RANGE_EXC, B): + CASE(OP_RANGE_EXC, B); printf("OP_RANGE_EXC\tR%d\n", a); break; - CASE(OP_DEF, BB): + CASE(OP_DEF, BB); printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b])); break; - CASE(OP_UNDEF, B): + CASE(OP_UNDEF, B); printf("OP_UNDEF\t:%s\n", mrb_sym_dump(mrb, irep->syms[a])); break; - CASE(OP_ALIAS, BB): + CASE(OP_ALIAS, BB); printf("OP_ALIAS\t:%s\t%s\n", mrb_sym_dump(mrb, irep->syms[a]), mrb_sym_dump(mrb, irep->syms[b])); break; - CASE(OP_ADD, B): + CASE(OP_ADD, B); printf("OP_ADD\tR%d\t\n", a); break; - CASE(OP_ADDI, BB): + CASE(OP_ADDI, BB); printf("OP_ADDI\tR%d\t%d\n", a, b); break; - CASE(OP_SUB, B): + CASE(OP_SUB, B); printf("OP_SUB\tR%d\t\n", a); break; - CASE(OP_SUBI, BB): + CASE(OP_SUBI, BB); printf("OP_SUBI\tR%d\t%d\n", a, b); break; - CASE(OP_MUL, B): + CASE(OP_MUL, B); printf("OP_MUL\tR%d\t\n", a); break; - CASE(OP_DIV, B): + CASE(OP_DIV, B); printf("OP_DIV\tR%d\t\n", a); break; - CASE(OP_LT, B): + CASE(OP_LT, B); printf("OP_LT\t\tR%d\t\n", a); break; - CASE(OP_LE, B): + CASE(OP_LE, B); printf("OP_LE\t\tR%d\t\n", a); break; - CASE(OP_GT, B): + CASE(OP_GT, B); printf("OP_GT\t\tR%d\t\n", a); break; - CASE(OP_GE, B): + CASE(OP_GE, B); printf("OP_GE\t\tR%d\t\n", a); break; - CASE(OP_EQ, B): + CASE(OP_EQ, B); printf("OP_EQ\t\tR%d\t\n", a); break; - CASE(OP_ARRAY, BB): + CASE(OP_ARRAY, BB); printf("OP_ARRAY\tR%d\t%d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_ARRAY2, BBB): + CASE(OP_ARRAY2, BBB); printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c); print_lv_ab(mrb, irep, a, b); break; - CASE(OP_ARYCAT, B): + CASE(OP_ARYCAT, B); printf("OP_ARYCAT\tR%d\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_ARYPUSH, B): + CASE(OP_ARYPUSH, B); printf("OP_ARYPUSH\tR%d\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_ARYDUP, B): + CASE(OP_ARYDUP, B); printf("OP_ARYDUP\tR%d\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_AREF, BBB): + CASE(OP_AREF, BBB); printf("OP_AREF\tR%d\tR%d\t%d", a, b, c); print_lv_ab(mrb, irep, a, b); break; - CASE(OP_ASET, BBB): + CASE(OP_ASET, BBB); printf("OP_ASET\tR%d\tR%d\t%d", a, b, c); print_lv_ab(mrb, irep, a, b); break; - CASE(OP_APOST, BBB): + CASE(OP_APOST, BBB); printf("OP_APOST\tR%d\t%d\t%d", a, b, c); print_lv_a(mrb, irep, a); break; - CASE(OP_INTERN, B): + CASE(OP_INTERN, B); printf("OP_INTERN\tR%d", a); print_lv_a(mrb, irep, a); break; - CASE(OP_STRING, BB): - { - mrb_value v = irep->pool[b]; - mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); - printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s)); + CASE(OP_STRING, BB); + if ((irep->pool[b].tt & IREP_TT_NFLAG) == 0) { + printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, irep->pool[b].u.str); + } + else { + printf("OP_STRING\tR%d\tL(%d)\t", a, b); } print_lv_a(mrb, irep, a); break; - CASE(OP_STRCAT, B): + CASE(OP_STRCAT, B); printf("OP_STRCAT\tR%d\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_HASH, BB): + CASE(OP_HASH, BB); printf("OP_HASH\tR%d\t%d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_HASHADD, BB): + CASE(OP_HASHADD, BB); printf("OP_HASHADD\tR%d\t%d\t", a, b); print_lv_a(mrb, irep, a); break; - CASE(OP_HASHCAT, B): + CASE(OP_HASHCAT, B); printf("OP_HASHCAT\tR%d\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_OCLASS, B): + CASE(OP_OCLASS, B); printf("OP_OCLASS\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_CLASS, BB): + CASE(OP_CLASS, BB); printf("OP_CLASS\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_MODULE, BB): + CASE(OP_MODULE, BB); printf("OP_MODULE\tR%d\t:%s", a, mrb_sym_dump(mrb, irep->syms[b])); print_lv_a(mrb, irep, a); break; - CASE(OP_EXEC, BB): + CASE(OP_EXEC, BB); printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]); print_lv_a(mrb, irep, a); break; - CASE(OP_SCLASS, B): + CASE(OP_SCLASS, B); printf("OP_SCLASS\tR%d\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_TCLASS, B): + CASE(OP_TCLASS, B); printf("OP_TCLASS\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_ERR, B): - { - mrb_value v = irep->pool[a]; - mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); - printf("OP_ERR\t%s\n", RSTRING_PTR(s)); + CASE(OP_ERR, B); + if ((irep->pool[a].tt & IREP_TT_NFLAG) == 0) { + printf("OP_ERR\t%s\n", irep->pool[a].u.str); + } + else { + printf("OP_ERR\tL(%d)\n", a); } break; - CASE(OP_EPUSH, B): - printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]); - break; - CASE(OP_ONERR, S): - printf("OP_ONERR\t%03d\n", a); - break; - CASE(OP_EXCEPT, B): + CASE(OP_EXCEPT, B); printf("OP_EXCEPT\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_RESCUE, BB): + CASE(OP_RESCUE, BB); printf("OP_RESCUE\tR%d\tR%d", a, b); print_lv_ab(mrb, irep, a, b); break; - CASE(OP_RAISE, B): - printf("OP_RAISE\tR%d\t\t", a); + CASE(OP_RAISEIF, B); + printf("OP_RAISEIF\tR%d\t\t", a); print_lv_a(mrb, irep, a); break; - CASE(OP_POPERR, B): - printf("OP_POPERR\t%d\t\t\n", a); - break; - CASE(OP_EPOP, B): - printf("OP_EPOP\t%d\n", a); - break; - CASE(OP_DEBUG, BBB): + CASE(OP_DEBUG, BBB); printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c); break; - CASE(OP_STOP, Z): + CASE(OP_STOP, Z); printf("OP_STOP\n"); break; - CASE(OP_EXT1, Z): - ins = READ_B(); - printf("OP_EXT1\n"); - print_header(mrb, irep, pc-irep->iseq-2); - switch (ins) { -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i; -#include "mruby/ops.h" -#undef OPCODE - } - break; - CASE(OP_EXT2, Z): - ins = READ_B(); - printf("OP_EXT2\n"); - print_header(mrb, irep, pc-irep->iseq-2); - switch (ins) { -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i; -#include "mruby/ops.h" -#undef OPCODE - } - break; - CASE(OP_EXT3, Z): - ins = READ_B(); - printf("OP_EXT3\n"); - print_header(mrb, irep, pc-irep->iseq-2); - switch (ins) { -#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i; -#include "mruby/ops.h" -#undef OPCODE - } - break; - default: printf("OP_unknown (0x%x)\n", ins); break; @@ -533,7 +527,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) } static void -codedump_recur(mrb_state *mrb, mrb_irep *irep) +codedump_recur(mrb_state *mrb, const mrb_irep *irep) { int i; diff --git a/src/debug.c b/src/debug.c index 32add68ae..dabc5a56d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -51,7 +51,7 @@ select_line_type(const uint16_t *lines, size_t lines_len) } MRB_API char const* -mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc) +mrb_debug_get_filename(mrb_state *mrb, const mrb_irep *irep, ptrdiff_t pc) { if (irep && pc >= 0 && pc < irep->ilen) { mrb_irep_debug_info_file* f = NULL; diff --git a/src/dump.c b/src/dump.c index a6bbe68f3..2bc1b0a53 100644 --- a/src/dump.c +++ b/src/dump.c @@ -13,32 +13,18 @@ #include <mruby/numeric.h> #include <mruby/debug.h> -#ifndef MRB_WITHOUT_FLOAT -#ifdef MRB_USE_FLOAT -#define MRB_FLOAT_FMT "%.9g" -#else +#ifndef MRB_NO_FLOAT +#include <mruby/endian.h> #define MRB_FLOAT_FMT "%.17g" #endif -#endif -static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); +static size_t get_irep_record_size_1(mrb_state *mrb, const mrb_irep *irep); #if UINT32_MAX > SIZE_MAX # error This code cannot be built on your environment. #endif static size_t -write_padding(uint8_t *buf) -{ - const size_t align = MRB_DUMP_ALIGNMENT; - size_t pad_len = -(intptr_t)buf & (align-1); - if (pad_len > 0) { - memset(buf, 0, pad_len); - } - return pad_len; -} - -static size_t get_irep_header_size(mrb_state *mrb) { size_t size = 0; @@ -50,7 +36,7 @@ get_irep_header_size(mrb_state *mrb) } static ptrdiff_t -write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_irep_header(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; @@ -64,87 +50,97 @@ write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) static size_t -get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) +get_iseq_block_size(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; - size += sizeof(uint32_t); /* ilen */ - size += sizeof(uint32_t); /* max padding */ - size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ + size += sizeof(uint16_t); /* ilen */ + size += irep->ilen * sizeof(mrb_code); /* iseq(n) */ return size; } static ptrdiff_t -write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags) +write_iseq_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf, uint8_t flags) { uint8_t *cur = buf; - cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */ - cur += write_padding(cur); + cur += uint16_to_bin(irep->ilen, cur); /* number of opcode */ memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code)); cur += irep->ilen * sizeof(mrb_code); return cur - buf; } -#ifndef MRB_WITHOUT_FLOAT -static mrb_value -float_to_str(mrb_state *mrb, mrb_value flt) +#ifndef MRB_NO_FLOAT +static void +dump_float(mrb_state *mrb, uint8_t *buf, mrb_float f) { - mrb_float f = mrb_float(flt); + /* dump IEEE754 binary in little endian */ + union { + double f; + char s[sizeof(double)]; + } u = {.f = (double)f}; + + if (littleendian) { + memcpy(buf, u.s, sizeof(double)); + } + else { + size_t i; - if (isinf(f)) { - return f < 0 ? mrb_str_new_lit(mrb, "I") : mrb_str_new_lit(mrb, "i"); + for (i=0; i<sizeof(double); i++) { + buf[i] = u.s[sizeof(double)-i-1]; + } } - return mrb_float_to_str(mrb, flt, MRB_FLOAT_FMT); } #endif static size_t -get_pool_block_size(mrb_state *mrb, mrb_irep *irep) +get_pool_block_size(mrb_state *mrb, const mrb_irep *irep) { int pool_no; size_t size = 0; - mrb_value str; - size += sizeof(uint32_t); /* plen */ - size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */ + size += sizeof(uint16_t); /* plen */ + size += irep->plen * sizeof(uint8_t); /* len(n) */ for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - switch (mrb_type(irep->pool[pool_no])) { - case MRB_TT_FIXNUM: - str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); + switch (irep->pool[pool_no].tt) { + case IREP_TT_INT64: +#ifdef MRB_64BIT { - mrb_int len = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; + int64_t i = irep->pool[pool_no].u.i64; + + if (i < INT32_MIN || INT32_MAX < i) + size += 8; + else + size += 4; } break; +#else + /* fall through */ +#endif + case IREP_TT_INT32: + size += 4; /* 32bits = 4bytes */ + break; -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: - str = float_to_str(mrb, irep->pool[pool_no]); + case IREP_TT_FLOAT: +#ifndef MRB_NO_FLOAT { - mrb_int len = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; + size += sizeof(double); } - break; #endif + break; - case MRB_TT_STRING: + default: /* packed IREP_TT_STRING */ { - mrb_int len = RSTRING_LEN(irep->pool[pool_no]); + mrb_int len = irep->pool[pool_no].tt >> 1; /* unpack length */ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; + size += (size_t)len+1; } break; - - default: - break; } mrb_gc_arena_restore(mrb, ai); } @@ -153,52 +149,63 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) } static ptrdiff_t -write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) { int pool_no; uint8_t *cur = buf; - uint16_t len; - mrb_value str; - const char *char_ptr; + mrb_int len; + const char *ptr; - cur += uint32_to_bin(irep->plen, cur); /* number of pool */ + cur += uint16_to_bin(irep->plen, cur); /* number of pool */ for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - switch (mrb_type(irep->pool[pool_no])) { - case MRB_TT_FIXNUM: - cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ - str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); + switch (irep->pool[pool_no].tt) { +#ifdef MRB_64BIT + case IREP_TT_INT64: + { + int64_t i = irep->pool[pool_no].u.i64; + if (i < INT32_MIN || INT32_MAX < i) { + cur += uint8_to_bin(IREP_TT_INT64, cur); /* data type */ + cur += uint32_to_bin((uint32_t)((i>>32) & 0xffffffff), cur); /* i64 hi */ + cur += uint32_to_bin((uint32_t)((i ) & 0xffffffff), cur); /* i64 lo */ + } + else { + cur += uint8_to_bin(IREP_TT_INT32, cur); /* data type */ + cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */ + } + } + break; +#endif + case IREP_TT_INT32: + cur += uint8_to_bin(IREP_TT_INT32, cur); /* data type */ + cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */ break; -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: + case IREP_TT_FLOAT: cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ - str = float_to_str(mrb, irep->pool[pool_no]); - break; +#ifndef MRB_NO_FLOAT + { + dump_float(mrb, cur,irep->pool[pool_no].u.f); + cur += sizeof(double); + } +#else + cur += uint16_to_bin(0, cur); /* zero length */ #endif - - case MRB_TT_STRING: - cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ - str = irep->pool[pool_no]; break; - default: - continue; - } - - char_ptr = RSTRING_PTR(str); - { - mrb_int tlen = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX); - len = (uint16_t)tlen; + default: /* string */ + cur += uint8_to_bin(IREP_TT_STR, cur); /* data type */ + ptr = irep->pool[pool_no].u.str; + len = irep->pool[pool_no].tt>>2; + mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX); + cur += uint16_to_bin((uint16_t)len, cur); /* data length */ + memcpy(cur, ptr, (size_t)len); + cur += len; + *cur++ = '\0'; + break; } - - cur += uint16_to_bin(len, cur); /* data length */ - memcpy(cur, char_ptr, (size_t)len); - cur += len; - mrb_gc_arena_restore(mrb, ai); } @@ -207,13 +214,13 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) static size_t -get_syms_block_size(mrb_state *mrb, mrb_irep *irep) +get_syms_block_size(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; int sym_no; mrb_int len; - size += sizeof(uint32_t); /* slen */ + size += sizeof(uint16_t); /* slen */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { size += sizeof(uint16_t); /* snl(n) */ if (irep->syms[sym_no] != 0) { @@ -226,13 +233,13 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep) } static ptrdiff_t -write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_syms_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) { int sym_no; uint8_t *cur = buf; const char *name; - cur += uint32_to_bin(irep->slen, cur); /* number of symbol */ + cur += uint16_to_bin(irep->slen, cur); /* number of symbol */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { if (irep->syms[sym_no] != 0) { @@ -255,19 +262,46 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } static size_t -get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) +get_catch_table_block_size(mrb_state *mrb, const mrb_irep *irep) +{ + size_t size = 0; + + size += sizeof(uint16_t); /* number of catch handler */ + size += (sizeof(struct mrb_irep_catch_handler)) * irep->clen; + + return size; +} + +static ptrdiff_t +write_catch_table_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) +{ + uint8_t *cur = buf; + const struct mrb_irep_catch_handler *e = mrb_irep_catch_handler_table(irep); + mrb_static_assert1(sizeof(*e) == 7); + + if (e == NULL) return 0; + /* irep->clen has already been written before iseq block */ + memcpy(cur, (const void *)e, sizeof(*e) * irep->clen); + cur += sizeof(*e) * irep->clen; + + return cur - buf; +} + +static size_t +get_irep_record_size_1(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; size += get_irep_header_size(mrb); size += get_iseq_block_size(mrb, irep); + size += get_catch_table_block_size(mrb, irep); size += get_pool_block_size(mrb, irep); size += get_syms_block_size(mrb, irep); return size; } static size_t -get_irep_record_size(mrb_state *mrb, mrb_irep *irep) +get_irep_record_size(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; int irep_no; @@ -280,7 +314,7 @@ get_irep_record_size(mrb_state *mrb, mrb_irep *irep) } static int -write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags) +write_irep_record(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags) { int i; uint8_t *src = bin; @@ -289,13 +323,14 @@ write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_rec return MRB_DUMP_INVALID_IREP; } - *irep_record_size = get_irep_record_size_1(mrb, irep); - if (*irep_record_size == 0) { - return MRB_DUMP_GENERAL_FAILURE; - } - bin += write_irep_header(mrb, irep, bin); + /* + * The catch handler table is after iseq block, but the number of + * elements is placed before iseq block. + */ + bin += uint16_to_bin(irep->clen, bin); bin += write_iseq_block(mrb, irep, bin, flags); + bin += write_catch_table_block(mrb, irep, bin); bin += write_pool_block(mrb, irep, bin); bin += write_syms_block(mrb, irep, bin); @@ -341,7 +376,7 @@ write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) } static int -write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags) +write_section_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags) { int result; size_t rsize = 0; @@ -364,7 +399,7 @@ write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, } static size_t -get_debug_record_size(mrb_state *mrb, mrb_irep *irep) +get_debug_record_size(mrb_state *mrb, const mrb_irep *irep) { size_t ret = 0; uint16_t f_idx; @@ -413,11 +448,11 @@ find_filename_index(const mrb_sym *ary, int ary_len, mrb_sym s) } static size_t -get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp) +get_filename_table_size(mrb_state *mrb, const mrb_irep *irep, mrb_sym **fp, uint16_t *lp) { mrb_sym *filenames = *fp; size_t size = 0; - mrb_irep_debug_info *di = irep->debug_info; + const mrb_irep_debug_info *di = irep->debug_info; int i; mrb_assert(lp); @@ -444,7 +479,7 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t * } static size_t -write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) +write_debug_record_1(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { uint8_t *cur; uint16_t f_idx; @@ -498,7 +533,7 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const } static size_t -write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) +write_debug_record(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { size_t size, len; int irep_no; @@ -516,7 +551,7 @@ write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* } static int -write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len) +write_section_debug(mrb_state *mrb, const mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len) { size_t section_size = 0; const uint8_t *bin = cur; @@ -566,7 +601,7 @@ create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32 } for (i = 0; i + 1 < irep->nlocals; ++i) { - mrb_sym const name = irep->lv[i].name; + mrb_sym const name = irep->lv[i]; if (name == 0) continue; if (find_filename_index(*syms, *syms_len, name) != -1) continue; @@ -609,16 +644,14 @@ write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym c int i; for (i = 0; i + 1 < irep->nlocals; ++i) { - if (irep->lv[i].name == 0) { + if (irep->lv[i] == 0) { cur += uint16_to_bin(RITE_LV_NULL_MARK, cur); - cur += uint16_to_bin(0, cur); } else { - int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i].name); + int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i]); mrb_assert(sym_idx != -1); /* local variable name must be in syms */ cur += uint16_to_bin(sym_idx, cur); - cur += uint16_to_bin(irep->lv[i].r, cur); } } @@ -632,12 +665,12 @@ write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym c } static size_t -get_lv_record_size(mrb_state *mrb, mrb_irep *irep) +get_lv_record_size(mrb_state *mrb, const mrb_irep *irep) { size_t ret = 0; int i; - ret += (sizeof(uint16_t) + sizeof(uint16_t)) * (irep->nlocals - 1); + ret += sizeof(uint16_t) * (irep->nlocals - 1); for (i = 0; i < irep->rlen; ++i) { ret += get_lv_record_size(mrb, irep->reps[i]); @@ -647,7 +680,7 @@ get_lv_record_size(mrb_state *mrb, mrb_irep *irep) } static size_t -get_lv_section_size(mrb_state *mrb, mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len) +get_lv_section_size(mrb_state *mrb, const mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len) { size_t ret = 0, i; @@ -665,7 +698,7 @@ get_lv_section_size(mrb_state *mrb, mrb_irep *irep, mrb_sym const *syms, uint32_ } static int -write_section_lv(mrb_state *mrb, mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len) +write_section_lv(mrb_state *mrb, const mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len) { uint8_t *cur = start; struct rite_section_lv_header *header; @@ -707,7 +740,8 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8 uint32_t offset; memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)); - memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)); + memcpy(header->major_version, RITE_BINARY_MAJOR_VER, sizeof(header->major_version)); + memcpy(header->minor_version, RITE_BINARY_MAJOR_VER, sizeof(header->minor_version)); memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); mrb_assert(binary_size <= UINT32_MAX); @@ -721,7 +755,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8 } static mrb_bool -debug_info_defined_p(mrb_irep *irep) +debug_info_defined_p(const mrb_irep *irep) { int i; @@ -733,7 +767,7 @@ debug_info_defined_p(mrb_irep *irep) } static mrb_bool -lv_defined_p(mrb_irep *irep) +lv_defined_p(const mrb_irep *irep) { int i; @@ -747,7 +781,7 @@ lv_defined_p(mrb_irep *irep) } static int -dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) +dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) { int result = MRB_DUMP_GENERAL_FAILURE; size_t malloc_size; @@ -835,7 +869,7 @@ error_exit: } int -mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) +mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) { return dump_irep(mrb, irep, flags, bin, bin_size); } @@ -843,7 +877,7 @@ mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size #ifndef MRB_DISABLE_STDIO int -mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp) +mrb_dump_irep_binary(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE* fp) { uint8_t *bin = NULL; size_t bin_size = 0; @@ -865,7 +899,7 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp) } int -mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) +mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) { uint8_t *bin = NULL; size_t bin_size = 0, bin_idx = 0; @@ -884,15 +918,8 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con "#ifdef __cplusplus\n" "extern const uint8_t %s[];\n" "#endif\n" - "const uint8_t\n" - "#if defined __GNUC__\n" - "__attribute__((aligned(%u)))\n" - "#elif defined _MSC_VER\n" - "__declspec(align(%u))\n" - "#endif\n" - "%s[] = {", - initname, - (uint16_t)MRB_DUMP_ALIGNMENT, (uint16_t)MRB_DUMP_ALIGNMENT, initname) < 0) { + "const uint8_t %s[] = {", + initname, initname) < 0) { mrb_free(mrb, bin); return MRB_DUMP_WRITE_FAULT; } @@ -918,4 +945,171 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con return result; } +static int +dump_pool(mrb_state *mrb, const mrb_pool_value *p, FILE *fp) +{ + if (p->tt & IREP_TT_NFLAG) { /* number */ + switch (p->tt) { +#ifdef MRB_64BIT + case IREP_TT_INT64: + if (p->u.i64 < INT32_MIN || INT32_MAX < p->u.i64) { + fprintf(fp, "{IREP_TT_INT64, {.i64=%" PRId64 "}},\n", p->u.i64); + } + else { + fprintf(fp, "{IREP_TT_INT32, {.i32=%" PRId32 "}},\n", (int32_t)p->u.i64); + } + break; +#endif + case IREP_TT_INT32: + fprintf(fp, "{IREP_TT_INT32, {.i32=%" PRId32 "}},\n", p->u.i32); + break; + case IREP_TT_FLOAT: + if (p->u.f == 0) { + fprintf(fp, "{IREP_TT_FLOAT, {.f=%#.1f}},\n", p->u.f); + } + else { + fprintf(fp, "{IREP_TT_FLOAT, {.f=" MRB_FLOAT_FMT "}},\n", p->u.f); + } + break; + } + } + else { /* string */ + int i, len = p->tt>>2; + const char *s = p->u.str; + fprintf(fp, "{IREP_TT_STR|(%d<<2), {\"", len); + for (i=0; i<len; i++) { + fprintf(fp, "\\x%02x", (int)s[i]&0xff); + } + fputs("\"}},\n", fp); + } + return MRB_DUMP_OK; +} + +mrb_bool mrb_sym_static_p(mrb_state *mrb, mrb_sym sym); + +static int +dump_sym(mrb_state *mrb, mrb_sym sym, FILE *fp) +{ + const char *name; + if (sym == 0) return MRB_DUMP_INVALID_ARGUMENT; + name = mrb_sym_name(mrb, sym); + if (!name) { + fprintf(stderr, "undefined symbol (%d) - define presym\n", sym); + } + if (!mrb_sym_static_p(mrb, sym)) { + fprintf(stderr, "no static symbol (%s) - define presym\n", name); + } + fprintf(fp, "%d /* %s */,", sym, name); + return MRB_DUMP_OK; +} + +static int +dump_irep_struct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *name, int n, int *mp) +{ + int i, len; + int max = *mp; + + /* dump reps */ + if (irep->reps) { + for (i=0,len=irep->rlen; i<len; i++) { + *mp += len; + if (dump_irep_struct(mrb, irep->reps[i], flags, fp, name, max+i, mp) != MRB_DUMP_OK) + return MRB_DUMP_INVALID_ARGUMENT; + } + fprintf(fp, "static const mrb_irep *%s_reps_%d[%d] = {\n", name, n, len); + for (i=0,len=irep->rlen; i<len; i++) { + fprintf(fp, " &%s_irep_%d,\n", name, max+i); + } + fputs("};\n", fp); + } + /* dump pool */ + if (irep->pool) { + len=irep->plen; + fprintf(fp, "static const mrb_pool_value %s_pool_%d[%d] = {\n", name, n, len); + for (i=0; i<len; i++) { + if (dump_pool(mrb, &irep->pool[i], fp) != MRB_DUMP_OK) + return MRB_DUMP_INVALID_ARGUMENT; + } + fputs("};\n", fp); + } + /* dump syms */ + if (irep->syms) { + len=irep->slen; + fprintf(fp, "static const mrb_sym %s_syms_%d[%d] = {", name, n, len); + for (i=0; i<len; i++) { + dump_sym(mrb, irep->syms[i], fp); + } + fputs("};\n", fp); + } + /* dump iseq */ + len=irep->ilen+sizeof(struct mrb_irep_catch_handler)*irep->clen; + fprintf(fp, "static const mrb_code %s_iseq_%d[%d] = {", name, n, len); + for (i=0; i<len; i++) { + if (i%20 == 0) fputs("\n", fp); + fprintf(fp, "0x%02x,", irep->iseq[i]); + } + fputs("};\n", fp); + /* dump lv */ + if (irep->lv) { + len=irep->nlocals; + fprintf(fp, "static const mrb_sym %s_lv_%d[%d] = {", name, n, len); + for (i=0; i+1<len; i++) { + fprintf(fp, "%uU, ", irep->lv[i]); + } + fputs("};\n", fp); + } + /* dump irep */ + fprintf(fp, "static const mrb_irep %s_irep_%d = {\n", name, n); + fprintf(fp, " %d,%d,%d,\n", irep->nlocals, irep->nregs, irep->clen); + fprintf(fp, " MRB_IREP_STATIC,%s_iseq_%d,\n", name, n); + if (irep->pool) { + fprintf(fp, " %s_pool_%d,", name, n); + } + else { + fputs( " NULL,", fp); + } + if (irep->syms) { + fprintf(fp, "%s_syms_%d,", name, n); + } + else { + fputs( "NULL,", fp); + } + if (irep->reps) { + fprintf(fp, "%s_reps_%d,\n", name, n); + } + else { + fputs( "NULL,\n", fp); + } + if (irep->lv) { + fprintf(fp, " %s_lv_%d,\n", name, n); + } + else { + fputs( " NULL,\t\t\t\t\t/* lv */\n", fp); + } + fputs( " NULL,\t\t\t\t\t/* debug_info */\n", fp); + fprintf(fp, " %d,%d,%d,%d,0\n};\n", irep->ilen, irep->plen, irep->slen, irep->rlen); + + return MRB_DUMP_OK; +} + +int +mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) +{ + int max = 1; + int n; + + if (fp == NULL || initname == NULL || initname[0] == '\0') { + return MRB_DUMP_INVALID_ARGUMENT; + } + if (fprintf(fp, "#include <mruby.h>\n" "#include <mruby/proc.h>\n\n") < 0) { + return MRB_DUMP_WRITE_FAULT; + } + n = dump_irep_struct(mrb, irep, flags, fp, initname, 0, &max); + if (n != MRB_DUMP_OK) return n; + fprintf(fp, "#ifdef __cplusplus\nextern const struct RProc %s[];\n#endif\n", initname); + fprintf(fp, "const struct RProc %s[] = {{\n", initname); + fprintf(fp, "NULL,NULL,MRB_TT_PROC,7,0,{&%s_irep_0},NULL,{NULL},\n}};\n", initname); + return MRB_DUMP_OK; +} + #endif /* MRB_DISABLE_STDIO */ diff --git a/src/enum.c b/src/enum.c index d31370188..b95956715 100644 --- a/src/enum.c +++ b/src/enum.c @@ -18,7 +18,7 @@ enum_update_hash(mrb_state *mrb, mrb_value self) mrb_get_args(mrb, "iii", &hash, &index, &hv); hash ^= ((uint32_t)hv << (index % 16)); - return mrb_fixnum_value(hash); + return mrb_int_value(mrb, hash); } void diff --git a/src/error.c b/src/error.c index 5d17209e5..b19f0ea43 100644 --- a/src/error.c +++ b/src/error.c @@ -45,7 +45,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc) mrb_value mesg; if (mrb_get_args(mrb, "|o", &mesg) == 1) { - mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg); + mrb_iv_set(mrb, exc, MRB_SYM(mesg), mesg); } return exc; } @@ -74,7 +74,7 @@ exc_exception(mrb_state *mrb, mrb_value self) if (argc == 0) return self; if (mrb_obj_equal(mrb, self, a)) return self; exc = mrb_obj_clone(mrb, self); - mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), a); + mrb_iv_set(mrb, exc, MRB_SYM(mesg), a); return exc; } @@ -90,7 +90,7 @@ exc_exception(mrb_state *mrb, mrb_value self) mrb_value exc_to_s(mrb_state *mrb, mrb_value exc) { - mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); + mrb_value mesg = mrb_attr_get(mrb, exc, MRB_SYM(mesg)); struct RObject *p; if (!mrb_string_p(mesg)) { @@ -114,7 +114,7 @@ exc_to_s(mrb_state *mrb, mrb_value exc) static mrb_value exc_message(mrb_state *mrb, mrb_value exc) { - return mrb_funcall(mrb, exc, "to_s", 0); + return mrb_funcall_id(mrb, exc, MRB_SYM(to_s), 0); } /* @@ -130,7 +130,7 @@ exc_message(mrb_state *mrb, mrb_value exc) mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc) { - mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); + mrb_value mesg = mrb_attr_get(mrb, exc, MRB_SYM(mesg)); mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc))); mesg = mrb_obj_as_string(mrb, mesg); return RSTRING_LEN(mesg) == 0 ? cname : mrb_format(mrb, "%v (%v)", mesg, cname); @@ -154,7 +154,7 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace) p++; } } - mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace); + mrb_iv_set(mrb, exc, MRB_SYM(backtrace), backtrace); } static mrb_value @@ -288,7 +288,7 @@ mrb_vformat(mrb_state *mrb, const char *format, va_list ap) #endif obj = mrb_fixnum_value(i); goto L_cat_obj; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case 'f': obj = mrb_float_value(mrb, (mrb_float)va_arg(ap, double)); goto L_cat_obj; @@ -474,7 +474,7 @@ mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv) n = 1; exception_call: { - mrb_sym exc = mrb_intern_lit(mrb, "exception"); + mrb_sym exc = MRB_SYM(exception); if (mrb_respond_to(mrb, argv[0], exc)) { mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); } @@ -622,11 +622,11 @@ mrb_init_exception(mrb_state *mrb) script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ stack_error = mrb_define_class(mrb, "SystemStackError", exception); - mrb->stack_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, stack_error, "stack level too deep")); + mrb->stack_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, stack_error, "stack level too deep")); nomem_error = mrb_define_class(mrb, "NoMemoryError", exception); - mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, nomem_error, "Out of memory")); + mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, nomem_error, "Out of memory")); #ifdef MRB_GC_FIXED_ARENA - mrb->arena_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, nomem_error, "arena overflow error")); + mrb->arena_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, nomem_error, "arena overflow error")); #endif } @@ -8,6 +8,7 @@ #include <mruby/string.h> #include <mruby/data.h> #include <mruby/class.h> +#include <mruby/numeric.h> MRB_API struct RData* mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type) @@ -69,21 +70,11 @@ mrb_obj_to_sym(mrb_state *mrb, mrb_value name) return 0; /* not reached */ } -MRB_API mrb_int -#ifdef MRB_WITHOUT_FLOAT -mrb_fixnum_id(mrb_int f) -#else -mrb_float_id(mrb_float f) -#endif +static mrb_int +make_num_id(const char *p, size_t len) { - const char *p = (const char*)&f; - int len = sizeof(f); uint32_t id = 0; -#ifndef MRB_WITHOUT_FLOAT - /* normalize -0.0 to 0.0 */ - if (f == 0) f = 0.0; -#endif while (len--) { id = id*65599 + *p; p++; @@ -94,6 +85,22 @@ mrb_float_id(mrb_float f) } MRB_API mrb_int +mrb_int_id(mrb_int n) +{ + return make_num_id((const char*)&n, sizeof(n)); +} + +#ifndef MRB_NO_FLOAT +MRB_API mrb_int +mrb_float_id(mrb_float f) +{ + /* normalize -0.0 to 0.0 */ + if (f == 0) f = 0.0; + return make_num_id((const char*)&f, sizeof(f)); +} +#endif + +MRB_API mrb_int mrb_obj_id(mrb_value obj) { mrb_int tt = mrb_type(obj); @@ -114,11 +121,9 @@ mrb_obj_id(mrb_value obj) return MakeID(2); case MRB_TT_SYMBOL: return MakeID(mrb_symbol(obj)); - case MRB_TT_FIXNUM: -#ifdef MRB_WITHOUT_FLOAT - return MakeID(mrb_fixnum_id(mrb_fixnum(obj))); -#else - return MakeID2(mrb_float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT); + case MRB_TT_INTEGER: + return MakeID(mrb_int_id(mrb_integer(obj))); +#ifdef MRB_NO_FLOAT case MRB_TT_FLOAT: return MakeID(mrb_float_id(mrb_float(obj))); #endif @@ -147,29 +152,32 @@ mrb_obj_id(mrb_value obj) #ifdef MRB_WORD_BOXING #define mrb_xxx_boxing_cptr_value mrb_word_boxing_cptr_value -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT MRB_API mrb_value mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) { - mrb_value v; + union mrb_value_ v; - v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); - v.value.fp->f = f; - MRB_SET_FROZEN_FLAG(v.value.bp); - return v; + v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); + v.fp->f = f; + MRB_SET_FROZEN_FLAG(v.bp); + return v.w; } +#endif /* MRB_NO_FLOAT */ MRB_API mrb_value -mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f) +mrb_word_boxing_int_value(mrb_state *mrb, mrb_int n) { - struct RFloat *nf = (struct RFloat *)mrb_malloc(mrb, sizeof(struct RFloat)); - nf->tt = MRB_TT_FLOAT; - nf->c = mrb->float_class; - nf->f = f; - MRB_SET_FROZEN_FLAG(nf); - return mrb_obj_value(nf); + if (FIXABLE(n)) return mrb_fixnum_value(n); + else { + union mrb_value_ v; + + v.p = mrb_obj_alloc(mrb, MRB_TT_INTEGER, mrb->integer_class); + v.ip->i = n; + MRB_SET_FROZEN_FLAG(v.ip); + return v.w; + } } -#endif /* MRB_WITHOUT_FLOAT */ #endif /* MRB_WORD_BOXING */ #if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT)) diff --git a/src/fmt_fp.c b/src/fmt_fp.c index 81ace6ec8..2c1e13c36 100644 --- a/src/fmt_fp.c +++ b/src/fmt_fp.c @@ -1,4 +1,4 @@ -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT #if defined(MRB_DISABLE_STDIO) || defined(_WIN32) || defined(_WIN64) /* @@ -6,6 +6,9 @@ #include <string.h> #include <stdlib.h> +#ifdef MRB_USE_MALLOC_TRIM +#include <malloc.h> +#endif #include <mruby.h> #include <mruby/array.h> #include <mruby/class.h> @@ -35,6 +38,11 @@ * Gray - Marked, But the child objects are unmarked. * Black - Marked, the child objects are also marked. + Extra color + + * Red - Static (ROM object) no need to be collected. + - All child objects should be Red as well. + == Two White Types There're two white color types in a flip-flop fashion: White-A and White-B, @@ -117,7 +125,7 @@ typedef struct { struct RException exc; struct RBreak brk; #ifdef MRB_WORD_BOXING -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT struct RFloat floatv; #endif struct RCptr cptr; @@ -185,6 +193,7 @@ gettimeofday_time(void) #define GC_WHITE_A 1 #define GC_WHITE_B (1 << 1) #define GC_BLACK (1 << 2) +#define GC_RED 7 #define GC_WHITES (GC_WHITE_A | GC_WHITE_B) #define GC_COLOR_MASK 7 @@ -194,7 +203,8 @@ gettimeofday_time(void) #define paint_partial_white(s, o) ((o)->color = (s)->current_white_part) #define is_gray(o) ((o)->color == GC_GRAY) #define is_white(o) ((o)->color & GC_WHITES) -#define is_black(o) ((o)->color & GC_BLACK) +#define is_black(o) ((o)->color == GC_BLACK) +#define is_red(o) ((o)->color == GC_RED) #define flip_white_part(s) ((s)->current_white_part = other_white_part(s)) #define other_white_part(s) ((s)->current_white_part ^ GC_WHITES) #define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE) @@ -581,11 +591,11 @@ add_gray_list(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) gc->gray_list = obj; } -static int +static mrb_int ci_nregs(mrb_callinfo *ci) { - struct RProc *p = ci->proc; - int n = 0; + const struct RProc *p = ci->proc; + mrb_int n = 0; if (!p) { if (ci->argc < 0) return 3; @@ -633,7 +643,6 @@ mark_context_stack(mrb_state *mrb, struct mrb_context *c) static void mark_context(mrb_state *mrb, struct mrb_context *c) { - int i; mrb_callinfo *ci; start: @@ -650,10 +659,6 @@ mark_context(mrb_state *mrb, struct mrb_context *c) mrb_gc_mark(mrb, (struct RBasic*)ci->target_class); } } - /* mark ensure stack */ - for (i=0; i<c->eidx; i++) { - mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]); - } /* mark fibers */ mrb_gc_mark(mrb, (struct RBasic*)c->fib); if (c->prev) { @@ -765,6 +770,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj) { if (obj == 0) return; if (!is_white(obj)) return; + if (is_red(obj)) return; mrb_assert((obj)->tt != MRB_TT_FREE); add_gray_list(mrb, &mrb->gc, obj); } @@ -776,12 +782,12 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) switch (obj->tt) { /* immediate - no mark */ case MRB_TT_TRUE: - case MRB_TT_FIXNUM: + case MRB_TT_INTEGER: case MRB_TT_SYMBOL: /* cannot happen */ return; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING break; @@ -803,12 +809,14 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) case MRB_TT_SCLASS: mrb_gc_free_mt(mrb, (struct RClass*)obj); mrb_gc_free_iv(mrb, (struct RObject*)obj); - mrb_mc_clear_by_class(mrb, (struct RClass*)obj); + if (!end) + mrb_mc_clear_by_class(mrb, (struct RClass*)obj); break; case MRB_TT_ICLASS: if (MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN)) mrb_gc_free_mt(mrb, (struct RClass*)obj); - mrb_mc_clear_by_class(mrb, (struct RClass*)obj); + if (!end) + mrb_mc_clear_by_class(mrb, (struct RClass*)obj); break; case MRB_TT_ENV: { @@ -868,7 +876,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) struct RProc *p = (struct RProc*)obj; if (!MRB_PROC_CFUNC_P(p) && p->body.irep) { - mrb_irep *irep = p->body.irep; + mrb_irep *irep = (mrb_irep*)p->body.irep; if (end) { mrb_irep_cutref(mrb, irep); } @@ -924,10 +932,10 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class); mrb_gc_mark(mrb, (struct RBasic*)mrb->range_class); -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class); #endif - mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class); + mrb_gc_mark(mrb, (struct RBasic*)mrb->integer_class); mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class); mrb_gc_mark(mrb, (struct RBasic*)mrb->false_class); mrb_gc_mark(mrb, (struct RBasic*)mrb->nil_class); @@ -1004,9 +1012,6 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) if (c->stbase + i > c->stend) i = c->stend - c->stbase; children += i; - /* mark ensure stack */ - children += c->eidx; - /* mark closure */ if (c->cibase) { for (i=0, ci = c->cibase; ci <= c->ci; i++, ci++) @@ -1317,6 +1322,9 @@ mrb_full_gc(mrb_state *mrb) gc->full = FALSE; } +#ifdef MRB_USE_MALLOC_TRIM + malloc_trim(0); +#endif GC_TIME_STOP_AND_REPORT; } diff --git a/src/hash.c b/src/hash.c index c891e1b22..d67fa6254 100644 --- a/src/hash.c +++ b/src/hash.c @@ -11,7 +11,7 @@ #include <mruby/string.h> #include <mruby/variable.h> -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT /* a function to get hash value of a float number */ mrb_int mrb_float_id(mrb_float f); #endif @@ -64,16 +64,16 @@ ht_hash_func(mrb_state *mrb, htable *t, mrb_value key) case MRB_TT_TRUE: case MRB_TT_FALSE: case MRB_TT_SYMBOL: - case MRB_TT_FIXNUM: -#ifndef MRB_WITHOUT_FLOAT + case MRB_TT_INTEGER: +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: #endif h = (size_t)mrb_obj_id(key); break; default: - hv = mrb_funcall(mrb, key, "hash", 0); - h = (size_t)tt ^ (size_t)mrb_fixnum(hv); + hv = mrb_funcall_id(mrb, key, MRB_SYM(hash), 0); + h = (size_t)tt ^ (size_t)mrb_integer(hv); break; } if (index && (index != t->index || capa != index->capa)) { @@ -95,28 +95,14 @@ ht_hash_equal(mrb_state *mrb, htable *t, mrb_value a, mrb_value b) if (!mrb_symbol_p(b)) return FALSE; return mrb_symbol(a) == mrb_symbol(b); - case MRB_TT_FIXNUM: - switch (mrb_type(b)) { - case MRB_TT_FIXNUM: - return mrb_fixnum(a) == mrb_fixnum(b); -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: - return (mrb_float)mrb_fixnum(a) == mrb_float(b); -#endif - default: - return FALSE; - } + case MRB_TT_INTEGER: + if (!mrb_integer_p(b)) return FALSE; + return mrb_integer(a) == mrb_integer(b); -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: - switch (mrb_type(b)) { - case MRB_TT_FIXNUM: - return mrb_float(a) == (mrb_float)mrb_fixnum(b); - case MRB_TT_FLOAT: - return mrb_float(a) == mrb_float(b); - default: - return FALSE; - } + if (!mrb_float_p(b)) return FALSE; + return mrb_float(a) == mrb_float(b); #endif default: @@ -589,7 +575,7 @@ ht_free(mrb_state *mrb, htable *t) mrb_free(mrb, t); } -static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); +static void hash_modify(mrb_state *mrb, mrb_value hash); static inline mrb_value ht_key(mrb_state *mrb, mrb_value key) @@ -683,7 +669,7 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self) vret = mrb_obj_value(copy); ifnone = RHASH_IFNONE(self); if (!mrb_nil_p(ifnone)) { - mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, vret, MRB_SYM(ifnone), ifnone); } return vret; } @@ -729,7 +715,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) return val; } - mid = mrb_intern_lit(mrb, "default"); + mid = MRB_SYM(default); if (mrb_func_basic_p(mrb, hash, mid, mrb_hash_default)) { return hash_default(mrb, hash, key); } @@ -752,7 +738,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) { - mrb_hash_modify(mrb, hash); + hash_modify(mrb, hash); key = KEY(key); ht_put(mrb, RHASH_TBL(hash), key, val); @@ -762,7 +748,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) } static void -mrb_hash_modify(mrb_state *mrb, mrb_value hash) +hash_modify(mrb_state *mrb, mrb_value hash) { mrb_check_frozen(mrb, mrb_hash_ptr(hash)); if (!RHASH_TBL(hash)) { @@ -814,7 +800,7 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash) ifnone = mrb_nil_value(); mrb_get_args(mrb, "&|o?", &block, &ifnone, &ifnone_p); - mrb_hash_modify(mrb, hash); + hash_modify(mrb, hash); if (!mrb_nil_p(block)) { if (ifnone_p) { mrb_argnum_error(mrb, 1, 0, 0); @@ -824,7 +810,7 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash) } if (!mrb_nil_p(ifnone)) { RHASH(hash)->flags |= MRB_HASH_DEFAULT; - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, MRB_SYM(ifnone), ifnone); } return hash; } @@ -856,7 +842,7 @@ hash_default(mrb_state *mrb, mrb_value hash, mrb_value key) { if (MRB_RHASH_DEFAULT_P(hash)) { if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + return mrb_funcall_id(mrb, RHASH_PROCDEFAULT(hash), MRB_SYM(call), 2, hash, key); } else { return RHASH_IFNONE(hash); @@ -897,7 +883,7 @@ mrb_hash_default(mrb_state *mrb, mrb_value hash) if (MRB_RHASH_DEFAULT_P(hash)) { if (MRB_RHASH_PROCDEFAULT_P(hash)) { if (!given) return mrb_nil_value(); - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + return mrb_funcall_id(mrb, RHASH_PROCDEFAULT(hash), MRB_SYM(call), 2, hash, key); } else { return RHASH_IFNONE(hash); @@ -932,8 +918,8 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash) { mrb_value ifnone = mrb_get_arg1(mrb); - mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); + hash_modify(mrb, hash); + mrb_iv_set(mrb, hash, MRB_SYM(ifnone), ifnone); RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT; if (!mrb_nil_p(ifnone)) { RHASH(hash)->flags |= MRB_HASH_DEFAULT; @@ -987,8 +973,8 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) { mrb_value ifnone = mrb_get_arg1(mrb); - mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); + hash_modify(mrb, hash); + mrb_iv_set(mrb, hash, MRB_SYM(ifnone), ifnone); if (!mrb_nil_p(ifnone)) { RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; RHASH(hash)->flags |= MRB_HASH_DEFAULT; @@ -1020,7 +1006,7 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self) { mrb_value key = mrb_get_arg1(mrb); - mrb_hash_modify(mrb, self); + hash_modify(mrb, self); return mrb_hash_delete_key(mrb, self, key); } @@ -1070,7 +1056,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) { htable *t = RHASH_TBL(hash); - mrb_hash_modify(mrb, hash); + hash_modify(mrb, hash); if (t && t->size > 0) { mrb_value del_key = mrb_nil_value(); mrb_value del_val = mrb_nil_value(); @@ -1083,7 +1069,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) if (MRB_RHASH_DEFAULT_P(hash)) { if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value()); + return mrb_funcall_id(mrb, RHASH_PROCDEFAULT(hash), MRB_SYM(call), 2, hash, mrb_nil_value()); } else { return RHASH_IFNONE(hash); @@ -1109,7 +1095,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash) { htable *t = RHASH_TBL(hash); - mrb_hash_modify(mrb, hash); + hash_modify(mrb, hash); if (t) { ht_free(mrb, t); RHASH_TBL(hash) = NULL; @@ -1368,7 +1354,7 @@ mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2) { htable *h1, *h2; - mrb_hash_modify(mrb, hash1); + hash_modify(mrb, hash1); hash2 = mrb_ensure_hash_type(mrb, hash2); h1 = RHASH_TBL(hash1); h2 = RHASH_TBL(hash2); diff --git a/src/kernel.c b/src/kernel.c index 10ed9f88e..c34d0bb6e 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -19,7 +19,7 @@ mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func) { struct RClass *c = mrb_class(mrb, obj); mrb_method_t m = mrb_method_search_vm(mrb, &c, mid); - struct RProc *p; + const struct RProc *p; if (MRB_METHOD_UNDEF_P(m)) return FALSE; if (MRB_METHOD_FUNC_P(m)) @@ -33,7 +33,7 @@ mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func) static mrb_bool mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { - return mrb_func_basic_p(mrb, obj, mrb_intern_lit(mrb, "to_s"), mrb_any_to_s); + return mrb_func_basic_p(mrb, obj, MRB_SYM(to_s), mrb_any_to_s); } /* 15.3.1.3.17 */ @@ -96,7 +96,7 @@ mrb_equal_m(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self) { - return mrb_fixnum_value(mrb_obj_id(self)); + return mrb_int_value(mrb, mrb_obj_id(self)); } static int @@ -143,7 +143,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) mrb_value *bp; int bidx; struct REnv *e = NULL; - struct RProc *p; + const struct RProc *p; if (ci <= cibase) { /* toplevel does not have block */ @@ -209,7 +209,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) * called with an explicit receiver, as <code>class</code> is also a * reserved word in Ruby. * - * 1.class #=> Fixnum + * 1.class #=> Integer * self.class #=> Object */ static mrb_value @@ -218,187 +218,6 @@ mrb_obj_class_m(mrb_state *mrb, mrb_value self) return mrb_obj_value(mrb_obj_class(mrb, self)); } -static struct RClass* -mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) -{ - struct RClass *klass = mrb_basic_ptr(obj)->c; - - if (klass->tt != MRB_TT_SCLASS) - return klass; - else { - /* copy singleton(unnamed) class */ - struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); - - switch (mrb_type(obj)) { - case MRB_TT_CLASS: - case MRB_TT_SCLASS: - break; - default: - clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); - break; - } - clone->super = klass->super; - if (klass->iv) { - mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); - mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj); - } - if (klass->mt) { - clone->mt = kh_copy(mt, mrb, klass->mt); - } - else { - clone->mt = kh_init(mt, mrb); - } - clone->tt = MRB_TT_SCLASS; - return clone; - } -} - -static void -copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) -{ - struct RClass *dc = mrb_class_ptr(dst); - struct RClass *sc = mrb_class_ptr(src); - /* if the origin is not the same as the class, then the origin and - the current class need to be copied */ - if (sc->flags & MRB_FL_CLASS_IS_PREPENDED) { - struct RClass *c0 = sc->super; - struct RClass *c1 = dc; - - /* copy prepended iclasses */ - while (!(c0->flags & MRB_FL_CLASS_IS_ORIGIN)) { - c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); - c1 = c1->super; - c0 = c0->super; - } - c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); - c1->super->flags |= MRB_FL_CLASS_IS_ORIGIN; - } - if (sc->mt) { - dc->mt = kh_copy(mt, mrb, sc->mt); - } - else { - dc->mt = kh_init(mt, mrb); - } - dc->super = sc->super; - MRB_SET_INSTANCE_TT(dc, MRB_INSTANCE_TT(sc)); -} - -static void -init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) -{ - switch (mrb_type(obj)) { - case MRB_TT_ICLASS: - copy_class(mrb, dest, obj); - return; - case MRB_TT_CLASS: - case MRB_TT_MODULE: - copy_class(mrb, dest, obj); - mrb_iv_copy(mrb, dest, obj); - mrb_iv_remove(mrb, dest, mrb_intern_lit(mrb, "__classname__")); - break; - case MRB_TT_OBJECT: - case MRB_TT_SCLASS: - case MRB_TT_HASH: - case MRB_TT_DATA: - case MRB_TT_EXCEPTION: - mrb_iv_copy(mrb, dest, obj); - break; - case MRB_TT_ISTRUCT: - mrb_istruct_copy(dest, obj); - break; - - default: - break; - } - mrb_funcall(mrb, dest, "initialize_copy", 1, obj); -} - -/* 15.3.1.3.8 */ -/* - * call-seq: - * obj.clone -> an_object - * - * Produces a shallow copy of <i>obj</i>---the instance variables of - * <i>obj</i> are copied, but not the objects they reference. Copies - * the frozen state of <i>obj</i>. See also the discussion - * under <code>Object#dup</code>. - * - * class Klass - * attr_accessor :str - * end - * s1 = Klass.new #=> #<Klass:0x401b3a38> - * s1.str = "Hello" #=> "Hello" - * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> - * s2.str[1,4] = "i" #=> "i" - * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" - * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">" - * - * This method may have class-specific behavior. If so, that - * behavior will be documented under the #+initialize_copy+ method of - * the class. - * - * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone. - */ -MRB_API mrb_value -mrb_obj_clone(mrb_state *mrb, mrb_value self) -{ - struct RObject *p; - mrb_value clone; - - if (mrb_immediate_p(self)) { - return self; - } - if (mrb_sclass_p(self)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class"); - } - p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self)); - p->c = mrb_singleton_class_clone(mrb, self); - mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c); - clone = mrb_obj_value(p); - init_copy(mrb, clone, self); - p->flags |= mrb_obj_ptr(self)->flags & MRB_FL_OBJ_IS_FROZEN; - - return clone; -} - -/* 15.3.1.3.9 */ -/* - * call-seq: - * obj.dup -> an_object - * - * Produces a shallow copy of <i>obj</i>---the instance variables of - * <i>obj</i> are copied, but not the objects they reference. - * <code>dup</code> copies the frozen state of <i>obj</i>. See also - * the discussion under <code>Object#clone</code>. In general, - * <code>clone</code> and <code>dup</code> may have different semantics - * in descendant classes. While <code>clone</code> is used to duplicate - * an object, including its internal state, <code>dup</code> typically - * uses the class of the descendant object to create the new instance. - * - * This method may have class-specific behavior. If so, that - * behavior will be documented under the #+initialize_copy+ method of - * the class. - */ - -MRB_API mrb_value -mrb_obj_dup(mrb_state *mrb, mrb_value obj) -{ - struct RBasic *p; - mrb_value dup; - - if (mrb_immediate_p(obj)) { - return obj; - } - if (mrb_sclass_p(obj)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class"); - } - p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj)); - dup = mrb_obj_value(p); - init_copy(mrb, dup, obj); - - return dup; -} - static mrb_value mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj) { @@ -411,8 +230,8 @@ mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj) mrb_check_type(mrb, argv[i], MRB_TT_MODULE); } while (argc--) { - mrb_funcall(mrb, argv[argc], "extend_object", 1, obj); - mrb_funcall(mrb, argv[argc], "extended", 1, obj); + mrb_funcall_id(mrb, argv[argc], MRB_SYM(extend_object), 1, obj); + mrb_funcall_id(mrb, argv[argc], MRB_SYM(extended), 1, obj); } return obj; } @@ -476,20 +295,20 @@ mrb_obj_frozen(mrb_state *mrb, mrb_value self) * call-seq: * obj.hash -> fixnum * - * Generates a <code>Fixnum</code> hash value for this object. This + * Generates a <code>Integer</code> hash value for this object. This * function must have the property that <code>a.eql?(b)</code> implies * <code>a.hash == b.hash</code>. The hash value is used by class * <code>Hash</code>. Any hash value that exceeds the capacity of a - * <code>Fixnum</code> will be truncated before being used. + * <code>Integer</code> will be truncated before being used. */ static mrb_value mrb_obj_hash(mrb_state *mrb, mrb_value self) { - return mrb_fixnum_value(mrb_obj_id(self)); + return mrb_int_value(mrb, mrb_obj_id(self)); } /* 15.3.1.3.16 */ -static mrb_value +mrb_value mrb_obj_init_copy(mrb_state *mrb, mrb_value self) { mrb_value orig = mrb_get_arg1(mrb); @@ -501,7 +320,6 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self) return self; } - MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) { @@ -564,9 +382,6 @@ mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, c)); } -KHASH_DECLARE(st, mrb_sym, char, FALSE) -KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal) - /* 15.3.1.3.32 */ /* * call_seq: @@ -749,7 +564,7 @@ obj_respond_to(mrb_state *mrb, mrb_value self) mrb_get_args(mrb, "n|b", &id, &priv); respond_to_p = basic_obj_respond_to(mrb, self, id, !priv); if (!respond_to_p) { - rtm_id = mrb_intern_lit(mrb, "respond_to_missing?"); + rtm_id = MRB_QSYM(respond_to_missing_p); if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) { mrb_value args[2], v; args[0] = mrb_symbol_value(id); @@ -766,7 +581,7 @@ mrb_obj_ceqq(mrb_state *mrb, mrb_value self) { mrb_value v = mrb_get_arg1(mrb); mrb_int i, len; - mrb_sym eqq = mrb_intern_lit(mrb, "==="); + mrb_sym eqq = MRB_QSYM(eqq); mrb_value ary; if (mrb_array_p(self)) { diff --git a/src/load.c b/src/load.c index 247d511df..c1a8c4c87 100644 --- a/src/load.c +++ b/src/load.c @@ -15,6 +15,7 @@ #include <mruby/debug.h> #include <mruby/error.h> #include <mruby/data.h> +#include <mruby/endian.h> #if SIZE_MAX < UINT32_MAX # error size_t must be at least 32 bits wide @@ -26,31 +27,32 @@ #define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size)) static size_t -skip_padding(const uint8_t *buf) -{ - const size_t align = MRB_DUMP_ALIGNMENT; - return -(intptr_t)buf & (align-1); -} - -static size_t offset_crc_body(void) { struct rite_binary_header header; return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc); } -#ifndef MRB_WITHOUT_FLOAT -double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck); - +#ifndef MRB_NO_FLOAT static double -str_to_double(mrb_state *mrb, const char *p, size_t len) +str_to_double(mrb_state *mrb, const char *p) { - /* `i`, `inf`, `infinity` */ - if (len > 0 && p[0] == 'i') return INFINITY; - - /* `I`, `-inf`, `-infinity` */ - if (p[0] == 'I' || (len > 1 && p[0] == '-' && p[1] == 'i')) return -INFINITY; - return mrb_str_len_to_dbl(mrb, p, len, TRUE); + /* dump IEEE754 little endian binary */ + union { + char s[sizeof(double)]; + double f; + } u; + + if (littleendian) { + memcpy(u.s, p, sizeof(double)); + } + else { + size_t i; + for (i=0; i<sizeof(double); i++) { + u.s[i] = p[sizeof(double)-i-1]; + } + } + return u.f; } #endif @@ -73,8 +75,10 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag uint16_t tt, pool_data_len, snl; int plen; struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); - mrb_irep *irep = mrb_add_irep(mrb); + mrb_pool_value *pool; + mrb_sym *syms; int ai = mrb_gc_arena_save(mrb); + mrb_irep *irep = mrb_add_irep(mrb); irep_obj->data = irep; @@ -94,110 +98,137 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag src += sizeof(uint16_t); /* Binary Data Section */ - /* ISEQ BLOCK */ - irep->ilen = (uint16_t)bin_to_uint32(src); - src += sizeof(uint32_t); - src += skip_padding(src); + /* ISEQ BLOCK (and CATCH HANDLER TABLE BLOCK) */ + irep->clen = bin_to_uint16(src); /* number of catch handler */ + src += sizeof(uint16_t); + irep->ilen = bin_to_uint16(src); + src += sizeof(uint16_t); if (irep->ilen > 0) { + size_t data_len = sizeof(mrb_code) * irep->ilen + + sizeof(struct mrb_irep_catch_handler) * irep->clen; + mrb_static_assert1(sizeof(struct mrb_irep_catch_handler) == 7); if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) { return NULL; } if ((flags & FLAG_SRC_MALLOC) == 0) { irep->iseq = (mrb_code*)src; - src += sizeof(mrb_code) * irep->ilen; irep->flags |= MRB_ISEQ_NO_FREE; } else { - size_t data_len = sizeof(mrb_code) * irep->ilen; void *buf = mrb_malloc(mrb, data_len); irep->iseq = (mrb_code *)buf; memcpy(buf, src, data_len); - src += data_len; } + src += data_len; } /* POOL BLOCK */ - plen = bin_to_uint32(src); /* number of pool */ - src += sizeof(uint32_t); + plen = bin_to_uint16(src); /* number of pool */ + src += sizeof(uint16_t); if (plen > 0) { if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) { return NULL; } - irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen); + irep->pool = pool = (mrb_pool_value*)mrb_calloc(mrb, sizeof(mrb_pool_value), plen); for (i = 0; i < plen; i++) { - const char *s; mrb_bool st = (flags & FLAG_SRC_MALLOC)==0; tt = *src++; /* pool TT */ - pool_data_len = bin_to_uint16(src); /* pool data length */ - src += sizeof(uint16_t); - s = (const char*)src; - src += pool_data_len; switch (tt) { /* pool data */ - case IREP_TT_FIXNUM: { - mrb_value num = mrb_str_len_to_inum(mrb, s, pool_data_len, 10, FALSE); -#ifdef MRB_WITHOUT_FLOAT - irep->pool[i] = num; + case IREP_TT_INT32: + { + mrb_int v = (int32_t)bin_to_uint32(src); + src += sizeof(uint32_t); +#ifdef MRB_64BIT + pool[i].tt = IREP_TT_INT64; + pool[i].u.i64 = (int64_t)v; #else - irep->pool[i] = mrb_float_p(num)? mrb_float_pool(mrb, mrb_float(num)) : num; + pool[i].tt = IREP_TT_INT32; + pool[i].u.i32 = v; #endif } break; + case IREP_TT_INT64: +#ifdef MRB_64BIT + { + uint64_t i = bin_to_uint32(src); + src += sizeof(uint32_t); + i <<= 32; + i |= bin_to_uint32(src); + src += sizeof(uint32_t); + pool[i].u.i64 = (int64_t)i; + } + break; +#else + return NULL; /* INT64 not supported on MRB_32BIT */ +#endif -#ifndef MRB_WITHOUT_FLOAT case IREP_TT_FLOAT: - irep->pool[i] = mrb_float_pool(mrb, str_to_double(mrb, s, pool_data_len)); +#ifndef MRB_NO_FLOAT + pool[i].tt = tt; + pool[i].u.f = str_to_double(mrb, (const char*)src); + src += sizeof(double); break; +#else + return NULL; /* MRB_NO_FLOAT */ #endif - case IREP_TT_STRING: - irep->pool[i] = mrb_str_pool(mrb, s, pool_data_len, st); + case IREP_TT_STR: + pool_data_len = bin_to_uint16(src); /* pool data length */ + src += sizeof(uint16_t); + if (st) { + pool[i].tt = (pool_data_len<<2) | IREP_TT_SSTR; + pool[i].u.str = (const char*)src; + } + else { + char *p; + pool[i].tt = (pool_data_len<<2) | IREP_TT_STR; + p = (char*)mrb_malloc(mrb, pool_data_len+1); + memcpy(p, src, pool_data_len+1); + pool[i].u.str = (const char*)p; + } + src += pool_data_len + 1; break; default: /* should not happen */ - irep->pool[i] = mrb_nil_value(); - break; + return NULL; } - irep->plen++; - mrb_gc_arena_restore(mrb, ai); + irep->plen = i+1; } } /* SYMS BLOCK */ - irep->slen = (uint16_t)bin_to_uint32(src); /* syms length */ - src += sizeof(uint32_t); + irep->slen = bin_to_uint16(src); /* syms length */ + src += sizeof(uint16_t); if (irep->slen > 0) { if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) { return NULL; } - irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen); + irep->syms = syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen); for (i = 0; i < irep->slen; i++) { snl = bin_to_uint16(src); /* symbol name length */ src += sizeof(uint16_t); if (snl == MRB_DUMP_NULL_SYM_LEN) { - irep->syms[i] = 0; + syms[i] = 0; continue; } if (flags & FLAG_SRC_MALLOC) { - irep->syms[i] = mrb_intern(mrb, (char *)src, snl); + syms[i] = mrb_intern(mrb, (char *)src, snl); } else { - irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl); + syms[i] = mrb_intern_static(mrb, (char *)src, snl); } src += snl + 1; - mrb_gc_arena_restore(mrb, ai); } } - irep->reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*)); - diff = src - bin; mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); *len = (size_t)diff; @@ -213,6 +244,7 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); int ai = mrb_gc_arena_save(mrb); mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags); + mrb_irep **reps; int i; mrb_gc_arena_restore(mrb, ai); @@ -220,15 +252,17 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) return NULL; } + reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*)); + irep->reps = (const mrb_irep**)reps; irep_obj->data = irep; bin += *len; for (i=0; i<irep->rlen; i++) { size_t rlen; - irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags); + reps[i] = read_irep_record(mrb, bin, &rlen, flags); mrb_gc_arena_restore(mrb, ai); - if (irep->reps[i] == NULL) { + if (reps[i] == NULL) { return NULL; } bin += rlen; @@ -257,25 +291,26 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * size_t record_size; uint16_t f_idx; int i; + mrb_irep_debug_info *debug; if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; } - irep->debug_info = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info)); - irep->debug_info->pc_count = (uint32_t)irep->ilen; + irep->debug_info = debug = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info)); + debug->pc_count = (uint32_t)irep->ilen; record_size = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); - irep->debug_info->flen = bin_to_uint16(bin); - irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*)); + debug->flen = bin_to_uint16(bin); + debug->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*)); bin += sizeof(uint16_t); - for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + for (f_idx = 0; f_idx < debug->flen; ++f_idx) { mrb_irep_debug_info_file *file; uint16_t filename_idx; file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file)); - irep->debug_info->files[f_idx] = file; + debug->files[f_idx] = file; file->start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); @@ -329,7 +364,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * size_t len; int ret; - ret = read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len); + ret = read_debug_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, filenames, filenames_len); if (ret != MRB_DUMP_OK) return ret; bin += len; } @@ -393,34 +428,31 @@ static int read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *record_len, mrb_sym const *syms, uint32_t syms_len) { const uint8_t *bin = start; + mrb_sym *lv; ptrdiff_t diff; int i; - irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1)); + irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (irep->nlocals - 1)); for (i = 0; i + 1< irep->nlocals; ++i) { uint16_t const sym_idx = bin_to_uint16(bin); bin += sizeof(uint16_t); if (sym_idx == RITE_LV_NULL_MARK) { - irep->lv[i].name = 0; - irep->lv[i].r = 0; + lv[i] = 0; } else { if (sym_idx >= syms_len) { return MRB_DUMP_GENERAL_FAILURE; } - irep->lv[i].name = syms[sym_idx]; - - irep->lv[i].r = bin_to_uint16(bin); + lv[i] = syms[sym_idx]; } - bin += sizeof(uint16_t); } for (i = 0; i < irep->rlen; ++i) { size_t len; int ret; - ret = read_lv_record(mrb, bin, irep->reps[i], &len, syms, syms_len); + ret = read_lv_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, syms, syms_len); if (ret != MRB_DUMP_OK) return ret; bin += len; } @@ -491,7 +523,12 @@ read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_ return MRB_DUMP_INVALID_FILE_HEADER; } - if (memcmp(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)) != 0) { + /* if major version is different, they are incompatible */ + if (memcmp(header->major_version, RITE_BINARY_MAJOR_VER, sizeof(header->major_version)) != 0) { + return MRB_DUMP_INVALID_FILE_HEADER; + } + /* if minor version is different, we can accept the older version */ + if (memcmp(header->minor_version, RITE_BINARY_MINOR_VER, sizeof(header->minor_version)) <= 0) { return MRB_DUMP_INVALID_FILE_HEADER; } @@ -587,7 +624,7 @@ void mrb_exc_set(mrb_state *mrb, mrb_value exc); static void irep_error(mrb_state *mrb) { - mrb_exc_set(mrb, mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error")); + mrb_exc_set(mrb, mrb_exc_new_lit(mrb, E_SCRIPT_ERROR, "irep load error")); } void mrb_codedump_all(mrb_state*, struct RProc*); @@ -642,6 +679,12 @@ mrb_load_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize) return mrb_load_irep_buf_cxt(mrb, buf, bufsize, NULL); } +MRB_API mrb_value +mrb_load_proc(mrb_state *mrb, const struct RProc *proc) +{ + return mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0); +} + #ifndef MRB_DISABLE_STDIO mrb_irep* diff --git a/src/numeric.c b/src/numeric.c index f4961928b..e1898301e 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1,10 +1,10 @@ /* -** numeric.c - Numeric, Integer, Float, Fixnum class +** numeric.c - Numeric, Integer, Float class ** ** See Copyright Notice in mruby.h */ -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT #include <float.h> #include <math.h> #endif @@ -18,8 +18,8 @@ #include <mruby/string.h> #include <mruby/class.h> -#ifndef MRB_WITHOUT_FLOAT -#ifdef MRB_USE_FLOAT +#ifndef MRB_NO_FLOAT +#ifdef MRB_USE_FLOAT32 #define trunc(f) truncf(f) #define floor(f) floorf(f) #define ceil(f) ceilf(f) @@ -30,13 +30,13 @@ #endif #endif -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value val) { switch (mrb_type(val)) { - case MRB_TT_FIXNUM: - return (mrb_float)mrb_fixnum(val); + case MRB_TT_INTEGER: + return (mrb_float)mrb_integer(val); case MRB_TT_FLOAT: break; default: @@ -44,15 +44,6 @@ mrb_to_flo(mrb_state *mrb, mrb_value val) } return mrb_float(val); } - -MRB_API mrb_value -mrb_int_value(mrb_state *mrb, mrb_float f) -{ - if (FIXABLE_FLOAT(f)) { - return mrb_fixnum_value((mrb_int)f); - } - return mrb_float_value(mrb, f); -} #endif /* @@ -65,80 +56,125 @@ mrb_int_value(mrb_state *mrb, mrb_float f) * 2.0**3 #=> 8.0 */ static mrb_value -integral_pow(mrb_state *mrb, mrb_value x) +int_pow(mrb_state *mrb, mrb_value x) { - mrb_value y = mrb_get_arg1(mrb); -#ifndef MRB_WITHOUT_FLOAT - mrb_float d; -#endif + mrb_int base = mrb_int(mrb, x); + mrb_int exp; +#ifndef MRB_NO_FLOAT + mrb_value y; + mrb_float z; - if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) { - /* try ipow() */ - mrb_int base = mrb_fixnum(x); - mrb_int exp = mrb_fixnum(y); - mrb_int result = 1; - - if (exp < 0) -#ifdef MRB_WITHOUT_FLOAT - return mrb_fixnum_value(0); + mrb_get_args(mrb, "o", &y); + if (!mrb_integer_p(y)) { + mrb_get_args(mrb, "f", &z); + z = pow((mrb_float)base, z); + return mrb_float_value(mrb, z); + } + else { + mrb_get_args(mrb, "i", &exp); + z = pow((double)base, (double)exp); + if (exp < 0 || z < (mrb_float)MRB_INT_MIN || (mrb_float)MRB_INT_MAX < z) { + return mrb_float_value(mrb, z); + } + } + return mrb_int_value(mrb, (mrb_int)z); #else - goto float_pow; -#endif - for (;;) { - if (exp & 1) { - if (mrb_int_mul_overflow(result, base, &result)) { -#ifndef MRB_WITHOUT_FLOAT - goto float_pow; -#endif - } - } - exp >>= 1; - if (exp == 0) break; - if (mrb_int_mul_overflow(base, base, &base)) { -#ifndef MRB_WITHOUT_FLOAT - goto float_pow; -#endif + mrb_int result = 1; + + mrb_get_args(mrb, "i", &exp); + if (exp < 0) { + return mrb_fixnum_value(0); + } + for (;;) { + if (exp & 1) { + if (mrb_int_mul_overflow(result, base, &result)) { + mrb_raise(mrb, E_RANGE_ERROR, "integer overflow in division"); } } - return mrb_fixnum_value(result); + exp >>= 1; + if (exp == 0) break; + if (mrb_int_mul_overflow(base, base, &base)) { + mrb_raise(mrb, E_RANGE_ERROR, "integer overflow in division"); + } } -#ifdef MRB_WITHOUT_FLOAT - mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); -#else - float_pow: - d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y)); - return mrb_float_value(mrb, d); + return mrb_int_value(mrb, result); #endif } -static mrb_value -integral_idiv(mrb_state *mrb, mrb_value x) -{ -#ifdef MRB_WITHOUT_FLOAT - mrb_value y = mrb_get_arg1(mrb); - if (!mrb_fixnum_p(y)) { - mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); +mrb_int +mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y) +{ + if (y == 0) { + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); } - return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y)); -#else - mrb_float y; + else if(x == MRB_INT_MIN && y == -1) { + mrb_raise(mrb, E_RANGE_ERROR, "integer overflow in division"); + } + else { + mrb_int div, mod; - mrb_get_args(mrb, "f", &y); - return mrb_int_value(mrb, mrb_to_flo(mrb, x) / y); -#endif + if (y < 0) { + if (x < 0) + div = -x / -y; + else + div = - (x / -y); + } + else { + if (x < 0) + div = - (-x / y); + else + div = x / y; + } + mod = x - div * y; + if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) { + div -= 1; + } + return div; + } + /* not reached */ + return 0; } /* 15.2.8.3.4 */ /* 15.2.9.3.4 */ /* * call-seq: - * num / other -> num + * int / other -> int * * Performs division: the class of the resulting object depends on * the class of <code>num</code> and on the magnitude of the * result. */ +static mrb_value +int_div(mrb_state *mrb, mrb_value xv) +{ +#ifndef MRB_NO_FLOAT + mrb_value yv; + + mrb_get_args(mrb, "o", &yv); + if (mrb_float_p(yv)) { + double d = mrb_integer(xv)/mrb_float(yv); +#ifdef MRB_INT32 + if (MRB_INT_MIN <= d && d <= MRB_INT_MAX) + return mrb_int_value(mrb, (mrb_int)d); + return mrb_float_value(mrb, d); +#else + return mrb_int_value(mrb, (mrb_int)d); +#endif + } + else +#endif + { + mrb_int y; + + mrb_get_args(mrb, "i", &y); + if (y == 0) { + mrb_raise(mrb, E_ZERODIV_ERROR, "devided by zero"); + } + return mrb_int_value(mrb, mrb_integer(xv) / y); + } +} /* 15.2.9.3.19(x) */ /* @@ -149,42 +185,32 @@ integral_idiv(mrb_state *mrb, mrb_value x) */ static mrb_value -integral_div(mrb_state *mrb, mrb_value xv) +int_quo(mrb_state *mrb, mrb_value xv) { -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_int y; mrb_get_args(mrb, "i", &y); if (y == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "devided by zero"); + mrb_raise(mrb, E_ZERODIV_ERROR, "devided by zero"); } return mrb_fixnum_value(mrb_fixnum(xv) / y); #else - mrb_float x, y; + mrb_float y; mrb_get_args(mrb, "f", &y); - x = mrb_to_flo(mrb, xv); - if (y == 0) { - if (x < 0) - y = -INFINITY; - else if (x > 0) - y = INFINITY; - else /* if (x == 0) */ - y = NAN; - return mrb_float_value(mrb, y); - } - return mrb_float_value(mrb, x / y); + return mrb_float_value(mrb, (mrb_float)mrb_integer(xv) / y); #endif } static mrb_value -integral_coerce_step_counter(mrb_state *mrb, mrb_value self) +coerce_step_counter(mrb_state *mrb, mrb_value self) { mrb_value num, step; mrb_get_args(mrb, "oo", &num, &step); -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) { return mrb_Float(mrb, self); } @@ -193,7 +219,7 @@ integral_coerce_step_counter(mrb_state *mrb, mrb_value self) return self; } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT /******************************************************************** * * Document-class: Float @@ -203,19 +229,59 @@ integral_coerce_step_counter(mrb_state *mrb, mrb_value self) * representation. */ -/* 15.2.9.3.16(x) */ -/* - * call-seq: - * flt.to_s -> string - * - * Returns a string containing a representation of self. As well as a - * fixed or exponential form of the number, the call may return - * "<code>NaN</code>", "<code>Infinity</code>", and - * "<code>-Infinity</code>". - */ +static mrb_value +flo_pow(mrb_state *mrb, mrb_value x) +{ + mrb_value y = mrb_get_arg1(mrb); + mrb_float d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y)); + return mrb_float_value(mrb, d); +} static mrb_value -flo_to_s(mrb_state *mrb, mrb_value flt) +flo_idiv(mrb_state *mrb, mrb_value x) +{ + mrb_float y; + + mrb_get_args(mrb, "f", &y); + y = mrb_to_flo(mrb, x) / y; +#ifdef MRB_INT32 + if (MRB_INT_MIN <= y && y <= MRB_INT_MAX) + return mrb_int_value(mrb, (mrb_int)y); + return mrb_float_value(mrb, y); +#else + return mrb_int_value(mrb, (mrb_int)y); +#endif +} + +mrb_float +mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y) +{ + mrb_float f; + + if (y == 0) { + if (x > 0) f = INFINITY; + else if (x < 0) f = -INFINITY; + else /* if (x == 0) */ f = NAN; + } + else { + f = x / y; + } + return f; +} + +static mrb_value +flo_div(mrb_state *mrb, mrb_value xv) +{ + mrb_float x, y; + + x = mrb_float(xv); + mrb_get_args(mrb, "f", &y); + x = mrb_num_div_flo(mrb, x, y); + return mrb_float_value(mrb, x); +} + +static mrb_value +flo_to_str(mrb_state *mrb, mrb_value flt, mrb_bool add_dot_zero) { mrb_float f = mrb_float(flt); mrb_value str; @@ -258,6 +324,9 @@ flo_to_s(mrb_state *mrb, mrb_value flt) str = mrb_float_to_str(mrb, flt, fmt); goto insert_dot_zero; } + else if (add_dot_zero) { + mrb_str_cat(mrb, str, ".0", 2); + } goto exit; } @@ -267,6 +336,49 @@ flo_to_s(mrb_state *mrb, mrb_value flt) return str; } +/* 15.2.9.3.16(x) */ +/* + * call-seq: + * flt.to_s -> string + * + * Returns a string containing a representation of self. As well as a + * fixed or exponential form of the number, the call may return + * "<code>NaN</code>", "<code>Infinity</code>", and + * "<code>-Infinity</code>". + * + * Trailing <code>.0</code> is removed. + * + * 3.0.to_s #=> 3 + * 3.25.to_s #=> 3.25 + */ + +static mrb_value +flo_to_s(mrb_state *mrb, mrb_value flt) +{ + return flo_to_str(mrb, flt, FALSE); +} + +/* + * call-seq: + * flt.inspect -> string + * + * Returns a string containing a representation of self. As well as a + * fixed or exponential form of the number, the call may return + * "<code>NaN</code>", "<code>Infinity</code>", and + * "<code>-Infinity</code>". + * + * Trailing <code>.0</code> is added. + * + * 3.0.to_s #=> 3.0 + * 3.25.to_s #=> 3.25 + */ + +static mrb_value +flo_inspect(mrb_state *mrb, mrb_value flt) +{ + return flo_to_str(mrb, flt, TRUE); +} + /* 15.2.9.3.2 */ /* * call-seq: @@ -378,15 +490,15 @@ flo_mod(mrb_state *mrb, mrb_value x) * (1.0).eql?(1.0) #=> true */ static mrb_value -fix_eql(mrb_state *mrb, mrb_value x) +int_eql(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); - if (!mrb_fixnum_p(y)) return mrb_false_value(); - return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); + if (!mrb_integer_p(y)) return mrb_false_value(); + return mrb_bool_value(mrb_integer(x) == mrb_integer(y)); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT static mrb_value flo_eql(mrb_state *mrb, mrb_value x) { @@ -415,8 +527,8 @@ flo_eq(mrb_state *mrb, mrb_value x) mrb_value y = mrb_get_arg1(mrb); switch (mrb_type(y)) { - case MRB_TT_FIXNUM: - return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y)); + case MRB_TT_INTEGER: + return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_integer(y)); case MRB_TT_FLOAT: return mrb_bool_value(mrb_float(x) == mrb_float(y)); default: @@ -428,8 +540,8 @@ static int64_t value_int64(mrb_state *mrb, mrb_value x) { switch (mrb_type(x)) { - case MRB_TT_FIXNUM: - return (int64_t)mrb_fixnum(x); + case MRB_TT_INTEGER: + return (int64_t)mrb_integer(x); case MRB_TT_FLOAT: return (int64_t)mrb_float(x); default: @@ -525,7 +637,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) val *= 2; } } - return mrb_int_value(mrb, val); + return mrb_int_value(mrb, (mrb_int)val); } static mrb_value @@ -631,7 +743,7 @@ flo_floor(mrb_state *mrb, mrb_value num) mrb_float f = floor(mrb_float(num)); mrb_check_num_exact(mrb, f); - return mrb_int_value(mrb, f); + return mrb_int_value(mrb, (mrb_int)f); } /* 15.2.9.3.8 */ @@ -654,7 +766,7 @@ flo_ceil(mrb_state *mrb, mrb_value num) mrb_float f = ceil(mrb_float(num)); mrb_check_num_exact(mrb, f); - return mrb_int_value(mrb, f); + return mrb_int_value(mrb, (mrb_int)f); } /* 15.2.9.3.12 */ @@ -736,7 +848,7 @@ flo_round(mrb_state *mrb, mrb_value num) if (!isfinite(number)) return num; return mrb_float_value(mrb, number); } - return mrb_int_value(mrb, number); + return mrb_int_value(mrb, (mrb_int)number); } /* 15.2.9.3.14 */ @@ -758,7 +870,7 @@ flo_truncate(mrb_state *mrb, mrb_value num) if (f < 0.0) f = ceil(f); mrb_check_num_exact(mrb, f); - return mrb_int_value(mrb, f); + return mrb_int_value(mrb, (mrb_int)f); } static mrb_value @@ -771,8 +883,7 @@ flo_nan_p(mrb_state *mrb, mrb_value num) /* * Document-class: Integer * - * <code>Integer</code> is the basis for the two concrete classes that - * hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>. + * <code>Integer</code> is hold whole numbers. * */ @@ -796,20 +907,20 @@ fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { + a = mrb_integer(x); + if (mrb_integer_p(y)) { mrb_int b, c; if (a == 0) return x; - b = mrb_fixnum(y); + b = mrb_integer(y); if (mrb_int_mul_overflow(a, b, &c)) { -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT return mrb_float_value(mrb, (mrb_float)a * (mrb_float)b); #endif } return mrb_fixnum_value(c); } -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); #else return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y)); @@ -819,10 +930,10 @@ fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y) { - if (mrb_fixnum_p(x)) { + if (mrb_integer_p(x)) { return fixnum_mul(mrb, x, y); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT if (mrb_float_p(x)) { return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y)); } @@ -842,7 +953,7 @@ mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y) */ static mrb_value -fix_mul(mrb_state *mrb, mrb_value x) +int_mul(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); @@ -888,29 +999,22 @@ fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp) */ static mrb_value -fix_mod(mrb_state *mrb, mrb_value x) +int_mod(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); mrb_int a, b; - a = mrb_fixnum(x); - if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) { + a = mrb_integer(x); + if (mrb_integer_p(y) && a != MRB_INT_MIN && (b=mrb_integer(y)) != MRB_INT_MIN) { mrb_int mod; if (b == 0) { -#ifdef MRB_WITHOUT_FLOAT - /* ZeroDivisionError */ - return mrb_fixnum_value(0); -#else - if (a > 0) return mrb_float_value(mrb, INFINITY); - if (a < 0) return mrb_float_value(mrb, INFINITY); - return mrb_float_value(mrb, NAN); -#endif + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); } fixdivmod(mrb, a, b, NULL, &mod); return mrb_fixnum_value(mod); } -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); #else else { @@ -929,42 +1033,35 @@ fix_mod(mrb_state *mrb, mrb_value x) * See <code>Numeric#divmod</code>. */ static mrb_value -fix_divmod(mrb_state *mrb, mrb_value x) +int_divmod(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); - if (mrb_fixnum_p(y)) { + if (mrb_integer_p(y)) { mrb_int div, mod; - if (mrb_fixnum(y) == 0) { -#ifdef MRB_WITHOUT_FLOAT - return mrb_assoc_new(mrb, mrb_fixnum_value(0), mrb_fixnum_value(0)); -#else - return mrb_assoc_new(mrb, ((mrb_fixnum(x) == 0) ? - mrb_float_value(mrb, NAN): - mrb_float_value(mrb, INFINITY)), - mrb_float_value(mrb, NAN)); -#endif + if (mrb_integer(y) == 0) { + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); } - fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); - return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); + fixdivmod(mrb, mrb_integer(x), mrb_integer(y), &div, &mod); + return mrb_assoc_new(mrb, mrb_int_value(mrb, div), mrb_int_value(mrb, mod)); } -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); #else else { mrb_float div, mod; mrb_value a, b; - flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod); - a = mrb_int_value(mrb, div); + flodivmod(mrb, (mrb_float)mrb_integer(x), mrb_to_flo(mrb, y), &div, &mod); + a = mrb_int_value(mrb, (mrb_int)div); b = mrb_float_value(mrb, mod); return mrb_assoc_new(mrb, a, b); } #endif } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT static mrb_value flo_divmod(mrb_state *mrb, mrb_value x) { @@ -973,7 +1070,7 @@ flo_divmod(mrb_state *mrb, mrb_value x) mrb_value a, b; flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod); - a = mrb_int_value(mrb, div); + a = mrb_int_value(mrb, (mrb_int)div); b = mrb_float_value(mrb, mod); return mrb_assoc_new(mrb, a, b); } @@ -992,16 +1089,16 @@ flo_divmod(mrb_state *mrb, mrb_value x) */ static mrb_value -fix_equal(mrb_state *mrb, mrb_value x) +int_equal(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); switch (mrb_type(y)) { - case MRB_TT_FIXNUM: - return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); -#ifndef MRB_WITHOUT_FLOAT + case MRB_TT_INTEGER: + return mrb_bool_value(mrb_integer(x) == mrb_integer(y)); +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: - return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y)); + return mrb_bool_value((mrb_float)mrb_integer(x) == mrb_float(y)); #endif default: return mrb_false_value(); @@ -1020,24 +1117,24 @@ fix_equal(mrb_state *mrb, mrb_value x) */ static mrb_value -fix_rev(mrb_state *mrb, mrb_value num) +int_rev(mrb_state *mrb, mrb_value num) { - mrb_int val = mrb_fixnum(num); + mrb_int val = mrb_integer(num); - return mrb_fixnum_value(~val); + return mrb_int_value(mrb, ~val); } -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT #define bit_op(x,y,op1,op2) do {\ - return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\ + return mrb_int_value(mrb, (mrb_integer(x) op2 mrb_integer(y)));\ } while(0) #else static mrb_value flo_and(mrb_state *mrb, mrb_value x); static mrb_value flo_or(mrb_state *mrb, mrb_value x); static mrb_value flo_xor(mrb_state *mrb, mrb_value x); #define bit_op(x,y,op1,op2) do {\ - if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\ - return flo_ ## op1(mrb, mrb_float_value(mrb, (mrb_float)mrb_fixnum(x)));\ + if (mrb_integer_p(y)) return mrb_int_value(mrb, (mrb_integer(x) op2 mrb_integer(y))); \ + return flo_ ## op1(mrb, mrb_float_value(mrb, (mrb_float)mrb_integer(x)));\ } while(0) #endif @@ -1050,7 +1147,7 @@ static mrb_value flo_xor(mrb_state *mrb, mrb_value x); */ static mrb_value -fix_and(mrb_state *mrb, mrb_value x) +int_and(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); @@ -1066,7 +1163,7 @@ fix_and(mrb_state *mrb, mrb_value x) */ static mrb_value -fix_or(mrb_state *mrb, mrb_value x) +int_or(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); @@ -1082,7 +1179,7 @@ fix_or(mrb_state *mrb, mrb_value x) */ static mrb_value -fix_xor(mrb_state *mrb, mrb_value x) +int_xor(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); @@ -1095,7 +1192,7 @@ static mrb_value lshift(mrb_state *mrb, mrb_int val, mrb_int width) { if (width < 0) { /* mrb_int overflow */ -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT return mrb_fixnum_value(0); #else return mrb_float_value(mrb, INFINITY); @@ -1104,27 +1201,27 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width) if (val > 0) { if ((width > NUMERIC_SHIFT_WIDTH_MAX) || (val > (MRB_INT_MAX >> width))) { -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT return mrb_fixnum_value(-1); #else goto bit_overflow; #endif } - return mrb_fixnum_value(val << width); + return mrb_int_value(mrb, val << width); } else { if ((width > NUMERIC_SHIFT_WIDTH_MAX) || (val <= (MRB_INT_MIN >> width))) { -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT return mrb_fixnum_value(0); #else goto bit_overflow; #endif } - return mrb_fixnum_value(val * ((mrb_int)1 << width)); + return mrb_int_value(mrb, (val * ((mrb_int)1 << width))); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT bit_overflow: { mrb_float f = (mrb_float)val; @@ -1137,7 +1234,7 @@ bit_overflow: } static mrb_value -rshift(mrb_int val, mrb_int width) +rshift(mrb_state *mrb, mrb_int val, mrb_int width) { if (width < 0) { /* mrb_int overflow */ return mrb_fixnum_value(0); @@ -1148,7 +1245,7 @@ rshift(mrb_int val, mrb_int width) } return mrb_fixnum_value(0); } - return mrb_fixnum_value(val >> width); + return mrb_int_value(mrb, val >> width); } /* 15.2.8.3.12 */ @@ -1160,7 +1257,7 @@ rshift(mrb_int val, mrb_int width) */ static mrb_value -fix_lshift(mrb_state *mrb, mrb_value x) +int_lshift(mrb_state *mrb, mrb_value x) { mrb_int width, val; @@ -1168,10 +1265,10 @@ fix_lshift(mrb_state *mrb, mrb_value x) if (width == 0) { return x; } - val = mrb_fixnum(x); + val = mrb_integer(x); if (val == 0) return x; if (width < 0) { - return rshift(val, -width); + return rshift(mrb, val, -width); } return lshift(mrb, val, width); } @@ -1185,7 +1282,7 @@ fix_lshift(mrb_state *mrb, mrb_value x) */ static mrb_value -fix_rshift(mrb_state *mrb, mrb_value x) +int_rshift(mrb_state *mrb, mrb_value x) { mrb_int width, val; @@ -1193,12 +1290,12 @@ fix_rshift(mrb_state *mrb, mrb_value x) if (width == 0) { return x; } - val = mrb_fixnum(x); + val = mrb_integer(x); if (val == 0) return x; if (width < 0) { return lshift(mrb, val, -width); } - return rshift(val, width); + return rshift(mrb, val, width); } /* 15.2.8.3.23 */ @@ -1210,11 +1307,11 @@ fix_rshift(mrb_state *mrb, mrb_value x) * */ -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT static mrb_value -fix_to_f(mrb_state *mrb, mrb_value num) +int_to_f(mrb_state *mrb, mrb_value num) { - return mrb_float_value(mrb, (mrb_float)mrb_fixnum(num)); + return mrb_float_value(mrb, (mrb_float)mrb_integer(num)); } /* @@ -1251,7 +1348,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) mrb_raisef(mrb, E_RANGE_ERROR, "number (%v) too big for integer", x); } } - return mrb_fixnum_value(z); + return mrb_int_value(mrb, z); } #endif @@ -1260,20 +1357,20 @@ fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { + a = mrb_integer(x); + if (mrb_integer_p(y)) { mrb_int b, c; if (a == 0) return y; - b = mrb_fixnum(y); + b = mrb_integer(y); if (mrb_int_add_overflow(a, b, &c)) { -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b); #endif } - return mrb_fixnum_value(c); + return mrb_int_value(mrb, c); } -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); #else return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y)); @@ -1283,10 +1380,10 @@ fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y) { - if (mrb_fixnum_p(x)) { + if (mrb_integer_p(x)) { return fixnum_plus(mrb, x, y); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT if (mrb_float_p(x)) { return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y)); } @@ -1305,7 +1402,7 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y) * result. */ static mrb_value -fix_plus(mrb_state *mrb, mrb_value self) +int_plus(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); @@ -1317,19 +1414,19 @@ fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { + a = mrb_integer(x); + if (mrb_integer_p(y)) { mrb_int b, c; - b = mrb_fixnum(y); + b = mrb_integer(y); if (mrb_int_sub_overflow(a, b, &c)) { -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b); #endif } - return mrb_fixnum_value(c); + return mrb_int_value(mrb, c); } -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); #else return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y)); @@ -1339,10 +1436,10 @@ fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y) { - if (mrb_fixnum_p(x)) { + if (mrb_integer_p(x)) { return fixnum_minus(mrb, x, y); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT if (mrb_float_p(x)) { return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); } @@ -1362,7 +1459,7 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y) * result. */ static mrb_value -fix_minus(mrb_state *mrb, mrb_value self) +int_minus(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); @@ -1375,7 +1472,7 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base) { char buf[MRB_INT_BIT+1]; char *b = buf + sizeof buf; - mrb_int val = mrb_fixnum(x); + mrb_int val = mrb_integer(x); mrb_value str; if (base < 2 || 36 < base) { @@ -1419,7 +1516,7 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base) * */ static mrb_value -fix_to_s(mrb_state *mrb, mrb_value self) +int_to_s(mrb_state *mrb, mrb_value self) { mrb_int base = 10; @@ -1431,26 +1528,26 @@ fix_to_s(mrb_state *mrb, mrb_value self) static mrb_int cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2) { -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT mrb_int x, y; #else mrb_float x, y; #endif -#ifdef MRB_WITHOUT_FLOAT - x = mrb_fixnum(v1); +#ifdef MRB_NO_FLOAT + x = mrb_integer(v1); #else x = mrb_to_flo(mrb, v1); #endif switch (mrb_type(v2)) { - case MRB_TT_FIXNUM: -#ifdef MRB_WITHOUT_FLOAT - y = mrb_fixnum(v2); + case MRB_TT_INTEGER: +#ifdef MRB_NO_FLOAT + y = mrb_integer(v2); #else - y = (mrb_float)mrb_fixnum(v2); + y = (mrb_float)mrb_integer(v2); #endif break; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: y = mrb_float(v2); break; @@ -1480,7 +1577,7 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2) * not comparable, it returns nil instead of raising an exception. */ static mrb_value -integral_cmp(mrb_state *mrb, mrb_value self) +num_cmp(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); mrb_int n; @@ -1497,7 +1594,7 @@ cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2) } static mrb_value -integral_lt(mrb_state *mrb, mrb_value self) +num_lt(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); mrb_int n; @@ -1509,7 +1606,7 @@ integral_lt(mrb_state *mrb, mrb_value self) } static mrb_value -integral_le(mrb_state *mrb, mrb_value self) +num_le(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); mrb_int n; @@ -1521,7 +1618,7 @@ integral_le(mrb_state *mrb, mrb_value self) } static mrb_value -integral_gt(mrb_state *mrb, mrb_value self) +num_gt(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); mrb_int n; @@ -1533,7 +1630,7 @@ integral_gt(mrb_state *mrb, mrb_value self) } static mrb_value -integral_ge(mrb_state *mrb, mrb_value self) +num_ge(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); mrb_int n; @@ -1550,7 +1647,7 @@ mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2) mrb_value v; switch (mrb_type(obj1)) { - case MRB_TT_FIXNUM: + case MRB_TT_INTEGER: case MRB_TT_FLOAT: return cmpnum(mrb, obj1, obj2); case MRB_TT_STRING: @@ -1558,10 +1655,10 @@ mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2) return -2; return mrb_str_cmp(mrb, obj1, obj2); default: - v = mrb_funcall(mrb, obj1, "<=>", 1, obj2); - if (mrb_nil_p(v) || !mrb_fixnum_p(v)) + v = mrb_funcall_id(mrb, obj1, MRB_SYM(cmp), 1, obj2); + if (mrb_nil_p(v) || !mrb_integer_p(v)) return -2; - return mrb_fixnum(v); + return mrb_integer(v); } } @@ -1585,7 +1682,7 @@ num_infinite_p(mrb_state *mrb, mrb_value self) * Returns a new float which is the sum of <code>float</code> * and <code>other</code>. */ -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT static mrb_value flo_plus(mrb_state *mrb, mrb_value x) { @@ -1599,72 +1696,81 @@ flo_plus(mrb_state *mrb, mrb_value x) void mrb_init_numeric(mrb_state *mrb) { - struct RClass *numeric, *integer, *fixnum, *integral; -#ifndef MRB_WITHOUT_FLOAT + struct RClass *numeric, *integer; +#ifndef MRB_NO_FLOAT struct RClass *fl; #endif - integral = mrb_define_module(mrb, "Integral"); - mrb_define_method(mrb, integral,"**", integral_pow, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,"/", integral_div, MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.6 */ - mrb_define_method(mrb, integral,"quo", integral_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ - mrb_define_method(mrb, integral,"div", integral_idiv, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,"<=>", integral_cmp, MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.1 */ - mrb_define_method(mrb, integral,"<", integral_lt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,"<=", integral_le, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,">", integral_gt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,">=", integral_ge, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,"__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2)); - /* Numeric Class */ numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE()); mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE()); /* Integer Class */ - integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ - MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM); + mrb->integer_class = integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ + MRB_SET_INSTANCE_TT(integer, MRB_TT_INTEGER); mrb_undef_class_method(mrb, integer, "new"); + mrb_define_method(mrb, integer, "**", int_pow, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integer, "/", int_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.6 */ + mrb_define_method(mrb, integer, "quo", int_quo, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ + mrb_define_method(mrb, integer, "div", int_div, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integer, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ + mrb_define_method(mrb, integer, "<", num_lt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integer, "<=", num_le, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integer, ">", num_gt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integer, ">=", num_ge, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); -#ifndef MRB_WITHOUT_FLOAT - mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.8 (x) */ - mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.10 (x) */ - mrb_define_method(mrb, integer, "round", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.12 (x) */ - mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.15 (x) */ +#ifndef MRB_NO_FLOAT + mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.14 */ + mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.17 */ + mrb_define_method(mrb, integer, "round", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.20 */ + mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.26 */ #endif - /* Fixnum Class */ - mrb->fixnum_class = fixnum = mrb_define_class(mrb, "Fixnum", integer); - mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ - mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ - mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ - mrb_define_method(mrb, fixnum, "%", fix_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */ - mrb_define_method(mrb, fixnum, "==", fix_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */ - mrb_define_method(mrb, fixnum, "~", fix_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */ - mrb_define_method(mrb, fixnum, "&", fix_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */ - mrb_define_method(mrb, fixnum, "|", fix_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */ - mrb_define_method(mrb, fixnum, "^", fix_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */ - mrb_define_method(mrb, fixnum, "<<", fix_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */ - mrb_define_method(mrb, fixnum, ">>", fix_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */ - mrb_define_method(mrb, fixnum, "eql?", fix_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ -#ifndef MRB_WITHOUT_FLOAT - mrb_define_method(mrb, fixnum, "to_f", fix_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */ + mrb_define_method(mrb, integer, "+", int_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ + mrb_define_method(mrb, integer, "-", int_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ + mrb_define_method(mrb, integer, "*", int_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ + mrb_define_method(mrb, integer, "%", int_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */ + mrb_define_method(mrb, integer, "==", int_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */ + mrb_define_method(mrb, integer, "~", int_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */ + mrb_define_method(mrb, integer, "&", int_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */ + mrb_define_method(mrb, integer, "|", int_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */ + mrb_define_method(mrb, integer, "^", int_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */ + mrb_define_method(mrb, integer, "<<", int_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */ + mrb_define_method(mrb, integer, ">>", int_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */ + mrb_define_method(mrb, integer, "eql?", int_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ +#ifndef MRB_NO_FLOAT + mrb_define_method(mrb, integer, "to_f", int_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */ #endif - mrb_define_method(mrb, fixnum, "to_s", fix_to_s, MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */ - mrb_define_method(mrb, fixnum, "inspect", fix_to_s, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ + mrb_define_method(mrb, integer, "to_s", int_to_s, MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */ + mrb_define_method(mrb, integer, "inspect", int_to_s, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, integer, "divmod", int_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ + mrb_define_method(mrb, integer, "__coerce_step_counter", coerce_step_counter, MRB_ARGS_REQ(2)); -#ifndef MRB_WITHOUT_FLOAT + /* Fixnum Class for compatibility */ + mrb_define_const(mrb, mrb->object_class, "Fixnum", mrb_obj_value(integer)); + +#ifndef MRB_NO_FLOAT /* Float Class */ mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT); mrb_undef_class_method(mrb, fl, "new"); - mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ - mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ - mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ - mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ - mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ + mrb_define_method(mrb, fl, "**", flo_pow, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "/", flo_div, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ + mrb_define_method(mrb, fl, "quo", flo_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ + mrb_define_method(mrb, fl, "div", flo_idiv, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ + mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.4 */ + mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ + mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ + mrb_define_method(mrb, fl, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ + mrb_define_method(mrb, fl, "<", num_lt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "<=", num_le, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, ">", num_gt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, ">=", num_ge, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ mrb_define_method(mrb, fl, "~", flo_rev, MRB_ARGS_NONE()); mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1)); @@ -1684,16 +1790,14 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ - mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, fl, "inspect", flo_inspect, MRB_ARGS_NONE()); mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE()); #ifdef INFINITY - mrb_define_const(mrb, fl, "INFINITY", mrb_float_value(mrb, INFINITY)); + mrb_define_const_id(mrb, fl, MRB_SYM(INFINITY), mrb_float_value(mrb, INFINITY)); #endif #ifdef NAN - mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN)); + mrb_define_const_id(mrb, fl, MRB_SYM(NAN), mrb_float_value(mrb, NAN)); #endif - - mrb_include_module(mrb, fl, integral); #endif } diff --git a/src/object.c b/src/object.c index 7257f402d..aaab4022d 100644 --- a/src/object.c +++ b/src/object.c @@ -19,12 +19,12 @@ mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) return TRUE; case MRB_TT_FALSE: - case MRB_TT_FIXNUM: - return (mrb_fixnum(v1) == mrb_fixnum(v2)); + case MRB_TT_INTEGER: + return (mrb_integer(v1) == mrb_integer(v2)); case MRB_TT_SYMBOL: return (mrb_symbol(v1) == mrb_symbol(v2)); -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: return (mrb_float(v1) == mrb_float(v2)); #endif @@ -47,18 +47,18 @@ mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2) mrb_value result; if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT /* value mixing with integer and float */ - if (mrb_fixnum_p(obj1)) { - if (mrb_float_p(obj2) && (mrb_float)mrb_fixnum(obj1) == mrb_float(obj2)) + if (mrb_integer_p(obj1)) { + if (mrb_float_p(obj2) && (mrb_float)mrb_integer(obj1) == mrb_float(obj2)) return TRUE; } else if (mrb_float_p(obj1)) { - if (mrb_fixnum_p(obj2) && mrb_float(obj1) == (mrb_float)mrb_fixnum(obj2)) + if (mrb_integer_p(obj2) && mrb_float(obj1) == (mrb_float)mrb_integer(obj2)) return TRUE; } #endif - result = mrb_funcall(mrb, obj1, "==", 1, obj2); + result = mrb_funcall_id(mrb, obj1, MRB_QSYM(eq), 1, obj2); if (mrb_test(result)) return TRUE; return FALSE; } @@ -94,7 +94,7 @@ mrb_true(mrb_state *mrb, mrb_value obj) static mrb_value nil_to_s(mrb_state *mrb, mrb_value obj) { - mrb_value str = mrb_str_new_frozen(mrb, 0, 0); + mrb_value str = mrb_str_new_frozen(mrb, NULL, 0); RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); return str; } @@ -315,110 +315,115 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, f, "inspect", false_to_s, MRB_ARGS_NONE()); } -static mrb_value -convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise) +static const struct types { + const enum mrb_vtype type; + const char *name; +} builtin_types[] = { +/* {MRB_TT_NIL, "nil"}, */ + {MRB_TT_FALSE, "false"}, + {MRB_TT_TRUE, "true"}, + {MRB_TT_INTEGER,"Integer"}, + {MRB_TT_SYMBOL, "Symbol"}, /* :symbol */ + {MRB_TT_MODULE, "Module"}, + {MRB_TT_OBJECT, "Object"}, + {MRB_TT_CLASS, "Class"}, + {MRB_TT_ICLASS, "iClass"}, /* internal use: mixed-in module holder */ + {MRB_TT_SCLASS, "SClass"}, + {MRB_TT_PROC, "Proc"}, +#ifndef MRB_NO_FLOAT + {MRB_TT_FLOAT, "Float"}, +#endif + {MRB_TT_ARRAY, "Array"}, + {MRB_TT_HASH, "Hash"}, + {MRB_TT_STRING, "String"}, + {MRB_TT_RANGE, "Range"}, +/* {MRB_TT_BIGNUM, "Bignum"}, */ + {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */ +/* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */ + {MRB_TT_MAXDEFINE, 0} +}; + +static const char* +type_name(enum mrb_vtype t) { - mrb_sym m = 0; + const struct types *type = builtin_types; + + while (type->type < MRB_TT_MAXDEFINE) { + if (type->type == t) return type->name; + type++; + } + return NULL; +} - m = mrb_intern_cstr(mrb, method); - if (!mrb_respond_to(mrb, val, m)) { +static mrb_value +convert_type(mrb_state *mrb, mrb_value val, const char *tname, mrb_sym method, mrb_bool raise) +{ + if (!mrb_respond_to(mrb, val, method)) { if (raise) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y into %s", val, tname); + if (tname) mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y into %s", val, tname); + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y", val); } return mrb_nil_value(); } - return mrb_funcall_argv(mrb, val, m, 0, 0); + return mrb_funcall_argv(mrb, val, method, 0, 0); } MRB_API mrb_value -mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) +mrb_type_convert(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym method) { mrb_value v; + const char *tname; if (mrb_type(val) == type) return val; + tname = type_name(type); v = convert_type(mrb, val, tname, method, TRUE); if (mrb_type(v) != type) { if (type == MRB_TT_STRING) return mrb_any_to_s(mrb, val); - mrb_raisef(mrb, E_TYPE_ERROR, "%v cannot be converted to %s by #%s", val, tname, method); + mrb_raisef(mrb, E_TYPE_ERROR, "%v cannot be converted to %s by #%n", val, tname, method); } return v; } MRB_API mrb_value -mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) +mrb_type_convert_check(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym method) { mrb_value v; if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_ISTRUCT) return val; - v = convert_type(mrb, val, tname, method, FALSE); + v = convert_type(mrb, val, type_name(type), method, FALSE); if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; } -static const struct types { - unsigned char type; - const char *name; -} builtin_types[] = { -/* {MRB_TT_NIL, "nil"}, */ - {MRB_TT_FALSE, "false"}, - {MRB_TT_TRUE, "true"}, - {MRB_TT_FIXNUM, "Fixnum"}, - {MRB_TT_SYMBOL, "Symbol"}, /* :symbol */ - {MRB_TT_MODULE, "Module"}, - {MRB_TT_OBJECT, "Object"}, - {MRB_TT_CLASS, "Class"}, - {MRB_TT_ICLASS, "iClass"}, /* internal use: mixed-in module holder */ - {MRB_TT_SCLASS, "SClass"}, - {MRB_TT_PROC, "Proc"}, -#ifndef MRB_WITHOUT_FLOAT - {MRB_TT_FLOAT, "Float"}, -#endif - {MRB_TT_ARRAY, "Array"}, - {MRB_TT_HASH, "Hash"}, - {MRB_TT_STRING, "String"}, - {MRB_TT_RANGE, "Range"}, -/* {MRB_TT_BIGNUM, "Bignum"}, */ - {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */ -/* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */ -/* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */ -/* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */ - {MRB_TT_MAXDEFINE, 0} -}; - MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) { - const struct types *type = builtin_types; - enum mrb_vtype xt; - - xt = mrb_type(x); - if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_ISTRUCT)) { - while (type->type < MRB_TT_MAXDEFINE) { - if (type->type == t) { - const char *etype; - - if (mrb_nil_p(x)) { - etype = "nil"; - } - else if (mrb_fixnum_p(x)) { - etype = "Fixnum"; - } - else if (mrb_symbol_p(x)) { - etype = "Symbol"; - } - else if (mrb_immediate_p(x)) { - etype = RSTRING_PTR(mrb_obj_as_string(mrb, x)); - } - else { - etype = mrb_obj_classname(mrb, x); - } - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)", - etype, type->name); - } - type++; - } - mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %d (%d given)", t, mrb_type(x)); + enum mrb_vtype xt = mrb_type(x); + const char *tname, *ename; + + if (t == xt) return; + + tname = type_name(t); + if (mrb_nil_p(x)) { + ename = "nil"; + } + else if (mrb_integer_p(x)) { + ename = "Fixnum"; + } + else if (mrb_symbol_p(x)) { + ename = "Symbol"; + } + else if (mrb_immediate_p(x)) { + ename = RSTRING_PTR(mrb_obj_as_string(mrb, x)); + } + else { + ename = mrb_obj_classname(mrb, x); + } + if (tname) { + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %s (expected %s)", + ename, tname); } + mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %d (%s given)", t, ename); } /* 15.3.1.3.46 */ @@ -504,8 +509,8 @@ MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val) { - if (!mrb_fixnum_p(val)) { -#ifndef MRB_WITHOUT_FLOAT + if (!mrb_integer_p(val)) { +#ifndef MRB_NO_FLOAT if (mrb_float_p(val)) { return mrb_flo_to_fixnum(mrb, val); } @@ -525,13 +530,13 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base) mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); } switch (mrb_type(val)) { -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: if (base != 0) goto arg_error; return mrb_flo_to_fixnum(mrb, val); #endif - case MRB_TT_FIXNUM: + case MRB_TT_INTEGER: if (base != 0) goto arg_error; return val; @@ -561,7 +566,7 @@ mrb_Integer(mrb_state *mrb, mrb_value val) return mrb_convert_to_integer(mrb, val, 0); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val) { @@ -569,8 +574,8 @@ mrb_Float(mrb_state *mrb, mrb_value val) mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float"); } switch (mrb_type(val)) { - case MRB_TT_FIXNUM: - return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val)); + case MRB_TT_INTEGER: + return mrb_float_value(mrb, (mrb_float)mrb_integer(val)); case MRB_TT_FLOAT: return val; @@ -579,7 +584,7 @@ mrb_Float(mrb_state *mrb, mrb_value val) return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE)); default: - return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f"); + return mrb_type_convert(mrb, val, MRB_TT_FLOAT, MRB_SYM(to_f)); } } #endif @@ -648,12 +653,12 @@ mrb_check_hash_type(mrb_state *mrb, mrb_value hash) MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { - return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0)); + return mrb_obj_as_string(mrb, mrb_funcall_id(mrb, obj, MRB_SYM(inspect), 0)); } MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2) { if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; - return mrb_test(mrb_funcall(mrb, obj1, "eql?", 1, obj2)); + return mrb_test(mrb_funcall_id(mrb, obj1, MRB_QSYM(eql_p), 1, obj2)); } diff --git a/src/print.c b/src/print.c index a75814d81..6bf7da6a5 100644 --- a/src/print.c +++ b/src/print.c @@ -60,11 +60,11 @@ mrb_print_error(mrb_state *mrb) MRB_API void mrb_show_version(mrb_state *mrb) { - printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")), stdout); + printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), MRB_SYM(MRUBY_DESCRIPTION)), stdout); } MRB_API void mrb_show_copyright(mrb_state *mrb) { - printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")), stdout); + printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), MRB_SYM(MRUBY_COPYRIGHT)), stdout); } diff --git a/src/proc.c b/src/proc.c index c00b09acf..b971b6520 100644 --- a/src/proc.c +++ b/src/proc.c @@ -14,8 +14,26 @@ static const mrb_code call_iseq[] = { OP_CALL, }; +static const mrb_irep call_irep = { + 0, /* nlocals */ + 2, /* nregs */ + 0, /* clen */ + MRB_ISEQ_NO_FREE | MRB_IREP_NO_FREE, /* flags */ + call_iseq, /* iseq */ + NULL, /* pool */ + NULL, /* syms */ + NULL, /* reps */ + NULL, /* lv */ + NULL, /* debug_info */ + 1, /* ilen */ + 0, /* plen */ + 0, /* slen */ + 1, /* rlen */ + 0, /* refcnt */ +}; + struct RProc* -mrb_proc_new(mrb_state *mrb, mrb_irep *irep) +mrb_proc_new(mrb_state *mrb, const mrb_irep *irep) { struct RProc *p; mrb_callinfo *ci = mrb->c->ci; @@ -34,7 +52,7 @@ mrb_proc_new(mrb_state *mrb, mrb_irep *irep) p->e.target_class = tc; } p->body.irep = irep; - mrb_irep_incref(mrb, irep); + mrb_irep_incref(mrb, (mrb_irep*)irep); return p; } @@ -44,7 +62,7 @@ env_new(mrb_state *mrb, mrb_int nlocals) { struct REnv *e; mrb_callinfo *ci = mrb->c->ci; - int bidx; + mrb_int bidx; e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL); MRB_ENV_SET_LEN(e, nlocals); @@ -63,7 +81,7 @@ static void closure_setup(mrb_state *mrb, struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; - struct RProc *up = p->upper; + const struct RProc *up = p->upper; struct REnv *e = NULL; if (ci && ci->env) { @@ -90,7 +108,7 @@ closure_setup(mrb_state *mrb, struct RProc *p) } struct RProc* -mrb_closure_new(mrb_state *mrb, mrb_irep *irep) +mrb_closure_new(mrb_state *mrb, const mrb_irep *irep) { struct RProc *p = mrb_proc_new(mrb, irep); @@ -153,7 +171,7 @@ mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals) MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx) { - struct RProc *p = mrb->c->ci->proc; + const struct RProc *p = mrb->c->ci->proc; struct REnv *e; if (!p || !MRB_PROC_CFUNC_P(p)) { @@ -181,7 +199,7 @@ mrb_proc_copy(struct RProc *a, struct RProc *b) a->flags = b->flags; a->body = b->body; if (!MRB_PROC_CFUNC_P(a) && a->body.irep) { - a->body.irep->refcnt++; + mrb_irep_incref(NULL, (mrb_irep*)a->body.irep); } a->upper = b->upper; a->e.env = b->e.env; @@ -200,7 +218,7 @@ mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class) p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class)); mrb_proc_copy(p, mrb_proc_ptr(blk)); proc = mrb_obj_value(p); - mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, proc); + mrb_funcall_with_block(mrb, proc, MRB_SYM(initialize), 0, NULL, proc); if (!MRB_PROC_STRICT_P(p) && mrb->c->ci > mrb->c->cibase && MRB_PROC_ENV(p) == mrb->c->ci[-1].env) { p->flags |= MRB_PROC_ORPHAN; @@ -224,7 +242,7 @@ mrb_proc_init_copy(mrb_state *mrb, mrb_value self) static mrb_value proc_arity(mrb_state *mrb, mrb_value self) { - return mrb_fixnum_value(mrb_proc_arity(mrb_proc_ptr(self))); + return mrb_int_value(mrb, mrb_proc_arity(mrb_proc_ptr(self))); } /* 15.3.1.2.6 */ @@ -262,7 +280,7 @@ proc_lambda(mrb_state *mrb, mrb_value self) mrb_int mrb_proc_arity(const struct RProc *p) { - struct mrb_irep *irep; + const mrb_irep *irep; const mrb_code *pc; mrb_aspec aspec; int ma, op, ra, pa, arity; @@ -293,40 +311,20 @@ mrb_proc_arity(const struct RProc *p) return arity; } -static void -tempirep_free(mrb_state *mrb, void *p) -{ - if (p) mrb_irep_free(mrb, (mrb_irep *)p); -} - -static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free }; - void mrb_init_proc(mrb_state *mrb) { struct RProc *p; mrb_method_t m; - struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); - mrb_irep *call_irep; - static const mrb_irep mrb_irep_zero = { 0 }; - - call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); - irep_obj->data = call_irep; - *call_irep = mrb_irep_zero; - call_irep->flags = MRB_ISEQ_NO_FREE; - call_irep->iseq = call_iseq; - call_irep->ilen = 1; - call_irep->nregs = 2; /* receiver and block */ mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE()); - p = mrb_proc_new(mrb, call_irep); - irep_obj->data = NULL; + p = mrb_proc_new(mrb, &call_irep); MRB_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m); + mrb_define_method_raw(mrb, mrb->proc_class, MRB_SYM(call), m); + mrb_define_method_raw(mrb, mrb->proc_class, MRB_QSYM(aref), m); mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.2.6 */ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.3.27 */ diff --git a/src/range.c b/src/range.c index 0b4e6dbca..c06a8a00b 100644 --- a/src/range.c +++ b/src/range.c @@ -23,11 +23,11 @@ r_check(mrb_state *mrb, mrb_value a, mrb_value b) ta = mrb_type(a); tb = mrb_type(b); -#ifdef MRB_WITHOUT_FLOAT - if (ta == MRB_TT_FIXNUM && tb == MRB_TT_FIXNUM ) { +#ifdef MRB_NO_FLOAT + if (ta == MRB_TT_INTEGER && tb == MRB_TT_INTEGER ) { #else - if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) && - (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) { + if ((ta == MRB_TT_INTEGER || ta == MRB_TT_FLOAT) && + (tb == MRB_TT_INTEGER || tb == MRB_TT_FLOAT)) { #endif return; } @@ -78,7 +78,7 @@ range_ptr_init(mrb_state *mrb, struct RRange *r, mrb_value beg, mrb_value end, m if (r) { if (RANGE_INITIALIZED_P(r)) { /* Ranges are immutable, so that they should be initialized only once. */ - mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "'initialize' called twice"); + mrb_name_error(mrb, MRB_SYM(initialize), "'initialize' called twice"); } else { range_ptr_alloc_edges(mrb, r); @@ -328,8 +328,8 @@ mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, con result = mrb_ary_new(mrb); for (i = 0; i < argc; ++i) { - if (mrb_fixnum_p(argv[i])) { - mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i]))); + if (mrb_integer_p(argv[i])) { + mrb_ary_push(mrb, result, func(mrb, obj, mrb_integer(argv[i]))); } else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == MRB_RANGE_OK) { mrb_int const end = olen < beg + len ? olen : beg + len; diff --git a/src/state.c b/src/state.c index 790f7ca13..1f85448a1 100644 --- a/src/state.c +++ b/src/state.c @@ -107,12 +107,14 @@ void mrb_free_symtbl(mrb_state *mrb); void mrb_irep_incref(mrb_state *mrb, mrb_irep *irep) { + if (irep->flags & MRB_IREP_NO_FREE) return; irep->refcnt++; } void mrb_irep_decref(mrb_state *mrb, mrb_irep *irep) { + if (irep->flags & MRB_IREP_NO_FREE) return; irep->refcnt--; if (irep->refcnt == 0) { mrb_irep_free(mrb, irep); @@ -122,12 +124,14 @@ mrb_irep_decref(mrb_state *mrb, mrb_irep *irep) void mrb_irep_cutref(mrb_state *mrb, mrb_irep *irep) { - mrb_irep *tmp; + mrb_irep **reps; int i; + if (irep->flags & MRB_IREP_NO_FREE) return; + reps = (mrb_irep**)irep->reps; for (i=0; i<irep->rlen; i++) { - tmp = irep->reps[i]; - irep->reps[i] = NULL; + mrb_irep *tmp = reps[i]; + reps[i] = NULL; if (tmp) mrb_irep_decref(mrb, tmp); } } @@ -137,29 +141,26 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) { int i; + if (irep->flags & MRB_IREP_NO_FREE) return; if (!(irep->flags & MRB_ISEQ_NO_FREE)) mrb_free(mrb, (void*)irep->iseq); - if (irep->pool) for (i=0; i<irep->plen; i++) { - if (mrb_string_p(irep->pool[i])) { - mrb_gc_free_str(mrb, RSTRING(irep->pool[i])); - mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); + if (irep->pool) { + for (i=0; i<irep->plen; i++) { + if ((irep->pool[i].tt & 3) == IREP_TT_STR) { + mrb_free(mrb, (void*)irep->pool[i].u.str); + } } -#if defined(MRB_WORD_BOXING) && !defined(MRB_WITHOUT_FLOAT) - else if (mrb_float_p(irep->pool[i])) { - mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); - } -#endif + mrb_free(mrb, (void*)irep->pool); } - mrb_free(mrb, irep->pool); - mrb_free(mrb, irep->syms); + mrb_free(mrb, (void*)irep->syms); if (irep->reps) { for (i=0; i<irep->rlen; i++) { if (irep->reps[i]) - mrb_irep_decref(mrb, irep->reps[i]); + mrb_irep_decref(mrb, (mrb_irep*)irep->reps[i]); } + mrb_free(mrb, (void*)irep->reps); } - mrb_free(mrb, irep->reps); - mrb_free(mrb, irep->lv); + mrb_free(mrb, (void*)irep->lv); mrb_debug_info_free(mrb, irep->debug_info); mrb_free(mrb, irep); } @@ -170,8 +171,6 @@ mrb_free_context(mrb_state *mrb, struct mrb_context *c) if (!c) return; mrb_free(mrb, c->stbase); mrb_free(mrb, c->cibase); - mrb_free(mrb, c->rescue); - mrb_free(mrb, c->ensure); mrb_free(mrb, c); } diff --git a/src/string.c b/src/string.c index c83e791b6..f27145296 100644 --- a/src/string.c +++ b/src/string.c @@ -8,7 +8,7 @@ # define _CRT_NONSTDC_NO_DEPRECATE #endif -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT #include <float.h> #include <math.h> #endif @@ -583,9 +583,6 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s) else if (RSTR_FSHARED_P(orig)) { str_init_fshared(orig, s, orig->as.heap.aux.fshared); } - else if (mrb_frozen_p(orig) && !RSTR_POOL_P(orig)) { - str_init_fshared(orig, s, orig); - } else { if (orig->as.heap.aux.capa > orig->as.heap.len) { orig->as.heap.ptr = (char *)mrb_realloc(mrb, orig->as.heap.ptr, len+1); @@ -597,29 +594,6 @@ str_share(mrb_state *mrb, struct RString *orig, struct RString *s) } mrb_value -mrb_str_pool(mrb_state *mrb, const char *p, mrb_int len, mrb_bool nofree) -{ - struct RString *s = (struct RString *)mrb_malloc(mrb, sizeof(struct RString)); - - s->tt = MRB_TT_STRING; - s->c = mrb->string_class; - s->flags = 0; - - if (RSTR_EMBEDDABLE_P(len)) { - str_init_embed(s, p, len); - } - else if (nofree) { - str_init_nofree(s, p, len); - } - else { - str_init_normal(mrb, s, p, len); - } - RSTR_SET_POOL_FLAG(s); - MRB_SET_FROZEN_FLAG(s); - return mrb_obj_value(s); -} - -mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) { struct RString *orig, *s; @@ -898,7 +872,7 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0) MRB_API void mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) { - other = mrb_str_to_str(mrb, other); + other = mrb_obj_as_string(mrb, other); mrb_str_cat_str(mrb, self, other); } @@ -1111,30 +1085,11 @@ mrb_str_equal_m(mrb_state *mrb, mrb_value str1) } /* ---------------------------------- */ -MRB_API mrb_value -mrb_str_to_str(mrb_state *mrb, mrb_value str) -{ - switch (mrb_type(str)) { - case MRB_TT_STRING: - return str; - case MRB_TT_SYMBOL: - return mrb_sym_str(mrb, mrb_symbol(str)); - case MRB_TT_FIXNUM: - return mrb_fixnum_to_str(mrb, str, 10); - case MRB_TT_SCLASS: - case MRB_TT_CLASS: - case MRB_TT_MODULE: - return mrb_mod_to_s(mrb, str); - default: - return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s"); - } -} - /* obslete: use RSTRING_PTR() */ MRB_API const char* mrb_string_value_ptr(mrb_state *mrb, mrb_value str) { - str = mrb_str_to_str(mrb, str); + str = mrb_obj_as_string(mrb, str); return RSTRING_PTR(str); } @@ -1180,8 +1135,8 @@ str_convert_range(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, } else { switch (mrb_type(indx)) { - case MRB_TT_FIXNUM: - *beg = mrb_fixnum(indx); + case MRB_TT_INTEGER: + *beg = mrb_integer(indx); *len = 1; return STR_CHAR_RANGE; @@ -1196,8 +1151,8 @@ str_convert_range(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, default: indx = mrb_to_int(mrb, indx); - if (mrb_fixnum_p(indx)) { - *beg = mrb_fixnum(indx); + if (mrb_integer_p(indx)) { + *beg = mrb_integer(indx); *len = 1; return STR_CHAR_RANGE; } @@ -1212,7 +1167,7 @@ range_arg: break; } - mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Fixnum"); + mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Integer"); } } return STR_OUT_OF_RANGE; @@ -1256,8 +1211,8 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen) * str.slice(range) => new_str or nil * str.slice(other_str) => new_str or nil * - * Element Reference---If passed a single <code>Fixnum</code>, returns the code - * of the character at that position. If passed two <code>Fixnum</code> + * Element Reference---If passed a single <code>Integer</code>, returns the code + * of the character at that position. If passed two <code>Integer</code> * objects, returns a substring starting at the offset given by the first, and * a length given by the second. If given a range, a substring containing * characters at offsets given by the range is returned. In all three cases, if @@ -1963,7 +1918,20 @@ mrb_str_intern(mrb_state *mrb, mrb_value self) MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj) { - return mrb_str_to_str(mrb, obj); + switch (mrb_type(obj)) { + case MRB_TT_STRING: + return obj; + case MRB_TT_SYMBOL: + return mrb_sym_str(mrb, mrb_symbol(obj)); + case MRB_TT_INTEGER: + return mrb_fixnum_to_str(mrb, obj, 10); + case MRB_TT_SCLASS: + case MRB_TT_CLASS: + case MRB_TT_MODULE: + return mrb_mod_to_s(mrb, obj); + default: + return mrb_type_convert(mrb, obj, MRB_TT_STRING, MRB_SYM(to_s)); + } } MRB_API mrb_value @@ -2391,7 +2359,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, i n *= base; n += c; if (n > (uint64_t)MRB_INT_MAX + (sign ? 0 : 1)) { -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT if (base == 10) { return mrb_float_value(mrb, mrb_str_to_dbl(mrb, mrb_str_new(mrb, str, len), badcheck)); } @@ -2502,7 +2470,7 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self) return mrb_str_to_inum(mrb, self, base, FALSE); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) { @@ -2524,8 +2492,8 @@ mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) if (!badcheck) return 0.0; x = mrb_str_len_to_inum(mrb, p, pend-p, 0, badcheck); - if (mrb_fixnum_p(x)) - d = (double)mrb_fixnum(x); + if (mrb_integer_p(x)) + d = (double)mrb_integer(x); else /* if (mrb_float_p(x)) */ d = mrb_float(x); return d; @@ -2900,7 +2868,7 @@ mrb_str_byteslice(mrb_state *mrb, mrb_value str) } } else { - beg = mrb_fixnum(mrb_to_int(mrb, a1)); + beg = mrb_integer(mrb_to_int(mrb, a1)); len = 1; empty = FALSE; } @@ -2963,7 +2931,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */ mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */ -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT mrb_define_method(mrb, s, "to_f", mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.38 */ #endif mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */ @@ -2980,7 +2948,7 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_ARG(1,1)); } -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT /* * Source code for the "strtod" library procedure. * diff --git a/src/symbol.c b/src/symbol.c index 992848797..add093d14 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -12,6 +12,59 @@ #include <mruby/dump.h> #include <mruby/class.h> +#undef MRB_PRESYM_MAX +#undef MRB_PRESYM_CSYM +#undef MRB_PRESYM_QSYM +#undef MRB_PRESYM_SYM +#define MRB_PRESYM_CSYM(sym, num) {#sym,sizeof(#sym)-1}, +#define MRB_PRESYM_QSYM(str, name, num) {str,sizeof(str)-1}, +#define MRB_PRESYM_SYM(str, num) {str,sizeof(str)-1}, + +static const struct { + const char *name; + uint16_t len; +} presym_table[] = { +#include <../build/presym.inc> + {0,0} +}; + +static mrb_sym +presym_find(const char *name, size_t len) +{ + int start = 0; + int end = MRB_PRESYM_MAX-1; + + while (start<=end) { + int mid = (start+end)/2; + size_t plen = presym_table[mid].len; + size_t tlen = (plen > len) ? len : plen; + int cmp; + + cmp = memcmp(name, presym_table[mid].name, tlen); + if (cmp == 0) { + if (len > plen) cmp = 1; + else if (len < plen) cmp = -1; + } + + if (cmp == 0) { + return mid+1; + } else if (cmp > 0) { + start = mid+1; + } else { + end = mid-1; + } + } + return 0; +} + +static const char* +presym_sym2name(mrb_sym sym, mrb_int *lenp) +{ + if (sym > MRB_PRESYM_MAX) return NULL; + if (lenp) *lenp = presym_table[sym-1].len; + return presym_table[sym-1].name; +} + /* ------------------------------------------------------ */ typedef struct symbol_name { mrb_bool lit : 1; @@ -20,20 +73,15 @@ typedef struct symbol_name { const char *name; } symbol_name; -#define SYMBOL_INLINE_BIT_POS 1 -#define SYMBOL_INLINE_LOWER_BIT_POS 2 -#define SYMBOL_INLINE (1 << (SYMBOL_INLINE_BIT_POS - 1)) -#define SYMBOL_INLINE_LOWER (1 << (SYMBOL_INLINE_LOWER_BIT_POS - 1)) -#define SYMBOL_NORMAL_SHIFT SYMBOL_INLINE_BIT_POS -#define SYMBOL_INLINE_SHIFT SYMBOL_INLINE_LOWER_BIT_POS #ifdef MRB_ENABLE_ALL_SYMBOLS +#define SYMBOL_SHIFT 0 # define SYMBOL_INLINE_P(sym) FALSE -# define SYMBOL_INLINE_LOWER_P(sym) FALSE # define sym_inline_pack(name, len) 0 # define sym_inline_unpack(sym, buf, lenp) NULL #else +#define SYMBOL_INLINE 1 +#define SYMBOL_SHIFT 1 # define SYMBOL_INLINE_P(sym) ((sym) & SYMBOL_INLINE) -# define SYMBOL_INLINE_LOWER_P(sym) ((sym) & SYMBOL_INLINE_LOWER) #endif static void @@ -50,16 +98,14 @@ static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS static mrb_sym sym_inline_pack(const char *name, size_t len) { - const size_t lower_length_max = (MRB_SYMBOL_BIT - 2) / 5; - const size_t mix_length_max = (MRB_SYMBOL_BIT - 2) / 6; + const size_t pack_length_max = (MRB_SYMBOL_BIT - 2) / 6; char c; const char *p; size_t i; mrb_sym sym = 0; - mrb_bool lower = TRUE; - if (len > lower_length_max) return 0; /* too long */ + if (len > pack_length_max) return 0; /* too long */ for (i=0; i<len; i++) { uint32_t bits; @@ -68,36 +114,21 @@ sym_inline_pack(const char *name, size_t len) p = strchr(pack_table, (int)c); if (p == 0) return 0; /* non alnum char */ bits = (uint32_t)(p - pack_table)+1; - if (bits > 27) lower = FALSE; - if (i >= mix_length_max) break; - sym |= bits<<(i*6+SYMBOL_INLINE_SHIFT); + if (i >= pack_length_max) break; + sym |= bits<<(i*6+SYMBOL_SHIFT); } - if (lower) { - sym = 0; - for (i=0; i<len; i++) { - uint32_t bits; - - c = name[i]; - p = strchr(pack_table, (int)c); - bits = (uint32_t)(p - pack_table)+1; - sym |= bits<<(i*5+SYMBOL_INLINE_SHIFT); - } - return sym | SYMBOL_INLINE | SYMBOL_INLINE_LOWER; - } - if (len > mix_length_max) return 0; return sym | SYMBOL_INLINE; } static const char* sym_inline_unpack(mrb_sym sym, char *buf, mrb_int *lenp) { - int bit_per_char = SYMBOL_INLINE_LOWER_P(sym) ? 5 : 6; int i; mrb_assert(SYMBOL_INLINE_P(sym)); - for (i=0; i<30/bit_per_char; i++) { - uint32_t bits = sym>>(i*bit_per_char+SYMBOL_INLINE_SHIFT) & ((1<<bit_per_char)-1); + for (i=0; i<5; i++) { + uint32_t bits = sym>>(i*6+SYMBOL_SHIFT) & ((1<<6)-1); if (bits == 0) break; buf[i] = pack_table[bits-1];; } @@ -130,6 +161,10 @@ find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp) symbol_name *sname; uint8_t hash; + /* presym */ + i = presym_find(name, len); + if (i > 0) return i<<SYMBOL_SHIFT; + /* inline symbol */ i = sym_inline_pack(name, len); if (i > 0) return i; @@ -142,14 +177,14 @@ find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp) do { sname = &mrb->symtbl[i]; if (sname->len == len && memcmp(sname->name, name, len) == 0) { - return i<<SYMBOL_NORMAL_SHIFT; + return (i+MRB_PRESYM_MAX)<<SYMBOL_SHIFT; } if (sname->prev == 0xff) { i -= 0xff; sname = &mrb->symtbl[i]; while (mrb->symtbl < sname) { if (sname->len == len && memcmp(sname->name, name, len) == 0) { - return (mrb_sym)(sname - mrb->symtbl)<<SYMBOL_NORMAL_SHIFT; + return (mrb_sym)(sname - mrb->symtbl)<<SYMBOL_SHIFT; } sname--; } @@ -205,7 +240,7 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) } mrb->symhash[hash] = mrb->symidx = sym; - return sym<<SYMBOL_NORMAL_SHIFT; + return (sym+MRB_PRESYM_MAX)<<SYMBOL_SHIFT; } MRB_API mrb_sym @@ -232,27 +267,51 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } -MRB_API mrb_value -mrb_check_intern(mrb_state *mrb, const char *name, size_t len) +MRB_API mrb_sym +mrb_intern_check(mrb_state *mrb, const char *name, size_t len) { mrb_sym sym; sym_validate_len(mrb, len); sym = find_symbol(mrb, name, len, NULL); - if (sym > 0) return mrb_symbol_value(sym); - return mrb_nil_value(); + if (sym > 0) return sym; + return 0; +} + +MRB_API mrb_value +mrb_check_intern(mrb_state *mrb, const char *name, size_t len) +{ + mrb_sym sym = mrb_intern_check(mrb, name, len); + if (sym == 0) return mrb_nil_value(); + return mrb_symbol_value(sym); +} + +MRB_API mrb_sym +mrb_intern_check_cstr(mrb_state *mrb, const char *name) +{ + return mrb_intern_check(mrb, name, strlen(name)); } MRB_API mrb_value mrb_check_intern_cstr(mrb_state *mrb, const char *name) { - return mrb_check_intern(mrb, name, strlen(name)); + mrb_sym sym = mrb_intern_check_cstr(mrb, name); + if (sym == 0) return mrb_nil_value(); + return mrb_symbol_value(sym); +} + +MRB_API mrb_sym +mrb_intern_check_str(mrb_state *mrb, mrb_value str) +{ + return mrb_intern_check(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } MRB_API mrb_value mrb_check_intern_str(mrb_state *mrb, mrb_value str) { - return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); + mrb_sym sym = mrb_intern_check_str(mrb, str); + if (sym == 0) return mrb_nil_value(); + return mrb_symbol_value(sym); } static const char* @@ -260,7 +319,13 @@ sym2name_len(mrb_state *mrb, mrb_sym sym, char *buf, mrb_int *lenp) { if (SYMBOL_INLINE_P(sym)) return sym_inline_unpack(sym, buf, lenp); - sym >>= SYMBOL_NORMAL_SHIFT; + sym >>= SYMBOL_SHIFT; + { + const char *name = presym_sym2name(sym, lenp); + if (name) return name; + } + sym -= MRB_PRESYM_MAX; + if (sym == 0 || mrb->symidx < sym) { if (lenp) *lenp = 0; return NULL; @@ -276,6 +341,15 @@ mrb_sym_name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) return sym2name_len(mrb, sym, mrb->symbuf, lenp); } +mrb_bool +mrb_sym_static_p(mrb_state *mrb, mrb_sym sym) +{ + if (SYMBOL_INLINE_P(sym)) return TRUE; + sym >>= SYMBOL_SHIFT; + if (sym > MRB_PRESYM_MAX) return FALSE; + return TRUE; +} + void mrb_free_symtbl(mrb_state *mrb) { @@ -497,7 +571,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym) char *sp; name = mrb_sym_name_len(mrb, id, &len); - str = mrb_str_new(mrb, 0, len+1); + str = mrb_str_new(mrb, NULL, len+1); sp = RSTRING_PTR(str); sp[0] = ':'; memcpy(sp+1, name, len); diff --git a/src/value_array.h b/src/value_array.h index bc5f28b06..6089b8aa0 100644 --- a/src/value_array.h +++ b/src/value_array.h @@ -6,6 +6,7 @@ static inline void value_move(mrb_value *s1, const mrb_value *s2, size_t n) { + if (n == 0) return; if (s1 > s2 && s1 < s2 + n) { s1 += n; diff --git a/src/variable.c b/src/variable.c index c36fea6e3..f1375fd4d 100644 --- a/src/variable.c +++ b/src/variable.c @@ -11,21 +11,16 @@ #include <mruby/string.h> #include <mruby/variable.h> -#ifndef MRB_IV_SEGMENT_SIZE -#define MRB_IV_SEGMENT_SIZE 4 -#endif - -typedef struct segment { - mrb_sym key[MRB_IV_SEGMENT_SIZE]; - mrb_value val[MRB_IV_SEGMENT_SIZE]; - struct segment *next; -} segment; +struct iv_elem { + mrb_sym key; + mrb_value val; +}; /* Instance variable table structure */ typedef struct iv_tbl { - segment *rootseg; size_t size; - size_t last_len; + size_t alloc; + struct iv_elem *table; } iv_tbl; /* Creates the instance variable table. */ @@ -36,67 +31,82 @@ iv_new(mrb_state *mrb) t = (iv_tbl*)mrb_malloc(mrb, sizeof(iv_tbl)); t->size = 0; - t->rootseg = NULL; - t->last_len = 0; + t->alloc = 0; + t->table = NULL; return t; } +static void iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val); + +static void +iv_rehash(mrb_state *mrb, iv_tbl *t) +{ + size_t old_alloc = t->alloc; + size_t new_alloc = old_alloc+1; + struct iv_elem *old_table = t->table; + + khash_power2(new_alloc); + if (old_alloc == new_alloc) return; + + t->alloc = new_alloc; + t->size = 0; + t->table = (struct iv_elem*)mrb_calloc(mrb, sizeof(struct iv_elem), new_alloc); + + for (size_t i = 0; i < old_alloc; i++) { + struct iv_elem *slot = &old_table[i]; + + /* key = 0 means empty; val = undef means deleted */ + if (slot->key != 0 && !mrb_undef_p(slot->val)) { + iv_put(mrb, t, slot->key, slot->val); + } + } + mrb_free(mrb, old_table); +} + +#define slot_empty_p(slot) ((slot)->key == 0 && !mrb_undef_p((slot)->val)) + /* Set the value for the symbol in the instance variable table. */ static void iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) { - segment *seg; - segment *prev = NULL; - segment *matched_seg = NULL; - size_t matched_idx = 0; - size_t i; + size_t hash, pos, start; + struct iv_elem *dslot = NULL; if (t == NULL) return; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_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; + if (t->alloc == 0) { + iv_rehash(mrb, t); + } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct iv_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + slot->val = val; + return; + } + else if (slot_empty_p(slot)) { + t->size++; + slot->key = sym; + slot->val = val; + return; + } + else if (!dslot && mrb_undef_p(slot->val)) { /* deleted */ + dslot = slot; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + if (dslot) { t->size++; + dslot->key = sym; + dslot->val = val; return; } - if (!matched_seg && key == 0) { - matched_seg = seg; - matched_idx = i; - } - else if (key == sym) { - seg->val[i] = val; - return; - } + /* no room */ + iv_rehash(mrb, t); + start = pos = hash & (t->alloc-1); } - prev = seg; - seg = seg->next; - } - - /* Not found */ - if (matched_seg) { - matched_seg->key[matched_idx] = sym; - matched_seg->val[matched_idx] = val; - t->size++; - return; - } - - seg = (segment*)mrb_malloc(mrb, sizeof(segment)); - seg->next = NULL; - seg->key[0] = sym; - seg->val[0] = val; - t->last_len = 1; - t->size++; - if (prev) { - prev->next = seg; - } - else { - t->rootseg = seg; } } @@ -104,80 +114,81 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { - segment *seg; - size_t i; + size_t hash, pos, start; if (t == NULL) return FALSE; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; + if (t->alloc == 0) return FALSE; + if (t->size == 0) return FALSE; - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key == sym) { - if (vp) *vp = seg->val[i]; - return TRUE; - } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct iv_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + if (vp) *vp = slot->val; + return TRUE; + } + else if (slot_empty_p(slot)) { + return FALSE; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + return FALSE; } - seg = seg->next; } - return FALSE; } /* Deletes the value for the symbol from the instance variable table. */ static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { - segment *seg; - size_t i; + size_t hash, pos, start; if (t == NULL) return FALSE; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; + if (t->alloc == 0) return FALSE; + if (t->size == 0) return FALSE; - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key == sym) { - t->size--; - seg->key[i] = 0; - if (vp) *vp = seg->val[i]; - return TRUE; - } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct iv_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + if (vp) *vp = slot->val; + t->size--; + slot->key = 0; + slot->val = mrb_undef_value(); + return TRUE; + } + else if (slot_empty_p(slot)) { + return FALSE; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + return FALSE; } - seg = seg->next; } - return FALSE; } /* Iterates over the instance variable table. */ static void iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p) { - segment *seg; size_t i; if (t == NULL) return; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; + if (t->alloc == 0) return; + if (t->size == 0) return; - /* no value in last segment after last_len */ - if (!seg->next && i >= t->last_len) { + for (i=0; i<t->alloc; i++) { + struct iv_elem *slot = &t->table[i]; + + if (slot->key && !mrb_undef_p(slot->val)) { + if ((*func)(mrb, slot->key, slot->val, p) != 0) { return; } - if (key != 0) { - if ((*func)(mrb, key, seg->val[i], p) != 0) { - return; - } - } } - seg = seg->next; } return; } @@ -186,47 +197,28 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p) static size_t iv_size(mrb_state *mrb, iv_tbl *t) { - segment *seg; - size_t size = 0; - if (t == NULL) 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_IV_SEGMENT_SIZE; - } - /* empty iv_tbl */ - return 0; + return t->size; } /* Copy the instance variable table. */ static iv_tbl* iv_copy(mrb_state *mrb, iv_tbl *t) { - segment *seg; iv_tbl *t2; - size_t i; - seg = t->rootseg; - t2 = iv_new(mrb); + if (t == NULL) return NULL; + if (t->alloc == 0) return NULL; + if (t->size == 0) return NULL; - while (seg != NULL) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; - mrb_value val = seg->val[i]; + t2 = iv_new(mrb); + for (i=0; i<t->alloc; i++) { + struct iv_elem *slot = &t->table[i]; - if ((seg->next == NULL) && (i >= t->last_len)) { - return t2; - } - iv_put(mrb, t2, key, val); + if (slot->key && !mrb_undef_p(slot->val)) { + iv_put(mrb, t2, slot->key, slot->val); } - seg = seg->next; } return t2; } @@ -235,14 +227,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t) 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->table); mrb_free(mrb, t); } @@ -379,11 +364,11 @@ assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) if (namespace_p(obj->tt) && namespace_p(mrb_type(v))) { struct RObject *c = mrb_obj_ptr(v); if (obj != c && ISUPPER(mrb_sym_name_len(mrb, sym, NULL)[0])) { - mrb_sym id_classname = mrb_intern_lit(mrb, "__classname__"); + mrb_sym id_classname = MRB_SYM(__classname__); mrb_value o = mrb_obj_iv_get(mrb, c, id_classname); if (mrb_nil_p(o)) { - mrb_sym id_outer = mrb_intern_lit(mrb, "__outer__"); + mrb_sym id_outer = MRB_SYM(__outer__); o = mrb_obj_iv_get(mrb, c, id_outer); if (mrb_nil_p(o)) { @@ -643,8 +628,7 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym) if (cls && cls->tt == MRB_TT_SCLASS) { mrb_value klass; - klass = mrb_obj_iv_get(mrb, (struct RObject *)cls, - mrb_intern_lit(mrb, "__attached__")); + klass = mrb_obj_iv_get(mrb, (struct RObject *)cls, MRB_SYM(__attached__)); c = mrb_class_ptr(klass); if (c->tt == MRB_TT_CLASS || c->tt == MRB_TT_MODULE) { given = FALSE; @@ -688,8 +672,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) if (cls && cls->tt == MRB_TT_SCLASS) { mrb_value klass; - klass = mrb_obj_iv_get(mrb, (struct RObject*)cls, - mrb_intern_lit(mrb, "__attached__")); + klass = mrb_obj_iv_get(mrb, (struct RObject*)cls, MRB_SYM(__attached__)); switch (mrb_type(klass)) { case MRB_TT_CLASS: case MRB_TT_MODULE: @@ -743,11 +726,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) { struct RClass *c; - struct RProc *p = mrb->c->ci->proc; + const struct RProc *p = mrb->c->ci->proc; for (;;) { c = MRB_PROC_TARGET_CLASS(p); - if (c->tt != MRB_TT_SCLASS) break; + if (c && c->tt != MRB_TT_SCLASS) break; p = p->upper; } return mrb_mod_cv_get(mrb, c, sym); @@ -757,11 +740,11 @@ void mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { struct RClass *c; - struct RProc *p = mrb->c->ci->proc; + const struct RProc *p = mrb->c->ci->proc; for (;;) { c = MRB_PROC_TARGET_CLASS(p); - if (c->tt != MRB_TT_SCLASS) break; + if (c && c->tt != MRB_TT_SCLASS) break; p = p->upper; } mrb_mod_cv_set(mrb, c, sym, v); @@ -803,7 +786,7 @@ L_RETRY: goto L_RETRY; } name = mrb_symbol_value(sym); - return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name); + return mrb_funcall_argv(mrb, mrb_obj_value(base), MRB_SYM(const_missing), 1, &name); } MRB_API mrb_value @@ -819,9 +802,10 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) struct RClass *c; struct RClass *c2; mrb_value v; - struct RProc *proc; + const struct RProc *proc; c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + if (!c) c = mrb->object_class; if (iv_get(mrb, c->iv, sym, &v)) { return v; } @@ -829,7 +813,7 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) while (c2 && c2->tt == MRB_TT_SCLASS) { mrb_value klass; - if (!iv_get(mrb, c2->iv, mrb_intern_lit(mrb, "__attached__"), &klass)) { + if (!iv_get(mrb, c2->iv, MRB_SYM(__attached__), &klass)) { c2 = NULL; break; } @@ -864,6 +848,7 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) struct RClass *c; c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + if (!c) c = mrb->object_class; mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); } @@ -875,6 +860,12 @@ mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym) } MRB_API void +mrb_define_const_id(mrb_state *mrb, struct RClass *mod, mrb_sym name, mrb_value v) +{ + mrb_obj_iv_set(mrb, (struct RObject*)mod, name, v); +} + +MRB_API 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_cstr(mrb, name), v); @@ -1070,7 +1061,7 @@ outer_class(mrb_state *mrb, struct RClass *c) { mrb_value ov; - ov = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__")); + ov = mrb_obj_iv_get(mrb, (struct RObject*)c, MRB_SYM(__outer__)); if (mrb_nil_p(ov)) return NULL; switch (mrb_type(ov)) { case MRB_TT_CLASS: @@ -1120,8 +1111,8 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) str = mrb_sym_name_len(mrb, name, &len); mrb_str_cat(mrb, path, str, len); if (RSTRING_PTR(path)[0] != '#') { - iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL); - iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path); + iv_del(mrb, c->iv, MRB_SYM(__outer__), NULL); + iv_put(mrb, c->iv, MRB_SYM(__classname__), path); mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path); path = mrb_str_dup(mrb, path); } @@ -1131,16 +1122,9 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) size_t mrb_obj_iv_tbl_memsize(mrb_state* mrb, mrb_value obj) { - size_t nseg = 0; - segment *seg; - - if (mrb_obj_ptr(obj)->iv == NULL) return 0; - seg = mrb_obj_ptr(obj)->iv->rootseg; - while (seg) { - nseg++; - seg = seg->next; - } - return sizeof(iv_tbl) + sizeof(segment)*nseg; + iv_tbl *t = mrb_obj_ptr(obj)->iv; + if (t == NULL) return 0; + return sizeof(iv_tbl) + t->alloc*sizeof(struct iv_elem); } #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) @@ -6,7 +6,7 @@ #include <stddef.h> #include <stdarg.h> -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT #include <math.h> #endif #include <mruby.h> @@ -23,6 +23,7 @@ #include <mruby/opcode.h> #include "value_array.h" #include <mruby/throw.h> +#include <mruby/dump.h> #ifdef MRB_DISABLE_STDIO #if defined(__cplusplus) @@ -222,9 +223,9 @@ mrb_stack_extend(mrb_state *mrb, mrb_int room) } static inline struct REnv* -uvenv(mrb_state *mrb, int up) +uvenv(mrb_state *mrb, mrb_int up) { - struct RProc *proc = mrb->c->ci->proc; + const struct RProc *proc = mrb->c->ci->proc; struct REnv *e; while (up--) { @@ -247,8 +248,8 @@ uvenv(mrb_state *mrb, int up) return NULL; } -static inline struct RProc* -top_proc(mrb_state *mrb, struct RProc *proc) +static inline const struct RProc* +top_proc(mrb_state *mrb, const struct RProc *proc) { while (proc->upper) { if (MRB_PROC_SCOPE_P(proc) || MRB_PROC_STRICT_P(proc)) @@ -263,8 +264,8 @@ top_proc(mrb_state *mrb, struct RProc *proc) #define CI_ACC_RESUMED -3 static inline mrb_callinfo* -cipush(mrb_state *mrb, const mrb_code *pc, int push_stacks, int acc, - struct RClass *target_class, struct RProc *proc, mrb_sym mid, int argc) +cipush(mrb_state *mrb, const mrb_code *pc, mrb_int push_stacks, mrb_int acc, + struct RClass *target_class, const struct RProc *proc, mrb_sym mid, mrb_int argc) { struct mrb_context *c = mrb->c; mrb_callinfo *ci = c->ci; @@ -280,8 +281,6 @@ cipush(mrb_state *mrb, const mrb_code *pc, int push_stacks, int acc, ci->mid = mid; ci->proc = proc; ci->stackent = c->stack; - ci->epos = c->eidx; - ci->ridx = ci[-1].ridx; ci->pc = pc; ci->argc = argc; ci->acc = acc; @@ -327,55 +326,7 @@ cipop(mrb_state *mrb) } void mrb_exc_set(mrb_state *mrb, mrb_value exc); -static mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self); - -static void -ecall(mrb_state *mrb) -{ - struct RProc *p; - struct mrb_context *c = mrb->c; - mrb_callinfo *ci = c->ci; - struct RObject *exc; - struct REnv *env; - ptrdiff_t cioff; - int ai = mrb_gc_arena_save(mrb); - uint16_t i; - int nregs; - - if (c->eidx == 0) return; - i = --c->eidx; - - /* restrict total call depth of ecall() */ - if (++mrb->ecall_nest > MRB_ECALL_DEPTH_MAX) { - mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); - } - p = c->ensure[i]; - if (!p) return; - mrb_assert(!MRB_PROC_CFUNC_P(p)); - c->ensure[i] = NULL; - nregs = p->upper->body.irep->nregs; - if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc) && - ci->proc->body.irep->nregs > nregs) { - nregs = ci->proc->body.irep->nregs; - } - cioff = ci - c->cibase; - ci = cipush(mrb, NULL, nregs, CI_ACC_SKIP, MRB_PROC_TARGET_CLASS(p), p, ci->mid, 0); - env = MRB_PROC_ENV(p); - mrb_assert(env); - exc = mrb->exc; mrb->exc = 0; - if (exc) { - mrb_gc_protect(mrb, mrb_obj_value(exc)); - } - if (mrb->c->fib) { - mrb_gc_protect(mrb, mrb_obj_value(mrb->c->fib)); - } - mrb_run(mrb, p, env->stack[0]); - mrb->c = c; - c->ci = c->cibase + cioff; - if (!mrb->exc) mrb->exc = exc; - mrb_gc_arena_restore(mrb, ai); - mrb->ecall_nest--; -} +static mrb_value mrb_run(mrb_state *mrb, const struct RProc* proc, mrb_value self); #ifndef MRB_FUNCALL_ARGC_MAX #define MRB_FUNCALL_ARGC_MAX 16 @@ -401,11 +352,30 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...) return mrb_funcall_argv(mrb, self, mid, argc, argv); } -static int +MRB_API mrb_value +mrb_funcall_id(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, ...) +{ + mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + va_list ap; + mrb_int i; + + if (argc > MRB_FUNCALL_ARGC_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")"); + } + + va_start(ap, argc); + for (i = 0; i < argc; i++) { + argv[i] = va_arg(ap, mrb_value); + } + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, argc, argv); +} + +static mrb_int ci_nregs(mrb_callinfo *ci) { - struct RProc *p; - int n = 0; + const struct RProc *p; + mrb_int n = 0; if (!ci) return 3; p = ci->proc; @@ -455,7 +425,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb_method_t m; struct RClass *c; mrb_callinfo *ci; - int n = ci_nregs(mrb->c->ci); + mrb_int n = ci_nregs(mrb->c->ci); ptrdiff_t voff = -1; if (!mrb->c->stack) { @@ -467,7 +437,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc c = mrb_class(mrb, self); m = mrb_method_search_vm(mrb, &c, mid); if (MRB_METHOD_UNDEF_P(m)) { - mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + mrb_sym missing = MRB_SYM(method_missing); mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); m = mrb_method_search_vm(mrb, &c, missing); if (MRB_METHOD_UNDEF_P(m)) { @@ -536,7 +506,7 @@ mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; - int keep, nregs; + mrb_int keep, nregs; mrb->c->stack[0] = self; ci->proc = p; @@ -721,7 +691,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value mrb_sym mid = mrb->c->ci->mid; mrb_callinfo *ci; mrb_value val; - int n; + mrb_int n; if (mrb_nil_p(b)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); @@ -802,17 +772,56 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const } static struct RBreak* -break_new(mrb_state *mrb, struct RProc *p, mrb_value val) +break_new(mrb_state *mrb, uint32_t tag, const struct RProc *p, mrb_value val) { struct RBreak *brk; brk = (struct RBreak*)mrb_obj_alloc(mrb, MRB_TT_BREAK, NULL); mrb_break_proc_set(brk, p); mrb_break_value_set(brk, val); + mrb_break_tag_set(brk, tag); return brk; } +#define MRB_CATCH_FILTER_RESCUE (UINT32_C(1) << MRB_CATCH_RESCUE) +#define MRB_CATCH_FILTER_ENSURE (UINT32_C(1) << MRB_CATCH_ENSURE) +#define MRB_CATCH_FILTER_ALL (MRB_CATCH_FILTER_RESCUE | MRB_CATCH_FILTER_ENSURE) + +static const struct mrb_irep_catch_handler * +catch_handler_find(mrb_state *mrb, mrb_callinfo *ci, const mrb_code *pc, uint32_t filter) +{ + const mrb_irep *irep; + ptrdiff_t xpc; + size_t cnt; + const struct mrb_irep_catch_handler *e; + +/* The comparison operators use `>` and `<=` because pc already points to the next instruction */ +#define catch_cover_p(pc, beg, end) ((pc) > (beg) && (pc) <= (end)) + + if (ci->proc == NULL || MRB_PROC_CFUNC_P(ci->proc)) return NULL; + irep = ci->proc->body.irep; + if (irep->clen < 1) return NULL; + xpc = pc - irep->iseq; + /* If it retry at the top level, pc will be 0, so check with -1 as the start position */ + mrb_assert(catch_cover_p(xpc, -1, irep->ilen)); + if (!catch_cover_p(xpc, -1, irep->ilen)) return NULL; + + /* Currently uses a simple linear search to avoid processing complexity. */ + cnt = irep->clen; + e = mrb_irep_catch_handler_table(irep) + cnt - 1; + for (; cnt > 0; cnt --, e --) { + if (((UINT32_C(1) << e->type) & filter) && + catch_cover_p(xpc, bin_to_uint16(e->begin), bin_to_uint16(e->end))) { + return e; + } + } + +#undef catch_cover_p + + return NULL; +} + typedef enum { LOCALJUMP_ERROR_RETURN = 0, LOCALJUMP_ERROR_BREAK = 1, @@ -859,6 +868,70 @@ argnum_error(mrb_state *mrb, mrb_int num) mrb_exc_set(mrb, exc); } +static mrb_bool +break_tag_p(struct RBreak *brk, uint32_t tag) +{ + return (brk != NULL && brk->tt == MRB_TT_BREAK) ? TRUE : FALSE; +} + +static void +prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb_value val) +{ + if (break_tag_p((struct RBreak*)mrb->exc, tag)) { + mrb_break_tag_set((struct RBreak*)mrb->exc, tag); + } + else { + mrb->exc = (struct RObject*)break_new(mrb, tag, proc, val); + } +} + +#define THROW_TAGGED_BREAK(mrb, tag, proc, val) \ + do { \ + prepare_tagged_break(mrb, tag, proc, val); \ + goto L_CATCH_TAGGED_BREAK; \ + } while (0) + +#define UNWIND_ENSURE(mrb, ci, pc, tag, proc, val) \ + do { \ + ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ENSURE); \ + if (ch) { \ + THROW_TAGGED_BREAK(mrb, tag, proc, val); \ + } \ + } while (0) + +/* + * CHECKPOINT_RESTORE(tag) { + * This part is executed when jumping by the same "tag" of RBreak (it is not executed the first time). + * Write the code required (initialization of variables, etc.) for the subsequent processing. + * } + * CHECKPOINT_MAIN(tag) { + * This part is always executed. + * } + * CHECKPOINT_END(tag); + * + * ... + * + * // Jump to CHECKPOINT_RESTORE with the same "tag". + * goto CHECKPOINT_LABEL_MAKE(tag); + */ + +#define CHECKPOINT_LABEL_MAKE(tag) L_CHECKPOINT_ ## tag + +#define CHECKPOINT_RESTORE(tag) \ + do { \ + if (FALSE) { \ + CHECKPOINT_LABEL_MAKE(tag): \ + do { + +#define CHECKPOINT_MAIN(tag) \ + } while (0); \ + } \ + do { + +#define CHECKPOINT_END(tag) \ + } while (0); \ + } while (0) + #define ERR_PC_SET(mrb) mrb->c->ci->err = pc0; #define ERR_PC_CLR(mrb) mrb->c->ci->err = 0; #ifdef MRB_ENABLE_DEBUG_HOOK @@ -882,15 +955,15 @@ argnum_error(mrb_state *mrb, mrb_int num) #ifndef DIRECT_THREADED #define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) { -#define CASE(insn,ops) case insn: pc0=pc++; FETCH_ ## ops ();; L_ ## insn ## _BODY: -#define NEXT break +#define CASE(insn,ops) case insn: pc0=pc++; FETCH_ ## ops (); pc_save = pc; +#define NEXT goto L_END_DISPATCH #define JUMP NEXT -#define END_DISPATCH }} +#define END_DISPATCH L_END_DISPATCH:;}} #else #define INIT_DISPATCH JUMP; return mrb_nil_value(); -#define CASE(insn,ops) L_ ## insn: pc0=pc++; FETCH_ ## ops (); L_ ## insn ## _BODY: +#define CASE(insn,ops) L_ ## insn: pc0=pc++; FETCH_ ## ops (); pc_save = pc; #define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn] #define JUMP NEXT @@ -899,13 +972,13 @@ argnum_error(mrb_state *mrb, mrb_int num) #endif MRB_API mrb_value -mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) +mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep) { - mrb_irep *irep = proc->body.irep; + const mrb_irep *irep = proc->body.irep; mrb_value result; struct mrb_context *c = mrb->c; ptrdiff_t cioff = c->ci - c->cibase; - unsigned int nregs = irep->nregs; + mrb_int nregs = irep->nregs; if (!c->stack) { stack_init(mrb); @@ -932,7 +1005,7 @@ static mrb_bool check_target_class(mrb_state *mrb) { if (!mrb->c->ci->target_class) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); + mrb_value exc = mrb_exc_new_lit(mrb, E_TYPE_ERROR, "no target class or module"); mrb_exc_set(mrb, exc); return FALSE; } @@ -942,13 +1015,14 @@ check_target_class(mrb_state *mrb) void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); MRB_API mrb_value -mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *pc) +mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) { /* mrb_assert(MRB_PROC_CFUNC_P(proc)) */ const mrb_code *pc0 = pc; - mrb_irep *irep = proc->body.irep; - mrb_value *pool = irep->pool; - mrb_sym *syms = irep->syms; + const mrb_code *volatile pc_save = pc; + const mrb_irep *irep = proc->body.irep; + const mrb_pool_value *pool = irep->pool; + const mrb_sym *syms = irep->syms; mrb_code insn; int ai = mrb_gc_arena_save(mrb); struct mrb_jmpbuf *prev_jmp = mrb->jmp; @@ -957,6 +1031,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *pc) uint16_t b; uint8_t c; mrb_sym mid; + const struct mrb_irep_catch_handler *ch; #ifdef DIRECT_THREADED static void *optable[] = { @@ -994,27 +1069,47 @@ RETRY_TRY_BLOCK: } CASE(OP_LOADL, BB) { -#ifdef MRB_WORD_BOXING - mrb_value val = pool[b]; -#ifndef MRB_WITHOUT_FLOAT - if (mrb_float_p(val)) { - val = mrb_float_value(mrb, mrb_float(val)); - } -#endif - regs[a] = val; + switch (pool[b].tt) { /* number */ + case IREP_TT_INT32: + regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i32); + break; + case IREP_TT_INT64: +#if defined(MRB_INT64) + regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i64); + break; #else - regs[a] = pool[b]; +#if defined(MRB_64BIT) + if (INT32_MIN <= pool[b].u.i64 && pool[b].u.i64 <= INT32_MAX) { + regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i64); + break; + } #endif + { + mrb_value exc = mrb_exc_new_lit(mrb, E_RUNTIME_ERROR, "integer overflow"); + mrb_exc_set(mrb, exc); + } + goto L_RAISE; +#endif +#ifndef MRB_NO_FLOAT + case IREP_TT_FLOAT: + regs[a] = mrb_float_value(mrb, pool[b].u.f); + break; +#endif + default: + /* should not happen (tt:string) */ + regs[a] = mrb_nil_value(); + break; + } NEXT; } CASE(OP_LOADI, BB) { - SET_INT_VALUE(regs[a], b); + SET_FIXNUM_VALUE(regs[a], b); NEXT; } CASE(OP_LOADINEG, BB) { - SET_INT_VALUE(regs[a], -b); + SET_FIXNUM_VALUE(regs[a], -b); NEXT; } @@ -1028,12 +1123,12 @@ RETRY_TRY_BLOCK: CASE(OP_LOADI_6,B) goto L_LOADI; CASE(OP_LOADI_7, B) { L_LOADI: - SET_INT_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0); + SET_FIXNUM_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0); NEXT; } CASE(OP_LOADI16, BS) { - SET_INT_VALUE(regs[a], (mrb_int)(int16_t)b); + SET_FIXNUM_VALUE(regs[a], (mrb_int)(int16_t)b); NEXT; } @@ -1192,32 +1287,49 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_ONERR, S) { - /* check rescue stack */ - if (mrb->c->ci->ridx == UINT16_MAX-1) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "too many nested rescues"); - mrb_exc_set(mrb, exc); - goto L_RAISE; + CASE(OP_JMPUW, S) { + CHECKPOINT_RESTORE(RBREAK_TAG_JUMP) { + struct RBreak *brk = (struct RBreak*)mrb->exc; + mrb_value target = mrb_break_value_get(brk); + mrb_assert(mrb_integer_p(target)); + a = (uint32_t)mrb_integer(target); + mrb_assert(a >= 0 && a < irep->ilen); } - /* expand rescue stack */ - if (mrb->c->rsize <= mrb->c->ci->ridx) { - if (mrb->c->rsize == 0) mrb->c->rsize = RESCUE_STACK_INIT_SIZE; - else { - mrb->c->rsize *= 2; - if (mrb->c->rsize <= mrb->c->ci->ridx) { - mrb->c->rsize = UINT16_MAX; + CHECKPOINT_MAIN(RBREAK_TAG_JUMP) { + ch = catch_handler_find(mrb, mrb->c->ci, pc, MRB_CATCH_FILTER_ENSURE); + if (ch) { + /* avoiding a jump from a catch handler into the same handler */ + if (a < bin_to_uint16(ch->begin) || a >= bin_to_uint16(ch->end)) { + THROW_TAGGED_BREAK(mrb, RBREAK_TAG_JUMP, proc, mrb_fixnum_value(a)); } } - mrb->c->rescue = (uint16_t*)mrb_realloc(mrb, mrb->c->rescue, sizeof(uint16_t)*mrb->c->rsize); } - /* push rescue stack */ - mrb->c->rescue[mrb->c->ci->ridx++] = a; - NEXT; + CHECKPOINT_END(RBREAK_TAG_JUMP); + + mrb->exc = NULL; /* clear break object */ + pc = irep->iseq + a; + JUMP; } CASE(OP_EXCEPT, B) { - mrb_value exc = mrb_obj_value(mrb->exc); - mrb->exc = 0; + mrb_value exc; + + if (mrb->exc == NULL) { + exc = mrb_nil_value(); + } + else { + switch (mrb->exc->tt) { + case MRB_TT_BREAK: + case MRB_TT_EXCEPTION: + exc = mrb_obj_value(mrb->exc); + break; + default: + mrb_assert(!"bad mrb_type"); + exc = mrb_nil_value(); + break; + } + mrb->exc = NULL; + } regs[a] = exc; NEXT; } @@ -1234,7 +1346,7 @@ RETRY_TRY_BLOCK: { mrb_value exc; - exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, + exc = mrb_exc_new_lit(mrb, E_TYPE_ERROR, "class or module required for rescue clause"); mrb_exc_set(mrb, exc); goto L_RAISE; @@ -1245,74 +1357,19 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_POPERR, B) { - mrb->c->ci->ridx -= a; - NEXT; - } - - CASE(OP_RAISE, B) { - mrb_exc_set(mrb, regs[a]); - goto L_RAISE; - } - - CASE(OP_EPUSH, B) { - struct RProc *p; - - p = mrb_closure_new(mrb, irep->reps[a]); - /* check ensure stack */ - if (mrb->c->eidx == UINT16_MAX-1) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "too many nested ensures"); - mrb_exc_set(mrb, exc); - goto L_RAISE; + CASE(OP_RAISEIF, B) { + mrb_value exc = regs[a]; + if (mrb_break_p(exc)) { + mrb->exc = mrb_obj_ptr(exc); + goto L_BREAK; } - /* expand ensure stack */ - if (mrb->c->esize <= mrb->c->eidx+1) { - if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE; - else { - mrb->c->esize *= 2; - if (mrb->c->esize <= mrb->c->eidx) { - mrb->c->esize = UINT16_MAX; - } - } - mrb->c->ensure = (struct RProc**)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*)*mrb->c->esize); + mrb_exc_set(mrb, exc); + if (mrb->exc) { + goto L_RAISE; } - /* push ensure stack */ - mrb->c->ensure[mrb->c->eidx++] = p; - mrb->c->ensure[mrb->c->eidx] = NULL; - mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_EPOP, B) { - mrb_callinfo *ci = mrb->c->ci; - unsigned int n, epos = ci->epos; - mrb_value self = regs[0]; - struct RClass *target_class = ci->target_class; - - if (mrb->c->eidx <= epos) { - NEXT; - } - - if (a > (int)mrb->c->eidx - epos) - a = mrb->c->eidx - epos; - for (n=0; n<a; n++) { - int nregs = irep->nregs; - - proc = mrb->c->ensure[epos+n]; - mrb->c->ensure[epos+n] = NULL; - if (proc == NULL) continue; - irep = proc->body.irep; - ci = cipush(mrb, pc, nregs, nregs, target_class, proc, ci->mid, 0); - mrb_stack_extend(mrb, irep->nregs); - regs[0] = self; - pc = irep->iseq; - } - pool = irep->pool; - syms = irep->syms; - mrb->c->eidx = epos; - JUMP; - } - CASE(OP_SENDV, BB) { c = CALL_MAXARGS; goto L_SEND; @@ -1344,8 +1401,8 @@ RETRY_TRY_BLOCK: mid = syms[b]; L_SENDB_SYM: { - int argc = (c == CALL_MAXARGS) ? -1 : c; - int bidx = (argc < 0) ? a+2 : a+c+1; + mrb_int argc = (c == CALL_MAXARGS) ? -1 : c; + mrb_int bidx = (argc < 0) ? a+2 : a+c+1; mrb_method_t m; struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; @@ -1356,15 +1413,15 @@ RETRY_TRY_BLOCK: recv = regs[a]; blk = regs[bidx]; if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) { - blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); - /* The stack might have been reallocated during mrb_convert_type(), + blk = mrb_type_convert(mrb, blk, MRB_TT_PROC, MRB_SYM(to_proc)); + /* The stack might have been reallocated during mrb_type_convert(), see #3622 */ regs[bidx] = blk; } cls = mrb_class(mrb, recv); m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { - mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + mrb_sym missing = MRB_SYM(method_missing); m = mrb_method_search_vm(mrb, &cls, missing); if (MRB_METHOD_UNDEF_P(m) || (missing == mrb->c->ci->mid && mrb_obj_eq(mrb, regs[0], recv))) { mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1); @@ -1479,7 +1536,7 @@ RETRY_TRY_BLOCK: mrb->c->stack[0] = mrb_nil_value(); a = 0; c = OP_R_NORMAL; - goto L_OP_RETURN_BODY; + goto L_RETURN; } pool = irep->pool; syms = irep->syms; @@ -1501,13 +1558,13 @@ RETRY_TRY_BLOCK: } CASE(OP_SUPER, BB) { - int argc = (b == CALL_MAXARGS) ? -1 : b; + mrb_int argc = (b == CALL_MAXARGS) ? -1 : b; int bidx = (argc < 0) ? a+2 : a+b+1; mrb_method_t m; struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; mrb_value recv, blk; - struct RProc *p = ci->proc; + const struct RProc *p = ci->proc; mrb_sym mid = ci->mid; struct RClass* target_class = MRB_PROC_TARGET_CLASS(p); @@ -1517,37 +1574,37 @@ RETRY_TRY_BLOCK: mrb_assert(bidx < irep->nregs); if (mid == 0 || !target_class) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); + mrb_value exc = mrb_exc_new_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); mrb_exc_set(mrb, exc); goto L_RAISE; } if (target_class->tt == MRB_TT_MODULE) { target_class = ci->target_class; if (target_class->tt != MRB_TT_ICLASS) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_RUNTIME_ERROR, "superclass info lost [mruby limitations]"); + mrb_value exc = mrb_exc_new_lit(mrb, E_RUNTIME_ERROR, "superclass info lost [mruby limitations]"); mrb_exc_set(mrb, exc); goto L_RAISE; } } recv = regs[0]; if (!mrb_obj_is_kind_of(mrb, recv, target_class)) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, + mrb_value exc = mrb_exc_new_lit(mrb, E_TYPE_ERROR, "self has wrong type to call super in this context"); mrb_exc_set(mrb, exc); goto L_RAISE; } blk = regs[bidx]; if (!mrb_nil_p(blk) && !mrb_proc_p(blk)) { - blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); + blk = mrb_type_convert(mrb, blk, MRB_TT_PROC, MRB_SYM(to_proc)); /* The stack or ci stack might have been reallocated during - mrb_convert_type(), see #3622 and #3784 */ + mrb_type_convert(), see #3622 and #3784 */ regs[bidx] = blk; ci = mrb->c->ci; } cls = target_class->super; m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { - mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); + mrb_sym missing = MRB_SYM(method_missing); if (mid != missing) { cls = mrb_class(mrb, recv); @@ -1586,6 +1643,7 @@ RETRY_TRY_BLOCK: mrb_gc_arena_restore(mrb, ai); if (mrb->exc) goto L_RAISE; ci = mrb->c->ci; + mrb_assert(!mrb_break_p(v)); if (!ci->target_class) { /* return from context modifying method (resume/yield) */ if (ci->acc == CI_ACC_RESUMED) { mrb->jmp = prev_jmp; @@ -1620,18 +1678,18 @@ RETRY_TRY_BLOCK: } CASE(OP_ARGARY, BS) { - int m1 = (b>>11)&0x3f; - int r = (b>>10)&0x1; - int m2 = (b>>5)&0x1f; - int kd = (b>>4)&0x1; - int lv = (b>>0)&0xf; + mrb_int m1 = (b>>11)&0x3f; + mrb_int r = (b>>10)&0x1; + mrb_int m2 = (b>>5)&0x1f; + mrb_int kd = (b>>4)&0x1; + mrb_int lv = (b>>0)&0xf; mrb_value *stack; if (mrb->c->ci->mid == 0 || mrb->c->ci->target_class == NULL) { mrb_value exc; L_NOSUPER: - exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); + exc = mrb_exc_new_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); mrb_exc_set(mrb, exc); goto L_RAISE; } @@ -1649,13 +1707,13 @@ RETRY_TRY_BLOCK: else { mrb_value *pp = NULL; struct RArray *rest; - int len = 0; + mrb_int len = 0; if (mrb_array_p(stack[m1])) { struct RArray *ary = mrb_ary_ptr(stack[m1]); pp = ARY_PTR(ary); - len = (int)ARY_LEN(ary); + len = ARY_LEN(ary); } regs[a] = mrb_ary_new_capa(mrb, m1+len+m2+kd); rest = mrb_ary_ptr(regs[a]); @@ -1679,22 +1737,22 @@ RETRY_TRY_BLOCK: } CASE(OP_ENTER, W) { - int m1 = MRB_ASPEC_REQ(a); - int o = MRB_ASPEC_OPT(a); - int r = MRB_ASPEC_REST(a); - int m2 = MRB_ASPEC_POST(a); - int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0; + mrb_int m1 = MRB_ASPEC_REQ(a); + mrb_int o = MRB_ASPEC_OPT(a); + mrb_int r = MRB_ASPEC_REST(a); + mrb_int m2 = MRB_ASPEC_POST(a); + mrb_int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0; /* unused int b = MRB_ASPEC_BLOCK(a); */ - int argc = mrb->c->ci->argc; + mrb_int argc = mrb->c->ci->argc; mrb_value *argv = regs+1; mrb_value * const argv0 = argv; - int const len = m1 + o + r + m2; - int const blk_pos = len + kd + 1; + mrb_int const len = m1 + o + r + m2; + mrb_int const blk_pos = len + kd + 1; mrb_value *blk = &argv[argc < 0 ? 1 : argc]; - mrb_value kdict; - int kargs = kd; + mrb_value kdict = mrb_nil_value(); + mrb_int kargs = kd; /* arguments is passed with Array */ if (argc < 0) { @@ -1746,7 +1804,7 @@ RETRY_TRY_BLOCK: /* no rest arguments */ if (argc-kargs < len) { - int mlen = m2; + mrb_int mlen = m2; if (argc < m1+m2) { mlen = m1 < argc ? argc - m1 : 0; } @@ -1754,7 +1812,7 @@ RETRY_TRY_BLOCK: if (kd) regs[len + 1] = kdict; /* copy mandatory and optional arguments */ - if (argv0 != argv) { + if (argv0 != argv && argv) { value_move(®s[1], argv, argc-mlen); /* m1 + o */ } if (argc < m1) { @@ -1776,7 +1834,7 @@ RETRY_TRY_BLOCK: pc += (argc - kargs - m1 - m2)*3; } else { - int rnum = 0; + mrb_int rnum = 0; if (argv0 != argv) { regs[blk_pos] = *blk; /* move block */ if (kd) regs[len + 1] = kdict; @@ -1862,13 +1920,7 @@ RETRY_TRY_BLOCK: c = OP_R_NORMAL; L_RETURN: { - mrb_callinfo *ci; - -#define ecall_adjust() do {\ - ptrdiff_t cioff = ci - mrb->c->cibase;\ - ecall(mrb);\ - ci = mrb->c->cibase + cioff;\ -} while (0) + mrb_callinfo *ci; ci = mrb->c->ci; if (ci->mid) { @@ -1896,17 +1948,20 @@ RETRY_TRY_BLOCK: L_RAISE: ci0 = ci = mrb->c->ci; if (ci == mrb->c->cibase) { - if (ci->ridx == 0) goto L_FTOP; - goto L_RESCUE; + ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ALL); + if (ch == NULL) goto L_FTOP; + goto L_CATCH; } - while (ci[0].ridx == ci[-1].ridx) { + while ((ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ALL)) == NULL) { ci = cipop(mrb); if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } + pc = ci[1].pc; if (ci == mrb->c->cibase) { - if (ci->ridx == 0) { + ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ALL); + if (ch == NULL) { L_FTOP: /* fiber top */ if (mrb->c == mrb->root_c) { mrb->c->stack = mrb->c->stbase; @@ -1915,9 +1970,6 @@ RETRY_TRY_BLOCK: else { struct mrb_context *c = mrb->c; - while (c->eidx > ci->epos) { - ecall_adjust(); - } c->status = MRB_FIBER_TERMINATED; mrb->c = c->prev; c->prev = NULL; @@ -1926,15 +1978,13 @@ RETRY_TRY_BLOCK: } break; } - /* call ensure only when we skip this callinfo */ - if (ci[0].ridx == ci[-1].ridx) { - while (mrb->c->eidx > ci->epos) { - ecall_adjust(); - } - } } - L_RESCUE: - if (ci->ridx == 0) goto L_STOP; + L_CATCH: + if (ch == NULL) goto L_STOP; + if (FALSE) { + L_CATCH_TAGGED_BREAK: /* from THROW_TAGGED_BREAK() or UNWIND_ENSURE() */ + ci = ci0 = mrb->c->ci; + } proc = ci->proc; irep = proc->body.irep; pool = irep->pool; @@ -1943,12 +1993,11 @@ RETRY_TRY_BLOCK: mrb->c->stack = ci[1].stackent; } mrb_stack_extend(mrb, irep->nregs); - pc = irep->iseq+mrb->c->rescue[--ci->ridx]; + pc = irep->iseq + bin_to_uint16(ch->target); } else { - int acc; + mrb_int acc; mrb_value v; - struct RProc *dst; ci = mrb->c->ci; v = regs[a]; @@ -1957,7 +2006,9 @@ RETRY_TRY_BLOCK: case OP_R_RETURN: /* Fall through to OP_R_NORMAL otherwise */ if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) { - mrb_callinfo *cibase = mrb->c->cibase; + const struct RProc *dst; + mrb_callinfo *cibase; + cibase = mrb->c->cibase; dst = top_proc(mrb, proc); if (MRB_PROC_ENV_P(dst)) { @@ -1968,37 +2019,58 @@ RETRY_TRY_BLOCK: goto L_RAISE; } } + /* check jump destination */ while (cibase <= ci && ci->proc != dst) { - if (ci->acc < 0) { + if (ci->acc < 0) { /* jump cross C boudary */ localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; } ci--; } - if (ci <= cibase) { + if (ci <= cibase) { /* no jump destination */ localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; } + ci = mrb->c->ci; + while (cibase <= ci && ci->proc != dst) { + CHECKPOINT_RESTORE(RBREAK_TAG_RETURN_BLOCK) { + cibase = mrb->c->cibase; + dst = top_proc(mrb, proc); + } + CHECKPOINT_MAIN(RBREAK_TAG_RETURN_BLOCK) { + UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN_BLOCK, proc, v); + } + CHECKPOINT_END(RBREAK_TAG_RETURN_BLOCK); + pc = ci->pc; + ci = cipop(mrb); + } + proc = ci->proc; + mrb->exc = NULL; /* clear break object */ break; } /* fallthrough */ case OP_R_NORMAL: NORMAL_RETURN: if (ci == mrb->c->cibase) { - struct mrb_context *c = mrb->c; + struct mrb_context *c; + c = mrb->c; if (!c->prev) { /* toplevel return */ regs[irep->nlocals] = v; - goto L_STOP; + goto CHECKPOINT_LABEL_MAKE(RBREAK_TAG_STOP); } if (c->prev->ci == c->prev->cibase) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume"); + mrb_value exc = mrb_exc_new_lit(mrb, E_FIBER_ERROR, "double resume"); mrb_exc_set(mrb, exc); goto L_RAISE; } - while (c->eidx > 0) { - ecall(mrb); + CHECKPOINT_RESTORE(RBREAK_TAG_RETURN_TOPLEVEL) { + c = mrb->c; + } + CHECKPOINT_MAIN(RBREAK_TAG_RETURN_TOPLEVEL) { + UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN_TOPLEVEL, proc, v); } + CHECKPOINT_END(RBREAK_TAG_RETURN_TOPLEVEL); /* automatic yield at the end */ c->status = MRB_FIBER_TERMINATED; mrb->c = c->prev; @@ -2006,6 +2078,14 @@ RETRY_TRY_BLOCK: mrb->c->status = MRB_FIBER_RUNNING; ci = mrb->c->ci; } + CHECKPOINT_RESTORE(RBREAK_TAG_RETURN) { + /* do nothing */ + } + CHECKPOINT_MAIN(RBREAK_TAG_RETURN) { + UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN, proc, v); + } + CHECKPOINT_END(RBREAK_TAG_RETURN); + mrb->exc = NULL; /* clear break object */ break; case OP_R_BREAK: if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN; @@ -2013,7 +2093,7 @@ RETRY_TRY_BLOCK: mrb_value exc; L_BREAK_ERROR: - exc = mrb_exc_new_str_lit(mrb, E_LOCALJUMP_ERROR, + exc = mrb_exc_new_lit(mrb, E_LOCALJUMP_ERROR, "break from proc-closure"); mrb_exc_set(mrb, exc); goto L_RAISE; @@ -2028,9 +2108,13 @@ RETRY_TRY_BLOCK: goto L_BREAK_ERROR; } } - while (mrb->c->eidx > mrb->c->ci->epos) { - ecall_adjust(); + CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) { + /* do nothing */ + } + CHECKPOINT_MAIN(RBREAK_TAG_BREAK) { + UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK, proc, v); } + CHECKPOINT_END(RBREAK_TAG_BREAK); /* break from fiber block */ if (ci == mrb->c->cibase && ci->pc) { struct mrb_context *c = mrb->c; @@ -2040,45 +2124,64 @@ RETRY_TRY_BLOCK: ci = mrb->c->ci; } if (ci->acc < 0) { + ci = cipop(mrb); mrb_gc_arena_restore(mrb, ai); mrb->c->vmexec = FALSE; - mrb->exc = (struct RObject*)break_new(mrb, proc, v); + mrb->exc = (struct RObject*)break_new(mrb, RBREAK_TAG_BREAK, proc, v); mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } if (FALSE) { + struct RBreak *brk; + L_BREAK: - v = mrb_break_value_get((struct RBreak*)mrb->exc); - proc = mrb_break_proc_get((struct RBreak*)mrb->exc); - mrb->exc = NULL; + brk = (struct RBreak*)mrb->exc; + proc = mrb_break_proc_get(brk); + v = mrb_break_value_get(brk); ci = mrb->c->ci; + + switch (mrb_break_tag_get(brk)) { +#define DISPATCH_CHECKPOINTS(n, i) case n: goto CHECKPOINT_LABEL_MAKE(n); + RBREAK_TAG_FOREACH(DISPATCH_CHECKPOINTS) +#undef DISPATCH_CHECKPOINTS + default: + mrb_assert(!"wrong break tag"); + } } mrb->c->stack = ci->stackent; - proc = proc->upper; - while (mrb->c->cibase < ci && ci[-1].proc != proc) { + while (mrb->c->cibase < ci && ci[-1].proc != proc->upper) { if (ci[-1].acc == CI_ACC_SKIP) { - while (ci < mrb->c->ci) { - cipop(mrb); - } goto L_BREAK_ERROR; } - ci--; + CHECKPOINT_RESTORE(RBREAK_TAG_BREAK_UPPER) { + /* do nothing */ + } + CHECKPOINT_MAIN(RBREAK_TAG_BREAK_UPPER) { + UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK_UPPER, proc, v); + } + CHECKPOINT_END(RBREAK_TAG_BREAK_UPPER); + pc = ci->pc; + ci = cipop(mrb); + } + CHECKPOINT_RESTORE(RBREAK_TAG_BREAK_INTARGET) { + /* do nothing */ } + CHECKPOINT_MAIN(RBREAK_TAG_BREAK_INTARGET) { + UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK_INTARGET, proc, v); + } + CHECKPOINT_END(RBREAK_TAG_BREAK_INTARGET); if (ci == mrb->c->cibase) { goto L_BREAK_ERROR; } + mrb->exc = NULL; /* clear break object */ break; default: /* cannot happen */ break; } - while (ci < mrb->c->ci) { - cipop(mrb); - } - ci[0].ridx = ci[-1].ridx; - while (mrb->c->eidx > ci->epos) { - ecall_adjust(); - } + mrb_assert(ci == mrb->c->ci); + mrb_assert(mrb->exc == NULL); + if (mrb->c->vmexec && !ci->target_class) { mrb_gc_arena_restore(mrb, ai); mrb->c->vmexec = FALSE; @@ -2142,23 +2245,23 @@ RETRY_TRY_BLOCK: OP_MATH_CASE_STRING_##op_name(); \ default: \ c = 1; \ - mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name)); \ + mid = MRB_QSYM(op_name); \ goto L_SEND_SYM; \ } \ NEXT; #define OP_MATH_CASE_FIXNUM(op_name) \ - case TYPES2(MRB_TT_FIXNUM, MRB_TT_FIXNUM): \ + case TYPES2(MRB_TT_INTEGER, MRB_TT_INTEGER): \ { \ - mrb_int x = mrb_fixnum(regs[a]), y = mrb_fixnum(regs[a+1]), z; \ + mrb_int x = mrb_integer(regs[a]), y = mrb_integer(regs[a+1]), z; \ if (mrb_int_##op_name##_overflow(x, y, &z)) \ OP_MATH_OVERFLOW_INT(op_name, x, y, z); \ else \ - SET_INT_VALUE(regs[a], z); \ + SET_INT_VALUE(mrb,regs[a], z); \ } \ break -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT #define OP_MATH_CASE_FLOAT(op_name, t1, t2) (void)0 -#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) SET_INT_VALUE(regs[a], z) +#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) SET_INT_VALUE(mrb,regs[a], z) #else #define OP_MATH_CASE_FLOAT(op_name, t1, t2) \ case TYPES2(OP_MATH_TT_##t1, OP_MATH_TT_##t2): \ @@ -2180,7 +2283,7 @@ RETRY_TRY_BLOCK: #define OP_MATH_OP_add + #define OP_MATH_OP_sub - #define OP_MATH_OP_mul * -#define OP_MATH_TT_fixnum MRB_TT_FIXNUM +#define OP_MATH_TT_fixnum MRB_TT_INTEGER #define OP_MATH_TT_float MRB_TT_FLOAT CASE(OP_ADD, B) { @@ -2196,31 +2299,30 @@ RETRY_TRY_BLOCK: } CASE(OP_DIV, B) { -#ifndef MRB_WITHOUT_FLOAT - double x, y, f; + mrb_int mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y); +#ifndef MRB_NO_FLOAT + mrb_float mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y); + mrb_float x, y, f; #endif /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): -#ifdef MRB_WITHOUT_FLOAT + case TYPES2(MRB_TT_INTEGER,MRB_TT_INTEGER): { - mrb_int x = mrb_fixnum(regs[a]); - mrb_int y = mrb_fixnum(regs[a+1]); - SET_INT_VALUE(regs[a], y ? x / y : 0); + mrb_int x = mrb_integer(regs[a]); + mrb_int y = mrb_integer(regs[a+1]); + mrb_int div = mrb_num_div_int(mrb, x, y); + SET_INT_VALUE(mrb, regs[a], div); } - break; -#else - x = (mrb_float)mrb_fixnum(regs[a]); - y = (mrb_float)mrb_fixnum(regs[a+1]); - break; - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): - x = (mrb_float)mrb_fixnum(regs[a]); + NEXT; +#ifndef MRB_NO_FLOAT + case TYPES2(MRB_TT_INTEGER,MRB_TT_FLOAT): + x = (mrb_float)mrb_integer(regs[a]); y = mrb_float(regs[a+1]); break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): + case TYPES2(MRB_TT_FLOAT,MRB_TT_INTEGER): x = mrb_float(regs[a]); - y = (mrb_float)mrb_fixnum(regs[a+1]); + y = (mrb_float)mrb_integer(regs[a+1]); break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): x = mrb_float(regs[a]); @@ -2229,19 +2331,12 @@ RETRY_TRY_BLOCK: #endif default: c = 1; - mid = mrb_intern_lit(mrb, "/"); + mid = MRB_QSYM(div); goto L_SEND_SYM; } -#ifndef MRB_WITHOUT_FLOAT - if (y == 0) { - if (x > 0) f = INFINITY; - else if (x < 0) f = -INFINITY; - else /* if (x == 0) */ f = NAN; - } - else { - f = x / y; - } +#ifndef MRB_NO_FLOAT + f = mrb_num_div_flo(mrb, x, y); SET_FLOAT_VALUE(mrb, regs[a], f); #endif NEXT; @@ -2253,23 +2348,23 @@ RETRY_TRY_BLOCK: OP_MATHI_CASE_FIXNUM(op_name); \ OP_MATHI_CASE_FLOAT(op_name); \ default: \ - SET_INT_VALUE(regs[a+1], b); \ + SET_INT_VALUE(mrb,regs[a+1], b); \ c = 1; \ - mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name)); \ + mid = MRB_QSYM(op_name); \ goto L_SEND_SYM; \ } \ NEXT; #define OP_MATHI_CASE_FIXNUM(op_name) \ - case MRB_TT_FIXNUM: \ + case MRB_TT_INTEGER: \ { \ - mrb_int x = mrb_fixnum(regs[a]), y = (mrb_int)b, z; \ + mrb_int x = mrb_integer(regs[a]), y = (mrb_int)b, z; \ if (mrb_int_##op_name##_overflow(x, y, &z)) \ OP_MATH_OVERFLOW_INT(op_name, x, y, z); \ else \ - SET_INT_VALUE(regs[a], z); \ + SET_INT_VALUE(mrb,regs[a], z); \ } \ break -#ifdef MRB_WITHOUT_FLOAT +#ifdef MRB_NO_FLOAT #define OP_MATHI_CASE_FLOAT(op_name) (void)0 #else #define OP_MATHI_CASE_FLOAT(op_name) \ @@ -2291,17 +2386,17 @@ RETRY_TRY_BLOCK: #define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1])) -#ifdef MRB_WITHOUT_FLOAT -#define OP_CMP(op) do {\ +#ifdef MRB_NO_FLOAT +#define OP_CMP(op,sym) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ + case TYPES2(MRB_TT_INTEGER,MRB_TT_INTEGER):\ result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ break;\ default:\ c = 1;\ - mid = mrb_intern_lit(mrb, # op);\ + mid = MRB_QSYM(sym);\ goto L_SEND_SYM;\ }\ if (result) {\ @@ -2312,17 +2407,17 @@ RETRY_TRY_BLOCK: }\ } while(0) #else -#define OP_CMP(op) do {\ +#define OP_CMP(op, sym) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ + case TYPES2(MRB_TT_INTEGER,MRB_TT_INTEGER):\ result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ break;\ - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\ + case TYPES2(MRB_TT_INTEGER,MRB_TT_FLOAT):\ result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\ break;\ - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\ + case TYPES2(MRB_TT_FLOAT,MRB_TT_INTEGER):\ result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\ break;\ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\ @@ -2330,7 +2425,7 @@ RETRY_TRY_BLOCK: break;\ default:\ c = 1;\ - mid = mrb_intern_lit(mrb, # op);\ + mid = MRB_QSYM(sym);\ goto L_SEND_SYM;\ }\ if (result) {\ @@ -2347,28 +2442,28 @@ RETRY_TRY_BLOCK: SET_TRUE_VALUE(regs[a]); } else { - OP_CMP(==); + OP_CMP(==,eq); } NEXT; } CASE(OP_LT, B) { - OP_CMP(<); + OP_CMP(<,lt); NEXT; } CASE(OP_LE, B) { - OP_CMP(<=); + OP_CMP(<=,le); NEXT; } CASE(OP_GT, B) { - OP_CMP(>); + OP_CMP(>,gt); NEXT; } CASE(OP_GE, B) { - OP_CMP(>=); + OP_CMP(>=,ge); NEXT; } @@ -2480,9 +2575,13 @@ RETRY_TRY_BLOCK: } CASE(OP_STRING, BB) { - mrb_value str = mrb_str_dup(mrb, pool[b]); - - regs[a] = str; + size_t len = pool[b].tt >> 2; + if (pool[b].tt & IREP_TT_SFLAG) { + regs[a] = mrb_str_new_static(mrb, pool[b].u.str, len); + } + else { + regs[a] = mrb_str_new(mrb, pool[b].u.str, len); + } mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2530,7 +2629,7 @@ RETRY_TRY_BLOCK: L_MAKE_LAMBDA: { struct RProc *p; - mrb_irep *nirep = irep->reps[b]; + const mrb_irep *nirep = irep->reps[b]; if (c & OP_L_CAPTURE) { p = mrb_closure_new(mrb, nirep); @@ -2581,6 +2680,7 @@ RETRY_TRY_BLOCK: super = regs[a+1]; if (mrb_nil_p(base)) { baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + if (!baseclass) baseclass = mrb->object_class; base = mrb_obj_value(baseclass); } c = mrb_vm_define_class(mrb, base, super, id); @@ -2597,6 +2697,7 @@ RETRY_TRY_BLOCK: base = regs[a]; if (mrb_nil_p(base)) { baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + if (!baseclass) baseclass = mrb->object_class; base = mrb_obj_value(baseclass); } cls = mrb_vm_define_module(mrb, base, id); @@ -2608,7 +2709,7 @@ RETRY_TRY_BLOCK: CASE(OP_EXEC, BB) { mrb_value recv = regs[a]; struct RProc *p; - mrb_irep *nirep = irep->reps[b]; + const mrb_irep *nirep = irep->reps[b]; /* prepare closure */ p = mrb_proc_new(mrb, nirep); @@ -2684,56 +2785,30 @@ RETRY_TRY_BLOCK: } CASE(OP_ERR, B) { - mrb_value msg = mrb_str_dup(mrb, pool[a]); + size_t len = pool[a].tt >> 2; mrb_value exc; - exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); + mrb_assert((pool[a].tt&IREP_TT_NFLAG)==0); + exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, pool[a].u.str, len); ERR_PC_SET(mrb); mrb_exc_set(mrb, exc); goto L_RAISE; } - CASE(OP_EXT1, Z) { - insn = READ_B(); - switch (insn) { -#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); goto L_OP_ ## insn ## _BODY; -#include "mruby/ops.h" -#undef OPCODE - } - pc--; - NEXT; - } - CASE(OP_EXT2, Z) { - insn = READ_B(); - switch (insn) { -#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); goto L_OP_ ## insn ## _BODY; -#include "mruby/ops.h" -#undef OPCODE - } - pc--; - NEXT; - } - CASE(OP_EXT3, Z) { - uint8_t insn = READ_B(); - switch (insn) { -#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); goto L_OP_ ## insn ## _BODY; -#include "mruby/ops.h" -#undef OPCODE - } - pc--; - NEXT; - } - CASE(OP_STOP, Z) { /* stop VM */ - L_STOP: - while (mrb->c->eidx > 0) { - ecall(mrb); + CHECKPOINT_RESTORE(RBREAK_TAG_STOP) { + /* do nothing */ + } + CHECKPOINT_MAIN(RBREAK_TAG_STOP) { + UNWIND_ENSURE(mrb, mrb->c->ci, pc, RBREAK_TAG_STOP, proc, mrb_nil_value()); } - mrb->c->cibase->ridx = 0; + CHECKPOINT_END(RBREAK_TAG_STOP); + L_STOP: ERR_PC_CLR(mrb); mrb->jmp = prev_jmp; if (mrb->exc) { + mrb_assert(mrb->exc->tt == MRB_TT_EXCEPTION); return mrb_obj_value(mrb->exc); } return regs[irep->nlocals]; @@ -2743,14 +2818,19 @@ RETRY_TRY_BLOCK: #undef regs } MRB_CATCH(&c_jmp) { + mrb_callinfo *ci = mrb->c->ci; + while (ci > mrb->c->cibase && ci->acc == CI_ACC_DIRECT) { + ci = cipop(mrb); + } exc_catched = TRUE; + pc = pc_save; goto RETRY_TRY_BLOCK; } MRB_END_EXC(&c_jmp); } static mrb_value -mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) +mrb_run(mrb_state *mrb, const struct RProc *proc, mrb_value self) { if (mrb->c->ci->argc < 0) { return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */ @@ -2761,7 +2841,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } MRB_API mrb_value -mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) +mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep) { mrb_value v; |
