Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 5030) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -3373,9 +3373,12 @@ |
} |
} else { |
- bool overwrite = |
+ bool can_overwrite = |
(node->expression()->AsBinaryOperation() != NULL && |
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); |
+ UnaryOverwriteMode overwrite = |
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
+ bool no_negative_zero = node->expression()->no_negative_zero(); |
Load(node->expression()); |
switch (op) { |
case Token::NOT: |
@@ -3385,7 +3388,10 @@ |
break; |
case Token::SUB: { |
- GenericUnaryOpStub stub(Token::SUB, overwrite); |
+ GenericUnaryOpStub stub( |
+ Token::SUB, |
+ overwrite, |
+ no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero); |
Result operand = frame_->Pop(); |
Result answer = frame_->CallStub(&stub, &operand); |
answer.set_type_info(TypeInfo::Number()); |
@@ -8506,6 +8512,11 @@ |
Label try_float; |
__ JumpIfNotSmi(rax, &try_float); |
+ if (negative_zero_ == kIgnoreNegativeZero) { |
+ __ SmiCompare(rax, Smi::FromInt(0)); |
+ __ j(equal, &done); |
+ } |
+ |
// Enter runtime system if the value of the smi is zero |
// to make sure that we switch between 0 and -0. |
// Also enter it if the value of the smi is Smi::kMinValue. |
@@ -8513,10 +8524,14 @@ |
// Either zero or Smi::kMinValue, neither of which become a smi when |
// negated. |
- __ SmiCompare(rax, Smi::FromInt(0)); |
- __ j(not_equal, &slow); |
- __ Move(rax, Factory::minus_zero_value()); |
- __ jmp(&done); |
+ if (negative_zero_ == kStrictNegativeZero) { |
+ __ SmiCompare(rax, Smi::FromInt(0)); |
+ __ j(not_equal, &slow); |
+ __ Move(rax, Factory::minus_zero_value()); |
+ __ jmp(&done); |
+ } else { |
+ __ jmp(&slow); |
+ } |
// Try floating point case. |
__ bind(&try_float); |
@@ -8529,7 +8544,7 @@ |
__ shl(kScratchRegister, Immediate(63)); |
__ xor_(rdx, kScratchRegister); // Flip sign. |
// rdx is value to store. |
- if (overwrite_) { |
+ if (overwrite_ == UNARY_OVERWRITE) { |
__ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); |
} else { |
__ AllocateHeapNumber(rcx, rbx, &slow); |
@@ -10596,6 +10611,7 @@ |
// the four basic operations. The stub stays in the DEFAULT state |
// forever for all other operations (also if smi code is skipped). |
GenerateTypeTransition(masm); |
+ break; |
} |
Label not_floats; |
@@ -10913,31 +10929,13 @@ |
void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
Label get_result; |
- // Keep a copy of operands on the stack and make sure they are also in |
- // rdx, rax. |
+ // Ensure the operands are on the stack. |
if (HasArgsInRegisters()) { |
GenerateRegisterArgsPush(masm); |
- } else { |
- GenerateLoadArguments(masm); |
} |
- // Internal frame is necessary to handle exceptions properly. |
- __ EnterInternalFrame(); |
- |
- // Push arguments on stack if the stub expects them there. |
- if (!HasArgsInRegisters()) { |
- __ push(rdx); |
- __ push(rax); |
- } |
- // Call the stub proper to get the result in rax. |
- __ call(&get_result); |
- __ LeaveInternalFrame(); |
- |
// Left and right arguments are already on stack. |
- __ pop(rcx); |
- // Push the operation result. The tail call to BinaryOp_Patch will |
- // return it to the original caller.. |
- __ push(rax); |
+ __ pop(rcx); // Save the return address. |
// Push this stub's key. |
__ Push(Smi::FromInt(MinorKey())); |
@@ -10948,17 +10946,13 @@ |
__ Push(Smi::FromInt(runtime_operands_type_)); |
- __ push(rcx); |
+ __ push(rcx); // The return address. |
// Perform patching to an appropriate fast case and return the result. |
__ TailCallExternalReference( |
ExternalReference(IC_Utility(IC::kBinaryOp_Patch)), |
- 6, |
+ 5, |
1); |
- |
- // The entry point for the result calculation is assumed to be immediately |
- // after this sequence. |
- __ bind(&get_result); |
} |