Refactor GenericBinaryOperation and its helper functions to always return a Result.

This is a preparation step for including number type information
in the virtual frame. We need a common place where we can update
the number type information of the result of a binary operation
since we should not modify the state of the virtual frame elements
directly.

Review URL: http://codereview.chromium.org/551080

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3661 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2010-01-20 16:13:53 +00:00
parent 6ad58b53f4
commit c757fa4604
4 changed files with 158 additions and 209 deletions

View File

@ -913,31 +913,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
return;
}
// Set the flags based on the operation, type and loop nesting level.
GenericBinaryFlags flags;
switch (op) {
case Token::BIT_OR:
case Token::BIT_AND:
case Token::BIT_XOR:
case Token::SHL:
case Token::SHR:
case Token::SAR:
// Bit operations always assume they likely operate on Smis. Still only
// generate the inline Smi check code if this operation is part of a loop.
flags = (loop_nesting() > 0)
? NO_SMI_CODE_IN_STUB
: NO_GENERIC_BINARY_FLAGS;
break;
default:
// By default only inline the Smi check code for likely smis if this
// operation is part of a loop.
flags = ((loop_nesting() > 0) && type->IsLikelySmi())
? NO_SMI_CODE_IN_STUB
: NO_GENERIC_BINARY_FLAGS;
break;
}
Result right = frame_->Pop();
Result left = frame_->Pop();
@ -971,7 +946,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi();
bool right_is_smi = right.is_constant() && right.handle()->IsSmi();
bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi();
bool generate_no_smi_code = false; // No smi code at all, inline or in stub.
if (left_is_smi && right_is_smi) {
// Compute the constant result at compile time, and leave it on the frame.
@ -980,33 +954,35 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
if (FoldConstantSmis(op, left_int, right_int)) return;
}
Result answer;
if (left_is_non_smi || right_is_non_smi) {
// Set flag so that we go straight to the slow case, with no smi code.
generate_no_smi_code = true;
} else if (right_is_smi) {
ConstantSmiBinaryOperation(op, &left, right.handle(),
type, false, overwrite_mode);
return;
} else if (left_is_smi) {
ConstantSmiBinaryOperation(op, &right, left.handle(),
type, true, overwrite_mode);
return;
}
if (((flags & NO_SMI_CODE_IN_STUB) != 0) && !generate_no_smi_code) {
LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
} else {
// Go straight to the slow case, with no smi code.
frame_->Push(&left);
frame_->Push(&right);
// If we know the arguments aren't smis, use the binary operation stub
// that does not check for the fast smi case.
if (generate_no_smi_code) {
flags = NO_SMI_CODE_IN_STUB;
GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB);
answer = frame_->CallStub(&stub, 2);
} else if (right_is_smi) {
answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
type, false, overwrite_mode);
} else if (left_is_smi) {
answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
type, true, overwrite_mode);
} else {
// Set the flags based on the operation, type and loop nesting level.
// Bit operations always assume they likely operate on Smis. Still only
// generate the inline Smi check code if this operation is part of a loop.
// For all other operations only inline the Smi check code for likely smis
// if the operation is part of a loop.
if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
} else {
frame_->Push(&left);
frame_->Push(&right);
GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS);
answer = frame_->CallStub(&stub, 2);
}
GenericBinaryOpStub stub(op, overwrite_mode, flags);
Result answer = frame_->CallStub(&stub, 2);
frame_->Push(&answer);
}
frame_->Push(&answer);
}
@ -1093,10 +1069,11 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
// Implements a binary operation using a deferred code object and some
// inline code to operate on smis quickly.
void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode) {
Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode) {
Result answer;
// Special handling of div and mod because they use fixed registers.
if (op == Token::DIV || op == Token::MOD) {
// We need eax as the quotient register, edx as the remainder
@ -1218,7 +1195,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&quotient);
answer = quotient;
} else {
ASSERT(op == Token::MOD);
// Check for a negative zero result. If the result is zero, and
@ -1234,9 +1211,10 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&remainder);
answer = remainder;
}
return;
ASSERT(answer.is_valid());
return answer;
}
// Special handling of shift operations because they use fixed
@ -1257,7 +1235,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
frame_->Spill(ecx);
// Use a fresh answer register to avoid spilling the left operand.
Result answer = allocator_->Allocate();
answer = allocator_->Allocate();
ASSERT(answer.is_valid());
// Check that both operands are smis using the answer register as a
// temporary.
@ -1321,8 +1299,8 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&answer);
return;
ASSERT(answer.is_valid());
return answer;
}
// Handle the other binary operations.
@ -1331,7 +1309,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
// A newly allocated register answer is used to hold the answer. The
// registers containing left and right are not modified so they don't
// need to be spilled in the fast case.
Result answer = allocator_->Allocate();
answer = allocator_->Allocate();
ASSERT(answer.is_valid());
// Perform the smi tag check.
@ -1406,7 +1384,8 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&answer);
ASSERT(answer.is_valid());
return answer;
}
@ -1575,36 +1554,34 @@ void DeferredInlineSmiSub::Generate() {
}
void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> value,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode) {
Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> value,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode) {
// NOTE: This is an attempt to inline (a bit) more of the code for
// some possible smi operations (like + and -) when (at least) one
// of the operands is a constant smi.
// Consumes the argument "operand".
// TODO(199): Optimize some special cases of operations involving a
// smi literal (multiply by 2, shift by 0, etc.).
if (IsUnsafeSmi(value)) {
Result unsafe_operand(value);
if (reversed) {
LikelySmiBinaryOperation(op, &unsafe_operand, operand,
overwrite_mode);
return LikelySmiBinaryOperation(op, &unsafe_operand, operand,
overwrite_mode);
} else {
LikelySmiBinaryOperation(op, operand, &unsafe_operand,
overwrite_mode);
return LikelySmiBinaryOperation(op, operand, &unsafe_operand,
overwrite_mode);
}
ASSERT(!operand->is_valid());
return;
}
// Get the literal value.
Smi* smi_value = Smi::cast(*value);
int int_value = smi_value->value();
Result answer;
switch (op) {
case Token::ADD: {
operand->ToRegister();
@ -1627,13 +1604,12 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
break;
}
case Token::SUB: {
DeferredCode* deferred = NULL;
Result answer; // Only allocate a new register if reversed.
if (reversed) {
// The reversed case is only hit when the right operand is not a
// constant.
@ -1661,15 +1637,14 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
deferred->Branch(not_zero);
deferred->BindExit();
operand->Unuse();
frame_->Push(&answer);
break;
}
case Token::SAR:
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
@ -1689,21 +1664,21 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
__ and_(operand->reg(), ~kSmiTagMask);
}
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
}
break;
case Token::SHR:
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
operand->ToRegister();
Result answer = allocator()->Allocate();
answer = allocator()->Allocate();
ASSERT(answer.is_valid());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
@ -1724,7 +1699,6 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
operand->Unuse();
__ SmiTag(answer.reg());
deferred->BindExit();
frame_->Push(&answer);
}
break;
@ -1749,7 +1723,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
}
operand->Unuse();
Result answer = allocator()->Allocate();
answer = allocator()->Allocate();
DeferredInlineSmiOperationReversed* deferred =
new DeferredInlineSmiOperationReversed(op,
answer.reg(),
@ -1765,7 +1739,6 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
__ SmiTag(answer.reg());
deferred->BindExit();
frame_->Push(&answer);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
@ -1783,10 +1756,10 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
} else {
// Use a fresh temporary for nonzero shift values.
Result answer = allocator()->Allocate();
answer = allocator()->Allocate();
ASSERT(answer.is_valid());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
@ -1808,7 +1781,6 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
deferred->Branch(overflow);
deferred->BindExit();
operand->Unuse();
frame_->Push(&answer);
}
}
break;
@ -1847,7 +1819,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
}
}
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
break;
}
@ -1873,7 +1845,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
__ and_(operand->reg(), (int_value << kSmiTagSize) - 1);
}
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
break;
}
// Fall through if we did not find a power of 2 on the right hand side!
@ -1881,16 +1853,17 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
default: {
Result constant_operand(value);
if (reversed) {
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
LikelySmiBinaryOperation(op, operand, &constant_operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, operand, &constant_operand,
overwrite_mode);
}
break;
}
}
ASSERT(!operand->is_valid());
ASSERT(answer.is_valid());
return answer;
}

