diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 17 | ||||
| -rw-r--r-- | src/codedump.c | 4 | ||||
| -rw-r--r-- | src/fmt_fp.c | 1 | ||||
| -rw-r--r-- | src/gc.c | 18 | ||||
| -rw-r--r-- | src/hash.c | 24 | ||||
| -rw-r--r-- | src/numeric.c | 24 | ||||
| -rw-r--r-- | src/string.c | 38 | ||||
| -rw-r--r-- | src/vm.c | 16 |
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 @@ -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 @@ -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(®s[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) { |
