Commit 1816e05d authored by kasperl@chromium.org's avatar kasperl@chromium.org

Prepare for optionally inlining smi cases in the code generated

by the full codegens.
Review URL: http://codereview.chromium.org/3116042

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5343 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6bd9d953
......@@ -665,19 +665,20 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Compile the label expression.
VisitForValue(clause->label(), kAccumulator);
// Perform the comparison as if via '==='. The comparison stub expects
// the smi vs. smi case to be handled before it is called.
Label slow_case;
// Perform the comparison as if via '==='.
__ ldr(r1, MemOperand(sp, 0)); // Switch value.
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &slow_case);
__ cmp(r1, r0);
__ b(ne, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ b(clause->body_target()->entry_label());
if (ShouldInlineSmiCase(Token::EQ_STRICT)) {
Label slow_case;
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &slow_case);
__ cmp(r1, r0);
__ b(ne, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ b(clause->body_target()->entry_label());
__ bind(&slow_case);
}
CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
__ CallStub(&stub);
__ cmp(r0, Operand(0));
......@@ -2672,26 +2673,26 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register r0.
// The generic unary operation stub expects the argument to be
// in the accumulator register r0.
VisitForValue(expr->expression(), kAccumulator);
// Avoid calling the stub for Smis.
Label smi, done;
__ BranchOnSmi(result_register(), &smi);
// Non-smi: call stub leaving result in accumulator register.
Label done;
if (ShouldInlineSmiCase(expr->op())) {
Label call_stub;
__ BranchOnNotSmi(r0, &call_stub);
__ mvn(r0, Operand(r0));
// Bit-clear inverted smi-tag.
__ bic(r0, r0, Operand(kSmiTagMask));
__ b(&done);
__ bind(&call_stub);
}
bool overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, mode);
__ CallStub(&stub);
__ b(&done);
// Perform operation directly on Smis.
__ bind(&smi);
__ mvn(result_register(), Operand(result_register()));
// Bit-clear inverted smi-tag.
__ bic(result_register(), result_register(), Operand(kSmiTagMask));
__ bind(&done);
Apply(context_, result_register());
Apply(context_, r0);
break;
}
......@@ -3055,16 +3056,15 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE();
}
// The comparison stub expects the smi vs. smi case to be handled
// before it is called.
Label slow_case;
__ orr(r2, r0, Operand(r1));
__ BranchOnNotSmi(r2, &slow_case);
__ cmp(r1, r0);
__ b(cc, if_true);
__ jmp(if_false);
if (ShouldInlineSmiCase(op)) {
Label slow_case;
__ orr(r2, r0, Operand(r1));
__ BranchOnNotSmi(r2, &slow_case);
__ cmp(r1, r0);
Split(cc, if_true, if_false, NULL);
__ bind(&slow_case);
}
__ bind(&slow_case);
CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
__ CallStub(&stub);
__ cmp(r0, Operand(0));
......
......@@ -318,9 +318,15 @@ int FullCodeGenerator::SlotOffset(Slot* slot) {
bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
if (Debugger::IsDebuggerActive()) return false;
if (op == Token::DIV ||op == Token::MOD) return false;
return loop_depth_ > 0;
// TODO(kasperl): Once the compare stub allows leaving out the
// inlined smi case, we should get rid of this check.
if (Token::IsCompareOp(op)) return true;
// TODO(kasperl): Once the unary bit not stub allows leaving out
// the inlined smi case, we should get rid of this check.
if (op == Token::BIT_NOT) return true;
// Inline smi case inside loops, but not division and modulo which
// are too complicated and take up too much space.
return (op != Token::DIV) && (op != Token::MOD) && (loop_depth_ > 0);
}
......
......@@ -668,20 +668,21 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Compile the label expression.
VisitForValue(clause->label(), kAccumulator);
// Perform the comparison as if via '==='. The comparison stub expects
// the smi vs. smi case to be handled before it is called.
Label slow_case;
// Perform the comparison as if via '==='.
__ mov(edx, Operand(esp, 0)); // Switch value.
__ mov(ecx, edx);
__ or_(ecx, Operand(eax));
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &slow_case, not_taken);
__ cmp(edx, Operand(eax));
__ j(not_equal, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ jmp(clause->body_target()->entry_label());
if (ShouldInlineSmiCase(Token::EQ_STRICT)) {
Label slow_case;
__ mov(ecx, edx);
__ or_(ecx, Operand(eax));
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &slow_case, not_taken);
__ cmp(edx, Operand(eax));
__ j(not_equal, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ jmp(clause->body_target()->entry_label());
__ bind(&slow_case);
}
__ bind(&slow_case);
CompareStub stub(equal, true);
__ CallStub(&stub);
__ test(eax, Operand(eax));
......@@ -2672,26 +2673,26 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register eax.
// The generic unary operation stub expects the argument to be
// in the accumulator register eax.
VisitForValue(expr->expression(), kAccumulator);
// Avoid calling the stub for Smis.
Label smi, done;
__ test(result_register(), Immediate(kSmiTagMask));
__ j(zero, &smi);
// Non-smi: call stub leaving result in accumulator register.
Label done;
if (ShouldInlineSmiCase(expr->op())) {
Label call_stub;
__ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &call_stub);
__ lea(eax, Operand(eax, kSmiTagMask));
__ not_(eax);
__ jmp(&done);
__ bind(&call_stub);
}
bool overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, mode);
__ CallStub(&stub);
__ jmp(&done);
// Perform operation directly on Smis.
__ bind(&smi);
__ not_(result_register());
__ and_(result_register(), ~kSmiTagMask); // Remove inverted smi-tag.
__ bind(&done);
Apply(context_, result_register());
Apply(context_, eax);
break;
}
......@@ -3066,18 +3067,17 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE();
}
// The comparison stub expects the smi vs. smi case to be
// handled before it is called.
Label slow_case;
__ mov(ecx, Operand(edx));
__ or_(ecx, Operand(eax));
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &slow_case, not_taken);
__ cmp(edx, Operand(eax));
__ j(cc, if_true);
__ jmp(if_false);
if (ShouldInlineSmiCase(op)) {
Label slow_case;
__ mov(ecx, Operand(edx));
__ or_(ecx, Operand(eax));
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &slow_case, not_taken);
__ cmp(edx, Operand(eax));
Split(cc, if_true, if_false, NULL);
__ bind(&slow_case);
}
__ bind(&slow_case);
CompareStub stub(cc, strict);
__ CallStub(&stub);
__ test(eax, Operand(eax));
......
......@@ -672,17 +672,18 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Compile the label expression.
VisitForValue(clause->label(), kAccumulator);
// Perform the comparison as if via '==='. The comparison stub expects
// the smi vs. smi case to be handled before it is called.
Label slow_case;
__ movq(rdx, Operand(rsp, 0)); // Switch value.
__ JumpIfNotBothSmi(rdx, rax, &slow_case);
__ SmiCompare(rdx, rax);
__ j(not_equal, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ jmp(clause->body_target()->entry_label());
// Perform the comparison as if via '==='.
if (ShouldInlineSmiCase(Token::EQ_STRICT)) {
Label slow_case;
__ movq(rdx, Operand(rsp, 0)); // Switch value.
__ JumpIfNotBothSmi(rdx, rax, &slow_case);
__ SmiCompare(rdx, rax);
__ j(not_equal, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ jmp(clause->body_target()->entry_label());
__ bind(&slow_case);
}
__ bind(&slow_case);
CompareStub stub(equal, true);
__ CallStub(&stub);
__ testq(rax, rax);
......@@ -2667,25 +2668,24 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register rax.
// The generic unary operation stub expects the argument to be
// in the accumulator register rax.
VisitForValue(expr->expression(), kAccumulator);
// Avoid calling the stub for Smis.
Label smi, done;
Condition is_smi = masm_->CheckSmi(result_register());
__ j(is_smi, &smi);
// Non-smi: call stub leaving result in accumulator register.
Label done;
if (ShouldInlineSmiCase(expr->op())) {
Label call_stub;
__ JumpIfNotSmi(rax, &call_stub);
__ SmiNot(rax, rax);
__ jmp(&done);
__ bind(&call_stub);
}
bool overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, mode);
__ CallStub(&stub);
__ jmp(&done);
// Perform operation directly on Smis.
__ bind(&smi);
__ SmiNot(result_register(), result_register());
__ bind(&done);
Apply(context_, result_register());
Apply(context_, rax);
break;
}
......@@ -3054,15 +3054,14 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE();
}
// The comparison stub expects the smi vs. smi case to be handled
// before it is called.
Label slow_case;
__ JumpIfNotBothSmi(rax, rdx, &slow_case);
__ SmiCompare(rdx, rax);
__ j(cc, if_true);
__ jmp(if_false);
if (ShouldInlineSmiCase(op)) {
Label slow_case;
__ JumpIfNotBothSmi(rax, rdx, &slow_case);
__ SmiCompare(rdx, rax);
Split(cc, if_true, if_false, NULL);
__ bind(&slow_case);
}
__ bind(&slow_case);
CompareStub stub(cc, strict);
__ CallStub(&stub);
__ testq(rax, rax);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment