summaryrefslogtreecommitdiff
path: root/insns.def
diff options
context:
space:
mode:
Diffstat (limited to 'insns.def')
-rw-r--r--insns.def547
1 files changed, 391 insertions, 156 deletions
diff --git a/insns.def b/insns.def
index 9f5ee7095a..3ad378081a 100644
--- a/insns.def
+++ b/insns.def
@@ -145,6 +145,7 @@ getblockparamproxy
(lindex_t idx, rb_num_t level)
()
(VALUE val)
+// attr bool zjit_profile = true;
{
const VALUE *ep = vm_get_ep(GET_EP(), level);
VM_ASSERT(VM_ENV_LOCAL_P(ep));
@@ -212,6 +213,7 @@ getinstancevariable
(VALUE val)
/* Ractor crashes when it accesses class/module-level instances variables. */
// attr bool leaf = false; /* has IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() */
+// attr bool zjit_profile = true;
{
val = vm_getinstancevariable(GET_ISEQ(), GET_SELF(), id, ic);
}
@@ -222,7 +224,8 @@ setinstancevariable
(ID id, IVC ic)
(VALUE val)
()
-// attr bool leaf = false; /* has rb_check_frozen_internal() */
+// attr bool leaf = false; /* has rb_check_frozen() */
+// attr bool zjit_profile = true;
{
vm_setinstancevariable(GET_ISEQ(), GET_SELF(), id, val, ic);
}
@@ -260,20 +263,7 @@ opt_getconstant_path
(VALUE val)
// attr bool leaf = false; /* may autoload or raise */
{
- const ID *segments = ic->segments;
- struct iseq_inline_constant_cache_entry *ice = ic->entry;
- if (ice && vm_ic_hit_p(ice, GET_EP())) {
- val = ice->value;
-
- VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));
- } else {
- ruby_vm_constant_cache_misses++;
- val = vm_get_ev_const_chain(ec, segments);
- vm_ic_track_const_chain(GET_CFP(), ic, segments);
- // Because leaf=false, we need to undo the PC increment to get the address to this instruction
- // INSN_ATTR(width) == 2
- vm_ic_update(GET_ISEQ(), ic, val, GET_EP(), GET_PC() - 2);
- }
+ val = rb_vm_opt_getconstant_path(ec, GET_CFP(), ic);
}
/* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants
@@ -383,12 +373,22 @@ putspecialobject
/* put string val. string will be copied. */
DEFINE_INSN
-putstring
+dupstring
+(VALUE str)
+()
+(VALUE val)
+{
+ val = rb_ec_str_resurrect(ec, str, false);
+}
+
+/* put chilled string val. string will be copied but frozen in the future. */
+DEFINE_INSN
+dupchilledstring
(VALUE str)
()
(VALUE val)
{
- val = rb_ec_str_resurrect(ec, str);
+ val = rb_ec_str_resurrect(ec, str, true);
}
/* put concatenate strings */
@@ -429,9 +429,7 @@ toregexp
// attr bool leaf = false;
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)cnt;
{
- const VALUE ary = rb_ary_tmp_new_from_values(0, cnt, STACK_ADDR_FROM_TOP(cnt));
- val = rb_reg_new_ary(ary, (int)opt);
- rb_ary_clear(ary);
+ val = rb_reg_new_from_values(cnt, STACK_ADDR_FROM_TOP(cnt), (int)opt);
}
/* intern str to Symbol and push it. */
@@ -455,23 +453,17 @@ newarray
val = rb_ec_ary_new_from_values(ec, num, STACK_ADDR_FROM_TOP(num));
}
-/* put new array initialized with num values on the stack. There
- should be at least one element on the stack, and the top element
- should be a hash. If the top element is empty, it is not
- included in the array.
+/* push hash onto array unless the hash is empty (as empty keyword
+ splats should be ignored).
*/
DEFINE_INSN
-newarraykwsplat
-(rb_num_t num)
-(...)
-(VALUE val)
-// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
+pushtoarraykwsplat
+()
+(VALUE ary, VALUE hash)
+(VALUE ary)
{
- if (RHASH_EMPTY_P(*STACK_ADDR_FROM_TOP(1))) {
- val = rb_ary_new4(num-1, STACK_ADDR_FROM_TOP(num));
- }
- else {
- val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
+ if (!RHASH_EMPTY_P(hash)) {
+ rb_ary_push(ary, hash);
}
}
@@ -511,13 +503,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
()
@@ -528,6 +523,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
@@ -539,6 +560,23 @@ 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() */
+// attr bool zjit_profile = true;
+{
+ 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
@@ -551,8 +589,7 @@ newhash
RUBY_DTRACE_CREATE_HOOK(HASH, num);
if (num) {
- val = rb_hash_new_with_size(num / 2);
- rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
+ val = rb_hash_new_with_bulk_insert(num, STACK_ADDR_FROM_TOP(num));
}
else {
val = rb_hash_new();
@@ -701,6 +738,21 @@ defined
}
}
+/* defined?(@foo) */
+DEFINE_INSN
+definedivar
+(ID id, IVC ic, VALUE pushval)
+()
+(VALUE val)
+// attr bool leaf = false;
+// attr bool zjit_profile = true;
+{
+ val = Qnil;
+ if (!UNDEF_P(vm_getivar(GET_SELF(), id, GET_ISEQ(), ic, NULL, FALSE, Qundef))) {
+ val = pushval;
+ }
+}
+
/* check `target' matches `pattern'.
`flag & VM_CHECKMATCH_TYPE_MASK' describe how to check pattern.
VM_CHECKMATCH_TYPE_WHEN: ignore target and check pattern is truthy.
@@ -752,13 +804,20 @@ defineclass
(VALUE val)
{
VALUE klass = vm_find_or_create_class_by_id(id, flags, cbase, super);
+ const rb_box_t *box = rb_current_box();
rb_iseq_check(class_iseq);
+ rb_cref_t *cref = vm_cref_push(ec, klass, NULL, FALSE, FALSE);
+
+ if (VM_DEFINECLASS_DYNAMIC_CREF_P(flags)) {
+ CREF_DYNAMIC_SET(cref);
+ }
+
/* 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, FALSE),
+ GC_GUARDED_PTR(box),
+ (VALUE)cref,
ISEQ_BODY(class_iseq)->iseq_encoded, GET_SP(),
ISEQ_BODY(class_iseq)->local_table_size,
ISEQ_BODY(class_iseq)->stack_max);
@@ -794,13 +853,42 @@ send
(CALL_DATA cd, ISEQ blockiseq)
(...)
(VALUE val)
+// attr bool zjit_profile = true;
// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
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 (UNDEF_P(val)) {
+ RESTORE_REGS();
+ NEXT_INSN();
+ }
+}
+
+/* invoke forward method. */
+DEFINE_INSN
+sendforward
+(CALL_DATA cd, ISEQ blockiseq)
+(...)
+(VALUE val)
+// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
+// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
+{
+ struct rb_forwarding_call_data adjusted_cd;
+ struct rb_callinfo adjusted_ci;
+
+ VALUE bh = vm_caller_setup_fwd_args(ec, GET_CFP(), cd, blockiseq, 0, &adjusted_cd, &adjusted_ci);
+
+ val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
+ JIT_EXEC(ec, val);
- if (val == Qundef) {
+ if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
+ RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc);
+ }
+
+ if (UNDEF_P(val)) {
RESTORE_REGS();
NEXT_INSN();
}
@@ -812,19 +900,47 @@ opt_send_without_block
(CALL_DATA cd)
(...)
(VALUE val)
+// attr bool zjit_profile = true;
// attr bool handles_sp = true;
// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
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();
}
}
+/* Jump if "new" method has been defined by user */
+DEFINE_INSN
+opt_new
+(CALL_DATA cd, OFFSET dst)
+()
+()
+// attr bool leaf = false;
+{
+ VALUE argc = vm_ci_argc(cd->ci);
+ VALUE val = TOPN(argc);
+
+ // The bookkeeping slot should be empty.
+ RUBY_ASSERT(TOPN(argc + 1) == Qnil);
+
+ if (vm_method_cfunc_is(GET_CFP(), cd, val, rb_class_new_instance_pass_kw)) {
+ RB_DEBUG_COUNTER_INC(opt_new_hit);
+ val = rb_obj_alloc(val);
+ TOPN(argc) = val;
+ TOPN(argc + 1) = val;
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(opt_new_miss);
+ JUMP(dst);
+ }
+}
+
/* Convert object to string using to_s or equivalent. */
DEFINE_INSN
objtostring
@@ -832,10 +948,41 @@ objtostring
(VALUE recv)
(VALUE val)
// attr bool leaf = false;
+// attr bool zjit_profile = true;
+{
+ val = vm_objtostring(GET_CFP(), recv, cd);
+
+ if (UNDEF_P(val)) {
+ CALL_SIMPLE_METHOD();
+ }
+}
+
+DEFINE_INSN
+opt_ary_freeze
+(VALUE ary, CALL_DATA cd)
+()
+(VALUE val)
{
- val = vm_objtostring(GET_ISEQ(), recv, cd);
+ val = vm_opt_ary_freeze(ary, BOP_FREEZE, idFreeze);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
+ RUBY_DTRACE_CREATE_HOOK(ARRAY, RARRAY_LEN(ary));
+ PUSH(rb_ary_resurrect(ary));
+ CALL_SIMPLE_METHOD();
+ }
+}
+
+DEFINE_INSN
+opt_hash_freeze
+(VALUE hash, CALL_DATA cd)
+()
+(VALUE val)
+{
+ val = vm_opt_hash_freeze(hash, BOP_FREEZE, idFreeze);
+
+ if (UNDEF_P(val)) {
+ RUBY_DTRACE_CREATE_HOOK(HASH, RHASH_SIZE(hash) << 1);
+ PUSH(rb_hash_resurrect(hash));
CALL_SIMPLE_METHOD();
}
}
@@ -848,7 +995,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();
}
@@ -860,10 +1007,11 @@ opt_nil_p
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
- val = vm_opt_nil_p(GET_ISEQ(), cd, recv);
+ val = vm_opt_nil_p(GET_CFP(), cd, recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -876,15 +1024,37 @@ 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_duparray_send
+(VALUE ary, ID method, rb_num_t argc)
+(...)
+(VALUE val)
+/* This instruction typically has no funcalls. But it may compare array
+ * contents to each other which may call methods when necessary.
+ * No way to detect such method calls beforehand.
+ * We must mark it as not leaf. */
+// attr bool leaf = false; /* has rb_funcall() */
+// attr rb_snum_t sp_inc = 1 - (rb_snum_t)argc;
+// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)argc;
+{
+ switch (method) {
+ case idIncludeP:
+ val = vm_opt_duparray_include_p(ec, ary, TOPN(0));
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+}
+
+DEFINE_INSN
+opt_newarray_send
+(rb_num_t num, rb_num_t method)
(...)
(VALUE val)
/* This instruction typically has no funcalls. But it compares array
@@ -893,35 +1063,89 @@ 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));
+// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)num;
+{
+ switch (method) {
+ case VM_OPT_NEWARRAY_SEND_HASH:
+ val = vm_opt_newarray_hash(ec, num, STACK_ADDR_FROM_TOP(num));
+ break;
+ case VM_OPT_NEWARRAY_SEND_MIN:
+ val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num));
+ break;
+ case VM_OPT_NEWARRAY_SEND_MAX:
+ val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num));
+ break;
+ case VM_OPT_NEWARRAY_SEND_INCLUDE_P:
+ val = vm_opt_newarray_include_p(ec, (long)num-1, STACK_ADDR_FROM_TOP(num), TOPN(0));
+ break;
+ case VM_OPT_NEWARRAY_SEND_PACK:
+ val = vm_opt_newarray_pack_buffer(ec, (long)num-1, STACK_ADDR_FROM_TOP(num), TOPN(0), Qundef);
+ break;
+ case VM_OPT_NEWARRAY_SEND_PACK_BUFFER:
+ val = vm_opt_newarray_pack_buffer(ec, (long)num-2, STACK_ADDR_FROM_TOP(num), TOPN(1), TOPN(0));
+ break;
+ default:
+ rb_bug("unreachable");
+ }
}
+/* super(args) # args.size => num */
DEFINE_INSN
-opt_newarray_min
-(rb_num_t num)
+invokesuper
+(CALL_DATA cd, ISEQ blockiseq)
(...)
(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 sp_inc = sp_inc_of_sendish(cd->ci);
+// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
+// attr bool zjit_profile = true;
+{
+ struct rb_callinfo adjusted_ci = VM_CI_ON_STACK(vm_ci_mid(cd->ci),
+ vm_ci_flag(cd->ci),
+ vm_ci_argc(cd->ci),
+ vm_ci_kwarg(cd->ci));
+ const struct rb_callcache *original_cc = rbimpl_atomic_ptr_load((void **)&cd->cc, RBIMPL_ATOMIC_ACQUIRE);
+ struct rb_call_data adjusted_cd = {
+ .ci = &adjusted_ci,
+ .cc = original_cc,
+ };
+
+ VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), adjusted_cd.ci, blockiseq, true);
+ val = vm_sendish(ec, GET_CFP(), &adjusted_cd, bh, mexp_search_super);
+ JIT_EXEC(ec, val);
+
+ if (original_cc != adjusted_cd.cc && vm_cc_markable(adjusted_cd.cc)) {
+ rbimpl_atomic_ptr_store((volatile void **)&cd->cc, (void *)adjusted_cd.cc, RBIMPL_ATOMIC_RELEASE);
+ RB_OBJ_WRITTEN(GET_ISEQ(), Qundef, adjusted_cd.cc);
+ }
+
+ if (UNDEF_P(val)) {
+ RESTORE_REGS();
+ NEXT_INSN();
+ }
}
/* super(args) # args.size => num */
DEFINE_INSN
-invokesuper
+invokesuperforward
(CALL_DATA cd, ISEQ blockiseq)
(...)
(VALUE val)
// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
- 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);
+ struct rb_forwarding_call_data adjusted_cd;
+ struct rb_callinfo adjusted_ci;
+
+ VALUE bh = vm_caller_setup_fwd_args(ec, GET_CFP(), cd, blockiseq, 1, &adjusted_cd, &adjusted_ci);
+
+ val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
+ JIT_EXEC(ec, val);
+
+ if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
+ RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc);
+ }
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
RESTORE_REGS();
NEXT_INSN();
}
@@ -936,11 +1160,13 @@ invokeblock
// attr bool handles_sp = true;
// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_invokeblock(ci);
+// attr bool zjit_profile = true;
{
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();
}
@@ -1007,7 +1233,7 @@ jump
()
()
/* Same discussion as leave. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
RUBY_VM_CHECK_INTS(ec);
JUMP(dst);
@@ -1020,7 +1246,7 @@ branchif
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
if (RTEST(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1035,7 +1261,7 @@ branchunless
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
if (!RTEST(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1050,7 +1276,7 @@ branchnil
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
if (NIL_P(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1058,6 +1284,56 @@ branchnil
}
}
+/* same as jump, but without interrupt check */
+DEFINE_INSN
+jump_without_ints
+(OFFSET dst)
+()
+()
+// attr bool leaf = true;
+{
+ JUMP(dst);
+}
+
+/* same as branchif, but without interrupt check */
+DEFINE_INSN
+branchif_without_ints
+(OFFSET dst)
+(VALUE val)
+()
+// attr bool leaf = true;
+{
+ if (RTEST(val)) {
+ JUMP(dst);
+ }
+}
+
+/* same as branchunless, but without interrupt check */
+DEFINE_INSN
+branchunless_without_ints
+(OFFSET dst)
+(VALUE val)
+()
+// attr bool leaf = true;
+{
+ if (!RTEST(val)) {
+ JUMP(dst);
+ }
+}
+
+/* same as branchnil, but without interrupt check */
+DEFINE_INSN
+branchnil_without_ints
+(OFFSET dst)
+(VALUE val)
+()
+// attr bool leaf = true;
+{
+ if (NIL_P(val)) {
+ JUMP(dst);
+ }
+}
+
/**********************************************************/
/* for optimize */
/**********************************************************/
@@ -1095,10 +1371,11 @@ opt_plus
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_plus(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1109,10 +1386,11 @@ opt_minus
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_minus(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1123,10 +1401,11 @@ opt_mult
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_mult(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1140,10 +1419,11 @@ opt_div
/* In case of division by zero, it raises. Thus
* ZeroDivisionError#initialize is called. */
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = vm_opt_div(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1156,10 +1436,11 @@ opt_mod
(VALUE val)
/* Same discussion as opt_div. */
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = vm_opt_mod(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1170,10 +1451,11 @@ opt_eq
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
- val = opt_equality(GET_ISEQ(), recv, obj, cd);
+ val = opt_equality(GET_CFP(), recv, obj, cd);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1184,10 +1466,11 @@ opt_neq
(CALL_DATA cd_eq, CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
- val = vm_opt_neq(GET_ISEQ(), cd, cd_eq, recv, obj);
+ val = vm_opt_neq(GET_CFP(), cd, cd_eq, recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1198,10 +1481,11 @@ opt_lt
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_lt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1212,10 +1496,11 @@ opt_le
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_le(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1226,10 +1511,11 @@ opt_gt
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_gt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1240,10 +1526,11 @@ opt_ge
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_ge(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1258,10 +1545,11 @@ opt_ltlt
* string. Then what happens if that codepoint does not exist in the
* string's encoding? Of course an exception. That's not a leaf. */
// attr bool leaf = false; /* has "invalid codepoint" exception */
+// attr bool zjit_profile = true;
{
val = vm_opt_ltlt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1272,10 +1560,11 @@ opt_and
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_and(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1286,10 +1575,11 @@ opt_or
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_or(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1305,10 +1595,11 @@ opt_aref
* default_proc. This is a method call. So opt_aref is
* (surprisingly) not leaf. */
// attr bool leaf = false; /* has rb_funcall() */ /* calls #yield */
+// attr bool zjit_profile = true;
{
val = vm_opt_aref(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1322,52 +1613,11 @@ opt_aset
/* This is another story than opt_aref. When vm_opt_aset() resorts
* to rb_hash_aset(), which should call #hash for `obj`. */
// attr bool leaf = false; /* has rb_funcall() */ /* calls #hash */
+// attr bool zjit_profile = true;
{
val = vm_opt_aset(recv, obj, set);
- if (val == Qundef) {
- CALL_SIMPLE_METHOD();
- }
-}
-
-/* recv[str] = set */
-DEFINE_INSN
-opt_aset_with
-(VALUE key, CALL_DATA cd)
-(VALUE recv, VALUE val)
-(VALUE val)
-/* Same discussion as opt_aset. */
-// attr bool leaf = false; /* has rb_funcall() */ /* calls #hash */
-{
- VALUE tmp = vm_opt_aset_with(recv, key, val);
-
- if (tmp != Qundef) {
- val = tmp;
- }
- else {
-#ifndef MJIT_HEADER
- TOPN(0) = rb_str_resurrect(key);
- PUSH(val);
-#endif
- CALL_SIMPLE_METHOD();
- }
-}
-
-/* recv[str] */
-DEFINE_INSN
-opt_aref_with
-(VALUE key, CALL_DATA cd)
-(VALUE recv)
-(VALUE val)
-/* Same discussion as opt_aref. */
-// attr bool leaf = false; /* has rb_funcall() */ /* calls #yield */
-{
- val = vm_opt_aref_with(recv, key);
-
- if (val == Qundef) {
-#ifndef MJIT_HEADER
- PUSH(rb_str_resurrect(key));
-#endif
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1378,10 +1628,11 @@ opt_length
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_length(recv, BOP_LENGTH);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1392,10 +1643,11 @@ opt_size
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_length(recv, BOP_SIZE);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1406,10 +1658,11 @@ opt_empty_p
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_empty_p(recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1420,10 +1673,11 @@ opt_succ
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_succ(recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1434,10 +1688,11 @@ opt_not
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
- val = vm_opt_not(GET_ISEQ(), cd, recv);
+ val = vm_opt_not(GET_CFP(), cd, recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1449,35 +1704,15 @@ opt_regexpmatch2
(VALUE obj2, VALUE obj1)
(VALUE val)
// attr bool leaf = false; /* match_at() has rb_thread_check_ints() */
+// attr bool zjit_profile = true;
{
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