| Index: src/x64/codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/codegen-x64.cc (revision 3660)
|
| +++ src/x64/codegen-x64.cc (working copy)
|
| @@ -5030,31 +5030,6 @@
|
| 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 @@
|
| 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 @@
|
| 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;
|
| + // Go straight to the slow case, with no smi code
|
| + frame_->Push(&left);
|
| + frame_->Push(&right);
|
| + GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB);
|
| + answer = frame_->CallStub(&stub, 2);
|
| } else if (right_is_smi) {
|
| - ConstantSmiBinaryOperation(op, &left, right.handle(),
|
| - type, false, overwrite_mode);
|
| - return;
|
| + answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
|
| + type, false, overwrite_mode);
|
| } 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);
|
| + answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
|
| + type, true, overwrite_mode);
|
| } else {
|
| - 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;
|
| + // 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 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 @@
|
| 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 @@
|
| 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 @@
|
| smi_value,
|
| deferred->entry_label());
|
| deferred->BindExit();
|
| - frame_->Push(operand);
|
| + answer = *operand;
|
| }
|
| break;
|
| }
|
| @@ -5285,8 +5259,8 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| deferred->entry_label());
|
| deferred->BindExit();
|
| operand->Unuse();
|
| - frame_->Push(&answer);
|
| }
|
| }
|
| break;
|
| @@ -5411,7 +5383,7 @@
|
| }
|
| }
|
| deferred->BindExit();
|
| - frame_->Push(operand);
|
| + answer = *operand;
|
| break;
|
| }
|
|
|
| @@ -5439,7 +5411,7 @@
|
| 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 @@
|
| 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 @@
|
| deferred->BindExit();
|
| left->Unuse();
|
| right->Unuse();
|
| - frame_->Push("ient);
|
| + 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 @@
|
| 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 @@
|
| 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 @@
|
| // 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 @@
|
| deferred->BindExit();
|
| left->Unuse();
|
| right->Unuse();
|
| - frame_->Push(&answer);
|
| + ASSERT(answer.is_valid());
|
| + return answer;
|
| }
|
|
|
|
|
|
|