View File

@ -444,20 +444,20 @@ class CodeGenerator: public AstVisitor {
// Emit code to perform a binary operation on a constant
// smi and a likely smi. Consumes the Result *operand.
void ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> constant_operand,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode);
Result ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> constant_operand,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode);
// Emit code to perform a binary operation on two likely smis.
// The code to handle smi arguments is produced inline.
// Consumes the Results *left and *right.
void LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode);
Result LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode);
void Comparison(AstNode* node,
Condition cc,

View File

@ -5030,31 +5030,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
return;
}
// Set the flags based on the operation, type and loop nesting level.
GenericBinaryFlags flags;
switch (op) {
case Token::BIT_OR:
case Token::BIT_AND:
case Token::BIT_XOR:
case Token::SHL:
case Token::SHR:
case Token::SAR:
// Bit operations always assume they likely operate on Smis. Still only
// generate the inline Smi check code if this operation is part of a loop.
flags = (loop_nesting() > 0)
? NO_SMI_CODE_IN_STUB
: NO_GENERIC_BINARY_FLAGS;
break;
default:
// By default only inline the Smi check code for likely smis if this
// operation is part of a loop.
flags = ((loop_nesting() > 0) && type->IsLikelySmi())
? NO_SMI_CODE_IN_STUB
: NO_GENERIC_BINARY_FLAGS;
break;
}
Result right = frame_->Pop();
Result left = frame_->Pop();
@ -5088,7 +5063,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi();
bool right_is_smi = right.is_constant() && right.handle()->IsSmi();
bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi();
bool generate_no_smi_code = false; // No smi code at all, inline or in stub.
if (left_is_smi && right_is_smi) {
// Compute the constant result at compile time, and leave it on the frame.
@ -5097,34 +5071,35 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
if (FoldConstantSmis(op, left_int, right_int)) return;
}
Result answer;
if (left_is_non_smi || right_is_non_smi) {
// Set flag so that we go straight to the slow case, with no smi code.
generate_no_smi_code = true;
} else if (right_is_smi) {
ConstantSmiBinaryOperation(op, &left, right.handle(),
type, false, overwrite_mode);
return;
} else if (left_is_smi) {
ConstantSmiBinaryOperation(op, &right, left.handle(),
type, true, overwrite_mode);
return;
}
if ((flags & NO_SMI_CODE_IN_STUB) != 0 && !generate_no_smi_code) {
LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
} else {
// Go straight to the slow case, with no smi code
frame_->Push(&left);
frame_->Push(&right);
// If we know the arguments aren't smis, use the binary operation stub
// that does not check for the fast smi case.
// The same stub is used for NO_SMI_CODE and SMI_CODE_INLINED.
if (generate_no_smi_code) {
flags = NO_SMI_CODE_IN_STUB;
GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB);
answer = frame_->CallStub(&stub, 2);
} else if (right_is_smi) {
answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
type, false, overwrite_mode);
} else if (left_is_smi) {
answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
type, true, overwrite_mode);
} else {
// Set the flags based on the operation, type and loop nesting level.
// Bit operations always assume they likely operate on Smis. Still only
// generate the inline Smi check code if this operation is part of a loop.
// For all other operations only inline the Smi check code for likely smis
// if the operation is part of a loop.
if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
} else {
frame_->Push(&left);
frame_->Push(&right);
GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS);
answer = frame_->CallStub(&stub, 2);
}
GenericBinaryOpStub stub(op, overwrite_mode, flags);
Result answer = frame_->CallStub(&stub, 2);
frame_->Push(&answer);
}
frame_->Push(&answer);
}
@ -5205,12 +5180,12 @@ void DeferredInlineSmiOperation::Generate() {
}
void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> value,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode) {
Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> value,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode) {
// NOTE: This is an attempt to inline (a bit) more of the code for
// some possible smi operations (like + and -) when (at least) one
// of the operands is a constant smi.
@ -5221,20 +5196,19 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
if (IsUnsafeSmi(value)) {
Result unsafe_operand(value);
if (reversed) {
LikelySmiBinaryOperation(op, &unsafe_operand, operand,
return LikelySmiBinaryOperation(op, &unsafe_operand, operand,
overwrite_mode);
} else {
LikelySmiBinaryOperation(op, operand, &unsafe_operand,
return LikelySmiBinaryOperation(op, operand, &unsafe_operand,
overwrite_mode);
}
ASSERT(!operand->is_valid());
return;
}
// Get the literal value.
Smi* smi_value = Smi::cast(*value);
int int_value = smi_value->value();
Result answer;
switch (op) {
case Token::ADD: {
operand->ToRegister();
@ -5255,15 +5229,15 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
smi_value,
deferred->entry_label());
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
break;
}
case Token::SUB: {
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
operand->ToRegister();
frame_->Spill(operand->reg());
@ -5277,7 +5251,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
smi_value,
deferred->entry_label());
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
}
break;
}
@ -5285,8 +5259,8 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
case Token::SAR:
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
@ -5304,21 +5278,21 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
operand->reg(),
shift_value);
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
}
break;
case Token::SHR:
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
operand->ToRegister();
Result answer = allocator()->Allocate();
answer = allocator()->Allocate();
ASSERT(answer.is_valid());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
@ -5333,15 +5307,14 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
deferred->entry_label());
deferred->BindExit();
operand->Unuse();
frame_->Push(&answer);
}
break;
case Token::SHL:
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
@ -5358,10 +5331,10 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
overwrite_mode);
__ JumpIfNotSmi(operand->reg(), deferred->entry_label());
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
} else {
// Use a fresh temporary for nonzero shift values.
Result answer = allocator()->Allocate();
answer = allocator()->Allocate();
ASSERT(answer.is_valid());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
@ -5376,7 +5349,6 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
deferred->entry_label());
deferred->BindExit();
operand->Unuse();
frame_->Push(&answer);
}
}
break;
@ -5411,7 +5383,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
}
}
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
break;
}
@ -5439,7 +5411,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
Smi::FromInt(int_value - 1));
}
deferred->BindExit();
frame_->Push(operand);
answer = *operand;
break; // This break only applies if we generated code for MOD.
}
// Fall through if we did not find a power of 2 on the right hand side!
@ -5448,22 +5420,24 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
default: {
Result constant_operand(value);
if (reversed) {
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
LikelySmiBinaryOperation(op, operand, &constant_operand,
overwrite_mode);
answer = LikelySmiBinaryOperation(op, operand, &constant_operand,
overwrite_mode);
}
break;
}
}
ASSERT(!operand->is_valid());
ASSERT(answer.is_valid());
return answer;
}
void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode) {
Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode) {
Result answer;
// Special handling of div and mod because they use fixed registers.
if (op == Token::DIV || op == Token::MOD) {
// We need rax as the quotient register, rdx as the remainder
@ -5545,16 +5519,17 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&quotient);
answer = quotient;
} else {
ASSERT(op == Token::MOD);
__ SmiMod(rdx, left->reg(), right->reg(), deferred->entry_label());
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&remainder);
answer = remainder;
}
return;
ASSERT(answer.is_valid());
return answer;
}
// Special handling of shift operations because they use fixed
@ -5575,7 +5550,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
frame_->Spill(rcx);
// Use a fresh answer register to avoid spilling the left operand.
Result answer = allocator_->Allocate();
answer = allocator_->Allocate();
ASSERT(answer.is_valid());
// Check that both operands are smis using the answer register as a
// temporary.
@ -5614,8 +5589,8 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&answer);
return;
ASSERT(answer.is_valid());
return answer;
}
// Handle the other binary operations.
@ -5624,7 +5599,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
// A newly allocated register answer is used to hold the answer. The
// registers containing left and right are not modified so they don't
// need to be spilled in the fast case.
Result answer = allocator_->Allocate();
answer = allocator_->Allocate();
ASSERT(answer.is_valid());
// Perform the smi tag check.
@ -5678,7 +5653,8 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
deferred->BindExit();
left->Unuse();
right->Unuse();
frame_->Push(&answer);
ASSERT(answer.is_valid());
return answer;
}

View File

@ -446,20 +446,20 @@ class CodeGenerator: public AstVisitor {
// Emit code to perform a binary operation on a constant
// smi and a likely smi. Consumes the Result *operand.
void ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> constant_operand,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode);
Result ConstantSmiBinaryOperation(Token::Value op,
Result* operand,
Handle<Object> constant_operand,
StaticType* type,
bool reversed,
OverwriteMode overwrite_mode);
// Emit code to perform a binary operation on two likely smis.
// The code to handle smi arguments is produced inline.
// Consumes the Results *left and *right.
void LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode);
Result LikelySmiBinaryOperation(Token::Value op,
Result* left,
Result* right,
OverwriteMode overwrite_mode);
void Comparison(Condition cc,
bool strict,