diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 60 | ||||
| -rw-r--r-- | src/backtrace.c | 4 | ||||
| -rw-r--r-- | src/class.c | 107 | ||||
| -rw-r--r-- | src/codedump.c | 4 | ||||
| -rw-r--r-- | src/debug.c | 15 | ||||
| -rw-r--r-- | src/dump.c | 68 | ||||
| -rw-r--r-- | src/error.c | 65 | ||||
| -rw-r--r-- | src/etc.c | 25 | ||||
| -rw-r--r-- | src/fmt_fp.c | 119 | ||||
| -rw-r--r-- | src/gc.c | 327 | ||||
| -rw-r--r-- | src/hash.c | 58 | ||||
| -rw-r--r-- | src/kernel.c | 87 | ||||
| -rw-r--r-- | src/load.c | 88 | ||||
| -rw-r--r-- | src/numeric.c | 145 | ||||
| -rw-r--r-- | src/object.c | 29 | ||||
| -rw-r--r-- | src/print.c | 30 | ||||
| -rw-r--r-- | src/proc.c | 33 | ||||
| -rw-r--r-- | src/range.c | 16 | ||||
| -rw-r--r-- | src/state.c | 47 | ||||
| -rw-r--r-- | src/string.c | 126 | ||||
| -rw-r--r-- | src/symbol.c | 25 | ||||
| -rw-r--r-- | src/variable.c | 21 | ||||
| -rw-r--r-- | src/vm.c | 243 |
23 files changed, 856 insertions, 886 deletions
diff --git a/src/array.c b/src/array.c index 8547cfff4..c33641264 100644 --- a/src/array.c +++ b/src/array.c @@ -522,8 +522,10 @@ mrb_ary_push_m(mrb_state *mrb, mrb_value self) } array_copy(ARY_PTR(a)+len, argv, alen); ARY_SET_LEN(a, len2); - mrb_write_barrier(mrb, (struct RBasic*)a); - + while (alen--) { + mrb_field_write_barrier_value(mrb, (struct RBasic*)a, *argv); + argv++; + } return self; } @@ -732,6 +734,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val argv = ARY_PTR(r); } } + else if (mrb_undef_p(rpl)) { + argc = 0; + argv = NULL; + } else { argc = 1; argv = &rpl; @@ -804,6 +810,13 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len) return mrb_obj_value(b); } +mrb_value +mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len) +{ + struct RArray *a = mrb_ary_ptr(ary); + return ary_subseq(mrb, a, beg, len); +} + static mrb_int aget_index(mrb_state *mrb, mrb_value index) { @@ -855,10 +868,12 @@ static mrb_value mrb_ary_aget(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - mrb_int i, len, alen; + mrb_int i; + mrb_int len, alen; mrb_value index; - if (mrb_get_args(mrb, "o|i", &index, &len) == 1) { + if (mrb_get_argc(mrb) == 1) { + index = mrb_get_arg1(mrb); switch (mrb_type(index)) { /* a[n..m] */ case MRB_TT_RANGE: @@ -875,6 +890,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) } } + mrb_get_args(mrb, "oi", &index, &len); i = aget_index(mrb, index); alen = ARY_LEN(a); if (i < 0) i += alen; @@ -927,8 +943,11 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self) mrb_value v1, v2, v3; mrb_int i, len; - mrb_ary_modify(mrb, mrb_ary_ptr(self)); - if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) { + ary_modify(mrb, mrb_ary_ptr(self)); + if (mrb_get_argc(mrb) == 2) { + mrb_value *vs = mrb_get_argv(mrb); + v1 = vs[0]; v2 = vs[1]; + /* a[n..m] = v */ switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) { case MRB_RANGE_TYPE_MISMATCH: @@ -944,6 +963,7 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self) return v2; } + mrb_get_args(mrb, "ooo", &v1, &v2, &v3); /* a[n,m] = v */ mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3); return v3; @@ -1027,10 +1047,9 @@ mrb_ary_last(mrb_state *mrb, mrb_value self) static mrb_value mrb_ary_index_m(mrb_state *mrb, mrb_value self) { - mrb_value obj; + mrb_value obj = mrb_get_arg1(mrb); mrb_int i; - mrb_get_args(mrb, "o", &obj); for (i = 0; i < RARRAY_LEN(self); i++) { if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) { return mrb_fixnum_value(i); @@ -1042,10 +1061,9 @@ mrb_ary_index_m(mrb_state *mrb, mrb_value self) static mrb_value mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) { - mrb_value obj; + mrb_value obj = mrb_get_arg1(mrb); mrb_int i, len; - mrb_get_args(mrb, "o", &obj); for (i = RARRAY_LEN(self) - 1; i >= 0; i--) { if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) { return mrb_fixnum_value(i); @@ -1060,22 +1078,26 @@ mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { - mrb_value a; + mrb_value ary; + struct RArray *a; if (mrb_array_p(v)) { - return v; + a = ary_dup(mrb, mrb_ary_ptr(v)); + return mrb_obj_value(a); } if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { return mrb_ary_new_from_values(mrb, 1, &v); } - a = mrb_funcall(mrb, v, "to_a", 0); - if (mrb_nil_p(a)) { + ary = mrb_funcall(mrb, v, "to_a", 0); + if (mrb_nil_p(ary)) { return mrb_ary_new_from_values(mrb, 1, &v); } - mrb_ensure_array_type(mrb, a); - return a; + mrb_ensure_array_type(mrb, ary); + a = mrb_ary_ptr(ary); + a = ary_dup(mrb, a); + return mrb_obj_value(a); } static mrb_value @@ -1219,9 +1241,8 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary) static mrb_value mrb_ary_eq(mrb_state *mrb, mrb_value ary1) { - mrb_value ary2; + mrb_value ary2 = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); if (!mrb_array_p(ary2)) { return mrb_false_value(); @@ -1234,9 +1255,8 @@ mrb_ary_eq(mrb_state *mrb, mrb_value ary1) static mrb_value mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) { - mrb_value ary2; + mrb_value ary2 = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0); if (!mrb_array_p(ary2)) { return mrb_nil_value(); diff --git a/src/backtrace.c b/src/backtrace.c index 186009523..591f4ea4b 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -79,7 +79,7 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr static void print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace) { - int i; + mrb_int i; mrb_int n = RARRAY_LEN(backtrace); mrb_value *loc, mesg; FILE *stream = stderr; @@ -89,7 +89,7 @@ print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace) for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) { if (mrb_string_p(*loc)) { fprintf(stream, "\t[%d] %.*s\n", - i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); + (int)i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc)); } } if (mrb_string_p(*loc)) { diff --git a/src/class.c b/src/class.c index c49f0f474..fc8a38ff9 100644 --- a/src/class.c +++ b/src/class.c @@ -549,6 +549,23 @@ mrb_get_argv(mrb_state *mrb) return array_argv; } +MRB_API mrb_value +mrb_get_arg1(mrb_state *mrb) +{ + mrb_int argc = mrb->c->ci->argc; + mrb_value *array_argv = mrb->c->stack + 1; + if (argc < 0) { + struct RArray *a = mrb_ary_ptr(*array_argv); + + argc = ARY_LEN(a); + array_argv = ARY_PTR(a); + } + if (argc != 1) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + } + return array_argv[0]; +} + void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); /* @@ -570,6 +587,7 @@ void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil z: String [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] b: boolean [mrb_bool] @@ -696,6 +714,22 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + case 'c': + { + struct RClass **p; + + p = va_arg(ap, struct RClass**); + if (i < argc) { + mrb_value ss; + + ss = argv[i++]; + if (!class_ptr_p(ss)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", ss); + } + *p = mrb_class_ptr(ss); + } + } + break; case 'S': { mrb_value *p; @@ -1134,22 +1168,22 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) static mrb_value mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod) { - mrb_value klass; + struct RClass *c; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + mrb_get_args(mrb, "c", &c); + mrb_prepend_module(mrb, c, mrb_class_ptr(mod)); return mod; } static mrb_value mrb_mod_append_features(mrb_state *mrb, mrb_value mod) { - mrb_value klass; + struct RClass *c; mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + mrb_get_args(mrb, "c", &c); + mrb_include_module(mrb, c, mrb_class_ptr(mod)); return mod; } @@ -1212,10 +1246,9 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self) static mrb_value mrb_mod_extend_object(mrb_state *mrb, mrb_value mod) { - mrb_value obj; + mrb_value obj = mrb_get_arg1(mrb); mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "o", &obj); mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod)); return mod; } @@ -1242,33 +1275,45 @@ mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod) return mod; } -MRB_API mrb_value -mrb_singleton_class(mrb_state *mrb, mrb_value v) +/* returns mrb_class_ptr(mrb_singleton_class()) */ +/* except that it return NULL for immediate values */ +MRB_API struct RClass* +mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v) { struct RBasic *obj; switch (mrb_type(v)) { case MRB_TT_FALSE: if (mrb_nil_p(v)) - return mrb_obj_value(mrb->nil_class); - return mrb_obj_value(mrb->false_class); + return mrb->nil_class; + return mrb->false_class; case MRB_TT_TRUE: - return mrb_obj_value(mrb->true_class); + return mrb->true_class; case MRB_TT_CPTR: - return mrb_obj_value(mrb->object_class); + return mrb->object_class; case MRB_TT_SYMBOL: case MRB_TT_FIXNUM: #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #endif - mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); - return mrb_nil_value(); /* not reached */ + return NULL; default: break; } obj = mrb_basic_ptr(v); prepare_singleton_class(mrb, obj); - return mrb_obj_value(obj->c); + return obj->c; +} + +MRB_API mrb_value +mrb_singleton_class(mrb_state *mrb, mrb_value v) +{ + struct RClass *c = mrb_singleton_class_ptr(mrb, v); + + if (c == NULL) { + mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); + } + return mrb_obj_value(c); } MRB_API void @@ -1481,9 +1526,8 @@ static mrb_value attr_writer(mrb_state *mrb, mrb_value obj) { mrb_value name = mrb_proc_cfunc_env_get(mrb, 0); - mrb_value val; + mrb_value val = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &val); mrb_iv_set(mrb, obj, to_sym(mrb, name), val); return val; } @@ -1651,21 +1695,11 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value self) { - mrb_value arg; + mrb_value arg = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &arg); return mrb_bool_value(mrb_obj_equal(mrb, self, arg)); } -static mrb_value -mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(!mrb_equal(mrb, self, arg)); -} - MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { @@ -1716,7 +1750,10 @@ mrb_class_real(struct RClass* cl) MRB_API const char* mrb_class_name(mrb_state *mrb, struct RClass* c) { - mrb_value name = class_name_str(mrb, c); + mrb_value name; + + if (c == NULL) return NULL; + name = class_name_str(mrb, c); return RSTRING_PTR(name); } @@ -1960,13 +1997,11 @@ mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id) static mrb_value mrb_mod_const_get(mrb_state *mrb, mrb_value mod) { - mrb_value path; + mrb_value path = mrb_get_arg1(mrb); mrb_sym id; char *ptr; mrb_int off, end, len; - mrb_get_args(mrb, "o", &path); - if (mrb_symbol_p(path)) { /* const get with symbol */ id = mrb_symbol(path); @@ -2119,10 +2154,9 @@ top_define_method(mrb_state *mrb, mrb_value self) static mrb_value mrb_mod_eqq(mrb_state *mrb, mrb_value mod) { - mrb_value obj; + mrb_value obj = mrb_get_arg1(mrb); mrb_bool eqq; - mrb_get_args(mrb, "o", &obj); eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)); return mrb_bool_value(eqq); @@ -2257,7 +2291,6 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ - mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.4 */ mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.5 */ mrb_define_method(mrb, bob, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ diff --git a/src/codedump.c b/src/codedump.c index 7faa39360..649be176b 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -130,6 +130,10 @@ codedump(mrb_state *mrb, mrb_irep *irep) printf("OP_LOADI\tR%d\t-%d\t", a, b); print_lv_a(mrb, irep, a); break; + 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): printf("OP_LOADI__1\tR%d\t\t", a); print_lv_a(mrb, irep, a); diff --git a/src/debug.c b/src/debug.c index b44c7d10e..32add68ae 100644 --- a/src/debug.c +++ b/src/debug.c @@ -64,7 +64,7 @@ mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc) } MRB_API int32_t -mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc) +mrb_debug_get_line(mrb_state *mrb, const mrb_irep *irep, size_t pc) { if (irep && pc >= 0 && pc < irep->ilen) { mrb_irep_debug_info_file* f = NULL; @@ -204,11 +204,14 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d) if (!d) { return; } - for (i = 0; i < d->flen; ++i) { - mrb_assert(d->files[i]); - mrb_free(mrb, d->files[i]->lines.ptr); - mrb_free(mrb, d->files[i]); + if (d->files) { + for (i = 0; i < d->flen; ++i) { + if (d->files[i]) { + mrb_free(mrb, d->files[i]->lines.ptr); + mrb_free(mrb, d->files[i]); + } + } + mrb_free(mrb, d->files); } - mrb_free(mrb, d->files); mrb_free(mrb, d); } diff --git a/src/dump.c b/src/dump.c index 183f3b67d..a6bbe68f3 100644 --- a/src/dump.c +++ b/src/dump.c @@ -13,9 +13,6 @@ #include <mruby/numeric.h> #include <mruby/debug.h> -#define FLAG_BYTEORDER_NATIVE 2 -#define FLAG_BYTEORDER_NONATIVE 0 - #ifndef MRB_WITHOUT_FLOAT #ifdef MRB_USE_FLOAT #define MRB_FLOAT_FMT "%.9g" @@ -709,22 +706,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8 uint16_t crc; uint32_t offset; - switch (flags & DUMP_ENDIAN_NAT) { - endian_big: - case DUMP_ENDIAN_BIG: - memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)); - break; - endian_little: - case DUMP_ENDIAN_LIL: - memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)); - break; - - case DUMP_ENDIAN_NAT: - if (bigendian_p()) goto endian_big; - goto endian_little; - break; - } - + 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->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); @@ -764,21 +746,6 @@ lv_defined_p(mrb_irep *irep) return FALSE; } -static uint8_t -dump_flags(uint8_t flags, uint8_t native) -{ - if (native == FLAG_BYTEORDER_NATIVE) { - if ((flags & DUMP_ENDIAN_NAT) == 0) { - return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT; - } - return flags; - } - if ((flags & DUMP_ENDIAN_NAT) == 0) { - return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG; - } - return flags; -} - static int dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) { @@ -870,7 +837,7 @@ error_exit: int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) { - return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size); + return dump_irep(mrb, irep, flags, bin, bin_size); } #ifndef MRB_DISABLE_STDIO @@ -886,7 +853,7 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp) return MRB_DUMP_INVALID_ARGUMENT; } - result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size); + result = dump_irep(mrb, irep, flags, &bin, &bin_size); if (result == MRB_DUMP_OK) { if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) { result = MRB_DUMP_WRITE_FAULT; @@ -897,20 +864,6 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp) return result; } -static mrb_bool -dump_bigendian_p(uint8_t flags) -{ - switch (flags & DUMP_ENDIAN_NAT) { - case DUMP_ENDIAN_BIG: - return TRUE; - case DUMP_ENDIAN_LIL: - return FALSE; - default: - case DUMP_ENDIAN_NAT: - return bigendian_p(); - } -} - int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) { @@ -921,23 +874,8 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con if (fp == NULL || initname == NULL || initname[0] == '\0') { return MRB_DUMP_INVALID_ARGUMENT; } - flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE); result = dump_irep(mrb, irep, flags, &bin, &bin_size); if (result == MRB_DUMP_OK) { - if (!dump_bigendian_p(flags)) { - if (fprintf(fp, "/* dumped in little endian order.\n" - " use `mrbc -E` option for big endian CPU. */\n") < 0) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } - else { - if (fprintf(fp, "/* dumped in big endian order.\n" - " use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */ mrb_free(mrb, bin); return MRB_DUMP_WRITE_FAULT; diff --git a/src/error.c b/src/error.c index 260ca7a3d..5d17209e5 100644 --- a/src/error.c +++ b/src/error.c @@ -160,9 +160,8 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace) static mrb_value exc_set_backtrace(mrb_state *mrb, mrb_value exc) { - mrb_value backtrace; + mrb_value backtrace = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &backtrace); set_backtrace(mrb, exc, backtrace); return backtrace; } @@ -185,6 +184,16 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) } } +static mrb_noreturn void +exc_throw(mrb_state *mrb, mrb_value exc) +{ + if (!mrb->jmp) { + mrb_p(mrb, exc); + abort(); + } + MRB_THROW(mrb->jmp); +} + MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc) { @@ -197,11 +206,7 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc) } mrb_exc_set(mrb, exc); } - if (!mrb->jmp) { - mrb_p(mrb, exc); - abort(); - } - MRB_THROW(mrb->jmp); + exc_throw(mrb, exc); } MRB_API mrb_noreturn void @@ -550,6 +555,52 @@ mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max) #undef FMT } +void mrb_core_init_printabort(void); + +int +mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque) +{ + struct mrb_jmpbuf *prev_jmp = mrb->jmp; + struct mrb_jmpbuf c_jmp; + int err = 1; + + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + body(mrb, opaque); + err = 0; + } MRB_CATCH(&c_jmp) { + if (mrb->exc) { + mrb_p(mrb, mrb_obj_value(mrb->exc)); + mrb->exc = NULL; + } + else { + mrb_core_init_printabort(); + } + } MRB_END_EXC(&c_jmp); + + mrb->jmp = prev_jmp; + + return err; +} + +mrb_noreturn void +mrb_core_init_abort(mrb_state *mrb) +{ + mrb->exc = NULL; + exc_throw(mrb, mrb_nil_value()); +} + +mrb_noreturn void +mrb_raise_nomemory(mrb_state *mrb) +{ + if (mrb->nomem_err) { + mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); + } + else { + mrb_core_init_abort(mrb); + } +} + void mrb_init_exception(mrb_state *mrb) { @@ -107,10 +107,11 @@ mrb_obj_id(mrb_value obj) return MakeID(0); /* not define */ case MRB_TT_FALSE: if (mrb_nil_p(obj)) - return MakeID(1); - return MakeID(0); + return MakeID(4); + else + return MakeID(0); case MRB_TT_TRUE: - return MakeID(1); + return MakeID(2); case MRB_TT_SYMBOL: return MakeID(mrb_symbol(obj)); case MRB_TT_FIXNUM: @@ -132,7 +133,6 @@ mrb_obj_id(mrb_value obj) case MRB_TT_HASH: case MRB_TT_RANGE: case MRB_TT_EXCEPTION: - case MRB_TT_FILE: case MRB_TT_DATA: case MRB_TT_ISTRUCT: default: @@ -140,7 +140,13 @@ mrb_obj_id(mrb_value obj) } } +#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT) +#define mrb_xxx_boxing_cptr_value mrb_nan_boxing_cptr_value +#endif + #ifdef MRB_WORD_BOXING +#define mrb_xxx_boxing_cptr_value mrb_word_boxing_cptr_value + #ifndef MRB_WITHOUT_FLOAT MRB_API mrb_value mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) @@ -164,17 +170,20 @@ mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f) return mrb_obj_value(nf); } #endif /* MRB_WITHOUT_FLOAT */ +#endif /* MRB_WORD_BOXING */ +#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT)) MRB_API mrb_value -mrb_word_boxing_cptr_value(mrb_state *mrb, void *p) +mrb_xxx_boxing_cptr_value(mrb_state *mrb, void *p) { mrb_value v; + struct RCptr *cptr = (struct RCptr*)mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class); - v.value.p = mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class); - v.value.vp->p = p; + SET_OBJ_VALUE(v, cptr); + cptr->p = p; return v; } -#endif /* MRB_WORD_BOXING */ +#endif #if defined _MSC_VER && _MSC_VER < 1900 diff --git a/src/fmt_fp.c b/src/fmt_fp.c index b77abe7b5..81ace6ec8 100644 --- a/src/fmt_fp.c +++ b/src/fmt_fp.c @@ -37,9 +37,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <mruby.h> #include <mruby/string.h> +struct fmt_args; + +typedef void output_func(struct fmt_args *f, const char *s, size_t l); + struct fmt_args { mrb_state *mrb; - mrb_value str; + output_func *output; + void *opaque; +}; + +struct mrb_cstr { + char *buf; + size_t len; }; #define MAX(a,b) ((a)>(b) ? (a) : (b)) @@ -54,15 +64,44 @@ struct fmt_args { #define PAD_POS (1U<<(' '-' ')) #define MARK_POS (1U<<('+'-' ')) +#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS) + +static output_func strcat_value; +static output_func strcat_cstr; + +static void +strcat_value(struct fmt_args *f, const char *s, size_t l) +{ + mrb_value str = *(mrb_value*)f->opaque; + mrb_str_cat(f->mrb, str, s, l); +} + +static void +strcat_cstr(struct fmt_args *f, const char *s, size_t l) +{ + struct mrb_cstr *cstr = (struct mrb_cstr*)f->opaque; + + if (l > cstr->len) { + mrb_state *mrb = f->mrb; + + mrb_raise(mrb, E_ARGUMENT_ERROR, "string buffer too small"); + } + + memcpy(cstr->buf, s, l); + + cstr->buf += l; + cstr->len -= l; +} + static void out(struct fmt_args *f, const char *s, size_t l) { - mrb_str_cat(f->mrb, f->str, s, l); + f->output(f, s, l); } #define PAD_SIZE 256 static void -pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint8_t fl) +pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint32_t fl) { char pad[PAD_SIZE]; if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return; @@ -92,7 +131,7 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double) #endif static int -fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t) +fmt_fp(struct fmt_args *f, long double y, ptrdiff_t w, ptrdiff_t p, uint32_t fl, int t) { uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion @@ -117,11 +156,11 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t) if (!isfinite(y)) { const char *ss = (t&32)?"inf":"INF"; if (y!=y) ss=(t&32)?"nan":"NAN"; - pad(f, ' ', 0, 3+pl, fl&~ZERO_PAD); + pad(f, ' ', w, 3+pl, fl&~ZERO_PAD); out(f, prefix, pl); out(f, ss, 3); - pad(f, ' ', 0, 3+pl, fl^LEFT_ADJ); - return 3+(int)pl; + pad(f, ' ', w, 3+pl, fl^LEFT_ADJ); + return (int)MAX(w, 3+pl); } y = frexp((double)y, &e2) * 2; @@ -169,14 +208,14 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t) else l = (s-buf) + (ebuf-estr); - pad(f, ' ', 0, pl+l, fl); + pad(f, ' ', w, pl+l, fl); out(f, prefix, pl); - pad(f, '0', 0, pl+l, fl^ZERO_PAD); + pad(f, '0', w, pl+l, fl^ZERO_PAD); out(f, buf, s-buf); pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0); out(f, estr, ebuf-estr); - pad(f, ' ', 0, pl+l, fl^LEFT_ADJ); - return (int)pl+(int)l; + pad(f, ' ', w, pl+l, fl^LEFT_ADJ); + return (int)MAX(w, pl+l); } if (p<0) p=6; @@ -288,9 +327,9 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t) l += ebuf-estr; } - pad(f, ' ', 0, pl+l, fl); + pad(f, ' ', w, pl+l, fl); out(f, prefix, pl); - pad(f, '0', 0, pl+l, fl^ZERO_PAD); + pad(f, '0', w, pl+l, fl^ZERO_PAD); if ((t|32)=='f') { if (a>r) a=r; @@ -325,21 +364,33 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t) out(f, estr, ebuf-estr); } - pad(f, ' ', 0, pl+l, fl^LEFT_ADJ); + pad(f, ' ', w, pl+l, fl^LEFT_ADJ); - return (int)pl+(int)l; + return (int)MAX(w, pl+l); } static int fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo) { - ptrdiff_t p; + ptrdiff_t w, p; + uint32_t fl; if (*fmt != '%') { return -1; } ++fmt; + /* Read modifier flags */ + for (fl=0; (unsigned)*fmt-' '<32 && (FLAGMASK&(1U<<(*fmt-' '))); fmt++) + fl |= 1U<<(*fmt-' '); + + /* - and 0 flags are mutually exclusive */ + if (fl & LEFT_ADJ) fl &= ~ZERO_PAD; + + for (w = 0; ISDIGIT(*fmt); ++fmt) { + w = 10 * w + (*fmt - '0'); + } + if (*fmt == '.') { ++fmt; for (p = 0; ISDIGIT(*fmt); ++fmt) { @@ -353,29 +404,49 @@ fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo) switch (*fmt) { case 'e': case 'f': case 'g': case 'a': case 'E': case 'F': case 'G': case 'A': - return fmt_fp(f, flo, p, 0, *fmt); + return fmt_fp(f, flo, w, p, fl, *fmt); default: return -1; } } -mrb_value +MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt) { struct fmt_args f; + mrb_value str = mrb_str_new_capa(mrb, 24); f.mrb = mrb; - f.str = mrb_str_new_capa(mrb, 24); + f.output = strcat_value; + f.opaque = (void*)&str; if (fmt_core(&f, fmt, mrb_float(flo)) < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string"); } - return f.str; + return str; +} + +MRB_API int +mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval) +{ + struct fmt_args f; + struct mrb_cstr cstr; + + cstr.buf = buf; + cstr.len = len - 1; /* reserve NUL terminator */ + f.mrb = mrb; + f.output = strcat_cstr; + f.opaque = (void*)&cstr; + if (fmt_core(&f, fmt, fval) < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string"); + } + *cstr.buf = '\0'; + return (int)(cstr.buf - buf); } #else /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */ #include <mruby.h> #include <stdio.h> -mrb_value +MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt) { char buf[25]; @@ -383,5 +454,11 @@ mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt) snprintf(buf, sizeof(buf), fmt, mrb_float(flo)); return mrb_str_new_cstr(mrb, buf); } + +MRB_API int +mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval) +{ + return snprintf(buf, len, fmt, fval); +} #endif /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */ #endif @@ -201,6 +201,8 @@ gettimeofday_time(void) #define objects(p) ((RVALUE *)p->objects) +mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); + MRB_API void* mrb_realloc_simple(mrb_state *mrb, void *p, size_t len) { @@ -223,14 +225,8 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len) p2 = mrb_realloc_simple(mrb, p, len); if (len == 0) return p2; if (p2 == NULL) { - if (mrb->gc.out_of_memory) { - mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); - /* mrb_panic(mrb); */ - } - else { - mrb->gc.out_of_memory = TRUE; - mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); - } + mrb->gc.out_of_memory = TRUE; + mrb_raise_nomemory(mrb); } else { mrb->gc.out_of_memory = FALSE; @@ -671,7 +667,6 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) { mrb_assert(is_gray(obj)); paint_black(obj); - gc->gray_list = obj->gcnext; mrb_gc_mark(mrb, (struct RBasic*)obj->c); switch (obj->tt) { case MRB_TT_ICLASS: @@ -714,10 +709,10 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) struct REnv *e = (struct REnv*)obj; mrb_int i, len; - if (MRB_ENV_STACK_SHARED_P(e) && e->cxt && e->cxt->fib) { + if (MRB_ENV_ONSTACK_P(e) && e->cxt && e->cxt->fib) { mrb_gc_mark(mrb, (struct RBasic*)e->cxt->fib); } - len = MRB_ENV_STACK_LEN(e); + len = MRB_ENV_LEN(e); for (i=0; i<len; i++) { mrb_gc_mark_value(mrb, e->stack[i]); } @@ -735,10 +730,11 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) case MRB_TT_ARRAY: { struct RArray *a = (struct RArray*)obj; - size_t i, e; + size_t i, e=ARY_LEN(a); + mrb_value *p = ARY_PTR(a); - for (i=0,e=ARY_LEN(a); i<e; i++) { - mrb_gc_mark_value(mrb, ARY_PTR(a)[i]); + for (i=0; i<e; i++) { + mrb_gc_mark_value(mrb, p[i]); } } break; @@ -818,7 +814,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) { struct REnv *e = (struct REnv*)obj; - if (MRB_ENV_STACK_SHARED_P(e)) { + if (MRB_ENV_ONSTACK_P(e)) { /* cannot be freed */ e->stack = NULL; break; @@ -840,7 +836,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) while (ce <= ci) { struct REnv *e = ci->env; if (e && !mrb_object_dead_p(mrb, (struct RBasic*)e) && - e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) { + e->tt == MRB_TT_ENV && MRB_ENV_ONSTACK_P(e)) { mrb_env_unshare(mrb, e); } ci--; @@ -958,13 +954,12 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) } } +/* rough estimation of number of GC marks (non recursive) */ static size_t -gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) +gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) { size_t children = 0; - gc_mark_children(mrb, gc, obj); - switch (obj->tt) { case MRB_TT_ICLASS: children++; @@ -989,7 +984,7 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) break; case MRB_TT_ENV: - children += MRB_ENV_STACK_LEN(obj); + children += MRB_ENV_LEN(obj); break; case MRB_TT_FIBER: @@ -1048,10 +1043,9 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) static void gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) { while (gc->gray_list) { - if (is_gray(gc->gray_list)) - gc_mark_children(mrb, gc, gc->gray_list); - else - gc->gray_list = gc->gray_list->gcnext; + struct RBasic *obj = gc->gray_list; + gc->gray_list = obj->gcnext; + gc_mark_children(mrb, gc, obj); } } @@ -1062,7 +1056,10 @@ incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) size_t tried_marks = 0; while (gc->gray_list && tried_marks < limit) { - tried_marks += gc_gray_mark(mrb, gc, gc->gray_list); + struct RBasic *obj = gc->gray_list; + gc->gray_list = obj->gcnext; + gc_mark_children(mrb, gc, obj); + tried_marks += gc_gray_counts(mrb, gc, obj); } return tried_marks; @@ -1079,7 +1076,9 @@ final_marking_phase(mrb_state *mrb, mrb_gc *gc) } mrb_gc_mark_gv(mrb); mark_context(mrb, mrb->c); - mark_context(mrb, mrb->root_c); + if (mrb->c != mrb->root_c) { + mark_context(mrb, mrb->root_c); + } mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); gc_mark_gray_list(mrb, gc); mrb_assert(gc->gray_list == NULL); @@ -1294,6 +1293,7 @@ mrb_full_gc(mrb_state *mrb) { mrb_gc *gc = &mrb->gc; + if (!mrb->c) return; if (gc->disabled || gc->iterating) return; GC_INVOKE_TIME_REPORT("mrb_full_gc()"); @@ -1601,6 +1601,12 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo } } +size_t +mrb_objspace_page_slot_size(void) +{ + return sizeof(RVALUE); +} + #ifdef GC_TEST #ifdef GC_DEBUG static mrb_value gc_test(mrb_state *, mrb_value); @@ -1632,272 +1638,3 @@ mrb_init_gc(mrb_state *mrb) #endif #endif } - -#ifdef GC_TEST -#ifdef GC_DEBUG -void -test_mrb_field_write_barrier(void) -{ - mrb_state *mrb = mrb_open(); - struct RBasic *obj, *value; - mrb_gc *gc = &mrb->gc; - - puts("test_mrb_field_write_barrier"); - gc->generational = FALSE; - obj = mrb_basic_ptr(mrb_ary_new(mrb)); - value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value")); - paint_black(obj); - paint_partial_white(gc, value); - - - puts(" in MRB_GC_STATE_MARK"); - gc->state = MRB_GC_STATE_MARK; - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(is_gray(value)); - - - puts(" in MRB_GC_STATE_SWEEP"); - paint_partial_white(gc, value); - gc->state = MRB_GC_STATE_SWEEP; - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(obj->color & gc->current_white_part); - mrb_assert(value->color & gc->current_white_part); - - - puts(" fail with black"); - gc->state = MRB_GC_STATE_MARK; - paint_white(obj); - paint_partial_white(gc, value); - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(obj->color & gc->current_white_part); - - - puts(" fail with gray"); - gc->state = MRB_GC_STATE_MARK; - paint_black(obj); - paint_gray(value); - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(is_gray(value)); - - - { - puts("test_mrb_field_write_barrier_value"); - obj = mrb_basic_ptr(mrb_ary_new(mrb)); - mrb_value value = mrb_str_new_lit(mrb, "value"); - paint_black(obj); - paint_partial_white(gc, mrb_basic_ptr(value)); - - gc->state = MRB_GC_STATE_MARK; - mrb_field_write_barrier_value(mrb, obj, value); - - mrb_assert(is_gray(mrb_basic_ptr(value))); - } - - mrb_close(mrb); -} - -void -test_mrb_write_barrier(void) -{ - mrb_state *mrb = mrb_open(); - struct RBasic *obj; - mrb_gc *gc = &mrb->gc; - - puts("test_mrb_write_barrier"); - obj = mrb_basic_ptr(mrb_ary_new(mrb)); - paint_black(obj); - - puts(" in MRB_GC_STATE_MARK"); - gc->state = MRB_GC_STATE_MARK; - mrb_write_barrier(mrb, obj); - - mrb_assert(is_gray(obj)); - mrb_assert(gc->atomic_gray_list == obj); - - - puts(" fail with gray"); - paint_gray(obj); - mrb_write_barrier(mrb, obj); - - mrb_assert(is_gray(obj)); - - mrb_close(mrb); -} - -void -test_add_gray_list(void) -{ - mrb_state *mrb = mrb_open(); - struct RBasic *obj1, *obj2; - mrb_gc *gc = &mrb->gc; - - puts("test_add_gray_list"); - change_gen_gc_mode(mrb, gc, FALSE); - mrb_assert(gc->gray_list == NULL); - obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); - add_gray_list(mrb, gc, obj1); - mrb_assert(gc->gray_list == obj1); - mrb_assert(is_gray(obj1)); - - obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); - add_gray_list(mrb, gc, obj2); - mrb_assert(gc->gray_list == obj2); - mrb_assert(gc->gray_list->gcnext == obj1); - mrb_assert(is_gray(obj2)); - - mrb_close(mrb); -} - -void -test_gc_gray_mark(void) -{ - mrb_state *mrb = mrb_open(); - mrb_value obj_v, value_v; - struct RBasic *obj; - size_t gray_num = 0; - mrb_gc *gc = &mrb->gc; - - puts("test_gc_gray_mark"); - - puts(" in MRB_TT_CLASS"); - obj = (struct RBasic*)mrb->object_class; - paint_gray(obj); - gray_num = gc_gray_mark(mrb, gc, obj); - mrb_assert(is_black(obj)); - mrb_assert(gray_num > 1); - - puts(" in MRB_TT_ARRAY"); - obj_v = mrb_ary_new(mrb); - value_v = mrb_str_new_lit(mrb, "test"); - paint_gray(mrb_basic_ptr(obj_v)); - paint_partial_white(gc, mrb_basic_ptr(value_v)); - mrb_ary_push(mrb, obj_v, value_v); - gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v)); - mrb_assert(is_black(mrb_basic_ptr(obj_v))); - mrb_assert(is_gray(mrb_basic_ptr(value_v))); - mrb_assert(gray_num == 1); - - mrb_close(mrb); -} - -void -test_incremental_gc(void) -{ - mrb_state *mrb = mrb_open(); - size_t max = ~0, live = 0, total = 0, freed = 0; - RVALUE *free; - mrb_heap_page *page; - mrb_gc *gc = &mrb->gc; - - puts("test_incremental_gc"); - change_gen_gc_mode(mrb, gc, FALSE); - - puts(" in mrb_full_gc"); - mrb_full_gc(mrb); - - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - puts(" in MRB_GC_STATE_ROOT"); - incremental_gc(mrb, gc, max); - mrb_assert(gc->state == MRB_GC_STATE_MARK); - puts(" in MRB_GC_STATE_MARK"); - incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP); - mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - - puts(" in MRB_GC_STATE_SWEEP"); - page = gc->heaps; - while (page) { - RVALUE *p = objects(page); - RVALUE *e = p + MRB_HEAP_PAGE_SIZE; - while (p<e) { - if (is_black(&p->as.basic)) { - live++; - } - if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) { - printf("%p\n", &p->as.basic); - } - p++; - } - page = page->next; - total += MRB_HEAP_PAGE_SIZE; - } - - mrb_assert(gc->gray_list == NULL); - - incremental_gc(mrb, gc, max); - mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - - incremental_gc(mrb, gc, max); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - - free = (RVALUE*)gc->heaps->freelist; - while (free) { - freed++; - free = (RVALUE*)free->as.free.next; - } - - mrb_assert(gc->live == live); - mrb_assert(gc->live == total-freed); - - puts("test_incremental_gc(gen)"); - incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP); - change_gen_gc_mode(mrb, gc, TRUE); - - mrb_assert(gc->full == FALSE); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - - puts(" in minor"); - mrb_assert(is_minor_gc(gc)); - mrb_assert(gc->majorgc_old_threshold > 0); - gc->majorgc_old_threshold = 0; - mrb_incremental_gc(mrb); - mrb_assert(gc->full == TRUE); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - - puts(" in major"); - mrb_assert(is_major_gc(gc)); - do { - mrb_incremental_gc(mrb); - } while (gc->state != MRB_GC_STATE_ROOT); - mrb_assert(gc->full == FALSE); - - mrb_close(mrb); -} - -void -test_incremental_sweep_phase(void) -{ - mrb_state *mrb = mrb_open(); - mrb_gc *gc = &mrb->gc; - - puts("test_incremental_sweep_phase"); - - add_heap(mrb, gc); - gc->sweeps = gc->heaps; - - mrb_assert(gc->heaps->next->next == NULL); - mrb_assert(gc->free_heaps->next->next == NULL); - incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3); - - mrb_assert(gc->heaps->next == NULL); - mrb_assert(gc->heaps == gc->free_heaps); - - mrb_close(mrb); -} - -static mrb_value -gc_test(mrb_state *mrb, mrb_value self) -{ - test_mrb_field_write_barrier(); - test_mrb_write_barrier(); - test_add_gray_list(); - test_gc_gray_mark(); - test_incremental_gc(); - test_incremental_sweep_phase(); - return mrb_nil_value(); -} -#endif /* GC_DEBUG */ -#endif /* GC_TEST */ diff --git a/src/hash.c b/src/hash.c index 70f437358..c891e1b22 100644 --- a/src/hash.c +++ b/src/hash.c @@ -73,7 +73,7 @@ ht_hash_func(mrb_state *mrb, htable *t, mrb_value key) default: hv = mrb_funcall(mrb, key, "hash", 0); - h = (size_t)t ^ (size_t)mrb_fixnum(hv); + h = (size_t)tt ^ (size_t)mrb_fixnum(hv); break; } if (index && (index != t->index || capa != index->capa)) { @@ -174,6 +174,11 @@ ht_index(mrb_state *mrb, htable *t) segment *seg; size_t i; + if (size == 0) { + t->index = NULL; + mrb_free(mrb, index); + return; + } /* allocate index table */ if (index && index->size >= UPPER_BOUND(index->capa)) { size = index->capa+1; @@ -194,7 +199,7 @@ ht_index(mrb_state *mrb, htable *t) index->table[i] = NULL; } - /* rebuld index */ + /* rebuild index */ mask = HT_MASK(index); seg = t->rootseg; while (seg) { @@ -222,9 +227,8 @@ static void ht_compact(mrb_state *mrb, htable *t) { segment *seg; - mrb_int i; + uint16_t i, i2; segment *seg2 = NULL; - mrb_int i2; mrb_int size = 0; if (t == NULL) return; @@ -366,7 +370,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val) if (!seg->next && i >= t->last_len) { seg->e[i].key = key; seg->e[i].val = val; - t->last_len = i+1; + t->last_len = (uint16_t)i+1; t->size++; return; } @@ -374,7 +378,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val) deleted++; continue; } - if (ht_hash_equal(mrb, t, k, key)) { + if (ht_hash_equal(mrb, t, key, k)) { seg->e[i].val = val; return; } @@ -408,7 +412,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val) } seg->e[i].key = key; seg->e[i].val = val; - t->last_len = i+1; + t->last_len = (uint16_t)i+1; if (t->index == NULL && t->size > MRB_HT_INIT_SIZE*4) { ht_index(mrb, t); } @@ -455,7 +459,7 @@ ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp) return FALSE; } if (mrb_undef_p(k)) continue; - if (ht_hash_equal(mrb, t, k, key)) { + if (ht_hash_equal(mrb, t, key, k)) { if (vp) *vp = seg->e[i].val; return TRUE; } @@ -519,6 +523,20 @@ ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p) } } +size_t +mrb_os_memsize_of_hash_table(mrb_value obj) +{ + struct htable *h = mrb_hash_ptr(obj)->ht; + size_t segkv_size = 0; + + if (h->index) segkv_size = (sizeof(struct segkv) * h->index->capa); + + return sizeof(htable) + + sizeof(segindex) + + (sizeof(segment) * h->size) + + segkv_size; +} + /* Iterates over the hash table. */ MRB_API void mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p) @@ -642,12 +660,11 @@ static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key); static mrb_value mrb_hash_init_copy(mrb_state *mrb, mrb_value self) { - mrb_value orig; + mrb_value orig = mrb_get_arg1(mrb); struct RHash* copy; htable *orig_h; mrb_value ifnone, vret; - mrb_get_args(mrb, "o", &orig); 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"); @@ -829,9 +846,8 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_aget(mrb_state *mrb, mrb_value self) { - mrb_value key; + mrb_value key = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &key); return mrb_hash_get(mrb, self, key); } @@ -914,9 +930,8 @@ mrb_hash_default(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_set_default(mrb_state *mrb, mrb_value hash) { - mrb_value ifnone; + mrb_value ifnone = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT; @@ -970,9 +985,8 @@ mrb_hash_default_proc(mrb_state *mrb, mrb_value hash) static mrb_value mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) { - mrb_value ifnone; + mrb_value ifnone = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); if (!mrb_nil_p(ifnone)) { @@ -1004,9 +1018,8 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) static mrb_value mrb_hash_delete(mrb_state *mrb, mrb_value self) { - mrb_value key; + mrb_value key = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &key); mrb_hash_modify(mrb, self); return mrb_hash_delete_key(mrb, self, key); } @@ -1059,7 +1072,8 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) mrb_hash_modify(mrb, hash); if (t && t->size > 0) { - mrb_value del_key, del_val; + mrb_value del_key = mrb_nil_value(); + mrb_value del_val = mrb_nil_value(); ht_shift(mrb, t, &del_key, &del_val); mrb_gc_protect(mrb, del_key); @@ -1289,10 +1303,9 @@ mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key) static mrb_value mrb_hash_has_key(mrb_state *mrb, mrb_value hash) { - mrb_value key; + mrb_value key = mrb_get_arg1(mrb); mrb_bool key_p; - mrb_get_args(mrb, "o", &key); key_p = mrb_hash_key_p(mrb, hash, key); return mrb_bool_value(key_p); } @@ -1332,10 +1345,9 @@ hash_has_value_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p) static mrb_value mrb_hash_has_value(mrb_state *mrb, mrb_value hash) { - mrb_value val; + mrb_value val = mrb_get_arg1(mrb); struct has_v_arg arg; - mrb_get_args(mrb, "o", &val); arg.found = FALSE; arg.val = val; ht_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg); diff --git a/src/kernel.c b/src/kernel.c index 8bb837eca..10ed9f88e 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -71,9 +71,8 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj) static mrb_value mrb_equal_m(mrb_state *mrb, mrb_value self) { - mrb_value arg; + mrb_value arg = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &arg); return mrb_bool_value(mrb_equal(mrb, self, arg)); } @@ -100,6 +99,18 @@ mrb_obj_id_m(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(mrb_obj_id(self)); } +static int +env_bidx(struct REnv *e) +{ + int bidx; + + /* use saved block arg position */ + bidx = MRB_ENV_BIDX(e); + /* bidx may be useless (e.g. define_method) */ + if (bidx >= MRB_ENV_LEN(e)) return -1; + return bidx; +} + /* 15.3.1.2.2 */ /* 15.3.1.2.5 */ /* 15.3.1.3.6 */ @@ -130,6 +141,8 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) mrb_callinfo *ci = &mrb->c->ci[-1]; mrb_callinfo *cibase = mrb->c->cibase; mrb_value *bp; + int bidx; + struct REnv *e = NULL; struct RProc *p; if (ci <= cibase) { @@ -140,29 +153,36 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) /* search method/class/module proc */ while (p) { if (MRB_PROC_SCOPE_P(p)) break; + e = MRB_PROC_ENV(p); p = p->upper; } if (p == NULL) return mrb_false_value(); + if (e) { + bidx = env_bidx(e); + if (bidx < 0) return mrb_false_value(); + bp = &e->stack[bidx]; + goto block_given; + } /* search ci corresponding to proc */ while (cibase < ci) { if (ci->proc == p) break; ci--; } if (ci == cibase) { - return mrb_false_value(); + /* proc is closure */ + if (!MRB_PROC_ENV_P(p)) return mrb_false_value(); + e = MRB_PROC_ENV(p); + bidx = env_bidx(e); + if (bidx < 0) return mrb_false_value(); + bp = &e->stack[bidx]; } else if (ci->env) { - struct REnv *e = ci->env; - int bidx; - + e = ci->env; /* top-level does not have block slot (always false) */ - if (e->stack == mrb->c->stbase) - return mrb_false_value(); - /* use saved block arg position */ - bidx = MRB_ENV_BIDX(e); + if (e->stack == mrb->c->stbase) return mrb_false_value(); + bidx = env_bidx(e); /* bidx may be useless (e.g. define_method) */ - if (bidx >= MRB_ENV_STACK_LEN(e)) - return mrb_false_value(); + if (bidx < 0) return mrb_false_value(); bp = &e->stack[bidx]; } else { @@ -174,6 +194,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) bp++; } } + block_given: if (mrb_nil_p(*bp)) return mrb_false_value(); return mrb_true_value(); @@ -325,7 +346,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self) mrb_value clone; if (mrb_immediate_p(self)) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %v", self); + return self; } if (mrb_sclass_p(self)) { mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class"); @@ -366,7 +387,7 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj) mrb_value dup; if (mrb_immediate_p(obj)) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %v", obj); + return obj; } if (mrb_sclass_p(obj)) { mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class"); @@ -471,9 +492,8 @@ mrb_obj_hash(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_init_copy(mrb_state *mrb, mrb_value self) { - mrb_value orig; + mrb_value orig = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &orig); 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"); @@ -500,11 +520,11 @@ mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) static mrb_value obj_is_instance_of(mrb_state *mrb, mrb_value self) { - mrb_value arg; + struct RClass *c; - mrb_get_args(mrb, "C", &arg); + mrb_get_args(mrb, "c", &c); - return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))); + return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, c)); } /* 15.3.1.3.24 */ @@ -537,11 +557,11 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) { - mrb_value arg; + struct RClass *c; - mrb_get_args(mrb, "C", &arg); + mrb_get_args(mrb, "c", &c); - return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))); + return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, c)); } KHASH_DECLARE(st, mrb_sym, char, FALSE) @@ -744,12 +764,29 @@ obj_respond_to(mrb_state *mrb, mrb_value self) static mrb_value mrb_obj_ceqq(mrb_state *mrb, mrb_value self) { - mrb_value v; + mrb_value v = mrb_get_arg1(mrb); mrb_int i, len; mrb_sym eqq = mrb_intern_lit(mrb, "==="); - mrb_value ary = mrb_ary_splat(mrb, self); + mrb_value ary; - mrb_get_args(mrb, "o", &v); + if (mrb_array_p(self)) { + ary = self; + } + else if (mrb_nil_p(self)) { + return mrb_false_value(); + } + else if (!mrb_respond_to(mrb, self, mrb_intern_lit(mrb, "to_a"))) { + mrb_value c = mrb_funcall_argv(mrb, self, eqq, 1, &v); + if (mrb_test(c)) return mrb_true_value(); + return mrb_false_value(); + } + else { + ary = mrb_funcall(mrb, self, "to_a", 0); + if (mrb_nil_p(ary)) { + return mrb_funcall_argv(mrb, self, eqq, 1, &v); + } + mrb_ensure_array_type(mrb, ary); + } len = RARRAY_LEN(ary); for (i=0; i<len; i++) { mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v); diff --git a/src/load.c b/src/load.c index e624c52d5..247d511df 100644 --- a/src/load.c +++ b/src/load.c @@ -14,14 +14,12 @@ #include <mruby/string.h> #include <mruby/debug.h> #include <mruby/error.h> +#include <mruby/data.h> #if SIZE_MAX < UINT32_MAX # error size_t must be at least 32 bits wide #endif -#define FLAG_BYTEORDER_BIG 2 -#define FLAG_BYTEORDER_LIL 4 -#define FLAG_BYTEORDER_NATIVE 8 #define FLAG_SRC_MALLOC 1 #define FLAG_SRC_STATIC 0 @@ -56,7 +54,15 @@ str_to_double(mrb_state *mrb, const char *p, size_t len) } #endif -mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck); +mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, int badcheck); + +static void +tempirep_free(mrb_state *mrb, void *p) +{ + if (p) mrb_irep_decref(mrb, (mrb_irep *)p); +} + +static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free }; static mrb_irep* read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) @@ -66,8 +72,11 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag ptrdiff_t diff; uint16_t tt, pool_data_len, snl; int plen; - int ai = mrb_gc_arena_save(mrb); + struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); mrb_irep *irep = mrb_add_irep(mrb); + int ai = mrb_gc_arena_save(mrb); + + irep_obj->data = irep; /* skip record size */ src += sizeof(uint32_t); @@ -94,8 +103,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) { return NULL; } - if ((flags & FLAG_SRC_MALLOC) == 0 && - (flags & FLAG_BYTEORDER_NATIVE)) { + if ((flags & FLAG_SRC_MALLOC) == 0) { irep->iseq = (mrb_code*)src; src += sizeof(mrb_code) * irep->ilen; irep->flags |= MRB_ISEQ_NO_FREE; @@ -188,36 +196,47 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag } } - irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen); + 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; + irep_obj->data = NULL; + return irep; } static mrb_irep* 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); int i; + mrb_gc_arena_restore(mrb, ai); if (irep == NULL) { return NULL; } + 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); + mrb_gc_arena_restore(mrb, ai); if (irep->reps[i] == NULL) { return NULL; } bin += rlen; *len += rlen; } + + irep_obj->data = NULL; + return irep; } @@ -241,21 +260,21 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; } - irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); + 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; 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_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen); + irep->debug_info->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) { mrb_irep_debug_info_file *file; uint16_t filename_idx; - file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); + file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file)); irep->debug_info->files[f_idx] = file; file->start_pos = bin_to_uint32(bin); @@ -285,8 +304,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * case mrb_debug_line_flat_map: { uint32_t l; - file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc( - mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count)); + file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc( + mrb, (size_t)(file->line_entry_count), sizeof(mrb_irep_debug_info_line)); for (l = 0; l < file->line_entry_count; ++l) { file->lines.flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); @@ -333,6 +352,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t int result; uint16_t filenames_len; mrb_sym *filenames; + mrb_value filenames_obj; bin = start; header = (struct rite_section_debug_header *)bin; @@ -340,7 +360,8 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t filenames_len = bin_to_uint16(bin); bin += sizeof(uint16_t); - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len); + filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len); + filenames = (mrb_sym*)RSTRING_PTR(filenames_obj); for (i = 0; i < filenames_len; ++i) { uint16_t f_len = bin_to_uint16(bin); bin += sizeof(uint16_t); @@ -364,7 +385,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t } debug_exit: - mrb_free(mrb, filenames); + mrb_str_resize(mrb, filenames_obj, 0); return result; } @@ -422,6 +443,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl int result; uint32_t syms_len; mrb_sym *syms; + mrb_value syms_obj; mrb_sym (*intern_func)(mrb_state*, const char*, size_t) = (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static; @@ -431,7 +453,8 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl syms_len = bin_to_uint32(bin); bin += sizeof(uint32_t); - syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len); + syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len); + syms = (mrb_sym*)RSTRING_PTR(syms_obj); for (i = 0; i < syms_len; ++i) { uint16_t const str_len = bin_to_uint16(bin); bin += sizeof(uint16_t); @@ -451,7 +474,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl } lv_exit: - mrb_free(mrb, syms); + mrb_str_resize(mrb, syms_obj, 0); return result; } @@ -464,19 +487,7 @@ read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_ return MRB_DUMP_READ_FAULT; } - if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) { - if (bigendian_p()) - *flags |= FLAG_BYTEORDER_NATIVE; - else - *flags |= FLAG_BYTEORDER_BIG; - } - else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) { - if (bigendian_p()) - *flags |= FLAG_BYTEORDER_LIL; - else - *flags |= FLAG_BYTEORDER_NATIVE; - } - else { + if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) != 0) { return MRB_DUMP_INVALID_FILE_HEADER; } @@ -500,6 +511,7 @@ static mrb_irep* read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) { int result; + struct RData *irep_obj = NULL; mrb_irep *irep = NULL; const struct rite_section_header *section_header; uint16_t crc; @@ -520,12 +532,15 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) return NULL; } + irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); + bin += sizeof(struct rite_binary_header); do { section_header = (const struct rite_section_header *)bin; if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) { irep = read_section_irep(mrb, bin, flags); if (!irep) return NULL; + irep_obj->data = irep; } else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) { if (!irep) return NULL; /* corrupted data */ @@ -544,6 +559,8 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) bin += bin_to_uint32(section_header->section_size); } while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0); + irep_obj->data = NULL; + return irep; } @@ -595,7 +612,16 @@ load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c) MRB_API mrb_value mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c) { - return load_irep(mrb, mrb_read_irep(mrb, bin), c); + struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); + mrb_irep *irep = mrb_read_irep(mrb, bin); + mrb_value ret; + + irep_obj->data = irep; + mrb_irep_incref(mrb, irep); + ret = load_irep(mrb, irep, c); + irep_obj->data = NULL; + mrb_irep_decref(mrb, irep); + return ret; } MRB_API mrb_value diff --git a/src/numeric.c b/src/numeric.c index 6cfd64280..83a4ef716 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -67,12 +67,11 @@ mrb_int_value(mrb_state *mrb, mrb_float f) static mrb_value integral_pow(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); #ifndef MRB_WITHOUT_FLOAT mrb_float d; #endif - mrb_get_args(mrb, "o", &y); if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) { /* try ipow() */ mrb_int base = mrb_fixnum(x); @@ -116,9 +115,8 @@ static mrb_value integral_idiv(mrb_state *mrb, mrb_value x) { #ifdef MRB_WITHOUT_FLOAT - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); if (!mrb_fixnum_p(y)) { mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); } @@ -151,21 +149,31 @@ integral_idiv(mrb_state *mrb, mrb_value x) */ static mrb_value -integral_div(mrb_state *mrb, mrb_value x) +integral_div(mrb_state *mrb, mrb_value xv) { #ifdef MRB_WITHOUT_FLOAT - mrb_value y; + mrb_int y; - mrb_get_args(mrb, "o", &y); - if (!mrb_fixnum_p(y)) { - mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); + mrb_get_args(mrb, "i", &y); + if (y == 0) { + mrb_raise(mrb, E_RUNTIME_ERROR, "devided by zero"); } - return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y)); + return mrb_fixnum_value(mrb, mrb_fixnum(xv) / y); #else - mrb_float y; + mrb_float x, y; mrb_get_args(mrb, "f", &y); - return mrb_float_value(mrb, mrb_to_flo(mrb, x) / 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); #endif } @@ -210,26 +218,30 @@ static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { mrb_float f = mrb_float(flt); + mrb_value str; if (isinf(f)) { - return f < 0 ? mrb_str_new_lit(mrb, "-Infinity") - : mrb_str_new_lit(mrb, "Infinity"); + str = f < 0 ? mrb_str_new_lit(mrb, "-Infinity") + : mrb_str_new_lit(mrb, "Infinity"); + goto exit; } else if (isnan(f)) { - return mrb_str_new_lit(mrb, "NaN"); + str = mrb_str_new_lit(mrb, "NaN"); + goto exit; } else { char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g"; - mrb_value str = mrb_float_to_str(mrb, flt, fmt); mrb_int len; char *begp, *p, *endp; + str = mrb_float_to_str(mrb, flt, fmt); + insert_dot_zero: begp = RSTRING_PTR(str); len = RSTRING_LEN(str); for (p = begp, endp = p + len; p < endp; ++p) { if (*p == '.') { - return str; + goto exit; } else if (*p == 'e') { ptrdiff_t e_pos = p - begp; @@ -237,7 +249,7 @@ flo_to_s(mrb_state *mrb, mrb_value flt) p = RSTRING_PTR(str) + e_pos; memmove(p + 2, p, len - e_pos); memcpy(p, ".0", 2); - return str; + goto exit; } } @@ -247,8 +259,12 @@ flo_to_s(mrb_state *mrb, mrb_value flt) goto insert_dot_zero; } - return str; + goto exit; } + + exit: + RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); + return str; } /* 15.2.9.3.2 */ @@ -263,9 +279,8 @@ flo_to_s(mrb_state *mrb, mrb_value flt) static mrb_value flo_minus(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); } @@ -281,9 +296,8 @@ flo_minus(mrb_state *mrb, mrb_value x) static mrb_value flo_mul(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y)); } @@ -343,11 +357,9 @@ flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp) static mrb_value flo_mod(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); mrb_float mod; - mrb_get_args(mrb, "o", &y); - flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod); return mrb_float_value(mrb, mod); } @@ -368,9 +380,8 @@ flo_mod(mrb_state *mrb, mrb_value x) static mrb_value fix_eql(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); if (!mrb_fixnum_p(y)) return mrb_false_value(); return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); } @@ -379,9 +390,8 @@ fix_eql(mrb_state *mrb, mrb_value x) static mrb_value flo_eql(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); if (!mrb_float_p(y)) return mrb_false_value(); return mrb_bool_value(mrb_float(x) == mrb_float(y)); } @@ -402,8 +412,7 @@ flo_eql(mrb_state *mrb, mrb_value x) static mrb_value flo_eq(mrb_state *mrb, mrb_value x) { - mrb_value y; - mrb_get_args(mrb, "o", &y); + mrb_value y = mrb_get_arg1(mrb); switch (mrb_type(y)) { case MRB_TT_FIXNUM: @@ -421,7 +430,6 @@ value_int64(mrb_state *mrb, mrb_value x) switch (mrb_type(x)) { case MRB_TT_FIXNUM: return (int64_t)mrb_fixnum(x); - break; case MRB_TT_FLOAT: return (int64_t)mrb_float(x); default: @@ -452,9 +460,8 @@ flo_rev(mrb_state *mrb, mrb_value x) static mrb_value flo_and(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); int64_t v1, v2; - mrb_get_args(mrb, "o", &y); v1 = (int64_t)mrb_float(x); v2 = value_int64(mrb, y); @@ -464,9 +471,8 @@ flo_and(mrb_state *mrb, mrb_value x) static mrb_value flo_or(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); int64_t v1, v2; - mrb_get_args(mrb, "o", &y); v1 = (int64_t)mrb_float(x); v2 = value_int64(mrb, y); @@ -476,9 +482,8 @@ flo_or(mrb_state *mrb, mrb_value x) static mrb_value flo_xor(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); int64_t v1, v2; - mrb_get_args(mrb, "o", &y); v1 = (int64_t)mrb_float(x); v2 = value_int64(mrb, y); @@ -839,9 +844,8 @@ mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y) static mrb_value fix_mul(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); return fixnum_mul(mrb, x, y); } @@ -886,12 +890,11 @@ 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) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); mrb_int a, b; - mrb_get_args(mrb, "o", &y); a = mrb_fixnum(x); - if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) { + if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) { mrb_int mod; if (b == 0) { @@ -928,9 +931,7 @@ fix_mod(mrb_state *mrb, mrb_value x) static mrb_value fix_divmod(mrb_state *mrb, mrb_value x) { - mrb_value y; - - mrb_get_args(mrb, "o", &y); + mrb_value y = mrb_get_arg1(mrb); if (mrb_fixnum_p(y)) { mrb_int div, mod; @@ -967,12 +968,10 @@ fix_divmod(mrb_state *mrb, mrb_value x) static mrb_value flo_divmod(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); mrb_float div, mod; mrb_value a, b; - mrb_get_args(mrb, "o", &y); - flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod); a = mrb_int_value(mrb, div); b = mrb_float_value(mrb, mod); @@ -995,9 +994,8 @@ flo_divmod(mrb_state *mrb, mrb_value x) static mrb_value fix_equal(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); switch (mrb_type(y)) { case MRB_TT_FIXNUM: return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); @@ -1054,9 +1052,8 @@ static mrb_value flo_xor(mrb_state *mrb, mrb_value x); static mrb_value fix_and(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); bit_op(x, y, and, &); } @@ -1071,9 +1068,8 @@ fix_and(mrb_state *mrb, mrb_value x) static mrb_value fix_or(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); bit_op(x, y, or, |); } @@ -1088,9 +1084,8 @@ fix_or(mrb_state *mrb, mrb_value x) static mrb_value fix_xor(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); bit_op(x, y, or, ^); } @@ -1312,9 +1307,8 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y) static mrb_value fix_plus(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &other); return fixnum_plus(mrb, self, other); } @@ -1370,9 +1364,8 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y) static mrb_value fix_minus(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &other); return fixnum_minus(mrb, self, other); } @@ -1383,6 +1376,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_value str; if (base < 2 || 36 < base) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base); @@ -1403,7 +1397,9 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base) } while (val /= base); } - return mrb_str_new(mrb, b, buf + sizeof(buf) - b); + str = mrb_str_new(mrb, b, buf + sizeof(buf) - b); + RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); + return str; } /* 15.2.8.3.25 */ @@ -1474,21 +1470,21 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2) /* 15.2.9.3.6 */ /* * call-seq: - * self.f <=> other.f => -1, 0, +1 + * self.f <=> other.f => -1, 0, +1, or nil * < => -1 * = => 0 * > => +1 * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is * less than, equal to, or greater than <i>numeric</i>. This is the - * basis for the tests in <code>Comparable</code>. + * basis for the tests in <code>Comparable</code>. When the operands are + * not comparable, it returns nil instead of raising an exception. */ static mrb_value integral_cmp(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); mrb_int n; - mrb_get_args(mrb, "o", &other); n = cmpnum(mrb, self, other); if (n == -2) return mrb_nil_value(); return mrb_fixnum_value(n); @@ -1503,10 +1499,9 @@ cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2) static mrb_value integral_lt(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); mrb_int n; - mrb_get_args(mrb, "o", &other); n = cmpnum(mrb, self, other); if (n == -2) cmperr(mrb, self, other); if (n < 0) return mrb_true_value(); @@ -1516,10 +1511,9 @@ integral_lt(mrb_state *mrb, mrb_value self) static mrb_value integral_le(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); mrb_int n; - mrb_get_args(mrb, "o", &other); n = cmpnum(mrb, self, other); if (n == -2) cmperr(mrb, self, other); if (n <= 0) return mrb_true_value(); @@ -1529,10 +1523,9 @@ integral_le(mrb_state *mrb, mrb_value self) static mrb_value integral_gt(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); mrb_int n; - mrb_get_args(mrb, "o", &other); n = cmpnum(mrb, self, other); if (n == -2) cmperr(mrb, self, other); if (n > 0) return mrb_true_value(); @@ -1542,10 +1535,9 @@ integral_gt(mrb_state *mrb, mrb_value self) static mrb_value integral_ge(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value other = mrb_get_arg1(mrb); mrb_int n; - mrb_get_args(mrb, "o", &other); n = cmpnum(mrb, self, other); if (n == -2) cmperr(mrb, self, other); if (n >= 0) return mrb_true_value(); @@ -1597,9 +1589,8 @@ num_infinite_p(mrb_state *mrb, mrb_value self) static mrb_value flo_plus(mrb_state *mrb, mrb_value x) { - mrb_value y; + mrb_value y = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &y); return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y)); } #endif diff --git a/src/object.c b/src/object.c index 33d570331..7257f402d 100644 --- a/src/object.c +++ b/src/object.c @@ -47,6 +47,17 @@ 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 + /* value mixing with integer and float */ + if (mrb_fixnum_p(obj1)) { + if (mrb_float_p(obj2) && (mrb_float)mrb_fixnum(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)) + return TRUE; + } +#endif result = mrb_funcall(mrb, obj1, "==", 1, obj2); if (mrb_test(result)) return TRUE; return FALSE; @@ -83,13 +94,17 @@ mrb_true(mrb_state *mrb, mrb_value obj) static mrb_value nil_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new_frozen(mrb, 0, 0); + mrb_value str = mrb_str_new_frozen(mrb, 0, 0); + RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); + return str; } static mrb_value nil_inspect(mrb_state *mrb, mrb_value obj) { - return mrb_str_new_lit_frozen(mrb, "nil"); + mrb_value str = mrb_str_new_lit_frozen(mrb, "nil"); + RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); + return str; } /*********************************************************************** @@ -150,7 +165,9 @@ true_xor(mrb_state *mrb, mrb_value obj) static mrb_value true_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new_lit_frozen(mrb, "true"); + mrb_value str = mrb_str_new_lit_frozen(mrb, "true"); + RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); + return str; } /* 15.2.5.3.4 */ @@ -257,7 +274,9 @@ false_or(mrb_state *mrb, mrb_value obj) static mrb_value false_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new_lit_frozen(mrb, "false"); + mrb_value str = mrb_str_new_lit_frozen(mrb, "false"); + RSTR_SET_ASCII_FLAG(mrb_str_ptr(str)); + return str; } void @@ -319,6 +338,7 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char if (mrb_type(val) == type) return val; 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); } return v; @@ -358,7 +378,6 @@ static const struct types { {MRB_TT_STRING, "String"}, {MRB_TT_RANGE, "Range"}, /* {MRB_TT_BIGNUM, "Bignum"}, */ - {MRB_TT_FILE, "File"}, {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 */ diff --git a/src/print.c b/src/print.c index 7d2d16086..a75814d81 100644 --- a/src/print.c +++ b/src/print.c @@ -7,24 +7,48 @@ #include <mruby.h> #include <mruby/string.h> #include <mruby/variable.h> +#include <mruby/error.h> +#include <string.h> #ifndef MRB_DISABLE_STDIO static void +printcstr(const char *str, size_t len, FILE *stream) +{ + if (str) { + fwrite(str, len, 1, stream); + putc('\n', stream); + } +} + +static void printstr(mrb_value obj, FILE *stream) { if (mrb_string_p(obj)) { - fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stream); - putc('\n', stream); + printcstr(RSTRING_PTR(obj), RSTRING_LEN(obj), stream); } } #else +# define printcstr(str, len, stream) (void)0 # define printstr(obj, stream) (void)0 #endif +void +mrb_core_init_printabort(void) +{ + static const char *str = "Failed mruby core initialization"; + printcstr(str, strlen(str), stdout); +} + MRB_API void mrb_p(mrb_state *mrb, mrb_value obj) { - printstr(mrb_inspect(mrb, obj), stdout); + if (mrb_type(obj) == MRB_TT_EXCEPTION && mrb_obj_ptr(obj) == mrb->nomem_err) { + static const char *str = "Out of memory"; + printcstr(str, strlen(str), stdout); + } + else { + printstr(mrb_inspect(mrb, obj), stdout); + } } MRB_API void diff --git a/src/proc.c b/src/proc.c index 0bc313eb9..c00b09acf 100644 --- a/src/proc.c +++ b/src/proc.c @@ -8,6 +8,7 @@ #include <mruby/class.h> #include <mruby/proc.h> #include <mruby/opcode.h> +#include <mruby/data.h> static const mrb_code call_iseq[] = { OP_CALL, @@ -46,7 +47,7 @@ env_new(mrb_state *mrb, mrb_int nlocals) int bidx; e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL); - MRB_ENV_SET_STACK_LEN(e, nlocals); + MRB_ENV_SET_LEN(e, nlocals); bidx = ci->argc; if (ci->argc < 0) bidx = 2; else bidx += 1; @@ -121,8 +122,15 @@ mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const p->e.env = e = env_new(mrb, argc); p->flags |= MRB_PROC_ENVSET; mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e); - MRB_ENV_UNSHARE_STACK(e); + MRB_ENV_CLOSE(e); + + /* NOTE: Prevents keeping invalid addresses when NoMemoryError is raised from `mrb_malloc()`. */ + e->stack = NULL; + MRB_ENV_SET_LEN(e, 0); + e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); + MRB_ENV_SET_LEN(e, argc); + if (argv) { for (i = 0; i < argc; ++i) { e->stack[i] = argv[i]; @@ -155,9 +163,9 @@ mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx) if (!e) { mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv."); } - if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) { + if (idx < 0 || MRB_ENV_LEN(e) <= idx) { mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %i (expected: 0 <= index < %i)", - idx, MRB_ENV_STACK_LEN(e)); + idx, MRB_ENV_LEN(e)); } return e->stack[idx]; @@ -203,9 +211,8 @@ mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class) static mrb_value mrb_proc_init_copy(mrb_state *mrb, mrb_value self) { - mrb_value proc; + mrb_value proc = mrb_get_arg1(mrb); - mrb_get_args(mrb, "o", &proc); if (!mrb_proc_p(proc)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); } @@ -286,14 +293,25 @@ 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; - mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); + 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; @@ -305,6 +323,7 @@ mrb_init_proc(mrb_state *mrb) mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE()); p = mrb_proc_new(mrb, call_irep); + irep_obj->data = NULL; 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); diff --git a/src/range.c b/src/range.c index 6df5d13a3..0b4e6dbca 100644 --- a/src/range.c +++ b/src/range.c @@ -182,11 +182,9 @@ range_eq(mrb_state *mrb, mrb_value range) { struct RRange *rr; struct RRange *ro; - mrb_value obj; + mrb_value obj = mrb_get_arg1(mrb); mrb_bool v1, v2; - mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */ return mrb_false_value(); @@ -211,13 +209,11 @@ range_eq(mrb_state *mrb, mrb_value range) static mrb_value range_include(mrb_state *mrb, mrb_value range) { - mrb_value val; + mrb_value val = mrb_get_arg1(mrb); struct RRange *r = mrb_range_ptr(mrb, range); mrb_value beg, end; mrb_bool include_p; - mrb_get_args(mrb, "o", &val); - beg = RANGE_BEG(r); end = RANGE_END(r); include_p = r_le(mrb, beg, val) && /* beg <= val */ @@ -289,11 +285,9 @@ range_inspect(mrb_state *mrb, mrb_value range) static mrb_value range_eql(mrb_state *mrb, mrb_value range) { - mrb_value obj; + mrb_value obj = mrb_get_arg1(mrb); struct RRange *r, *o; - mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value(); if (!mrb_range_p(obj)) return mrb_false_value(); @@ -312,11 +306,9 @@ range_eql(mrb_state *mrb, mrb_value range) static mrb_value range_initialize_copy(mrb_state *mrb, mrb_value copy) { - mrb_value src; + mrb_value src = mrb_get_arg1(mrb); struct RRange *r; - mrb_get_args(mrb, "o", &src); - if (mrb_obj_equal(mrb, copy, src)) return copy; if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) { mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); diff --git a/src/state.c b/src/state.c index 3e5ebb483..790f7ca13 100644 --- a/src/state.c +++ b/src/state.c @@ -19,11 +19,25 @@ void mrb_init_mrbgems(mrb_state*); void mrb_gc_init(mrb_state*, mrb_gc *gc); void mrb_gc_destroy(mrb_state*, mrb_gc *gc); +int mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque); + +static void +init_gc_and_core(mrb_state *mrb, void *opaque) +{ + static const struct mrb_context mrb_context_zero = { 0 }; + + mrb_gc_init(mrb, &mrb->gc); + mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); + *mrb->c = mrb_context_zero; + mrb->root_c = mrb->c; + + mrb_init_core(mrb); +} + MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud) { static const mrb_state mrb_state_zero = { 0 }; - static const struct mrb_context mrb_context_zero = { 0 }; mrb_state *mrb; if (f == NULL) f = mrb_default_allocf; @@ -35,12 +49,10 @@ mrb_open_core(mrb_allocf f, void *ud) mrb->allocf = f; mrb->atexit_stack_len = 0; - mrb_gc_init(mrb, &mrb->gc); - mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); - *mrb->c = mrb_context_zero; - mrb->root_c = mrb->c; - - mrb_init_core(mrb); + if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) { + mrb_close(mrb); + return NULL; + } return mrb; } @@ -65,6 +77,12 @@ mrb_open(void) return mrb; } +static void +init_mrbgems(mrb_state *mrb, void *opaque) +{ + mrb_init_mrbgems(mrb); +} + MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud) { @@ -75,7 +93,10 @@ mrb_open_allocf(mrb_allocf f, void *ud) } #ifndef DISABLE_GEMS - mrb_init_mrbgems(mrb); + if (mrb_core_init_protect(mrb, init_mrbgems, NULL)) { + mrb_close(mrb); + return NULL; + } mrb_gc_arena_restore(mrb, 0); #endif return mrb; @@ -131,9 +152,11 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) } mrb_free(mrb, irep->pool); mrb_free(mrb, irep->syms); - for (i=0; i<irep->rlen; i++) { - if (irep->reps[i]) - mrb_irep_decref(mrb, irep->reps[i]); + if (irep->reps) { + for (i=0; i<irep->rlen; i++) { + if (irep->reps[i]) + mrb_irep_decref(mrb, irep->reps[i]); + } } mrb_free(mrb, irep->reps); mrb_free(mrb, irep->lv); @@ -141,8 +164,6 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) mrb_free(mrb, irep); } -void mrb_free_backtrace(mrb_state *mrb); - MRB_API void mrb_free_context(mrb_state *mrb, struct mrb_context *c) { diff --git a/src/string.c b/src/string.c index c7b9db17a..f2c52404e 100644 --- a/src/string.c +++ b/src/string.c @@ -301,8 +301,8 @@ static const char utf8len_codepage[256] = 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1, }; -static mrb_int -utf8len(const char* p, const char* e) +mrb_int +mrb_utf8len(const char* p, const char* e) { mrb_int len; mrb_int i; @@ -318,14 +318,14 @@ utf8len(const char* p, const char* e) } mrb_int -mrb_utf8_len(const char *str, mrb_int byte_len) +mrb_utf8_strlen(const char *str, mrb_int byte_len) { mrb_int total = 0; const char *p = str; const char *e = p + byte_len; while (p < e) { - p += utf8len(p, e); + p += mrb_utf8len(p, e); total++; } return total; @@ -341,7 +341,7 @@ utf8_strlen(mrb_value str) return byte_len; } else { - mrb_int utf8_len = mrb_utf8_len(RSTR_PTR(s), byte_len); + mrb_int utf8_len = mrb_utf8_strlen(RSTR_PTR(s), byte_len); if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s); return utf8_len; } @@ -362,7 +362,7 @@ chars2bytes(mrb_value s, mrb_int off, mrb_int idx) const char *e = RSTRING_END(s); for (b=i=0; p<e && i<idx; i++) { - n = utf8len(p, e); + n = mrb_utf8len(p, e); b += n; p += n; } @@ -379,7 +379,7 @@ bytes2chars(char *p, mrb_int len, mrb_int bi) mrb_int i; for (i = 0; p < pivot; i ++) { - p += utf8len(p, e); + p += mrb_utf8len(p, e); } if (p != pivot) return -1; return i; @@ -400,7 +400,7 @@ char_adjust(const char *beg, const char *end, const char *ptr) while (p > beg) { p --; if ((*p & 0xc0) != 0x80) { - int clen = utf8len(p, end); + int clen = mrb_utf8len(p, end); if (clen > ptr - p) return p; break; } @@ -463,10 +463,10 @@ str_index_str_by_char_search(mrb_state *mrb, const char *p, const char *pend, co } pivot = p + qstable[(unsigned char)p[slen - 1]]; - if (pivot > pend || pivot < p /* overflowed */) { return -1; } + if (pivot >= pend || pivot < p /* overflowed */) { return -1; } do { - p += utf8len(p, pend); + p += mrb_utf8len(p, pend); off ++; } while (p < pivot); } @@ -485,7 +485,7 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) for (; pos > 0; pos --) { if (pend - p < 1) { return -1; } - p += utf8len(p, pend); + p += mrb_utf8len(p, pend); } if (slen < 1) { return off; } @@ -504,25 +504,45 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) #define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos) #endif +#ifndef MRB_QS_SHORT_STRING_LENGTH +#define MRB_QS_SHORT_STRING_LENGTH 2048 +#endif + static inline mrb_int mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) { - const unsigned char *x = xs, *xe = xs + m; - const unsigned char *y = ys; - int i; - ptrdiff_t qstable[256]; + if (n + m < MRB_QS_SHORT_STRING_LENGTH) { + const unsigned char *y = ys; + const unsigned char *ye = ys+n-m+1; - /* Preprocessing */ - for (i = 0; i < 256; ++i) - qstable[i] = m + 1; - for (; x < xe; ++x) - qstable[*x] = xe - x; - /* Searching */ - for (; y + m <= ys + n; y += *(qstable + y[m])) { - if (*xs == *y && memcmp(xs, y, m) == 0) - return (mrb_int)(y - ys); + for (;;) { + y = (const unsigned char*)memchr(y, xs[0], (size_t)(ye-y)); + if (y == NULL) return -1; + if (memcmp(xs, y, m) == 0) { + return (mrb_int)(y - ys); + } + y++; + } + return -1; + } + else { + const unsigned char *x = xs, *xe = xs + m; + const unsigned char *y = ys; + int i; + ptrdiff_t qstable[256]; + + /* Preprocessing */ + for (i = 0; i < 256; ++i) + qstable[i] = m + 1; + for (; x < xe; ++x) + qstable[*x] = xe - x; + /* Searching */ + for (; y + m <= ys + n; y += *(qstable + y[m])) { + if (*xs == *y && memcmp(xs, y, m) == 0) + return (mrb_int)(y - ys); + } + return -1; } - return -1; } static mrb_int @@ -1041,10 +1061,9 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2) static mrb_value mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) { - mrb_value str2; + mrb_value str2 = mrb_get_arg1(mrb); mrb_int result; - mrb_get_args(mrb, "o", &str2); if (!mrb_string_p(str2)) { return mrb_nil_value(); } @@ -1086,9 +1105,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) static mrb_value mrb_str_equal_m(mrb_state *mrb, mrb_value str1) { - mrb_value str2; - - mrb_get_args(mrb, "o", &str2); + mrb_value str2 = mrb_get_arg1(mrb); return mrb_bool_value(mrb_str_equal(mrb, str1, str2)); } @@ -1104,6 +1121,7 @@ mrb_str_to_str(mrb_state *mrb, mrb_value str) 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); @@ -1342,7 +1360,7 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect) unsigned char c, cc; #ifdef MRB_UTF8_STRING if (inspect) { - mrb_int clen = utf8len(p, pend); + mrb_int clen = mrb_utf8len(p, pend); if (clen > 1) { mrb_int i; @@ -1645,7 +1663,7 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str) const char* t = RSTR_PTR(s), *p = t; const char* e = p + RSTR_LEN(s); while (p<e) { - mrb_int clen = utf8len(p, e); + mrb_int clen = mrb_utf8len(p, e); if (p + clen>=e) break; p += clen; } @@ -1771,10 +1789,9 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self) static mrb_value mrb_str_eql(mrb_state *mrb, mrb_value self) { - mrb_value str2; + mrb_value str2 = mrb_get_arg1(mrb); mrb_bool eql_p; - mrb_get_args(mrb, "o", &str2); eql_p = (mrb_string_p(str2)) && str_eql(mrb, self, str2); return mrb_bool_value(eql_p); @@ -2017,7 +2034,7 @@ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) p = RSTR_PTR(s); e = p + RSTR_LEN(s); while (p<e) { - mrb_int clen = utf8len(p, e); + mrb_int clen = mrb_utf8len(p, e); str_reverse(p, p + clen - 1); p += clen; } @@ -2241,7 +2258,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) } mrb_value -mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck) +mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, int badcheck) { const char *p = str; const char *pend = str + len; @@ -2739,7 +2756,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr) { - return mrb_str_cat(mrb, str, ptr, strlen(ptr)); + return mrb_str_cat(mrb, str, ptr, ptr ? strlen(ptr) : 0); } MRB_API mrb_value @@ -2869,25 +2886,32 @@ mrb_str_setbyte(mrb_state *mrb, mrb_value str) static mrb_value mrb_str_byteslice(mrb_state *mrb, mrb_value str) { - mrb_value a1, a2; + mrb_value a1; mrb_int str_len = RSTRING_LEN(str), beg, len; mrb_bool empty = TRUE; - if (mrb_get_args(mrb, "o|o", &a1, &a2) == 2) { - beg = mrb_fixnum(mrb_to_int(mrb, a1)); - len = mrb_fixnum(mrb_to_int(mrb, a2)); - } - else if (mrb_range_p(a1)) { - if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) { - return mrb_nil_value(); + len = mrb_get_argc(mrb); + switch (len) { + case 2: + mrb_get_args(mrb, "ii", &beg, &len); + break; + case 1: + a1 = mrb_get_arg1(mrb); + if (mrb_range_p(a1)) { + if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) { + return mrb_nil_value(); + } } + else { + beg = mrb_fixnum(mrb_to_int(mrb, a1)); + len = 1; + empty = FALSE; + } + break; + default: + mrb_argnum_error(mrb, len, 1, 2); + break; } - else { - beg = mrb_fixnum(mrb_to_int(mrb, a1)); - len = 1; - empty = FALSE; - } - if (mrb_str_beg_len(str_len, &beg, &len) && (empty || len != 0)) { return mrb_str_byte_subseq(mrb, str, beg, len); } diff --git a/src/symbol.c b/src/symbol.c index b8d0ea1e7..992848797 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -48,14 +48,14 @@ sym_validate_len(mrb_state *mrb, size_t len) static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static mrb_sym -sym_inline_pack(const char *name, uint16_t len) +sym_inline_pack(const char *name, size_t len) { - const int lower_length_max = (MRB_SYMBOL_BIT - 2) / 5; - const int mix_length_max = (MRB_SYMBOL_BIT - 2) / 6; + const size_t lower_length_max = (MRB_SYMBOL_BIT - 2) / 5; + const size_t mix_length_max = (MRB_SYMBOL_BIT - 2) / 6; char c; const char *p; - int i; + size_t i; mrb_sym sym = 0; mrb_bool lower = TRUE; @@ -124,7 +124,7 @@ symhash(const char *key, size_t len) } static mrb_sym -find_symbol(mrb_state *mrb, const char *name, uint16_t len, uint8_t *hashp) +find_symbol(mrb_state *mrb, const char *name, size_t len, uint8_t *hashp) { mrb_sym i; symbol_name *sname; @@ -172,11 +172,13 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) if (sym > 0) return sym; /* registering a new symbol */ - sym = ++mrb->symidx; + sym = mrb->symidx + 1; if (mrb->symcapa < sym) { - if (mrb->symcapa == 0) mrb->symcapa = 100; - else mrb->symcapa = (size_t)(mrb->symcapa * 6 / 5); - mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1)); + size_t symcapa = mrb->symcapa; + if (symcapa == 0) symcapa = 100; + else symcapa = (size_t)(symcapa * 6 / 5); + mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(symcapa+1)); + mrb->symcapa = symcapa; } sname = &mrb->symtbl[sym]; sname->len = (uint16_t)len; @@ -201,7 +203,7 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) else { sname->prev = 0; } - mrb->symhash[hash] = sym; + mrb->symhash[hash] = mrb->symidx = sym; return sym<<SYMBOL_NORMAL_SHIFT; } @@ -562,10 +564,9 @@ mrb_sym_dump(mrb_state *mrb, mrb_sym sym) static mrb_value sym_cmp(mrb_state *mrb, mrb_value s1) { - mrb_value s2; + mrb_value s2 = mrb_get_arg1(mrb); mrb_sym sym1, sym2; - mrb_get_args(mrb, "o", &s2); if (!mrb_symbol_p(s2)) return mrb_nil_value(); sym1 = mrb_symbol(s1); sym2 = mrb_symbol(s2); diff --git a/src/variable.c b/src/variable.c index 030aa7b00..c36fea6e3 100644 --- a/src/variable.c +++ b/src/variable.c @@ -349,7 +349,7 @@ mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value obj->iv = iv_new(mrb); } iv_put(mrb, obj->iv, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)obj); + mrb_field_write_barrier_value(mrb, (struct RBasic*)obj, v); } MRB_API void @@ -679,7 +679,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) if (iv_get(mrb, t, sym, NULL)) { mrb_check_frozen(mrb, c); iv_put(mrb, t, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)c); + mrb_field_write_barrier_value(mrb, (struct RBasic*)c, v); return; } c = c->super; @@ -711,7 +711,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) } iv_put(mrb, c->iv, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)c); + mrb_field_write_barrier_value(mrb, (struct RBasic*)c, v); } MRB_API void @@ -1128,6 +1128,21 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) return path; } +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; +} + #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) mrb_bool @@ -102,26 +102,20 @@ void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value static inline void stack_clear(mrb_value *from, size_t count) { -#ifndef MRB_NAN_BOXING - const mrb_value mrb_value_zero = { { 0 } }; - - while (count-- > 0) { - *from++ = mrb_value_zero; - } -#else +#ifdef MRB_NAN_BOXING while (count-- > 0) { SET_NIL_VALUE(*from); from++; } +#else + memset(from, 0, sizeof(mrb_value)*count); #endif } static inline void stack_copy(mrb_value *dst, const mrb_value *src, size_t size) { - while (size-- > 0) { - *dst++ = *src++; - } + memcpy(dst, src, sizeof(mrb_value)*size); } static void @@ -152,7 +146,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize struct REnv *e = ci->env; mrb_value *st; - if (e && MRB_ENV_STACK_SHARED_P(e) && + if (e && MRB_ENV_ONSTACK_P(e) && (st = e->stack) && oldbase <= st && st < oldbase+oldsize) { ptrdiff_t off = e->stack - oldbase; @@ -162,7 +156,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize if (ci->proc && MRB_PROC_ENV_P(ci->proc) && ci->env != MRB_PROC_ENV(ci->proc)) { e = MRB_PROC_ENV(ci->proc); - if (e && MRB_ENV_STACK_SHARED_P(e) && + if (e && MRB_ENV_ONSTACK_P(e) && (st = e->stack) && oldbase <= st && st < oldbase+oldsize) { ptrdiff_t off = e->stack - oldbase; @@ -269,14 +263,12 @@ top_proc(mrb_state *mrb, struct RProc *proc) #define CI_ACC_RESUMED -3 static inline mrb_callinfo* -cipush(mrb_state *mrb) +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) { struct mrb_context *c = mrb->c; - static const mrb_callinfo ci_zero = { 0 }; mrb_callinfo *ci = c->ci; - int ridx = ci->ridx; - if (ci + 1 == c->ciend) { ptrdiff_t size = ci - c->cibase; @@ -285,9 +277,18 @@ cipush(mrb_state *mrb) c->ciend = c->cibase + size * 2; } ci = ++c->ci; - *ci = ci_zero; - ci->epos = mrb->c->eidx; - ci->ridx = ridx; + 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; + ci->target_class = target_class; + ci->err = 0; + ci->env = 0; + c->stack += push_stacks; return ci; } @@ -297,10 +298,10 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e) { if (e == NULL) return; else { - size_t len = (size_t)MRB_ENV_STACK_LEN(e); + size_t len = (size_t)MRB_ENV_LEN(e); mrb_value *p; - if (!MRB_ENV_STACK_SHARED_P(e)) return; + if (!MRB_ENV_ONSTACK_P(e)) return; if (e->cxt != mrb->c) return; if (e == mrb->c->cibase->env) return; /* for mirb */ p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); @@ -308,22 +309,25 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e) stack_copy(p, e->stack, len); } e->stack = p; - MRB_ENV_UNSHARE_STACK(e); + MRB_ENV_CLOSE(e); mrb_write_barrier(mrb, (struct RBasic *)e); } } -static inline void +static inline mrb_callinfo* cipop(mrb_state *mrb) { struct mrb_context *c = mrb->c; struct REnv *env = c->ci->env; + mrb->c->stack = c->ci->stackent; c->ci--; if (env) mrb_env_unshare(mrb, env); + return c->ci; } 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) @@ -335,10 +339,12 @@ ecall(mrb_state *mrb) struct REnv *env; ptrdiff_t cioff; int ai = mrb_gc_arena_save(mrb); - uint16_t i = --c->eidx; + uint16_t i; int nregs; - if (i<0) return; + 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)); @@ -353,16 +359,9 @@ ecall(mrb_state *mrb) nregs = ci->proc->body.irep->nregs; } cioff = ci - c->cibase; - ci = cipush(mrb); - ci->stackent = mrb->c->stack; - ci->mid = ci[-1].mid; - ci->acc = CI_ACC_SKIP; - ci->argc = 0; - ci->proc = p; - ci->target_class = MRB_PROC_TARGET_CLASS(p); + 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); - c->stack += nregs; exc = mrb->exc; mrb->exc = 0; if (exc) { mrb_gc_protect(mrb, mrb_obj_value(exc)); @@ -430,6 +429,7 @@ MRB_API mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk) { mrb_value val; + int ai = mrb_gc_arena_save(mrb); if (!mrb->jmp) { struct mrb_jmpbuf c_jmp; @@ -443,7 +443,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc } MRB_CATCH(&c_jmp) { /* error */ while (nth_ci < (mrb->c->ci - mrb->c->cibase)) { - mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } mrb->jmp = 0; @@ -482,12 +481,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) { mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } - ci = cipush(mrb); - ci->mid = mid; - ci->stackent = mrb->c->stack; - ci->argc = (int)argc; - ci->target_class = c; - mrb->c->stack = mrb->c->stack + n; + ci = cipush(mrb, NULL, n, 0, c, NULL, mid, argc); if (argc < 0) argc = 1; if (mrb->c->stbase <= argv && argv < mrb->c->stend) { voff = argv - mrb->c->stbase; @@ -518,19 +512,16 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb->c->stack[argc+1] = blk; if (MRB_METHOD_CFUNC_P(m)) { - int ai = mrb_gc_arena_save(mrb); - ci->acc = CI_ACC_DIRECT; val = MRB_METHOD_CFUNC(m)(mrb, self); - mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); - mrb_gc_arena_restore(mrb, ai); } else { ci->acc = CI_ACC_SKIP; val = mrb_run(mrb, MRB_METHOD_PROC(m), self); } } + mrb_gc_arena_restore(mrb, ai); mrb_gc_protect(mrb, val); return val; } @@ -563,11 +554,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) stack_clear(mrb->c->stack+keep, nregs-keep); } - ci = cipush(mrb); - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; + cipush(mrb, p->body.irep->iseq, 0, 0, NULL, NULL, 0, 0); return self; } @@ -625,7 +612,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self) ci->argc--; } else { /* variable length arguments */ - mrb_ary_shift(mrb, regs[0]); + regs[0] = mrb_ary_subseq(mrb, regs[0], 1, RARRAY_LEN(regs[0]) - 1); } if (MRB_METHOD_CFUNC_P(m)) { @@ -649,8 +636,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) } ci = mrb->c->ci; if (ci->acc == CI_ACC_DIRECT) { - ci->target_class = c; - return mrb_yield_cont(mrb, blk, self, 1, &self); + return mrb_yield_with_class(mrb, blk, 1, &self, self, c); } ci->target_class = c; p = mrb_proc_ptr(blk); @@ -670,11 +656,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) mrb->c->stack[0] = self; mrb->c->stack[1] = self; stack_clear(mrb->c->stack+2, nregs-2); - ci = cipush(mrb); - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; + ci = cipush(mrb, p->body.irep->iseq, 0, 0, NULL, NULL, 0, 0); return self; } @@ -725,26 +707,11 @@ mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) { mrb_value a, b; - mrb_value cv; - struct RClass *c; if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); } - switch (mrb_type(self)) { - case MRB_TT_SYMBOL: - case MRB_TT_FIXNUM: -#ifndef MRB_WITHOUT_FLOAT - case MRB_TT_FLOAT: -#endif - c = 0; - break; - default: - cv = mrb_singleton_class(mrb, self); - c = mrb_class_ptr(cv); - break; - } - return eval_under(mrb, self, b, c); + return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self)); } MRB_API mrb_value @@ -765,26 +732,28 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } p = mrb_proc_ptr(b); - ci = cipush(mrb); - ci->mid = mid; - ci->proc = p; - ci->stackent = mrb->c->stack; - ci->argc = (int)argc; - ci->target_class = c; - ci->acc = CI_ACC_SKIP; - n = MRB_PROC_CFUNC_P(p) ? (int)(argc+2) : p->body.irep->nregs; - mrb->c->stack = mrb->c->stack + n; + ci = cipush(mrb, NULL, n, CI_ACC_SKIP, c, p, mid, 0 /* dummy */); + if (argc >= CALL_MAXARGS) { + ci->argc = -1; + n = 3; + } + else { + ci->argc = (int)argc; + n = argc + 2; + } mrb_stack_extend(mrb, n); - mrb->c->stack[0] = self; - if (argc > 0) { + if (ci->argc < 0) { + mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv); + argc = 1; + } + else if (argc > 0) { stack_copy(mrb->c->stack+1, argv, argc); } mrb->c->stack[argc+1] = mrb_nil_value(); if (MRB_PROC_CFUNC_P(p)) { val = MRB_PROC_CFUNC(p)(mrb, self); - mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } else { @@ -1063,6 +1032,11 @@ RETRY_TRY_BLOCK: NEXT; } + CASE(OP_LOADI16, BS) { + SET_INT_VALUE(regs[a], (mrb_int)(int16_t)b); + NEXT; + } + CASE(OP_LOADSYM, BB) { SET_SYM_VALUE(regs[a], syms[b]); NEXT; @@ -1100,13 +1074,13 @@ RETRY_TRY_BLOCK: } CASE(OP_GETSV, BB) { - mrb_value val = mrb_vm_special_get(mrb, b); + mrb_value val = mrb_vm_special_get(mrb, syms[b]); regs[a] = val; NEXT; } CASE(OP_SETSV, BB) { - mrb_vm_special_set(mrb, b, regs[a]); + mrb_vm_special_set(mrb, syms[b], regs[a]); NEXT; } @@ -1169,7 +1143,7 @@ RETRY_TRY_BLOCK: mrb_value *regs_a = regs + a; struct REnv *e = uvenv(mrb, c); - if (e && b < MRB_ENV_STACK_LEN(e)) { + if (e && b < MRB_ENV_LEN(e)) { *regs_a = e->stack[b]; } else { @@ -1184,7 +1158,7 @@ RETRY_TRY_BLOCK: if (e) { mrb_value *regs_a = regs + a; - if (b < MRB_ENV_STACK_LEN(e)) { + if (b < MRB_ENV_LEN(e)) { e->stack[b] = *regs_a; mrb_write_barrier(mrb, (struct RBasic*)e); } @@ -1328,15 +1302,7 @@ RETRY_TRY_BLOCK: mrb->c->ensure[epos+n] = NULL; if (proc == NULL) continue; irep = proc->body.irep; - ci = cipush(mrb); - ci->mid = ci[-1].mid; - ci->argc = 0; - ci->proc = proc; - ci->stackent = mrb->c->stack; - ci->target_class = target_class; - ci->pc = pc; - ci->acc = nregs; - mrb->c->stack += ci->acc; + ci = cipush(mrb, pc, nregs, nregs, target_class, proc, ci->mid, 0); mrb_stack_extend(mrb, irep->nregs); regs[0] = self; pc = irep->iseq; @@ -1418,17 +1384,7 @@ RETRY_TRY_BLOCK: } /* push callinfo */ - ci = cipush(mrb); - ci->mid = mid; - ci->stackent = mrb->c->stack; - ci->target_class = cls; - ci->argc = argc; - - ci->pc = pc; - ci->acc = a; - - /* prepare stack */ - mrb->c->stack += a; + ci = cipush(mrb, pc, a, a, cls, NULL, mid, argc); if (MRB_METHOD_CFUNC_P(m)) { if (MRB_METHOD_PROC_P(m)) { @@ -1470,7 +1426,6 @@ RETRY_TRY_BLOCK: } mrb->c->stack[0] = recv; /* pop stackpos */ - mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); JUMP; @@ -1497,14 +1452,7 @@ RETRY_TRY_BLOCK: ci->target_class = MRB_PROC_TARGET_CLASS(m); ci->proc = m; if (MRB_PROC_ENV_P(m)) { - mrb_sym mid; - struct REnv *e = MRB_PROC_ENV(m); - - mid = e->mid; - if (mid) ci->mid = mid; - if (!e->stack) { - e->stack = mrb->c->stack; - } + ci->mid = MRB_PROC_ENV(m)->mid; } /* prepare stack */ @@ -1515,10 +1463,9 @@ RETRY_TRY_BLOCK: if (mrb->exc) goto L_RAISE; /* pop stackpos */ ci = mrb->c->ci; - mrb->c->stack = ci->stackent; - regs[ci->acc] = recv; pc = ci->pc; cipop(mrb); + regs[ci->acc] = recv; irep = mrb->c->ci->proc->body.irep; pool = irep->pool; syms = irep->syms; @@ -1624,15 +1571,9 @@ RETRY_TRY_BLOCK: } /* push callinfo */ - ci = cipush(mrb); - ci->mid = mid; - ci->stackent = mrb->c->stack; - ci->target_class = cls; - ci->pc = pc; - ci->argc = argc; + ci = cipush(mrb, pc, a, 0, cls, NULL, mid, argc); /* prepare stack */ - mrb->c->stack += a; mrb->c->stack[0] = recv; if (MRB_METHOD_CFUNC_P(m)) { @@ -1659,8 +1600,6 @@ RETRY_TRY_BLOCK: } } mrb->c->stack[0] = v; - /* pop stackpos */ - mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); JUMP; @@ -1700,7 +1639,7 @@ RETRY_TRY_BLOCK: else { struct REnv *e = uvenv(mrb, lv-1); if (!e) goto L_NOSUPER; - if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1) + if (MRB_ENV_LEN(e) <= m1+r+m2+kd+1) goto L_NOSUPER; stack = e->stack + 1; } @@ -1961,13 +1900,11 @@ RETRY_TRY_BLOCK: goto L_RESCUE; } while (ci[0].ridx == ci[-1].ridx) { - cipop(mrb); - mrb->c->stack = ci->stackent; - if (ci->acc == CI_ACC_SKIP && prev_jmp) { + ci = cipop(mrb); + if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } - ci = mrb->c->ci; if (ci == mrb->c->cibase) { if (ci->ridx == 0) { L_FTOP: /* fiber top */ @@ -2026,7 +1963,7 @@ RETRY_TRY_BLOCK: if (MRB_PROC_ENV_P(dst)) { struct REnv *e = MRB_PROC_ENV(dst); - if (!MRB_ENV_STACK_SHARED_P(e) || (e->cxt && e->cxt != mrb->c)) { + if (!MRB_ENV_ONSTACK_P(e) || (e->cxt && e->cxt != mrb->c)) { localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; } @@ -2081,7 +2018,7 @@ RETRY_TRY_BLOCK: mrb_exc_set(mrb, exc); goto L_RAISE; } - if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_STACK_SHARED_P(MRB_PROC_ENV(proc))) { + if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) { goto L_BREAK_ERROR; } else { @@ -2149,15 +2086,13 @@ RETRY_TRY_BLOCK: return v; } acc = ci->acc; - mrb->c->stack = ci->stackent; - cipop(mrb); + ci = cipop(mrb); if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) { mrb_gc_arena_restore(mrb, ai); mrb->jmp = prev_jmp; return v; } - pc = ci->pc; - ci = mrb->c->ci; + pc = ci[1].pc; DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid))); proc = mrb->c->ci->proc; irep = proc->body.irep; @@ -2181,8 +2116,8 @@ RETRY_TRY_BLOCK: if (lv == 0) stack = regs + 1; else { struct REnv *e = uvenv(mrb, lv-1); - if (!e || (!MRB_ENV_STACK_SHARED_P(e) && e->mid == 0) || - MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) { + if (!e || (!MRB_ENV_ONSTACK_P(e) && e->mid == 0) || + MRB_ENV_LEN(e) <= m1+r+m2+1) { localjump_error(mrb, LOCALJUMP_ERROR_YIELD); goto L_RAISE; } @@ -2671,7 +2606,6 @@ RETRY_TRY_BLOCK: } CASE(OP_EXEC, BB) { - mrb_callinfo *ci; mrb_value recv = regs[a]; struct RProc *p; mrb_irep *nirep = irep->reps[b]; @@ -2684,19 +2618,7 @@ RETRY_TRY_BLOCK: p->flags |= MRB_PROC_SCOPE; /* prepare call stack */ - ci = cipush(mrb); - ci->pc = pc; - ci->acc = a; - ci->mid = 0; - ci->stackent = mrb->c->stack; - ci->argc = 0; - ci->target_class = mrb_class_ptr(recv); - - /* prepare stack */ - mrb->c->stack += a; - - /* setup block to call */ - ci->proc = p; + cipush(mrb, pc, a, a, mrb_class_ptr(recv), p, 0, 0); irep = p->body.irep; pool = irep->pool; @@ -2827,7 +2749,7 @@ RETRY_TRY_BLOCK: MRB_END_EXC(&c_jmp); } -MRB_API mrb_value +static mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { if (mrb->c->ci->argc < 0) { @@ -2841,7 +2763,6 @@ 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_callinfo *ci; mrb_value v; if (!mrb->c->cibase) { @@ -2851,11 +2772,7 @@ mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int sta mrb->c->ci->env = NULL; return mrb_vm_run(mrb, proc, self, stack_keep); } - ci = cipush(mrb); - ci->stackent = mrb->c->stack; - ci->mid = 0; - ci->acc = CI_ACC_SKIP; - ci->target_class = mrb->object_class; + cipush(mrb, NULL, 0, CI_ACC_SKIP, mrb->object_class, NULL, 0, 0); v = mrb_vm_run(mrb, proc, self, stack_keep); return v; |
