summaryrefslogtreecommitdiff
path: root/insns.def
diff options
context:
space:
mode:
Diffstat (limited to 'insns.def')
-rw-r--r--insns.def267
1 files changed, 150 insertions, 117 deletions
diff --git a/insns.def b/insns.def
index 15c4734b8b..9c649904b8 100644
--- a/insns.def
+++ b/insns.def
@@ -253,6 +253,16 @@ setclassvariable
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
are searched in the current scope. Otherwise, get constant under klass
class or module.
@@ -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 */
@@ -452,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
@@ -488,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
()
@@ -505,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
@@ -516,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
@@ -674,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;
}
}
@@ -776,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();
}
@@ -795,8 +889,9 @@ 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();
}
@@ -812,7 +907,7 @@ objtostring
{
val = vm_objtostring(GET_ISEQ(), recv, cd);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -825,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();
}
@@ -840,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();
}
}
@@ -853,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
@@ -870,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 */
@@ -897,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();
}
@@ -916,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();
}
@@ -1039,46 +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 there isn't an entry, then we're going to walk through the ISEQ
- // starting at this instruction until we get to the associated
- // opt_setinlinecache and associate this inline cache with every getconstant
- // listed in between. We're doing this here instead of when the instructions
- // are first compiled because it's possible to turn off inline caches and we
- // want this to work in either case.
- if (!ice) {
- vm_ic_compile(GET_CFP(), ic);
- }
-
- if (ice && vm_ic_hit_p(ice, GET_EP())) {
- val = ice->value;
- JUMP(dst);
- }
- else {
- ruby_vm_constant_cache_misses++;
- 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
@@ -1115,7 +1173,7 @@ opt_plus
{
val = vm_opt_plus(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1129,7 +1187,7 @@ opt_minus
{
val = vm_opt_minus(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1143,7 +1201,7 @@ opt_mult
{
val = vm_opt_mult(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1160,7 +1218,7 @@ opt_div
{
val = vm_opt_div(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1176,7 +1234,7 @@ opt_mod
{
val = vm_opt_mod(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1190,7 +1248,7 @@ opt_eq
{
val = opt_equality(GET_ISEQ(), recv, obj, cd);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1204,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();
}
}
@@ -1218,7 +1276,7 @@ opt_lt
{
val = vm_opt_lt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1232,7 +1290,7 @@ opt_le
{
val = vm_opt_le(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1246,7 +1304,7 @@ opt_gt
{
val = vm_opt_gt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1260,7 +1318,7 @@ opt_ge
{
val = vm_opt_ge(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1278,7 +1336,7 @@ opt_ltlt
{
val = vm_opt_ltlt(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1292,7 +1350,7 @@ opt_and
{
val = vm_opt_and(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1306,7 +1364,7 @@ opt_or
{
val = vm_opt_or(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1325,7 +1383,7 @@ opt_aref
{
val = vm_opt_aref(recv, obj);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1342,7 +1400,7 @@ opt_aset
{
val = vm_opt_aset(recv, obj, set);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1358,14 +1416,12 @@ opt_aset_with
{
VALUE tmp = vm_opt_aset_with(recv, key, val);
- if (tmp != Qundef) {
+ if (!UNDEF_P(tmp)) {
val = tmp;
}
else {
-#ifndef MJIT_HEADER
TOPN(0) = rb_str_resurrect(key);
PUSH(val);
-#endif
CALL_SIMPLE_METHOD();
}
}
@@ -1381,10 +1437,8 @@ opt_aref_with
{
val = vm_opt_aref_with(recv, key);
- if (val == Qundef) {
-#ifndef MJIT_HEADER
+ if (UNDEF_P(val)) {
PUSH(rb_str_resurrect(key));
-#endif
CALL_SIMPLE_METHOD();
}
}
@@ -1398,7 +1452,7 @@ opt_length
{
val = vm_opt_length(recv, BOP_LENGTH);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1412,7 +1466,7 @@ opt_size
{
val = vm_opt_length(recv, BOP_SIZE);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1426,7 +1480,7 @@ opt_empty_p
{
val = vm_opt_empty_p(recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1440,7 +1494,7 @@ opt_succ
{
val = vm_opt_succ(recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1454,7 +1508,7 @@ opt_not
{
val = vm_opt_not(GET_ISEQ(), cd, recv);
- if (val == Qundef) {
+ if (UNDEF_P(val)) {
CALL_SIMPLE_METHOD();
}
}
@@ -1469,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