* compile.c (NODE_CALL): add optimization shortcut for Array#max/min.
Now `[x, y].max` is optimized so that a temporal array object is not created in some condition. * insns.def (opt_newarray_max, opt_newarray_min): added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54153 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4ca0483a28
commit
3c7c983300
@ -1,3 +1,11 @@
|
|||||||
|
Thu Mar 17 21:45:02 2016 Yusuke Endoh <mame@ruby-lang.org>
|
||||||
|
|
||||||
|
* compile.c (NODE_CALL): add optimization shortcut for Array#max/min.
|
||||||
|
Now `[x, y].max` is optimized so that a temporal array object is not
|
||||||
|
created in some condition.
|
||||||
|
|
||||||
|
* insns.def (opt_newarray_max, opt_newarray_min): added.
|
||||||
|
|
||||||
Thu Mar 17 21:35:52 2016 Yusuke Endoh <mame@ruby-lang.org>
|
Thu Mar 17 21:35:52 2016 Yusuke Endoh <mame@ruby-lang.org>
|
||||||
|
|
||||||
* array.c (rb_ary_max, rb_ary_min): implement Array#max and min with
|
* array.c (rb_ary_max, rb_ary_min): implement Array#max and min with
|
||||||
|
20
compile.c
20
compile.c
@ -4916,6 +4916,26 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* optimization shortcut
|
||||||
|
* [a, b, ...].max/min -> a, b, c, opt_newarray_max/min
|
||||||
|
*/
|
||||||
|
if (node->nd_recv && nd_type(node->nd_recv) == NODE_ARRAY &&
|
||||||
|
(node->nd_mid == idMax || node->nd_mid == idMin) && node->nd_args == NULL &&
|
||||||
|
ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
|
||||||
|
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
|
||||||
|
COMPILE(ret, "recv", node->nd_recv);
|
||||||
|
if (((INSN*)ret->last)->insn_id == BIN(newarray)) {
|
||||||
|
((INSN*)ret->last)->insn_id =
|
||||||
|
node->nd_mid == idMax ? BIN(opt_newarray_max) : BIN(opt_newarray_min);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADD_SEND(ret, line, node->nd_mid, INT2FIX(0));
|
||||||
|
}
|
||||||
|
if (poped) {
|
||||||
|
ADD_INSN(ret, line, pop);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NODE_QCALL:
|
case NODE_QCALL:
|
||||||
case NODE_FCALL:
|
case NODE_FCALL:
|
||||||
case NODE_VCALL:{ /* VCALL: variable or call */
|
case NODE_VCALL:{ /* VCALL: variable or call */
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# -*- mode: ruby; coding: us-ascii -*-
|
# -*- mode: ruby; coding: us-ascii -*-
|
||||||
firstline, predefined = __LINE__+1, %[\
|
firstline, predefined = __LINE__+1, %[\
|
||||||
|
max
|
||||||
|
min
|
||||||
freeze
|
freeze
|
||||||
inspect
|
inspect
|
||||||
intern
|
intern
|
||||||
|
68
insns.def
68
insns.def
@ -986,6 +986,74 @@ opt_str_freeze
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_INSN
|
||||||
|
opt_newarray_max
|
||||||
|
(rb_num_t num)
|
||||||
|
(...)
|
||||||
|
(VALUE val) // inc += 1 - num;
|
||||||
|
{
|
||||||
|
#define id_cmp idCmp
|
||||||
|
if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
|
||||||
|
if (num == 0) {
|
||||||
|
val = Qnil;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct cmp_opt_data cmp_opt = { 0, 0 };
|
||||||
|
VALUE result = Qundef;
|
||||||
|
rb_num_t i = num - 1;
|
||||||
|
result = TOPN(i);
|
||||||
|
while (i-- > 0) {
|
||||||
|
const VALUE v = TOPN(i);
|
||||||
|
if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) {
|
||||||
|
result = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = result == Qundef ? Qnil : result;
|
||||||
|
}
|
||||||
|
POPN(num);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VALUE ary = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
|
||||||
|
val = rb_funcall(ary, idMax, 0);
|
||||||
|
POPN(num);
|
||||||
|
}
|
||||||
|
#undef id_cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_INSN
|
||||||
|
opt_newarray_min
|
||||||
|
(rb_num_t num)
|
||||||
|
(...)
|
||||||
|
(VALUE val) // inc += 1 - num;
|
||||||
|
{
|
||||||
|
#define id_cmp idCmp
|
||||||
|
if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
|
||||||
|
if (num == 0) {
|
||||||
|
val = Qnil;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct cmp_opt_data cmp_opt = { 0, 0 };
|
||||||
|
VALUE result = Qundef;
|
||||||
|
rb_num_t i = num - 1;
|
||||||
|
result = TOPN(i);
|
||||||
|
while (i-- > 0) {
|
||||||
|
const VALUE v = TOPN(i);
|
||||||
|
if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) {
|
||||||
|
result = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = result == Qundef ? Qnil : result;
|
||||||
|
}
|
||||||
|
POPN(num);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VALUE ary = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
|
||||||
|
val = rb_funcall(ary, idMin, 0);
|
||||||
|
POPN(num);
|
||||||
|
}
|
||||||
|
#undef id_cmp
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@c optimize
|
@c optimize
|
||||||
@e Invoke method without block
|
@e Invoke method without block
|
||||||
|
2
vm.c
2
vm.c
@ -1475,6 +1475,8 @@ vm_init_redefined_flag(void)
|
|||||||
OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
|
OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
|
||||||
OP(EqTilde, MATCH), (C(Regexp), C(String));
|
OP(EqTilde, MATCH), (C(Regexp), C(String));
|
||||||
OP(Freeze, FREEZE), (C(String));
|
OP(Freeze, FREEZE), (C(String));
|
||||||
|
OP(Max, MAX), (C(Array));
|
||||||
|
OP(Min, MIN), (C(Array));
|
||||||
#undef C
|
#undef C
|
||||||
#undef OP
|
#undef OP
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user