summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c60
-rw-r--r--src/backtrace.c4
-rw-r--r--src/class.c107
-rw-r--r--src/codedump.c4
-rw-r--r--src/debug.c15
-rw-r--r--src/dump.c68
-rw-r--r--src/error.c65
-rw-r--r--src/etc.c25
-rw-r--r--src/fmt_fp.c119
-rw-r--r--src/gc.c327
-rw-r--r--src/hash.c58
-rw-r--r--src/kernel.c87
-rw-r--r--src/load.c88
-rw-r--r--src/numeric.c145
-rw-r--r--src/object.c29
-rw-r--r--src/print.c30
-rw-r--r--src/proc.c33
-rw-r--r--src/range.c16
-rw-r--r--src/state.c47
-rw-r--r--src/string.c126
-rw-r--r--src/symbol.c25
-rw-r--r--src/variable.c21
-rw-r--r--src/vm.c243
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)
{
diff --git a/src/etc.c b/src/etc.c
index 607e82ca1..74b9ab03b 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -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
diff --git a/src/gc.c b/src/gc.c
index 8d9a1806c..5531207db 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -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
diff --git a/src/vm.c b/src/vm.c
index 2ccc03e30..cc9a187b7 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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;