Feature #18897 ยป 0001-Emit-special-instruction-for-array-literal-.-hash-mi.patch
array.c | ||
---|---|---|
return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
|
||
}
|
||
VALUE
|
||
rb_ary_hash_values(long len, const VALUE *elements)
|
||
{
|
||
long i;
|
||
st_index_t h;
|
||
VALUE n;
|
||
h = rb_hash_start(len);
|
||
h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
|
||
for (i=0; i<len; i++) {
|
||
n = rb_hash(elements[i]);
|
||
h = rb_hash_uint(h, NUM2LONG(n));
|
||
}
|
||
h = rb_hash_end(h);
|
||
return ST2FIX(h);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* array.hash -> integer
|
||
... | ... | |
static VALUE
|
||
rb_ary_hash(VALUE ary)
|
||
{
|
||
long i;
|
||
st_index_t h;
|
||
VALUE n;
|
||
h = rb_hash_start(RARRAY_LEN(ary));
|
||
h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
|
||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||
n = rb_hash(RARRAY_AREF(ary, i));
|
||
h = rb_hash_uint(h, NUM2LONG(n));
|
||
}
|
||
h = rb_hash_end(h);
|
||
return ST2FIX(h);
|
||
return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
|
||
}
|
||
/*
|
bootstraptest/test_insns.rb | ||
---|---|---|
'true'.freeze
|
||
},
|
||
[ 'opt_newarray_max', %q{ [ ].max.nil? }, ],
|
||
[ 'opt_newarray_max', %q{ [1, x = 2, 3].max == 3 }, ],
|
||
[ 'opt_newarray_max', <<-'},', ], # {
|
||
[ 'opt_newarray_send', %q{ [ ].hash.nil? }, ],
|
||
[ 'opt_newarray_send', %q{ [ ].max.nil? }, ],
|
||
[ 'opt_newarray_send', %q{ [1, x = 2, 3].max == 3 }, ],
|
||
[ 'opt_newarray_send', <<-'},', ], # {
|
||
class Array
|
||
def max
|
||
true
|
||
... | ... | |
end
|
||
[1, x = 2, 3].max
|
||
},
|
||
[ 'opt_newarray_min', %q{ [ ].min.nil? }, ],
|
||
[ 'opt_newarray_min', %q{ [3, x = 2, 1].min == 1 }, ],
|
||
[ 'opt_newarray_min', <<-'},', ], # {
|
||
[ 'opt_newarray_send', %q{ [ ].min.nil? }, ],
|
||
[ 'opt_newarray_send', %q{ [3, x = 2, 1].min == 1 }, ],
|
||
[ 'opt_newarray_send', <<-'},', ], # {
|
||
class Array
|
||
def min
|
||
true
|
compile.c | ||
---|---|---|
if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
|
||
switch (vm_ci_mid(ci)) {
|
||
case idMax:
|
||
iobj->insn_id = BIN(opt_newarray_max);
|
||
ELEM_REMOVE(&niobj->link);
|
||
return COMPILE_OK;
|
||
case idMin:
|
||
iobj->insn_id = BIN(opt_newarray_min);
|
||
ELEM_REMOVE(&niobj->link);
|
||
return COMPILE_OK;
|
||
case idHash:
|
||
{
|
||
rb_num_t num = (rb_num_t)iobj->operands[0];
|
||
iobj->insn_id = BIN(opt_newarray_send);
|
||
iobj->operands = compile_data_calloc2(iseq, insn_len(iobj->insn_id) - 1, sizeof(VALUE));
|
||
iobj->operands[0] = (VALUE)num;
|
||
iobj->operands[1] = (VALUE)rb_id2sym(vm_ci_mid(ci));
|
||
iobj->operand_size = insn_len(iobj->insn_id) - 1;
|
||
ELEM_REMOVE(&niobj->link);
|
||
return COMPILE_OK;
|
||
}
|
||
}
|
||
}
|
||
}
|
defs/id.def | ||
---|---|---|
firstline, predefined = __LINE__+1, %[\
|
||
max
|
||
min
|
||
hash
|
||
freeze
|
||
nil?
|
||
inspect
|
insns.def | ||
---|---|---|
}
|
||
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
|
||
... | ... | |
* 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;
|
||
// attr rb_snum_t comptime_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));
|
||
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 */
|
internal/array.h | ||
---|---|---|
#define RARRAY_PTR_IN_USE_FLAG FL_USER14
|
||
/* array.c */
|
||
VALUE rb_ary_hash_values(long len, const VALUE *elements);
|
||
VALUE rb_ary_last(int, const VALUE *, VALUE);
|
||
void rb_ary_set_len(VALUE, long);
|
||
void rb_ary_delete_same(VALUE, VALUE);
|
vm.c | ||
---|---|---|
OP(UMinus, UMINUS), (C(String));
|
||
OP(Max, MAX), (C(Array));
|
||
OP(Min, MIN), (C(Array));
|
||
OP(Hash, HASH), (C(Array));
|
||
OP(Call, CALL), (C(Proc));
|
||
OP(And, AND), (C(Integer));
|
||
OP(Or, OR), (C(Integer));
|
vm_core.h | ||
---|---|---|
BOP_UMINUS,
|
||
BOP_MAX,
|
||
BOP_MIN,
|
||
BOP_HASH,
|
||
BOP_CALL,
|
||
BOP_AND,
|
||
BOP_OR,
|
vm_insnhelper.c | ||
---|---|---|
}
|
||
}
|
||
static VALUE
|
||
vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr)
|
||
{
|
||
// If Array#hash is _not_ monkeypatched, use the optimized call
|
||
if (BASIC_OP_UNREDEFINED_P(BOP_HASH, ARRAY_REDEFINED_OP_FLAG)) {
|
||
return rb_ary_hash_values(num, ptr);
|
||
}
|
||
else {
|
||
return rb_vm_call_with_refinements(ec, rb_ary_new4(num, ptr), idHash, 0, NULL, RB_NO_KEYWORDS);
|
||
}
|
||
}
|
||
#undef id_cmp
|
||
#define IMEMO_CONST_CACHE_SHAREABLE IMEMO_FL_USER0
|