| Index: src/x64/codegen-x64.cc
|
| diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
|
| index 462b9600eed66b337b6f388d051ab98ebbe50974..f271860961a42be68ef471bed3b8d9874bd9e140 100644
|
| --- a/src/x64/codegen-x64.cc
|
| +++ b/src/x64/codegen-x64.cc
|
| @@ -6217,7 +6217,7 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
|
| if (answer >= Smi::kMinValue && answer <= Smi::kMaxValue) {
|
| // If the product is zero and the non-zero factor is negative,
|
| // the spec requires us to return floating point negative zero.
|
| - if (answer != 0 || (left >= 0 && right >= 0)) {
|
| + if (answer != 0 || (left + right) >= 0) {
|
| answer_object = Smi::FromInt(static_cast<int>(answer));
|
| }
|
| }
|
| @@ -6285,24 +6285,54 @@ bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
|
| void UnarySubStub::Generate(MacroAssembler* masm) {
|
| Label slow;
|
| Label done;
|
| -
|
| + Label try_float;
|
| + Label special;
|
| // Check whether the value is a smi.
|
| __ testl(rax, Immediate(kSmiTagMask));
|
| - // TODO(X64): Add inline code that handles floats, as on ia32 platform.
|
| - __ j(not_zero, &slow);
|
| + __ j(not_zero, &try_float);
|
| +
|
| // 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
|
| __ testl(rax, Immediate(0x7FFFFFFE));
|
| - __ j(zero, &slow);
|
| + __ j(zero, &special);
|
| __ neg(rax);
|
| __ jmp(&done);
|
| +
|
| + __ bind(&special);
|
| + // Either zero or -0x4000000, neither of which become a smi when negated.
|
| + __ testl(rax, rax);
|
| + __ j(not_zero, &slow);
|
| + __ Move(rax, Factory::minus_zero_value());
|
| + __ jmp(&done);
|
| +
|
| // Enter runtime system.
|
| __ bind(&slow);
|
| __ pop(rcx); // pop return address
|
| __ push(rax);
|
| __ push(rcx); // push return address
|
| __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
|
| + __ jmp(&done);
|
| +
|
| + // Try floating point case.
|
| + __ bind(&try_float);
|
| + __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
|
| + __ Cmp(rdx, Factory::heap_number_map());
|
| + __ j(not_equal, &slow);
|
| + // Operand is a float, negate its value by flipping sign bit.
|
| + __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
|
| + __ movq(kScratchRegister, Immediate(0x01));
|
| + __ shl(kScratchRegister, Immediate(63));
|
| + __ xor_(rdx, kScratchRegister); // Flip sign.
|
| + // rdx is value to store.
|
| + if (overwrite_) {
|
| + __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx);
|
| + } else {
|
| + FloatingPointHelper::AllocateHeapNumber(masm, &slow, rbx, rcx);
|
| + // rcx: allocated 'empty' number
|
| + __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx);
|
| + __ movq(rax, rcx);
|
| + }
|
|
|
| __ bind(&done);
|
| __ StubReturn(1);
|
|
|