From: fschneider@chromium.org Date: Fri, 22 Jan 2010 14:07:25 +0000 (+0000) Subject: Inline smi code in count operations in the full code generator. X-Git-Tag: upstream/4.7.83~22626 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4d3a5968a575be8b611d39215f38d31c3da55aed;p=platform%2Fupstream%2Fv8.git Inline smi code in count operations in the full code generator. We now test for a smi before calling ToNumber and inline the smi increment/decrement for ++ and --. There only a small increase in code size but loops in top-level code are becoming much faster as a result. Review URL: http://codereview.chromium.org/553056 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3681 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 40851d8..b871e5f 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1376,7 +1376,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (assign_type == VARIABLE) { ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); Location saved_location = location_; - location_ = kStack; + location_ = kAccumulator; EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), Expression::kValue); location_ = saved_location; @@ -1393,11 +1393,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VisitForValue(prop->key(), kStack); EmitKeyedPropertyLoad(prop); } - __ push(r0); } - // Convert to number. + // Call ToNumber only if operand is not a smi. + Label no_conversion; + __ tst(r0, Operand(kSmiTagMask)); + __ b(eq, &no_conversion); + __ push(r0); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); + __ bind(&no_conversion); // Save result for postfix expressions. if (expr->is_postfix()) { @@ -1429,12 +1433,28 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } - // Call stub for +1/-1. + + // Inline smi case if we are in a loop. + Label stub_call, done; + if (loop_depth() > 0) { + __ add(r0, r0, Operand(expr->op() == Token::INC + ? Smi::FromInt(1) + : Smi::FromInt(-1))); + __ b(vs, &stub_call); + // We could eliminate this smi check if we split the code at + // the first smi check before calling ToNumber. + __ tst(r0, Operand(kSmiTagMask)); + __ b(eq, &done); + __ bind(&stub_call); + // Call stub. Undo operation first. + __ sub(r0, r0, Operand(r1)); + } __ mov(r1, Operand(expr->op() == Token::INC ? Smi::FromInt(1) : Smi::FromInt(-1))); GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE); __ CallStub(&stub); + __ bind(&done); // Store the value returned in r0. switch (assign_type) { diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index de42e1a..78a5908 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1482,7 +1482,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (assign_type == VARIABLE) { ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); Location saved_location = location_; - location_ = kStack; + location_ = kAccumulator; EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), Expression::kValue); location_ = saved_location; @@ -1498,11 +1498,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VisitForValue(prop->key(), kStack); EmitKeyedPropertyLoad(prop); } - __ push(eax); } - // Convert to number. + // Call ToNumber only if operand is not a smi. + Label no_conversion; + __ test(eax, Immediate(kSmiTagMask)); + __ j(zero, &no_conversion); + __ push(eax); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); + __ bind(&no_conversion); // Save result for postfix expressions. if (expr->is_postfix()) { @@ -1534,6 +1538,27 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } + // Inline smi case if we are in a loop. + Label stub_call, done; + if (loop_depth() > 0) { + if (expr->op() == Token::INC) { + __ add(Operand(eax), Immediate(Smi::FromInt(1))); + } else { + __ sub(Operand(eax), Immediate(Smi::FromInt(1))); + } + __ j(overflow, &stub_call); + // We could eliminate this smi check if we split the code at + // the first smi check before calling ToNumber. + __ test(eax, Immediate(kSmiTagMask)); + __ j(zero, &done); + __ bind(&stub_call); + // Call stub. Undo operation first. + if (expr->op() == Token::INC) { + __ sub(Operand(eax), Immediate(Smi::FromInt(1))); + } else { + __ add(Operand(eax), Immediate(Smi::FromInt(1))); + } + } // Call stub for +1/-1. __ push(eax); __ push(Immediate(Smi::FromInt(1))); @@ -1541,6 +1566,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); __ CallStub(&stub); + __ bind(&done); // Store the value returned in eax. switch (assign_type) { diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 860b1e4..49f29ce 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -1489,7 +1489,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (assign_type == VARIABLE) { ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); Location saved_location = location_; - location_ = kStack; + location_ = kAccumulator; EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), Expression::kValue); location_ = saved_location; @@ -1505,11 +1505,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VisitForValue(prop->key(), kStack); EmitKeyedPropertyLoad(prop); } - __ push(rax); } - // Convert to number. + // Call ToNumber only if operand is not a smi. + Label no_conversion; + Condition is_smi; + is_smi = masm_->CheckSmi(rax); + __ j(is_smi, &no_conversion); + __ push(rax); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); + __ bind(&no_conversion); // Save result for postfix expressions. if (expr->is_postfix()) { @@ -1541,6 +1546,27 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } + // Inline smi case if we are in a loop. + Label stub_call, done; + if (loop_depth() > 0) { + if (expr->op() == Token::INC) { + __ SmiAddConstant(rax, rax, Smi::FromInt(1)); + } else { + __ SmiSubConstant(rax, rax, Smi::FromInt(1)); + } + __ j(overflow, &stub_call); + // We could eliminate this smi check if we split the code at + // the first smi check before calling ToNumber. + is_smi = masm_->CheckSmi(rax); + __ j(is_smi, &done); + __ bind(&stub_call); + // Call stub. Undo operation first. + if (expr->op() == Token::INC) { + __ SmiSubConstant(rax, rax, Smi::FromInt(1)); + } else { + __ SmiAddConstant(rax, rax, Smi::FromInt(1)); + } + } // Call stub for +1/-1. __ push(rax); __ Push(Smi::FromInt(1)); @@ -1548,6 +1574,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS); __ CallStub(&stub); + __ bind(&done); // Store the value returned in rax. switch (assign_type) {