summaryrefslogtreecommitdiff
path: root/insns.def
diff options
context:
space:
mode:
Diffstat (limited to 'insns.def')
-rw-r--r--insns.def216
1 files changed, 153 insertions, 63 deletions
diff --git a/insns.def b/insns.def
index ed6becc88a..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);
}
@@ -223,6 +225,7 @@ setinstancevariable
(VALUE val)
()
// attr bool leaf = false; /* has rb_check_frozen() */
+// attr bool zjit_profile = true;
{
vm_setinstancevariable(GET_ISEQ(), GET_SELF(), id, val, ic);
}
@@ -370,7 +373,7 @@ putspecialobject
/* put string val. string will be copied. */
DEFINE_INSN
-putstring
+dupstring
(VALUE str)
()
(VALUE val)
@@ -380,7 +383,7 @@ putstring
/* put chilled string val. string will be copied but frozen in the future. */
DEFINE_INSN
-putchilledstring
+dupchilledstring
(VALUE str)
()
(VALUE val)
@@ -426,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. */
@@ -566,6 +567,7 @@ 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;
@@ -587,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();
@@ -744,6 +745,7 @@ definedivar
()
(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))) {
@@ -802,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);
@@ -844,6 +853,7 @@ 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);
{
@@ -869,7 +879,7 @@ sendforward
struct rb_forwarding_call_data adjusted_cd;
struct rb_callinfo adjusted_ci;
- VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq, 0, &adjusted_cd, &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);
@@ -890,6 +900,7 @@ 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);
@@ -904,6 +915,32 @@ opt_send_without_block
}
}
+/* 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
@@ -911,8 +948,9 @@ objtostring
(VALUE recv)
(VALUE val)
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
- val = vm_objtostring(GET_ISEQ(), recv, cd);
+ val = vm_objtostring(GET_CFP(), recv, cd);
if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
@@ -969,8 +1007,9 @@ 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 (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
@@ -1004,7 +1043,7 @@ opt_duparray_send
// 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) {
+ switch (method) {
case idIncludeP:
val = vm_opt_duparray_include_p(ec, ary, TOPN(0));
break;
@@ -1026,7 +1065,7 @@ opt_newarray_send
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)num;
{
- switch(method) {
+ switch (method) {
case VM_OPT_NEWARRAY_SEND_HASH:
val = vm_opt_newarray_hash(ec, num, STACK_ADDR_FROM_TOP(num));
break;
@@ -1058,11 +1097,27 @@ invokesuper
(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);
+// 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();
@@ -1081,7 +1136,7 @@ invokesuperforward
struct rb_forwarding_call_data adjusted_cd;
struct rb_callinfo adjusted_ci;
- VALUE bh = vm_caller_setup_fwd_args(GET_EC(), GET_CFP(), cd, blockiseq, 1, &adjusted_cd, &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);
@@ -1105,6 +1160,7 @@ 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);
@@ -1177,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);
@@ -1190,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);
@@ -1205,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);
@@ -1220,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);
@@ -1228,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 */
/**********************************************************/
@@ -1265,6 +1371,7 @@ opt_plus
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_plus(recv, obj);
@@ -1279,6 +1386,7 @@ opt_minus
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_minus(recv, obj);
@@ -1293,6 +1401,7 @@ opt_mult
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_mult(recv, obj);
@@ -1310,6 +1419,7 @@ 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);
@@ -1326,6 +1436,7 @@ opt_mod
(VALUE val)
/* Same discussion as opt_div. */
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = vm_opt_mod(recv, obj);
@@ -1340,8 +1451,9 @@ 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 (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
@@ -1354,8 +1466,9 @@ 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 (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
@@ -1368,6 +1481,7 @@ opt_lt
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_lt(recv, obj);
@@ -1382,6 +1496,7 @@ opt_le
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_le(recv, obj);
@@ -1396,6 +1511,7 @@ opt_gt
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_gt(recv, obj);
@@ -1410,6 +1526,7 @@ opt_ge
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_ge(recv, obj);
@@ -1428,6 +1545,7 @@ 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);
@@ -1442,6 +1560,7 @@ opt_and
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_and(recv, obj);
@@ -1456,6 +1575,7 @@ opt_or
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_or(recv, obj);
@@ -1475,6 +1595,7 @@ 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);
@@ -1492,6 +1613,7 @@ 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);
@@ -1500,50 +1622,13 @@ opt_aset
}
}
-/* 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 (!UNDEF_P(tmp)) {
- val = tmp;
- }
- else {
- TOPN(0) = rb_str_resurrect(key);
- PUSH(val);
- 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 (UNDEF_P(val)) {
- PUSH(rb_str_resurrect(key));
- CALL_SIMPLE_METHOD();
- }
-}
-
/* optimized length */
DEFINE_INSN
opt_length
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_length(recv, BOP_LENGTH);
@@ -1558,6 +1643,7 @@ opt_size
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_length(recv, BOP_SIZE);
@@ -1572,6 +1658,7 @@ opt_empty_p
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_empty_p(recv);
@@ -1586,6 +1673,7 @@ opt_succ
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_succ(recv);
@@ -1600,8 +1688,9 @@ 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 (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
@@ -1615,6 +1704,7 @@ 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);