diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 9 | ||||
| -rw-r--r-- | src/dump.c | 24 | ||||
| -rw-r--r-- | src/hash.c | 95 | ||||
| -rw-r--r-- | src/print.c | 15 | ||||
| -rw-r--r-- | src/vm.c | 2 |
5 files changed, 98 insertions, 47 deletions
diff --git a/src/array.c b/src/array.c index a66ff8183..8ab30bd8e 100644 --- a/src/array.c +++ b/src/array.c @@ -56,18 +56,17 @@ mrb_ary_new(mrb_state *mrb) } /* - * to copy array, use this instead of memcpy because of portability + * To copy array, use this instead of memcpy because of portability * * gcc on ARM may fail optimization of memcpy - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3934.html + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56620 * * gcc on MIPS also fail - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39755 + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39755 * * memcpy doesn't exist on freestanding environment * * If you optimize for binary size, use memcpy instead of this at your own risk * of above portability issue. * - * see also http://togetter.com/li/462898 - * + * See also https://togetter.com/li/462898 (Japanese) */ static inline void array_copy(mrb_value *dst, const mrb_value *src, mrb_int size) diff --git a/src/dump.c b/src/dump.c index 5173b88e5..e3f3320ea 100644 --- a/src/dump.c +++ b/src/dump.c @@ -806,7 +806,7 @@ dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, si section_irep_size += get_irep_record_size(mrb, irep); /* DEBUG section size */ - if (flags & DUMP_DEBUG_INFO) { + if (flags & MRB_DUMP_DEBUG_INFO) { if (debug_info_defined) { section_lineno_size += sizeof(struct rite_section_debug_header); /* filename table */ @@ -842,7 +842,7 @@ dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, si sizeof(struct rite_binary_footer); /* write DEBUG section */ - if (flags & DUMP_DEBUG_INFO) { + if (flags & MRB_DUMP_DEBUG_INFO) { if (debug_info_defined) { result = write_section_debug(mrb, irep, cur, filenames, filenames_len); if (result != MRB_DUMP_OK) { @@ -920,11 +920,13 @@ mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *f return MRB_DUMP_WRITE_FAULT; } if (fprintf(fp, - "#ifdef __cplusplus\n" - "extern const uint8_t %s[];\n" - "#endif\n" + "%s\n" "const uint8_t %s[] = {", - initname, initname) < 0) { + (flags & MRB_DUMP_STATIC) ? "static" + : "#ifdef __cplusplus\n" + "extern\n" + "#endif", + initname) < 0) { mrb_free(mrb, bin); return MRB_DUMP_WRITE_FAULT; } @@ -1232,8 +1234,14 @@ mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE int max = 1; int n = dump_irep_struct(mrb, irep, flags, fp, initname, 0, init_syms_code, &max); if (n != MRB_DUMP_OK) return n; - fprintf(fp, "#ifdef __cplusplus\nextern const struct RProc %s[];\n#endif\n", initname); - fprintf(fp, "const struct RProc %s[] = {{\n", initname); + fprintf(fp, + "%s\n" + "const struct RProc %s[] = {{\n", + (flags & MRB_DUMP_STATIC) ? "static" + : "#ifdef __cplusplus\n" + "extern\n" + "#endif", + initname); fprintf(fp, "NULL,NULL,MRB_TT_PROC,7,0,{&%s_irep_0},NULL,{NULL},\n}};\n", initname); fputs("static void\n", fp); fprintf(fp, "%s_init_syms(mrb_state *mrb)\n", initname); diff --git a/src/hash.c b/src/hash.c index 289f02a91..c5b4c5cbe 100644 --- a/src/hash.c +++ b/src/hash.c @@ -215,40 +215,70 @@ DEFINE_SWITCHER(ht, HT) } while (0) /* - * `h_check_modified` raises an exception when a dangerous modification is - * made to `h` by executing `code`. - * - * This macro is not called if `h->ht` (`h->ea`) is `NULL` (`Hash` size is - * zero). And because the `hash_entry` is rather large, `h->ht->ea` and - * `h->ht->ea_capa` are able to be safely accessed even in AR. This nature - * is used to eliminate branch of AR or HT. - * - * `HT_ASSERT_SAFE_READ` checks if members can be accessed according to its - * assumptions. + * In `h_check_modified()`, in the case of `MRB_NO_BOXING`, `ht_ea()` or + * `ht_ea_capa()` for AR may read uninitialized area (#5332). Therefore, do + * not use those macros for AR in `MRB_NO_BOXING` (but in the case of + * `MRB_64BIT`, `ht_ea_capa()` is the same as `ar_ea_capa()`, so use it). */ -#define HT_ASSERT_SAFE_READ(attr_name) \ +#ifdef MRB_NO_BOXING +# define H_CHECK_MODIFIED_USE_HT_EA_FOR_AR FALSE +# ifdef MRB_64BIT +# define H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR TRUE +# else +# define H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR FALSE +# endif /* MRB_64BIT */ +#else +# define H_CHECK_MODIFIED_USE_HT_EA_FOR_AR TRUE +# define H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR TRUE + /* + * `h_check_modified` raises an exception when a dangerous modification is + * made to `h` by executing `code`. + * + * `h_check_modified` macro is not called if `h->ht` (`h->ea`) is `NULL` + * (`Hash` size is zero). And because the `hash_entry` is rather large, + * `h->ht->ea` and `h->ht->ea_capa` are able to be safely accessed even for + * AR. This nature is used to eliminate branch of AR or HT. + * + * `HT_ASSERT_SAFE_READ` checks if members can be accessed according to its + * assumptions. + */ +# define HT_ASSERT_SAFE_READ(attr_name) \ mrb_static_assert1( \ offsetof(hash_table, attr_name) + sizeof(((hash_table*)0)->attr_name) <= \ sizeof(hash_entry)) HT_ASSERT_SAFE_READ(ea); -#ifdef MRB_32BIT +# ifdef MRB_32BIT HT_ASSERT_SAFE_READ(ea_capa); -#endif -#undef HT_ASSERT_SAFE_READ -#define h_check_modified(mrb, h, code) do { \ - struct RHash *h__ = h; \ - uint32_t mask = MRB_HASH_HT|MRB_HASH_IB_BIT_MASK|MRB_HASH_AR_EA_CAPA_MASK; \ - uint32_t flags = h__->flags & mask; \ - void* tbl__ = (mrb_assert(h__->ht), h__->ht); \ - uint32_t ht_ea_capa__ = ht_ea_capa(h__); \ - hash_entry *ht_ea__ = ht_ea(h__); \ - code; \ - if (flags != (h__->flags & mask) || \ - tbl__ != h__->ht || \ - ht_ea_capa__ != ht_ea_capa(h__) || \ - ht_ea__ != ht_ea(h__)) { \ - mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified"); \ - } \ +# endif +# undef HT_ASSERT_SAFE_READ +#endif /* MRB_NO_BOXING */ + +/* + * `h_check_modified` raises an exception when a dangerous modification is + * made to `h` by executing `code`. + */ +#define h_check_modified(mrb, h, code) do { \ + struct RHash *h__ = h; \ + uint32_t mask__ = MRB_HASH_HT|MRB_HASH_IB_BIT_MASK|MRB_HASH_AR_EA_CAPA_MASK; \ + uint32_t flags__ = h__->flags & mask__; \ + void* tbl__ = (mrb_assert(h__->ht), h__->ht); \ + uint32_t ht_ea_capa__ = 0; \ + hash_entry *ht_ea__ = NULL; \ + if (H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR || h_ht_p(h__)) { \ + ht_ea_capa__ = ht_ea_capa(h__); \ + } \ + if (H_CHECK_MODIFIED_USE_HT_EA_FOR_AR || h_ht_p(h__)) { \ + ht_ea__ = ht_ea(h__); \ + } \ + code; \ + if (flags__ != (h__->flags & mask__) || \ + tbl__ != h__->ht || \ + ((H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR || h_ht_p(h__)) && \ + ht_ea_capa__ != ht_ea_capa(h__)) || \ + ((H_CHECK_MODIFIED_USE_HT_EA_FOR_AR || h_ht_p(h__)) && \ + ht_ea__ != ht_ea(h__))) { \ + mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified"); \ + } \ } while (0) #define U32(v) ((uint32_t)(v)) @@ -718,6 +748,7 @@ ib_bit_for(uint32_t size) static uint32_t ib_byte_size_for(uint32_t ib_bit) { + mrb_assert(IB_INIT_BIT <= ib_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; @@ -892,7 +923,13 @@ static void ht_rehash(mrb_state *mrb, struct RHash *h) { /* see comments in `h_rehash` */ - uint32_t size = ht_size(h), w_size = 0, ea_capa = ht_ea_capa(h); + uint32_t size = ht_size(h); + if (size <= AR_MAX_SIZE) { + ht_to_ar(mrb, h); + ar_rehash(mrb, h); + return; + } + uint32_t w_size = 0, ea_capa = ht_ea_capa(h); hash_entry *ea = ht_ea(h); ht_init(mrb, h, 0, ea, ea_capa, h_ht(h), ib_bit_for(size)); ht_set_size(h, size); diff --git a/src/print.c b/src/print.c index 607eb9d1f..c96189fe9 100644 --- a/src/print.c +++ b/src/print.c @@ -28,10 +28,6 @@ printstr(mrb_value obj, FILE *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) @@ -51,6 +47,17 @@ mrb_p(mrb_state *mrb, mrb_value obj) printstr(mrb_inspect(mrb, obj), stdout); } } +#else +void +mrb_core_init_printabort(void) +{ +} + +MRB_API void +mrb_p(mrb_state *mrb, mrb_value obj) +{ +} +#endif MRB_API void mrb_print_error(mrb_state *mrb) @@ -1022,7 +1022,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) const struct mrb_irep_catch_handler *ch; #ifdef DIRECT_THREADED - static void *optable[] = { + static const void * const optable[] = { #define OPCODE(x,_) &&L_OP_ ## x, #include "mruby/ops.h" #undef OPCODE |
