summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class.c17
-rw-r--r--src/codedump.c4
-rw-r--r--src/fmt_fp.c1
-rw-r--r--src/gc.c18
-rw-r--r--src/hash.c24
-rw-r--r--src/numeric.c24
-rw-r--r--src/string.c38
-rw-r--r--src/vm.c16
8 files changed, 80 insertions, 62 deletions
diff --git a/src/class.c b/src/class.c
index e5fa71f62..85a26d343 100644
--- a/src/class.c
+++ b/src/class.c
@@ -840,7 +840,7 @@ mrb_get_arg1(mrb_state *mrb)
array_argv = ARY_PTR(a);
}
if (argc != 1) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ mrb_argnum_error(mrb, argc, 1, 1);
}
return array_argv[0];
}
@@ -894,7 +894,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_bool given = TRUE;
mrb_value kdict;
mrb_bool reqkarg = FALSE;
- mrb_int needargc = 0;
+ int argc_min = 0, argc_max = 0;
if (!argv_on_stack) {
struct RArray *a = mrb_ary_ptr(*array_argv);
@@ -912,6 +912,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
break;
case '*':
opt_skip = FALSE;
+ argc_max = -1;
if (!reqkarg) reqkarg = strchr(fmt, ':') ? TRUE : FALSE;
goto check_exit;
case '!':
@@ -923,13 +924,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (opt) opt_skip = FALSE;
break;
default:
- if (!opt) needargc ++;
+ if (!opt) argc_min++;
+ argc_max++;
break;
}
}
check_exit:
- if (reqkarg && argc > needargc && mrb_hash_p(kdict = ARGV[argc - 1])) {
+ if (reqkarg && argc > argc_min && mrb_hash_p(kdict = ARGV[argc - 1])) {
mrb_hash_check_kdict(mrb, kdict);
argc --;
}
@@ -952,7 +954,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
given = FALSE;
}
else {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ mrb_argnum_error(mrb, argc, argc_min, argc_max);
}
}
break;
@@ -1315,7 +1317,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
#undef ARGV
if (!c && argc > i) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ mrb_argnum_error(mrb, argc, argc_min, argc_max);
}
finish:
@@ -1458,7 +1460,7 @@ fix_prepend_module(mrb_state *mrb, struct RBasic *obj, void *data)
if (p->tt == MRB_TT_CLASS) break;
if (p->c == m[0]) {
include_module_at(mrb, ins_pos, ins_pos, m[1], 0);
- break;
+ break;
}
c = p;
p = p->super;
@@ -2232,7 +2234,6 @@ mrb_define_alias_id(mrb_state *mrb, struct RClass *klass, mrb_sym a, mrb_sym b)
mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
-
if (mrb_sclass_p(klass)) {
mrb_value v = mrb_iv_get(mrb, klass, MRB_SYM(__attached__));
mrb_value str = mrb_str_new_lit(mrb, "#<Class:");
diff --git a/src/codedump.c b/src/codedump.c
index 576ff6ceb..e6c6e6c3d 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -172,7 +172,7 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
print_lv_a(mrb, irep, a);
break;
CASE(OP_LOADI32, BSS);
- printf("OP_LOADI32\tR%d\t%d\t", a, (int)(((uint32_t)b<<16)+c));
+ printf("OP_LOADI32\tR%d\t%d\t", a, (int32_t)(((uint32_t)b<<16)+c));
print_lv_a(mrb, irep, a);
break;
CASE(OP_LOADI__1, B);
@@ -219,7 +219,7 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
print_lv_a(mrb, irep, a);
break;
CASE(OP_SETGV, BB);
- printf("OP_SETGV\t;%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
+ printf("OP_SETGV\t:%s\tR%d", mrb_sym_dump(mrb, irep->syms[b]), a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_GETSV, BB);
diff --git a/src/fmt_fp.c b/src/fmt_fp.c
index c46baabbc..448c20df8 100644
--- a/src/fmt_fp.c
+++ b/src/fmt_fp.c
@@ -443,7 +443,6 @@ mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_fl
return (int)(cstr.buf - buf);
}
#else /* MRB_NO_STDIO || _WIN32 || _WIN64 */
-#include <mruby.h>
#include <stdio.h>
MRB_API mrb_value
diff --git a/src/gc.c b/src/gc.c
index fb3a7bd16..eeabc3bf9 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -45,7 +45,7 @@
== Two White Types
- There're two white color types in a flip-flop fashion: White-A and White-B,
+ There are two white color types in a flip-flop fashion: White-A and White-B,
which respectively represent the Current White color (the newly allocated
objects in the current GC cycle) and the Sweep Target White color (the
dead objects to be swept).
@@ -107,8 +107,14 @@ struct free_obj {
struct RBasic *next;
};
+struct RVALUE_initializer {
+ MRB_OBJECT_HEADER;
+ char padding[sizeof(void*) * 4 - sizeof(uint32_t)];
+};
+
typedef struct {
union {
+ struct RVALUE_initializer init; /* must be first member to ensure initialization */
struct free_obj free;
struct RBasic basic;
struct RObject object;
@@ -1608,11 +1614,6 @@ mrb_objspace_page_slot_size(void)
return sizeof(RVALUE);
}
-#ifdef GC_TEST
-#ifdef GC_DEBUG
-static mrb_value gc_test(mrb_state *, mrb_value);
-#endif
-#endif
void
mrb_init_gc(mrb_state *mrb)
@@ -1633,9 +1634,4 @@ mrb_init_gc(mrb_state *mrb)
mrb_define_class_method(mrb, gc, "step_ratio=", gc_step_ratio_set, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, gc, "generational_mode=", gc_generational_mode_set, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, gc, "generational_mode", gc_generational_mode_get, MRB_ARGS_NONE());
-#ifdef GC_TEST
-#ifdef GC_DEBUG
- mrb_define_class_method(mrb, gc, "test", gc_test, MRB_ARGS_NONE());
-#endif
-#endif
}
diff --git a/src/hash.c b/src/hash.c
index b800a251a..fe14865cf 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -251,7 +251,6 @@ HT_ASSERT_SAFE_READ(ea_capa);
} while (0)
#define U32(v) ((uint32_t)(v))
-#define U64(v) ((uint64_t)(v))
#define h_ar_p(h) (!h_ht_p(h))
#define h_ar_on(h) h_ht_off(h)
#define lesser(a, b) ((a) < (b) ? (a) : (b))
@@ -360,7 +359,13 @@ ea_next_capa_for(uint32_t size, uint32_t max_capa)
return AR_DEFAULT_CAPA;
}
else {
- uint64_t capa = U64(size) * EA_INCREASE_RATIO, inc = capa - size;
+ /*
+ * For 32-bit CPU, the theoretical value of max EA capa is
+ * `UINT32_MAX / sizeof (hash_entry)`. At this time, if
+ * `EA_INCREASE_RATIO` is the current value, 32-bit range will not be
+ * exceeded during the calculation of `capa`, so `size_t` is used.
+ */
+ size_t capa = size * EA_INCREASE_RATIO, inc = capa - size;
if (EA_MAX_INCREASE < inc) capa = size + EA_MAX_INCREASE;
return capa <= max_capa ? U32(capa) : max_capa;
}
@@ -621,10 +626,13 @@ ib_it_next(index_buckets_iter *it)
* \ `-- bit_pos(34)
* `-- bit(5)
*/
- uint64_t bit_pos;
- bit_pos = U64(it->bit) * (it->pos + 1) - 1;
- it->ary_index = U32(bit_pos / IB_TYPE_BIT);
- it->shift2 = U32((U64(it->ary_index) + 1) * IB_TYPE_BIT - bit_pos - 1);
+
+ /* Slide to handle as `capa == 32` to avoid 64-bit operations */
+ uint32_t slid_pos = it->pos & (IB_TYPE_BIT - 1);
+ uint32_t slid_bit_pos = it->bit * (slid_pos + 1) - 1;
+ uint32_t slid_ary_index = slid_bit_pos / IB_TYPE_BIT;
+ it->ary_index = slid_ary_index + it->pos / IB_TYPE_BIT * it->bit;
+ it->shift2 = (slid_ary_index + 1) * IB_TYPE_BIT - slid_bit_pos - 1;
it->ea_index = (ht_ib(it->h)[it->ary_index] >> it->shift2) & it->mask;
if (IB_TYPE_BIT - it->bit < it->shift2) {
it->shift1 = IB_TYPE_BIT - it->shift2;
@@ -707,7 +715,9 @@ ib_bit_for(uint32_t size)
static uint32_t
ib_byte_size_for(uint32_t ib_bit)
{
- uint64_t ary_size = (U64(1) << ib_bit) * ib_bit / IB_TYPE_BIT;
+ uint32_t ary_size = IB_INIT_BIT == 4 ?
+ ib_bit_to_capa(ib_bit) * 2 / IB_TYPE_BIT * ib_bit / 2 :
+ ib_bit_to_capa(ib_bit) / IB_TYPE_BIT * ib_bit;
return U32(sizeof(uint32_t) * ary_size);
}
diff --git a/src/numeric.c b/src/numeric.c
index ab39bd463..117f447e5 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -75,7 +75,7 @@ int_pow(mrb_state *mrb, mrb_value x)
#ifndef MRB_NO_FLOAT
mrb_value y = mrb_get_arg1(mrb);
mrb_float z;
-
+
if (!mrb_integer_p(y)) {
mrb_get_args(mrb, "f", &z);
z = pow((mrb_float)base, z);
@@ -484,7 +484,12 @@ value_int64(mrb_state *mrb, mrb_value x)
case MRB_TT_INTEGER:
return (int64_t)mrb_integer(x);
case MRB_TT_FLOAT:
- return (int64_t)mrb_float(x);
+ {
+ double f = mrb_float(x);
+
+ if ((mrb_float)INT64_MAX >= f && f >= (mrb_float)INT64_MIN)
+ return (int64_t)f;
+ }
default:
mrb_raise(mrb, E_TYPE_ERROR, "cannot convert to Integer");
break;
@@ -496,17 +501,16 @@ value_int64(mrb_state *mrb, mrb_value x)
static mrb_value
int64_value(mrb_state *mrb, int64_t v)
{
- if (TYPED_FIXABLE(v,int64_t)) {
- return mrb_fixnum_value((mrb_int)v);
+ if (!TYPED_FIXABLE(v,int64_t)) {
+ int_overflow(mrb, "bit operation");
}
- return mrb_float_value(mrb, (mrb_float)v);
+ return mrb_fixnum_value((mrb_int)v);
}
static mrb_value
flo_rev(mrb_state *mrb, mrb_value x)
{
- int64_t v1;
- v1 = (int64_t)mrb_float(x);
+ int64_t v1 = value_int64(mrb, x);
return int64_value(mrb, ~v1);
}
@@ -516,7 +520,7 @@ flo_and(mrb_state *mrb, mrb_value x)
mrb_value y = mrb_get_arg1(mrb);
int64_t v1, v2;
- v1 = (int64_t)mrb_float(x);
+ v1 = value_int64(mrb, x);
v2 = value_int64(mrb, y);
return int64_value(mrb, v1 & v2);
}
@@ -527,7 +531,7 @@ flo_or(mrb_state *mrb, mrb_value x)
mrb_value y = mrb_get_arg1(mrb);
int64_t v1, v2;
- v1 = (int64_t)mrb_float(x);
+ v1 = value_int64(mrb, x);
v2 = value_int64(mrb, y);
return int64_value(mrb, v1 | v2);
}
@@ -538,7 +542,7 @@ flo_xor(mrb_state *mrb, mrb_value x)
mrb_value y = mrb_get_arg1(mrb);
int64_t v1, v2;
- v1 = (int64_t)mrb_float(x);
+ v1 = value_int64(mrb, x);
v2 = value_int64(mrb, y);
return int64_value(mrb, v1 ^ v2);
}
diff --git a/src/string.c b/src/string.c
index cf71914b3..946dc8be1 100644
--- a/src/string.c
+++ b/src/string.c
@@ -1752,13 +1752,17 @@ mrb_str_hash(mrb_state *mrb, mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_int len = RSTR_LEN(s);
char *p = RSTR_PTR(s);
- uint64_t key = 0;
+ uint32_t hash = 0;
- while (len--) {
- key = key*65599 + *p;
- p++;
+ for(int i = 0; i < len; ++i) {
+ hash += p[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
}
- return (uint32_t)(key + (key>>5));
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+ return hash;
}
/* 15.2.10.5.20 */
@@ -2216,7 +2220,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, i
const char *pend = str + len;
char sign = 1;
int c;
- uint64_t n = 0;
+ mrb_int n = 0;
mrb_int val;
#define conv_digit(c) \
@@ -2343,19 +2347,17 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, mrb_int base, i
if (c < 0 || c >= base) {
break;
}
- n *= base;
- n += c;
- if (n > (uint64_t)MRB_INT_MAX + (sign ? 0 : 1)) {
-#ifndef MRB_NO_FLOAT
- if (base == 10) {
- return mrb_float_value(mrb, mrb_str_to_dbl(mrb, mrb_str_new(mrb, str, len), badcheck));
- }
- else
-#endif
- {
- mrb_raisef(mrb, E_RANGE_ERROR, "string (%l) too big for integer", str, pend-str);
+ if (mrb_int_mul_overflow(n, base, &n)) goto overflow;
+ if (MRB_INT_MAX - c < n) {
+ if (sign == 0 && MRB_INT_MAX - n == c - 1) {
+ n = MRB_INT_MIN;
+ sign = 1;
+ break;
}
+ overflow:
+ mrb_raisef(mrb, E_RANGE_ERROR, "string (%l) too big for integer", str, pend-str);
}
+ n += c;
}
val = (mrb_int)n;
if (badcheck) {
@@ -2997,7 +2999,7 @@ mrb_float_read(const char *string, char **endPtr)
int c;
int exp = 0; /* Exponent read from "EX" field. */
int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
+ * part. Under normal circumstances, it is
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
diff --git a/src/vm.c b/src/vm.c
index b56e960a2..57b38ee39 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1134,7 +1134,7 @@ RETRY_TRY_BLOCK:
}
CASE(OP_LOADI32, BSS) {
- SET_INT_VALUE(mrb, regs[a], (mrb_int)(((uint32_t)b<<16)+c));
+ SET_INT_VALUE(mrb, regs[a], (int32_t)(((uint32_t)b<<16)+c));
NEXT;
}
@@ -1840,11 +1840,11 @@ RETRY_TRY_BLOCK:
if (mlen < m2) {
stack_clear(&regs[len-m2+mlen+1], m2-mlen);
}
- /* initalize rest arguments with empty Array */
+ /* initialize rest arguments with empty Array */
if (r) {
regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
}
- /* skip initailizer of passed arguments */
+ /* skip initializer of passed arguments */
if (o > 0 && argc-kargs > m1+m2)
pc += (argc - kargs - m1 - m2)*3;
}
@@ -2074,7 +2074,7 @@ RETRY_TRY_BLOCK:
regs[irep->nlocals] = v;
goto CHECKPOINT_LABEL_MAKE(RBREAK_TAG_STOP);
}
- if (c->prev->ci == c->prev->cibase) {
+ if (!c->vmexec && c->prev->ci == c->prev->cibase) {
mrb_value exc = mrb_exc_new_lit(mrb, E_FIBER_ERROR, "double resume");
mrb_exc_set(mrb, exc);
goto L_RAISE;
@@ -2089,8 +2089,14 @@ RETRY_TRY_BLOCK:
/* automatic yield at the end */
c->status = MRB_FIBER_TERMINATED;
mrb->c = c->prev;
- c->prev = NULL;
mrb->c->status = MRB_FIBER_RUNNING;
+ c->prev = NULL;
+ if (c->vmexec) {
+ mrb_gc_arena_restore(mrb, ai);
+ c->vmexec = FALSE;
+ mrb->jmp = prev_jmp;
+ return v;
+ }
ci = mrb->c->ci;
}
CHECKPOINT_RESTORE(RBREAK_TAG_RETURN) {