mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
6 changed files with 102 additions and 0 deletions
|
@ -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>
|
||||
|
||||
* 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;
|
||||
}
|
||||
/* 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_FCALL:
|
||||
case NODE_VCALL:{ /* VCALL: variable or call */
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# -*- mode: ruby; coding: us-ascii -*-
|
||||
firstline, predefined = __LINE__+1, %[\
|
||||
max
|
||||
min
|
||||
freeze
|
||||
inspect
|
||||
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
|
||||
@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(EqTilde, MATCH), (C(Regexp), C(String));
|
||||
OP(Freeze, FREEZE), (C(String));
|
||||
OP(Max, MAX), (C(Array));
|
||||
OP(Min, MIN), (C(Array));
|
||||
#undef C
|
||||
#undef OP
|
||||
}
|
||||
|
|
|
@ -453,6 +453,8 @@ enum ruby_basic_operators {
|
|||
BOP_NEQ,
|
||||
BOP_MATCH,
|
||||
BOP_FREEZE,
|
||||
BOP_MAX,
|
||||
BOP_MIN,
|
||||
|
||||
BOP_LAST_
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue