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
This commit is contained in:
parent
c7445d9284
commit
4d3a5968a5
@ -1376,7 +1376,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
if (assign_type == VARIABLE) {
|
if (assign_type == VARIABLE) {
|
||||||
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
|
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
|
||||||
Location saved_location = location_;
|
Location saved_location = location_;
|
||||||
location_ = kStack;
|
location_ = kAccumulator;
|
||||||
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
||||||
Expression::kValue);
|
Expression::kValue);
|
||||||
location_ = saved_location;
|
location_ = saved_location;
|
||||||
@ -1393,11 +1393,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
VisitForValue(prop->key(), kStack);
|
VisitForValue(prop->key(), kStack);
|
||||||
EmitKeyedPropertyLoad(prop);
|
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);
|
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
|
||||||
|
__ bind(&no_conversion);
|
||||||
|
|
||||||
// Save result for postfix expressions.
|
// Save result for postfix expressions.
|
||||||
if (expr->is_postfix()) {
|
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
|
__ mov(r1, Operand(expr->op() == Token::INC
|
||||||
? Smi::FromInt(1)
|
? Smi::FromInt(1)
|
||||||
: Smi::FromInt(-1)));
|
: Smi::FromInt(-1)));
|
||||||
GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE);
|
GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
|
__ bind(&done);
|
||||||
|
|
||||||
// Store the value returned in r0.
|
// Store the value returned in r0.
|
||||||
switch (assign_type) {
|
switch (assign_type) {
|
||||||
|
@ -1482,7 +1482,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
if (assign_type == VARIABLE) {
|
if (assign_type == VARIABLE) {
|
||||||
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
|
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
|
||||||
Location saved_location = location_;
|
Location saved_location = location_;
|
||||||
location_ = kStack;
|
location_ = kAccumulator;
|
||||||
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
||||||
Expression::kValue);
|
Expression::kValue);
|
||||||
location_ = saved_location;
|
location_ = saved_location;
|
||||||
@ -1498,11 +1498,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
VisitForValue(prop->key(), kStack);
|
VisitForValue(prop->key(), kStack);
|
||||||
EmitKeyedPropertyLoad(prop);
|
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);
|
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
|
||||||
|
__ bind(&no_conversion);
|
||||||
|
|
||||||
// Save result for postfix expressions.
|
// Save result for postfix expressions.
|
||||||
if (expr->is_postfix()) {
|
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.
|
// Call stub for +1/-1.
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
__ push(Immediate(Smi::FromInt(1)));
|
__ push(Immediate(Smi::FromInt(1)));
|
||||||
@ -1541,6 +1566,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
NO_OVERWRITE,
|
NO_OVERWRITE,
|
||||||
NO_GENERIC_BINARY_FLAGS);
|
NO_GENERIC_BINARY_FLAGS);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
|
__ bind(&done);
|
||||||
|
|
||||||
// Store the value returned in eax.
|
// Store the value returned in eax.
|
||||||
switch (assign_type) {
|
switch (assign_type) {
|
||||||
|
@ -1489,7 +1489,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
if (assign_type == VARIABLE) {
|
if (assign_type == VARIABLE) {
|
||||||
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
|
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
|
||||||
Location saved_location = location_;
|
Location saved_location = location_;
|
||||||
location_ = kStack;
|
location_ = kAccumulator;
|
||||||
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
|
||||||
Expression::kValue);
|
Expression::kValue);
|
||||||
location_ = saved_location;
|
location_ = saved_location;
|
||||||
@ -1505,11 +1505,16 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
VisitForValue(prop->key(), kStack);
|
VisitForValue(prop->key(), kStack);
|
||||||
EmitKeyedPropertyLoad(prop);
|
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);
|
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
|
||||||
|
__ bind(&no_conversion);
|
||||||
|
|
||||||
// Save result for postfix expressions.
|
// Save result for postfix expressions.
|
||||||
if (expr->is_postfix()) {
|
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.
|
// Call stub for +1/-1.
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
__ Push(Smi::FromInt(1));
|
__ Push(Smi::FromInt(1));
|
||||||
@ -1548,6 +1574,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
NO_OVERWRITE,
|
NO_OVERWRITE,
|
||||||
NO_GENERIC_BINARY_FLAGS);
|
NO_GENERIC_BINARY_FLAGS);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
|
__ bind(&done);
|
||||||
|
|
||||||
// Store the value returned in rax.
|
// Store the value returned in rax.
|
||||||
switch (assign_type) {
|
switch (assign_type) {
|
||||||
|
Loading…
Reference in New Issue
Block a user