Add VM_CALL_ARGS_SPLAT_MUT callinfo flag
This flag is set when the caller has already created a new array to handle a splat, such as for `f(*a, b)` and `f(*a, *b)`. Previously, if `f` was defined as `def f(*a)`, these calls would create an extra array on the callee side, instead of using the new array created by the caller. This modifies `setup_args_core` to set the flag whenver it would add a `splatarray true` instruction. However, when `splatarray true` is changed to `splatarray false` in the peephole optimizer, to avoid unnecessary allocations on the caller side, the flag must be removed. Add `optimize_args_splat_no_copy` and have the peephole optimizer call that. This significantly simplifies the related peephole optimizer code. On the callee side, in `setup_parameters_complex`, set `args->rest_dupped` to true if the flag is set. This takes a similar approach for optimizing regular splats that was previiously used for keyword splats in d2c41b1bff1f3102544bb0d03d4e82356d034d33 (via VM_CALL_KW_SPLAT_MUT).
This commit is contained in:
parent
ef276858d9
commit
22e488464a
193
compile.c
193
compile.c
@ -3190,6 +3190,30 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc)
|
|||||||
return nci;
|
return nci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
optimize_args_splat_no_copy(rb_iseq_t *iseq, INSN *insn, LINK_ELEMENT *niobj,
|
||||||
|
unsigned int set_flags, unsigned int unset_flags)
|
||||||
|
{
|
||||||
|
LINK_ELEMENT *iobj = (LINK_ELEMENT *)insn;
|
||||||
|
if (!IS_NEXT_INSN_ID(niobj, send)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
niobj = niobj->next;
|
||||||
|
|
||||||
|
const struct rb_callinfo *ci = (const struct rb_callinfo *)OPERAND_AT(niobj, 0);
|
||||||
|
unsigned int flags = vm_ci_flag(ci);
|
||||||
|
if ((flags & set_flags) == set_flags && !(flags & unset_flags)) {
|
||||||
|
RUBY_ASSERT(flags & VM_CALL_ARGS_SPLAT_MUT);
|
||||||
|
OPERAND_AT(iobj, 0) = Qfalse;
|
||||||
|
const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
|
||||||
|
flags & ~VM_CALL_ARGS_SPLAT_MUT, vm_ci_argc(ci), vm_ci_kwarg(ci));
|
||||||
|
RB_OBJ_WRITTEN(iseq, ci, nci);
|
||||||
|
OPERAND_AT(niobj, 0) = (VALUE)nci;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
|
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
|
||||||
{
|
{
|
||||||
@ -3879,58 +3903,46 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
|
|||||||
* splatarray false
|
* splatarray false
|
||||||
* send
|
* send
|
||||||
*/
|
*/
|
||||||
if (IS_NEXT_INSN_ID(niobj, send)) {
|
if (optimize_args_splat_no_copy(iseq, iobj, niobj,
|
||||||
niobj = niobj->next;
|
VM_CALL_ARGS_SPLAT, VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG)) goto optimized_splat;
|
||||||
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));
|
|
||||||
if ((flag & VM_CALL_ARGS_SPLAT) && !(flag & (VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG))) {
|
if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) {
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) {
|
|
||||||
niobj = niobj->next;
|
niobj = niobj->next;
|
||||||
|
|
||||||
if (IS_NEXT_INSN_ID(niobj, send)) {
|
/*
|
||||||
niobj = niobj->next;
|
* Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv)
|
||||||
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));
|
*
|
||||||
|
* splatarray true
|
||||||
|
* getlocal / getinstancevariable
|
||||||
|
* send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
|
||||||
|
* =>
|
||||||
|
* splatarray false
|
||||||
|
* getlocal / getinstancevariable
|
||||||
|
* send
|
||||||
|
*/
|
||||||
|
if (optimize_args_splat_no_copy(iseq, iobj, niobj,
|
||||||
|
VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT)) goto optimized_splat;
|
||||||
|
|
||||||
if ((flag & VM_CALL_ARGS_SPLAT)) {
|
/*
|
||||||
/*
|
* Eliminate array allocation for f(*a, **lvar) and f(*a, **@iv)
|
||||||
* Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv)
|
*
|
||||||
*
|
* splatarray true
|
||||||
* splatarray true
|
* getlocal / getinstancevariable
|
||||||
* getlocal / getinstancevariable
|
* send ARGS_SPLAT|KW_SPLAT and not ARGS_BLOCKARG
|
||||||
* send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
|
* =>
|
||||||
* =>
|
* splatarray false
|
||||||
* splatarray false
|
* getlocal / getinstancevariable
|
||||||
* getlocal / getinstancevariable
|
* send
|
||||||
* send
|
*/
|
||||||
*/
|
if (optimize_args_splat_no_copy(iseq, iobj, niobj,
|
||||||
if ((flag & VM_CALL_ARGS_BLOCKARG) && !(flag & VM_CALL_KW_SPLAT)) {
|
VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT, VM_CALL_ARGS_BLOCKARG)) goto optimized_splat;
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
|
||||||
* Eliminate array allocation for f(*a, **lvar) and f(*a, **@iv)
|
IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
|
||||||
*
|
|
||||||
* splatarray true
|
|
||||||
* getlocal / getinstancevariable
|
|
||||||
* send ARGS_SPLAT|KW_SPLAT and not ARGS_BLOCKARG
|
|
||||||
* =>
|
|
||||||
* splatarray false
|
|
||||||
* getlocal / getinstancevariable
|
|
||||||
* send
|
|
||||||
*/
|
|
||||||
else if (!(flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT)) {
|
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
|
|
||||||
IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
|
|
||||||
niobj = niobj->next;
|
niobj = niobj->next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Eliminate array allocation for f(*a, **lvar, &lvar) and f(*a, **@iv, &@iv)
|
* Eliminate array allocation for f(*a, **lvar, &{arg,lvar,@iv})
|
||||||
*
|
*
|
||||||
* splatarray true
|
* splatarray true
|
||||||
* getlocal / getinstancevariable
|
* getlocal / getinstancevariable
|
||||||
@ -3942,40 +3954,24 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
|
|||||||
* getlocal / getinstancevariable / getblockparamproxy
|
* getlocal / getinstancevariable / getblockparamproxy
|
||||||
* send
|
* send
|
||||||
*/
|
*/
|
||||||
if (IS_NEXT_INSN_ID(niobj, send)) {
|
optimize_args_splat_no_copy(iseq, iobj, niobj,
|
||||||
niobj = niobj->next;
|
VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG, 0);
|
||||||
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));
|
|
||||||
|
|
||||||
if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) && (flag & VM_CALL_ARGS_BLOCKARG)) {
|
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
|
||||||
else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
|
/*
|
||||||
niobj = niobj->next;
|
* Eliminate array allocation for f(1, *a, &arg)
|
||||||
|
*
|
||||||
if (IS_NEXT_INSN_ID(niobj, send)) {
|
* splatarray true
|
||||||
niobj = niobj->next;
|
* getblockparamproxy
|
||||||
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));
|
* send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
|
||||||
|
* =>
|
||||||
/*
|
* splatarray false
|
||||||
* Eliminate array allocation for f(1, *a, &arg)
|
* getblockparamproxy
|
||||||
*
|
* send
|
||||||
* splatarray true
|
*/
|
||||||
* getblockparamproxy
|
optimize_args_splat_no_copy(iseq, iobj, niobj,
|
||||||
* send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
|
VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT);
|
||||||
* =>
|
} else if (IS_NEXT_INSN_ID(niobj, duphash)) {
|
||||||
* splatarray false
|
|
||||||
* getblockparamproxy
|
|
||||||
* send
|
|
||||||
*/
|
|
||||||
if ((flag & VM_CALL_ARGS_BLOCKARG) & (flag & VM_CALL_ARGS_SPLAT) && !(flag & VM_CALL_KW_SPLAT)) {
|
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_NEXT_INSN_ID(niobj, duphash)) {
|
|
||||||
niobj = niobj->next;
|
niobj = niobj->next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3989,21 +3985,13 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
|
|||||||
* duphash
|
* duphash
|
||||||
* send
|
* send
|
||||||
*/
|
*/
|
||||||
if (IS_NEXT_INSN_ID(niobj, send)) {
|
if (optimize_args_splat_no_copy(iseq, iobj, niobj->next,
|
||||||
niobj = niobj->next;
|
VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT, VM_CALL_ARGS_BLOCKARG)) goto optimized_splat;
|
||||||
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));
|
|
||||||
|
|
||||||
if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) &&
|
|
||||||
(flag & VM_CALL_KW_SPLAT_MUT) && !(flag & VM_CALL_ARGS_BLOCKARG)) {
|
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
|
|
||||||
IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
|
|
||||||
niobj = niobj->next;
|
|
||||||
|
|
||||||
|
if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
|
||||||
|
IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
|
||||||
/*
|
/*
|
||||||
* Eliminate array allocation for f(*a, kw: 1, &lvar) and f(*a, kw: 1, &@iv)
|
* Eliminate array allocation for f(*a, kw: 1, &{arg,lvar,@iv})
|
||||||
*
|
*
|
||||||
* splatarray true
|
* splatarray true
|
||||||
* duphash
|
* duphash
|
||||||
@ -4015,18 +4003,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
|
|||||||
* getlocal / getinstancevariable / getblockparamproxy
|
* getlocal / getinstancevariable / getblockparamproxy
|
||||||
* send
|
* send
|
||||||
*/
|
*/
|
||||||
if (IS_NEXT_INSN_ID(niobj, send)) {
|
optimize_args_splat_no_copy(iseq, iobj, niobj->next,
|
||||||
niobj = niobj->next;
|
VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG, 0);
|
||||||
unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0));
|
|
||||||
|
|
||||||
if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) &&
|
|
||||||
(flag & VM_CALL_KW_SPLAT_MUT) && (flag & VM_CALL_ARGS_BLOCKARG)) {
|
|
||||||
OPERAND_AT(iobj, 0) = Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
optimized_splat:
|
||||||
|
|
||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
}
|
}
|
||||||
@ -6190,12 +6172,15 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
|
|||||||
// f(*a)
|
// f(*a)
|
||||||
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
|
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
|
||||||
ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
|
ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
|
||||||
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
|
if (flag_ptr) {
|
||||||
|
*flag_ptr |= VM_CALL_ARGS_SPLAT;
|
||||||
|
if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
|
||||||
|
}
|
||||||
RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
|
RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case NODE_ARGSCAT: {
|
case NODE_ARGSCAT: {
|
||||||
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
|
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
|
||||||
int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL);
|
int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL);
|
||||||
|
|
||||||
if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
|
if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
|
||||||
@ -6229,7 +6214,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
|
|||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
case NODE_ARGSPUSH: {
|
case NODE_ARGSPUSH: {
|
||||||
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
|
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
|
||||||
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
|
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
|
||||||
|
|
||||||
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
|
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
|
||||||
@ -9080,7 +9065,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
|||||||
}
|
}
|
||||||
ADD_INSN1(ret, node, dupn, INT2FIX(dup_argn));
|
ADD_INSN1(ret, node, dupn, INT2FIX(dup_argn));
|
||||||
flag |= asgnflag;
|
flag |= asgnflag;
|
||||||
ADD_SEND_R(ret, node, idAREF, argc, NULL, INT2FIX(flag & ~VM_CALL_KW_SPLAT_MUT), keywords);
|
ADD_SEND_R(ret, node, idAREF, argc, NULL, INT2FIX(flag & ~(VM_CALL_ARGS_SPLAT_MUT|VM_CALL_KW_SPLAT_MUT)), keywords);
|
||||||
|
|
||||||
if (id == idOROP || id == idANDOP) {
|
if (id == idOROP || id == idANDOP) {
|
||||||
/* a[x] ||= y or a[x] &&= y
|
/* a[x] ||= y or a[x] &&= y
|
||||||
|
1
iseq.c
1
iseq.c
@ -2315,6 +2315,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
|
|||||||
VALUE flags = rb_ary_new();
|
VALUE flags = rb_ary_new();
|
||||||
# define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
|
# define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
|
||||||
CALL_FLAG(ARGS_SPLAT);
|
CALL_FLAG(ARGS_SPLAT);
|
||||||
|
CALL_FLAG(ARGS_SPLAT_MUT);
|
||||||
CALL_FLAG(ARGS_BLOCKARG);
|
CALL_FLAG(ARGS_BLOCKARG);
|
||||||
CALL_FLAG(FCALL);
|
CALL_FLAG(FCALL);
|
||||||
CALL_FLAG(VCALL);
|
CALL_FLAG(VCALL);
|
||||||
|
@ -510,7 +510,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
|
|||||||
args = &args_body;
|
args = &args_body;
|
||||||
given_argc = args->argc = calling->argc;
|
given_argc = args->argc = calling->argc;
|
||||||
args->argv = locals;
|
args->argv = locals;
|
||||||
args->rest_dupped = FALSE;
|
args->rest_dupped = vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT;
|
||||||
|
|
||||||
if (kw_flag & VM_CALL_KWARG) {
|
if (kw_flag & VM_CALL_KWARG) {
|
||||||
args->kw_arg = vm_ci_kwarg(ci);
|
args->kw_arg = vm_ci_kwarg(ci);
|
||||||
|
@ -25,6 +25,7 @@ enum vm_call_flag_bits {
|
|||||||
VM_CALL_ZSUPER_bit, // zsuper
|
VM_CALL_ZSUPER_bit, // zsuper
|
||||||
VM_CALL_OPT_SEND_bit, // internal flag
|
VM_CALL_OPT_SEND_bit, // internal flag
|
||||||
VM_CALL_KW_SPLAT_MUT_bit, // kw splat hash can be modified (to avoid allocating a new one)
|
VM_CALL_KW_SPLAT_MUT_bit, // kw splat hash can be modified (to avoid allocating a new one)
|
||||||
|
VM_CALL_ARGS_SPLAT_MUT_bit, // args splat can be modified (to avoid allocating a new one)
|
||||||
VM_CALL__END
|
VM_CALL__END
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ enum vm_call_flag_bits {
|
|||||||
#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit)
|
#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit)
|
||||||
#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit)
|
#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit)
|
||||||
#define VM_CALL_KW_SPLAT_MUT (0x01 << VM_CALL_KW_SPLAT_MUT_bit)
|
#define VM_CALL_KW_SPLAT_MUT (0x01 << VM_CALL_KW_SPLAT_MUT_bit)
|
||||||
|
#define VM_CALL_ARGS_SPLAT_MUT (0x01 << VM_CALL_ARGS_SPLAT_MUT_bit)
|
||||||
|
|
||||||
struct rb_callinfo_kwarg {
|
struct rb_callinfo_kwarg {
|
||||||
int keyword_len;
|
int keyword_len;
|
||||||
|
@ -632,7 +632,8 @@ pub const VM_CALL_SUPER_bit: vm_call_flag_bits = 8;
|
|||||||
pub const VM_CALL_ZSUPER_bit: vm_call_flag_bits = 9;
|
pub const VM_CALL_ZSUPER_bit: vm_call_flag_bits = 9;
|
||||||
pub const VM_CALL_OPT_SEND_bit: vm_call_flag_bits = 10;
|
pub const VM_CALL_OPT_SEND_bit: vm_call_flag_bits = 10;
|
||||||
pub const VM_CALL_KW_SPLAT_MUT_bit: vm_call_flag_bits = 11;
|
pub const VM_CALL_KW_SPLAT_MUT_bit: vm_call_flag_bits = 11;
|
||||||
pub const VM_CALL__END: vm_call_flag_bits = 12;
|
pub const VM_CALL_ARGS_SPLAT_MUT_bit: vm_call_flag_bits = 12;
|
||||||
|
pub const VM_CALL__END: vm_call_flag_bits = 13;
|
||||||
pub type vm_call_flag_bits = u32;
|
pub type vm_call_flag_bits = u32;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct rb_callinfo {
|
pub struct rb_callinfo {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user