Skip nil? method call in if conditionals.

Compile `if expr.nil?` to use `OP_JMPNIL` instead of calls.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2019-08-30 15:51:18 +09:00
parent 49896abe2b
commit 49967097ed
+32 -15
View File
@@ -1558,7 +1558,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_IF: case NODE_IF:
{ {
int pos1, pos2; int pos1, pos2, nil_p = FALSE;
node *elsepart = tree->cdr->cdr->car; node *elsepart = tree->cdr->cdr->car;
if (!tree->car) { if (!tree->car) {
@@ -1575,38 +1575,55 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NIL: case NODE_NIL:
codegen(s, elsepart, val); codegen(s, elsepart, val);
goto exit; goto exit;
case NODE_CALL:
{
node *n = tree->car->cdr;
mrb_sym mid = nsym(n->cdr->car);
mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
if (mid == mnil && n->cdr->cdr->car == NULL) {
nil_p = TRUE;
codegen(s, n->car, VAL);
}
}
break;
}
if (!nil_p) {
codegen(s, tree->car, VAL);
} }
codegen(s, tree->car, VAL);
pop(); pop();
if (val || tree->cdr->car) { if (val || tree->cdr->car) {
pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val); if (nil_p) {
pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
pos1 = genjmp(s, OP_JMP, 0);
dispatch(s, pos2);
}
else {
pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
}
codegen(s, tree->cdr->car, val); codegen(s, tree->cdr->car, val);
if (elsepart) { if (val) pop();
if (val) pop(); if (elsepart || val) {
pos2 = genjmp(s, OP_JMP, 0); pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1); dispatch(s, pos1);
codegen(s, elsepart, val); codegen(s, elsepart, val);
dispatch(s, pos2); dispatch(s, pos2);
} }
else if (val) {
pop();
pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
genop_1(s, OP_LOADNIL, cursp());
dispatch(s, pos2);
push();
}
else { else {
dispatch(s, pos1); dispatch(s, pos1);
} }
} }
else { /* empty then-part */ else { /* empty then-part */
if (elsepart) { if (elsepart) {
pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val); if (nil_p) {
pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
}
else {
pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
}
codegen(s, elsepart, val); codegen(s, elsepart, val);
dispatch(s, pos1); dispatch(s, pos1);
} }
else if (val) { else if (val && !nil_p) {
genop_1(s, OP_LOADNIL, cursp()); genop_1(s, OP_LOADNIL, cursp());
push(); push();
} }