diff --git a/Makefile.in b/Makefile.in index a55a738fea2452..eeda81b0b373ab 100644 --- a/Makefile.in +++ b/Makefile.in @@ -538,7 +538,7 @@ un-runnable: mjit_config.h: $(ECHO) making $@ @{ \ - $(Q:@=:) set -x; \ + test "$(Q)" = @ || set -x; \ echo '#ifndef RUBY_MJIT_CONFIG_H'; \ echo '#define RUBY_MJIT_CONFIG_H 1'; \ \ diff --git a/array.c b/array.c index 2789acd56f3fe5..a821575676d87e 100644 --- a/array.c +++ b/array.c @@ -2804,6 +2804,34 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func return result; } +static VALUE +append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx) +{ + long beg, len; + if (FIXNUM_P(idx)) { + beg = FIX2LONG(idx); + } + /* check if idx is Range */ + else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) { + if (len > 0) { + const VALUE *const src = RARRAY_CONST_PTR(ary); + const long end = beg + len; + const long prevlen = RARRAY_LEN(result); + if (beg < olen) { + rb_ary_cat(result, src + beg, end > olen ? olen-beg : len); + } + if (end > olen) { + rb_ary_store(result, prevlen + len - 1, Qnil); + } + } + return result; + } + else { + beg = NUM2LONG(idx); + } + return rb_ary_push(result, rb_ary_entry(ary, beg)); +} + /* * call-seq: * ary.values_at(selector, ...) -> new_ary @@ -2825,7 +2853,13 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func static VALUE rb_ary_values_at(int argc, VALUE *argv, VALUE ary) { - return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry); + long i, olen = RARRAY_LEN(ary); + VALUE result = rb_ary_new_capa(argc); + for (i = 0; i < argc; ++i) { + append_values_at_single(result, ary, olen, argv[i]); + } + RB_GC_GUARD(ary); + return result; } diff --git a/benchmark/bm_array_values_at_int.rb b/benchmark/bm_array_values_at_int.rb new file mode 100644 index 00000000000000..6cb394cb9fd8f7 --- /dev/null +++ b/benchmark/bm_array_values_at_int.rb @@ -0,0 +1,2 @@ +ary = Array.new(10000) {|i| i} +100000.times { ary.values_at(500) } diff --git a/benchmark/bm_array_values_at_range.rb b/benchmark/bm_array_values_at_range.rb new file mode 100644 index 00000000000000..5b53806d1ca974 --- /dev/null +++ b/benchmark/bm_array_values_at_range.rb @@ -0,0 +1,2 @@ +ary = Array.new(10000) {|i| i} +100000.times { ary.values_at(1..2000) } diff --git a/compile.c b/compile.c index 5bca0dca994129..2610836e78b2e7 100644 --- a/compile.c +++ b/compile.c @@ -562,15 +562,6 @@ APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *before, LI #define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem)) #endif -static int -iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v) -{ - if (!SPECIAL_CONST_P(v)) { - rb_iseq_add_mark_object(iseq, v); - } - return COMPILE_OK; -} - static int iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v) { @@ -749,6 +740,7 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq) encoded[i] = (VALUE)table[insn]; i += len; } + FL_SET(iseq, ISEQ_TRANSLATED); #endif return COMPILE_OK; } @@ -1235,7 +1227,7 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, rb_iseq_path(iseq), rb_iseq_realpath(iseq), INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); debugs("[new_child_iseq]< ---------------------------------------\n"); - iseq_add_mark_object(iseq, (VALUE)ret_iseq); + iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq); return ret_iseq; } @@ -1250,7 +1242,7 @@ new_child_iseq_ifunc(rb_iseq_t *iseq, const struct vm_ifunc *ifunc, rb_iseq_path(iseq), rb_iseq_realpath(iseq), INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); debugs("[new_child_iseq_ifunc]< ---------------------------------------\n"); - iseq_add_mark_object(iseq, (VALUE)ret_iseq); + iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq); return ret_iseq; } @@ -1501,7 +1493,6 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, switch (nd_type(val_node)) { case NODE_LIT: dv = val_node->nd_lit; - iseq_add_mark_object(iseq, dv); break; case NODE_NIL: dv = Qnil; @@ -2027,6 +2018,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) rb_hash_rehash(map); freeze_hide_obj(map); generated_iseq[code_index + 1 + j] = map; + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); break; } case TS_LINDEX: @@ -2037,6 +2029,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) { VALUE v = operands[j]; generated_iseq[code_index + 1 + j] = v; + if (!SPECIAL_CONST_P(v)) { + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + } break; } case TS_VALUE: /* VALUE */ @@ -2044,7 +2039,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) VALUE v = operands[j]; generated_iseq[code_index + 1 + j] = v; /* to mark ruby object */ - iseq_add_mark_object(iseq, v); + if (!SPECIAL_CONST_P(v)) { + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + } break; } case TS_IC: /* inline cache */ @@ -2057,6 +2054,17 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) generated_iseq[code_index + 1 + j] = (VALUE)ic; break; } + case TS_ISE: /* inline storage entry */ + { + unsigned int ic_index = FIX2UINT(operands[j]); + IC ic = (IC)&iseq->body->is_entries[ic_index]; + if (UNLIKELY(ic_index >= iseq->body->is_size)) { + rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->body->is_size); + } + generated_iseq[code_index + 1 + j] = (VALUE)ic; + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + break; + } case TS_CALLINFO: /* call info */ { struct rb_call_info *base_ci = (struct rb_call_info *)operands[j]; @@ -2209,11 +2217,6 @@ iseq_set_exception_table(rb_iseq_t *iseq) entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); entry->iseq = (rb_iseq_t *)ptr[3]; - /* register iseq as mark object */ - if (entry->iseq != 0) { - iseq_add_mark_object(iseq, (VALUE)entry->iseq); - } - /* stack depth */ if (ptr[4]) { LABEL *lobj = (LABEL *)(ptr[4] & ~1); @@ -2851,11 +2854,11 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0); /* * freezestring debug_info - * send <:+@, 0, ARG_SIMPLE> + * send <:+@, 0, ARG_SIMPLE> # :-@, too * => - * send <:+@, 0, ARG_SIMPLE> + * send <:+@, 0, ARG_SIMPLE> # :-@, too */ - if (ci->mid == idUPlus && + if ((ci->mid == idUPlus || ci->mid == idUMinus) && (ci->flag & VM_CALL_ARGS_SIMPLE) && ci->orig_argc == 0) { ELEM_REMOVE(list); @@ -4827,7 +4830,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod } if (only_special_literals) { - iseq_add_mark_object(iseq, literals); + iseq_add_mark_object_compile_time(iseq, literals); ADD_INSN(ret, nd_line(orig_node), dup); ADD_INSN2(ret, nd_line(orig_node), opt_case_dispatch, literals, elselabel); @@ -7304,6 +7307,7 @@ insn_data_to_s_detail(INSN *iobj) break; } case TS_IC: /* inline cache */ + case TS_ISE: /* inline storage entry */ rb_str_catf(str, "", FIX2INT(OPERAND_AT(iobj, j))); break; case TS_CALLINFO: /* call info */ @@ -7543,7 +7547,6 @@ iseq_build_load_iseq(const rb_iseq_t *iseq, VALUE op) } loaded_iseq = rb_iseqw_to_iseq(iseqw); - iseq_add_mark_object(iseq, (VALUE)loaded_iseq); return loaded_iseq; } @@ -7674,7 +7677,6 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, break; case TS_VALUE: argv[j] = op; - iseq_add_mark_object(iseq, op); break; case TS_ISEQ: { @@ -7691,6 +7693,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, argv[j] = (VALUE)rb_global_entry(SYM2ID(op)); break; case TS_IC: + case TS_ISE: argv[j] = op; if (NUM2UINT(op) >= iseq->body->is_size) { iseq->body->is_size = NUM2INT(op) + 1; @@ -7721,7 +7724,6 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, } RB_GC_GUARD(op); argv[j] = map; - rb_iseq_add_mark_object(iseq, map); } break; case TS_FUNCPTR: @@ -8297,6 +8299,7 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) code[code_index] = (VALUE)ibf_dump_iseq(dump, (const rb_iseq_t *)op); break; case TS_IC: + case TS_ISE: { unsigned int i; for (i=0; ibody->is_size; i++) { @@ -8362,6 +8365,7 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct r code[code_index] = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op); break; case TS_IC: + case TS_ISE: code[code_index] = (VALUE)&is_entries[(int)op]; break; case TS_CALLINFO: @@ -8662,7 +8666,8 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) dump_body.is_entries = NULL; dump_body.ci_entries = ibf_dump_ci_entries(dump, iseq); dump_body.cc_entries = NULL; - dump_body.mark_ary = ISEQ_FLIP_CNT(iseq); + dump_body.variable.coverage = Qnil; + dump_body.variable.original_iseq = Qnil; return ibf_dump_write(dump, &dump_body, sizeof(dump_body)); } @@ -8694,7 +8699,7 @@ ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t of load_body->ci_kw_size = body->ci_kw_size; load_body->insns_info.size = body->insns_info.size; - RB_OBJ_WRITE(iseq, &load_body->mark_ary, iseq_mark_ary_create((int)body->mark_ary)); + iseq_mark_ary_create(iseq, (int)body->variable.flip_count); { VALUE realpath = Qnil, path = ibf_load_object(load, body->location.pathobj); @@ -9325,7 +9330,6 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index) rb_ary_store(load->obj_list, (long)object_index, obj); } - iseq_add_mark_object(load->iseq, obj); return obj; } } @@ -9512,9 +9516,6 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq) ibf_load_iseq_complete(iseq); #endif /* !USE_LAZY_LOAD */ - if (load->iseq) { - iseq_add_mark_object(load->iseq, (VALUE)iseq); - } return iseq; } } diff --git a/configure.ac b/configure.ac index 800e44ae89d77a..19b41971165887 100644 --- a/configure.ac +++ b/configure.ac @@ -2256,7 +2256,7 @@ AS_IF([test "${universal_binary-no}" = yes ], [ AS_IF([test x"$enable_pthread" = xyes], [ for pthread_lib in thr pthread pthreads c c_r root; do - AC_CHECK_LIB($pthread_lib, pthread_kill, + AC_CHECK_LIB($pthread_lib, pthread_create, rb_with_pthread=yes, rb_with_pthread=no) AS_IF([test "$rb_with_pthread" = "yes"], [ break; fi done @@ -2290,7 +2290,7 @@ AS_IF([test x"$enable_pthread" = xyes], [ AC_DEFINE(NON_SCALAR_THREAD_ID) ]) AC_CHECK_FUNCS(sched_yield pthread_attr_setinheritsched \ - pthread_attr_get_np pthread_attr_getstack \ + pthread_attr_get_np pthread_attr_getstack pthread_attr_getguardsize \ pthread_get_stackaddr_np pthread_get_stacksize_np \ thr_stksegment pthread_stackseg_np pthread_getthrds_np \ pthread_condattr_setclock \ diff --git a/gc.c b/gc.c index a1e6bc4bc23e86..ad4cd55b2a392d 100644 --- a/gc.c +++ b/gc.c @@ -3996,6 +3996,11 @@ init_mark_stack(mark_stack_t *stack) #define STACK_END (ec->machine.stack_end) #define STACK_LEVEL_MAX (ec->machine.stack_maxsize/sizeof(VALUE)) +#ifdef __EMSCRIPTEN__ +#undef STACK_GROW_DIRECTION +#define STACK_GROW_DIRECTION 1 +#endif + #if STACK_GROW_DIRECTION < 0 # define STACK_LENGTH (size_t)(STACK_START - STACK_END) #elif STACK_GROW_DIRECTION > 0 diff --git a/insns.def b/insns.def index d06368466ed1db..4f791ed16b801c 100644 --- a/insns.def +++ b/insns.def @@ -971,11 +971,11 @@ setinlinecache /* run iseq only once */ DEFINE_INSN once -(ISEQ iseq, IC ic) +(ISEQ iseq, ISE ise) () (VALUE val) { - val = vm_once_dispatch(ec, iseq, ic); + val = vm_once_dispatch(ec, iseq, ise); } /* case dispatcher, jump by table if possible */ diff --git a/iseq.c b/iseq.c index b703baa2c4b53d..fcac257fb3701a 100644 --- a/iseq.c +++ b/iseq.c @@ -115,6 +115,100 @@ rb_iseq_free(const rb_iseq_t *iseq) RUBY_FREE_LEAVE("iseq"); } +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE +static int +rb_vm_insn_addr2insn2(const void *addr) +{ + int insn; + const void * const *table = rb_vm_get_insns_address_table(); + + for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) { + if (table[insn] == addr) { + return insn; + } + } + rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr); +} +#endif + +static int +rb_vm_insn_null_translator(const void *addr) +{ + return (int)addr; +} + +typedef void iseq_value_itr_t(void *ctx, VALUE obj); +typedef int rb_vm_insns_translator_t(const void *addr); + +static int +iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator) +{ + VALUE insn = translator((void *)code[pos]); + int len = insn_len(insn); + int op_no; + const char *types = insn_op_types(insn); + + for (op_no = 0; types[op_no]; op_no++) { + char type = types[op_no]; + switch (type) { + case TS_CDHASH: + case TS_ISEQ: + case TS_VALUE: + { + VALUE op = code[pos + op_no + 1]; + if (!SPECIAL_CONST_P(op)) { + func(data, op); + } + break; + } + case TS_ISE: + { + union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1]; + if (is->once.value) { + func(data, is->once.value); + } + break; + } + default: + break; + } + } + + return len; +} + +static void +rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) +{ + unsigned int size; + const VALUE *code; + size_t n; + rb_vm_insns_translator_t * translator; + + size = iseq->body->iseq_size; + code = iseq->body->iseq_encoded; + +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE + if (FL_TEST(iseq, ISEQ_TRANSLATED)) { + translator = rb_vm_insn_addr2insn2; + } else { + translator = rb_vm_insn_null_translator; + } +#else + translator = rb_vm_insn_null_translator; +#endif + + for (n = 0; n < size;) { + n += iseq_extract_values(code, n, func, data, translator); + } +} + +static void +each_insn_value(void *ctx, VALUE obj) +{ + rb_gc_mark(obj); +} + void rb_iseq_mark(const rb_iseq_t *iseq) { @@ -123,13 +217,31 @@ rb_iseq_mark(const rb_iseq_t *iseq) if (iseq->body) { const struct rb_iseq_constant_body *body = iseq->body; - RUBY_MARK_UNLESS_NULL(body->mark_ary); + if(FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) { + rb_iseq_each_value(iseq, each_insn_value, NULL); + } + + rb_gc_mark(body->variable.coverage); + rb_gc_mark(body->variable.original_iseq); rb_gc_mark(body->location.label); rb_gc_mark(body->location.base_label); rb_gc_mark(body->location.pathobj); RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq); + + if (body->catch_table) { + const struct iseq_catch_table *table = body->catch_table; + unsigned int i; + for(i = 0; i < table->size; i++) { + const struct iseq_catch_table_entry *entry; + entry = &table->entries[i]; + if (entry->iseq) { + rb_gc_mark((VALUE)entry->iseq); + } + } + } } + if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) { rb_gc_mark(iseq->aux.loader.obj); } @@ -299,13 +411,6 @@ set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq) } } -void -rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj) -{ - /* TODO: check dedup */ - rb_ary_push(ISEQ_MARK_ARY(iseq), obj); -} - static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, @@ -326,7 +431,7 @@ prepare_iseq_build(rb_iseq_t *iseq, if (iseq != iseq->body->local_iseq) { RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label); } - RB_OBJ_WRITE(iseq, &iseq->body->mark_ary, iseq_mark_ary_create(0)); + iseq_mark_ary_create(iseq, 0); ISEQ_COMPILE_DATA_ALLOC(iseq); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info); @@ -1612,6 +1717,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, break; case TS_IC: + case TS_ISE: ret = rb_sprintf("", (union iseq_inline_storage_entry *)op - iseq->body->is_entries); break; @@ -2355,6 +2461,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) } break; case TS_IC: + case TS_ISE: { union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq; rb_ary_push(ary, INT2FIX(is - iseq->body->is_entries)); diff --git a/iseq.h b/iseq.h index 0c316e2cb2863c..31a3232e3be1f7 100644 --- a/iseq.h +++ b/iseq.h @@ -28,44 +28,33 @@ rb_call_info_kw_arg_bytes(int keyword_len) return sizeof(struct rb_call_info_kw_arg) + sizeof(VALUE) * (keyword_len - 1); } -enum iseq_mark_ary_index { - ISEQ_MARK_ARY_COVERAGE, - ISEQ_MARK_ARY_FLIP_CNT, - ISEQ_MARK_ARY_ORIGINAL_ISEQ, - ISEQ_MARK_ARY_INITIAL_SIZE -}; - -static inline VALUE -iseq_mark_ary_create(int flip_cnt) +static inline void +iseq_mark_ary_create(rb_iseq_t *iseq, int flip_cnt) { - VALUE ary = rb_ary_tmp_new(ISEQ_MARK_ARY_INITIAL_SIZE); - rb_ary_push(ary, Qnil); /* ISEQ_MARK_ARY_COVERAGE */ - rb_ary_push(ary, INT2FIX(flip_cnt)); /* ISEQ_MARK_ARY_FLIP_CNT */ - rb_ary_push(ary, Qnil); /* ISEQ_MARK_ARY_ORIGINAL_ISEQ */ - return ary; + RB_OBJ_WRITE(iseq, &iseq->body->variable.coverage, Qnil); + RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, Qnil); + iseq->body->variable.flip_count = flip_cnt; } -#define ISEQ_MARK_ARY(iseq) (iseq)->body->mark_ary - -#define ISEQ_COVERAGE(iseq) RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_COVERAGE) -#define ISEQ_COVERAGE_SET(iseq, cov) RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_COVERAGE, cov) +#define ISEQ_COVERAGE(iseq) iseq->body->variable.coverage +#define ISEQ_COVERAGE_SET(iseq, cov) RB_OBJ_WRITE(iseq, &iseq->body->variable.coverage, cov) #define ISEQ_LINE_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_LINES) #define ISEQ_BRANCH_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_BRANCHES) -#define ISEQ_FLIP_CNT(iseq) FIX2INT(RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_FLIP_CNT)) +#define ISEQ_FLIP_CNT(iseq) (iseq)->body->variable.flip_count static inline int ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq) { - int cnt = ISEQ_FLIP_CNT(iseq); - RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_FLIP_CNT, INT2FIX(cnt+1)); + int cnt = iseq->body->variable.flip_count; + iseq->body->variable.flip_count += 1; return cnt; } static inline VALUE * ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq) { - VALUE str = RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_ORIGINAL_ISEQ); + VALUE str = iseq->body->variable.original_iseq; if (RTEST(str)) return (VALUE *)RSTRING_PTR(str); return NULL; } @@ -73,14 +62,14 @@ ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq) static inline void ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq) { - RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_ORIGINAL_ISEQ, Qnil); + RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, Qnil); } static inline VALUE * ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) { VALUE str = rb_str_tmp_new(size * sizeof(VALUE)); - RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_ORIGINAL_ISEQ, str); + RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, str); return (VALUE *)RSTRING_PTR(str); } @@ -94,6 +83,8 @@ ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) #define ISEQ_NOT_LOADED_YET IMEMO_FL_USER1 #define ISEQ_USE_COMPILE_DATA IMEMO_FL_USER2 +#define ISEQ_TRANSLATED IMEMO_FL_USER3 +#define ISEQ_MARKABLE_ISEQ IMEMO_FL_USER4 struct iseq_compile_data { /* GC is needed */ @@ -173,7 +164,6 @@ void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE exception, VALUE body); /* iseq.c */ -void rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj); VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt); VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc); struct st_table *ruby_insn_make_insn_table(void); diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb index 764c5e1a61360a..1368502b042d60 100644 --- a/test/io/console/test_io_console.rb +++ b/test/io/console/test_io_console.rb @@ -212,6 +212,7 @@ def test_oflush s.oflush # oflush may be issued after "a" is already sent. s.print "b" s.flush + sleep 0.1 assert_include(["b", "ab"], m.readpartial(10)) } end diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 6e463e18639a9c..8aa5c39323a9d6 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -557,8 +557,9 @@ def test_peephole_string_literal_range when "1.8.0"..."1.8.8" then :bar end end; - [ nil, { frozen_string_literal: true } ].each do |opt| - iseq = RubyVM::InstructionSequence.compile(code, nil, nil, opt) + [ true, false ].each do |opt| + iseq = RubyVM::InstructionSequence.compile(code, + frozen_string_literal: opt) insn = iseq.disasm assert_match %r{putobject\s+#{Regexp.quote('"1.8.0"..."1.8.8"')}}, insn assert_match %r{putobject\s+#{Regexp.quote('"2.0.0".."2.3.2"')}}, insn @@ -567,6 +568,21 @@ def test_peephole_string_literal_range end end + def test_peephole_dstr + code = "#{<<~'begin;'}\n#{<<~'end;'}" + begin; + exp = (-'a').object_id + z = 'a' + exp == (-"#{z}").object_id + end; + [ false, true ].each do |fsl| + iseq = RubyVM::InstructionSequence.compile(code, + frozen_string_literal: fsl) + assert_equal(true, iseq.eval, + "[ruby-core:85542] [Bug #14475] fsl: #{fsl}") + end + end + def test_branch_condition_backquote bug = '[ruby-core:80740] [Bug #13444] redefined backquote should be called' class << self diff --git a/thread_pthread.c b/thread_pthread.c index 381114d1ce0083..d36c1494830c1b 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -561,8 +561,12 @@ get_stack(void **addr, size_t *size) CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif +# ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; +# else + *size -= getpagesize(); +# endif pthread_attr_destroy(&attr); #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */ pthread_attr_t attr; diff --git a/tool/ruby_vm/models/typemap.rb b/tool/ruby_vm/models/typemap.rb index d818ce9878bb30..7c5c872d7cb104 100644 --- a/tool/ruby_vm/models/typemap.rb +++ b/tool/ruby_vm/models/typemap.rb @@ -18,6 +18,7 @@ "GENTRY" => %w[G TS_GENTRY], "IC" => %w[K TS_IC], "ID" => %w[I TS_ID], + "ISE" => %w[T TS_ISE], "ISEQ" => %w[S TS_ISEQ], "OFFSET" => %w[O TS_OFFSET], "VALUE" => %w[V TS_VALUE], diff --git a/vm_core.h b/vm_core.h index 0a62b66db82b1d..4b8f2474f1e2f4 100644 --- a/vm_core.h +++ b/vm_core.h @@ -411,7 +411,11 @@ struct rb_iseq_constant_body { */ struct rb_call_cache *cc_entries; /* size is ci_size = ci_kw_size */ - VALUE mark_ary; /* Array: includes operands which should be GC marked */ + struct { + rb_num_t flip_count; + VALUE coverage; + VALUE original_iseq; + } variable; unsigned int local_table_size; unsigned int is_size; @@ -1009,6 +1013,7 @@ enum vm_svar_index { /* inline cache */ typedef struct iseq_inline_cache_entry *IC; +typedef union iseq_inline_storage_entry *ISE; typedef struct rb_call_info *CALL_INFO; typedef struct rb_call_cache *CALL_CACHE; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 5567c6b20f0d84..cd17a129c3fe62 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3285,11 +3285,10 @@ vm_ic_update(IC ic, VALUE val, const VALUE *reg_ep) } static VALUE -vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, IC ic) +vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, ISE is) { rb_thread_t *th = rb_ec_thread_ptr(ec); rb_thread_t *const RUNNING_THREAD_ONCE_DONE = (rb_thread_t *)(0x1); - union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)ic; again: if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) { @@ -3298,10 +3297,10 @@ vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, IC ic) else if (is->once.running_thread == NULL) { VALUE val; is->once.running_thread = th; - val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is); + val = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is); + RB_OBJ_WRITE(ec->cfp->iseq, &is->once.value, val); /* is->once.running_thread is cleared by vm_once_clear() */ is->once.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */ - rb_iseq_add_mark_object(ec->cfp->iseq, val); return val; } else if (is->once.running_thread == th) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy