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
This commit is contained in:
parent
6bd9d953dd
commit
1816e05dc2
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user