diff options
Diffstat (limited to 'insns.def')
-rw-r--r-- | insns.def | 412 |
1 files changed, 246 insertions, 166 deletions
@@ -109,14 +109,14 @@ getblockparam VM_ASSERT(VM_ENV_LOCAL_P(ep)); if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) { - val = rb_vm_bh_to_procval(ec, VM_ENV_BLOCK_HANDLER(ep)); - vm_env_write(ep, -(int)idx, val); - VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM); + val = rb_vm_bh_to_procval(ec, VM_ENV_BLOCK_HANDLER(ep)); + vm_env_write(ep, -(int)idx, val); + VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM); } else { - val = *(ep - idx); - RB_DEBUG_COUNTER_INC(lvar_get); - (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0); + val = *(ep - idx); + RB_DEBUG_COUNTER_INC(lvar_get); + (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0); } } @@ -150,35 +150,35 @@ getblockparamproxy VM_ASSERT(VM_ENV_LOCAL_P(ep)); if (!VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)) { - VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep); - - if (block_handler) { - switch (vm_block_handler_type(block_handler)) { - case block_handler_type_iseq: - case block_handler_type_ifunc: - val = rb_block_param_proxy; - break; - case block_handler_type_symbol: - val = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler)); - goto INSN_LABEL(set); - case block_handler_type_proc: - val = VM_BH_TO_PROC(block_handler); - goto INSN_LABEL(set); - default: - VM_UNREACHABLE(getblockparamproxy); - } - } - else { - val = Qnil; - INSN_LABEL(set): - vm_env_write(ep, -(int)idx, val); - VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM); - } + VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep); + + if (block_handler) { + switch (vm_block_handler_type(block_handler)) { + case block_handler_type_iseq: + case block_handler_type_ifunc: + val = rb_block_param_proxy; + break; + case block_handler_type_symbol: + val = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler)); + goto INSN_LABEL(set); + case block_handler_type_proc: + val = VM_BH_TO_PROC(block_handler); + goto INSN_LABEL(set); + default: + VM_UNREACHABLE(getblockparamproxy); + } + } + else { + val = Qnil; + INSN_LABEL(set): + vm_env_write(ep, -(int)idx, val); + VM_ENV_FLAGS_SET(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM); + } } else { - val = *(ep - idx); - RB_DEBUG_COUNTER_INC(lvar_get); - (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0); + val = *(ep - idx); + RB_DEBUG_COUNTER_INC(lvar_get); + (void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0); } } @@ -230,28 +230,37 @@ setinstancevariable /* Get value of class variable id of klass as val. */ DEFINE_INSN getclassvariable -(ID id, IVC ic) +(ID id, ICVARC ic) () (VALUE val) /* "class variable access from toplevel" warning can be hooked. */ // attr bool leaf = false; /* has rb_warning() */ { - rb_cref_t * cref = vm_get_cref(GET_EP()); rb_control_frame_t *cfp = GET_CFP(); - val = vm_getclassvariable(GET_ISEQ(), cref, cfp, id, (ICVARC)ic); + val = vm_getclassvariable(GET_ISEQ(), cfp, id, ic); } /* Set value of class variable id of klass as val. */ DEFINE_INSN setclassvariable -(ID id, IVC ic) +(ID id, ICVARC ic) (VALUE val) () /* "class variable access from toplevel" warning can be hooked. */ // attr bool leaf = false; /* has rb_warning() */ { vm_ensure_not_refinement_module(GET_SELF()); - vm_setclassvariable(GET_ISEQ(), vm_get_cref(GET_EP()), GET_CFP(), id, val, (ICVARC)ic); + vm_setclassvariable(GET_ISEQ(), GET_CFP(), id, val, ic); +} + +DEFINE_INSN +opt_getconstant_path +(IC ic) +() +(VALUE val) +// attr bool leaf = false; /* may autoload or raise */ +{ + val = rb_vm_opt_getconstant_path(ec, GET_CFP(), ic); } /* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants @@ -351,6 +360,7 @@ putspecialobject (rb_num_t value_type) () (VALUE val) +// attr bool leaf = (value_type == VM_SPECIAL_OBJECT_VMCORE); /* others may raise when allocating singleton */ { enum vm_special_object_type type; @@ -365,7 +375,17 @@ putstring () (VALUE val) { - val = rb_ec_str_resurrect(ec, str); + val = rb_ec_str_resurrect(ec, str, false); +} + +/* put chilled string val. string will be copied but frozen in the future. */ +DEFINE_INSN +putchilledstring +(VALUE str) +() +(VALUE val) +{ + val = rb_ec_str_resurrect(ec, str, true); } /* put concatenate strings */ @@ -382,9 +402,10 @@ concatstrings val = rb_str_concat_literals(num, STACK_ADDR_FROM_TOP(num)); } -/* push the result of to_s. */ +/* Convert the result to string if not already a string. + This is used as a backup if to_s does not return a string. */ DEFINE_INSN -tostring +anytostring () (VALUE val, VALUE str) (VALUE val) @@ -451,6 +472,20 @@ newarraykwsplat } } +/* push hash onto array unless the hash is empty (as empty keyword + splats should be ignored). + */ +DEFINE_INSN +pushtoarraykwsplat +() +(VALUE ary, VALUE hash) +(VALUE ary) +{ + if (!RHASH_EMPTY_P(hash)) { + rb_ary_push(ary, hash); + } +} + /* dup array */ DEFINE_INSN duparray @@ -487,13 +522,16 @@ expandarray (rb_num_t num, rb_num_t flag) (..., VALUE ary) (...) +// attr bool handles_sp = true; // attr bool leaf = false; /* has rb_check_array_type() */ // attr rb_snum_t sp_inc = (rb_snum_t)num - 1 + (flag & 1 ? 1 : 0); { - vm_expandarray(GET_SP(), ary, num, (int)flag); + vm_expandarray(GET_CFP(), ary, num, (int)flag); } -/* concat two arrays */ +/* concat two arrays, without modifying first array. + * attempts to convert both objects to arrays using to_a. + */ DEFINE_INSN concatarray () @@ -504,6 +542,32 @@ concatarray ary = vm_concat_array(ary1, ary2); } +/* concat second array to first array. + * first argument must already be an array. + * attempts to convert second object to array using to_a. + */ +DEFINE_INSN +concattoarray +() +(VALUE ary1, VALUE ary2) +(VALUE ary) +// attr bool leaf = false; /* has rb_check_array_type() */ +{ + ary = vm_concat_to_array(ary1, ary2); +} + +/* push given number of objects to array directly before. */ +DEFINE_INSN +pushtoarray +(rb_num_t num) +(...) +(VALUE val) +// attr rb_snum_t sp_inc = -(rb_snum_t)num; +{ + const VALUE *objp = STACK_ADDR_FROM_TOP(num); + val = rb_ary_cat(*(objp-1), objp, num); +} + /* call to_a on array ary to splat */ DEFINE_INSN splatarray @@ -515,6 +579,22 @@ splatarray obj = vm_splat_array(flag, ary); } +/* call to_hash on hash to keyword splat before converting block */ +DEFINE_INSN +splatkw +() +(VALUE hash, VALUE block) +(VALUE obj, VALUE block) +// attr bool leaf = false; /* has rb_to_hash_type() */ +{ + if (NIL_P(hash)) { + obj = Qnil; + } + else { + obj = rb_to_hash_type(hash); + } +} + /* put new Hash from n elements. n must be an even number. */ DEFINE_INSN newhash @@ -596,6 +676,25 @@ swap /* none */ } +/* reverse stack top N order. */ +DEFINE_INSN +opt_reverse +(rb_num_t n) +(...) +(...) +// attr rb_snum_t sp_inc = 0; +{ + rb_num_t i; + VALUE *sp = STACK_ADDR_FROM_TOP(n); + + for (i=0; i<n/2; i++) { + VALUE v0 = sp[i]; + VALUE v1 = TOPN(i); + sp[i] = v1; + TOPN(i) = v0; + } +} + /* for stack caching. */ DEFINE_INSN_IF(STACK_CACHING) reput @@ -654,7 +753,21 @@ defined { val = Qnil; if (vm_defined(ec, GET_CFP(), op_type, obj, v)) { - val = pushval; + val = pushval; + } +} + +/* defined?(@foo) */ +DEFINE_INSN +definedivar +(ID id, IVC ic, VALUE pushval) +() +(VALUE val) +// attr bool leaf = false; +{ + val = Qnil; + if (!UNDEF_P(vm_getivar(GET_SELF(), id, GET_ISEQ(), ic, NULL, FALSE, Qundef))) { + val = pushval; } } @@ -692,7 +805,7 @@ checktype (VALUE val) (VALUE ret) { - ret = (TYPE(val) == (int)type) ? Qtrue : Qfalse; + ret = RBOOL(TYPE(val) == (int)type); } /**********************************************************/ @@ -714,11 +827,11 @@ defineclass /* enter scope */ vm_push_frame(ec, class_iseq, VM_FRAME_MAGIC_CLASS | VM_ENV_FLAG_LOCAL, klass, - GET_BLOCK_HANDLER(), - (VALUE)vm_cref_push(ec, klass, NULL, FALSE), - class_iseq->body->iseq_encoded, GET_SP(), - class_iseq->body->local_table_size, - class_iseq->body->stack_max); + GET_BLOCK_HANDLER(), + (VALUE)vm_cref_push(ec, klass, NULL, FALSE, FALSE), + ISEQ_BODY(class_iseq)->iseq_encoded, GET_SP(), + ISEQ_BODY(class_iseq)->local_table_size, + ISEQ_BODY(class_iseq)->stack_max); RESTORE_REGS(); NEXT_INSN(); } @@ -756,8 +869,9 @@ send { VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, false); val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method); + JIT_EXEC(ec, val); - if (val == Qundef) { + if (UNDEF_P(val)) { RESTORE_REGS(); NEXT_INSN(); } @@ -775,13 +889,29 @@ opt_send_without_block { VALUE bh = VM_BLOCK_HANDLER_NONE; val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method); + JIT_EXEC(ec, val); - if (val == Qundef) { + if (UNDEF_P(val)) { RESTORE_REGS(); NEXT_INSN(); } } +/* Convert object to string using to_s or equivalent. */ +DEFINE_INSN +objtostring +(CALL_DATA cd) +(VALUE recv) +(VALUE val) +// attr bool leaf = false; +{ + val = vm_objtostring(GET_ISEQ(), recv, cd); + + if (UNDEF_P(val)) { + CALL_SIMPLE_METHOD(); + } +} + DEFINE_INSN opt_str_freeze (VALUE str, CALL_DATA cd) @@ -790,7 +920,7 @@ opt_str_freeze { val = vm_opt_str_freeze(str, BOP_FREEZE, idFreeze); - if (val == Qundef) { + if (UNDEF_P(val)) { PUSH(rb_str_resurrect(str)); CALL_SIMPLE_METHOD(); } @@ -805,7 +935,7 @@ opt_nil_p { val = vm_opt_nil_p(GET_ISEQ(), cd, recv); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -818,15 +948,15 @@ opt_str_uminus { val = vm_opt_str_freeze(str, BOP_UMINUS, idUMinus); - if (val == Qundef) { + if (UNDEF_P(val)) { PUSH(rb_str_resurrect(str)); CALL_SIMPLE_METHOD(); } } DEFINE_INSN -opt_newarray_max -(rb_num_t num) +opt_newarray_send +(rb_num_t num, ID method) (...) (VALUE val) /* This instruction typically has no funcalls. But it compares array @@ -835,20 +965,21 @@ opt_newarray_max * cannot but mark it being not leaf. */ // attr bool leaf = false; /* has rb_funcall() */ // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; -{ - val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num)); -} - -DEFINE_INSN -opt_newarray_min -(rb_num_t num) -(...) -(VALUE val) -/* Same discussion as opt_newarray_max. */ -// attr bool leaf = false; /* has rb_funcall() */ -// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; -{ - val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num)); +// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)num; +{ + switch(method) { + case idHash: + val = vm_opt_newarray_hash(ec, num, STACK_ADDR_FROM_TOP(num)); + break; + case idMin: + val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num)); + break; + case idMax: + val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num)); + break; + default: + rb_bug("unreachable"); + } } /* super(args) # args.size => num */ @@ -862,8 +993,9 @@ invokesuper { VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, true); val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super); + JIT_EXEC(ec, val); - if (val == Qundef) { + if (UNDEF_P(val)) { RESTORE_REGS(); NEXT_INSN(); } @@ -881,8 +1013,9 @@ invokeblock { VALUE bh = VM_BLOCK_HANDLER_NONE; val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock); + JIT_EXEC(ec, val); - if (val == Qundef) { + if (UNDEF_P(val)) { RESTORE_REGS(); NEXT_INSN(); } @@ -904,19 +1037,19 @@ leave const VALUE *const bp = vm_base_ptr(GET_CFP()); if (GET_SP() != bp) { vm_stack_consistency_error(ec, GET_CFP(), bp); - } + } } if (vm_pop_frame(ec, GET_CFP(), GET_EP())) { #if OPT_CALL_THREADED_CODE - rb_ec_thread_ptr(ec)->retval = val; - return 0; + rb_ec_thread_ptr(ec)->retval = val; + return 0; #else - return val; + return val; #endif } else { - RESTORE_REGS(); + RESTORE_REGS(); } } @@ -965,8 +1098,8 @@ branchif // attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { if (RTEST(val)) { - RUBY_VM_CHECK_INTS(ec); - JUMP(dst); + RUBY_VM_CHECK_INTS(ec); + JUMP(dst); } } @@ -980,8 +1113,8 @@ branchunless // attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { if (!RTEST(val)) { - RUBY_VM_CHECK_INTS(ec); - JUMP(dst); + RUBY_VM_CHECK_INTS(ec); + JUMP(dst); } } @@ -995,8 +1128,8 @@ branchnil // attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */ { if (NIL_P(val)) { - RUBY_VM_CHECK_INTS(ec); - JUMP(dst); + RUBY_VM_CHECK_INTS(ec); + JUMP(dst); } } @@ -1004,34 +1137,6 @@ branchnil /* for optimize */ /**********************************************************/ -/* push inline-cached value and go to dst if it is valid */ -DEFINE_INSN -opt_getinlinecache -(OFFSET dst, IC ic) -() -(VALUE val) -{ - struct iseq_inline_constant_cache_entry *ice = ic->entry; - if (ice && vm_ic_hit_p(ice, GET_EP())) { - val = ice->value; - JUMP(dst); - } - else { - val = Qnil; - } -} - -/* set inline cache */ -DEFINE_INSN -opt_setinlinecache -(IC ic) -(VALUE val) -(VALUE val) -// attr bool leaf = false; -{ - vm_ic_update(GET_ISEQ(), ic, val, GET_EP()); -} - /* run iseq only once */ DEFINE_INSN once @@ -1053,7 +1158,7 @@ opt_case_dispatch OFFSET dst = vm_case_dispatch(hash, else_offset, key); if (dst) { - JUMP(dst); + JUMP(dst); } } @@ -1068,7 +1173,7 @@ opt_plus { val = vm_opt_plus(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1082,7 +1187,7 @@ opt_minus { val = vm_opt_minus(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1096,7 +1201,7 @@ opt_mult { val = vm_opt_mult(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1113,7 +1218,7 @@ opt_div { val = vm_opt_div(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1129,7 +1234,7 @@ opt_mod { val = vm_opt_mod(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1143,7 +1248,7 @@ opt_eq { val = opt_equality(GET_ISEQ(), recv, obj, cd); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1157,7 +1262,7 @@ opt_neq { val = vm_opt_neq(GET_ISEQ(), cd, cd_eq, recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1171,7 +1276,7 @@ opt_lt { val = vm_opt_lt(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1185,7 +1290,7 @@ opt_le { val = vm_opt_le(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1199,7 +1304,7 @@ opt_gt { val = vm_opt_gt(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1213,7 +1318,7 @@ opt_ge { val = vm_opt_ge(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1231,7 +1336,7 @@ opt_ltlt { val = vm_opt_ltlt(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1245,7 +1350,7 @@ opt_and { val = vm_opt_and(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1259,7 +1364,7 @@ opt_or { val = vm_opt_or(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1278,7 +1383,7 @@ opt_aref { val = vm_opt_aref(recv, obj); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1295,7 +1400,7 @@ opt_aset { val = vm_opt_aset(recv, obj, set); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1311,14 +1416,12 @@ opt_aset_with { VALUE tmp = vm_opt_aset_with(recv, key, val); - if (tmp != Qundef) { - val = tmp; + if (!UNDEF_P(tmp)) { + val = tmp; } else { -#ifndef MJIT_HEADER - TOPN(0) = rb_str_resurrect(key); - PUSH(val); -#endif + TOPN(0) = rb_str_resurrect(key); + PUSH(val); CALL_SIMPLE_METHOD(); } } @@ -1334,10 +1437,8 @@ opt_aref_with { val = vm_opt_aref_with(recv, key); - if (val == Qundef) { -#ifndef MJIT_HEADER - PUSH(rb_str_resurrect(key)); -#endif + if (UNDEF_P(val)) { + PUSH(rb_str_resurrect(key)); CALL_SIMPLE_METHOD(); } } @@ -1351,7 +1452,7 @@ opt_length { val = vm_opt_length(recv, BOP_LENGTH); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1365,7 +1466,7 @@ opt_size { val = vm_opt_length(recv, BOP_SIZE); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1379,7 +1480,7 @@ opt_empty_p { val = vm_opt_empty_p(recv); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1393,7 +1494,7 @@ opt_succ { val = vm_opt_succ(recv); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1407,7 +1508,7 @@ opt_not { val = vm_opt_not(GET_ISEQ(), cd, recv); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } @@ -1422,32 +1523,11 @@ opt_regexpmatch2 { val = vm_opt_regexpmatch2(obj2, obj1); - if (val == Qundef) { + if (UNDEF_P(val)) { CALL_SIMPLE_METHOD(); } } -/* call native compiled method */ -DEFINE_INSN_IF(SUPPORT_CALL_C_FUNCTION) -opt_call_c_function -(rb_insn_func_t funcptr) -() -() -// attr bool leaf = false; /* anything can happen inside */ -// attr bool handles_sp = true; -{ - reg_cfp = (funcptr)(ec, reg_cfp); - - if (reg_cfp == 0) { - VALUE err = ec->errinfo; - ec->errinfo = Qnil; - THROW_EXCEPTION(err); - } - - RESTORE_REGS(); - NEXT_INSN(); -} - /* call specific function with args */ DEFINE_INSN invokebuiltin |