Chromium Code Reviews| Index: src/x64/code-stubs-x64.cc |
| diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
| index 2098ed12f5de2684889d8187c61624903989a86d..8d12512274d3c160d5e4f27f9d960502f3e5ff3d 100644 |
| --- a/src/x64/code-stubs-x64.cc |
| +++ b/src/x64/code-stubs-x64.cc |
| @@ -460,6 +460,26 @@ class FloatingPointHelper : public AllStatic { |
| // As above, but we know the operands to be numbers. In that case, |
| // conversion can't fail. |
| static void LoadNumbersAsIntegers(MacroAssembler* masm); |
| + |
| + // Tries to convert two values to smis losslessly. |
| + // This fails if either argument is not a Smi nor a HeapNumber, |
| + // or if it's a HeapNumber with a value that can't be converted |
| + // losslessly to a Smi. In that case, control transitions to the |
| + // on_not_smis label. |
| + // On success, either control goes to the on_success label, |
| + // or it falls through at the end of the code. |
| + // (If you just want to fall through in all cases, put the success |
|
William Hesse
2011/04/08 12:01:27
Why let the user of this function make a mistake.
Lasse Reichstein
2011/04/08 12:07:46
Done.
|
| + // label at the fall-through point). |
| + // At this point, both first and second holds Smi tagged values. |
| + // One of first or second must be non-Smi. |
| + static void NumbersToSmis(MacroAssembler* masm, |
| + Register first, |
| + Register second, |
| + Register scratch1, |
| + Register scratch2, |
| + Register scratch3, |
| + Label* on_success, |
| + Label* on_not_smis); |
| }; |
| @@ -1105,29 +1125,30 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
| Label* slow, |
| SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
| + // Arguments to TypeRecordingBinaryOpStub are in rdx and rax. |
| + Register left = rdx; |
| + Register right = rax; |
| + |
| // We only generate heapnumber answers for overflowing calculations |
| - // for the four basic arithmetic operations. |
| + // for the four basic arithmetic operations and logical right shift by 0. |
| bool generate_inline_heapnumber_results = |
| (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) && |
| (op_ == Token::ADD || op_ == Token::SUB || |
| op_ == Token::MUL || op_ == Token::DIV || op_ == Token::SHR); |
| - // Arguments to TypeRecordingBinaryOpStub are in rdx and rax. |
| - Register left = rdx; |
| - Register right = rax; |
| - |
| - |
| // Smi check of both operands. If op is BIT_OR, the check is delayed |
| // until after the OR operation. |
| Label not_smis; |
| Label use_fp_on_smis; |
| - Label restore_MOD_registers; // Only used if op_ == Token::MOD. |
| + Label fail; |
| if (op_ != Token::BIT_OR) { |
| Comment smi_check_comment(masm, "-- Smi check arguments"); |
| __ JumpIfNotBothSmi(left, right, ¬_smis); |
| } |
| + Label smi_values; |
| + __ bind(&smi_values); |
| // Perform the operation. |
| Comment perform_smi(masm, "-- Perform smi operation"); |
| switch (op_) { |
| @@ -1166,9 +1187,7 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
| case Token::BIT_OR: { |
| ASSERT(right.is(rax)); |
| - __ movq(rcx, right); // Save the right operand. |
| - __ SmiOr(right, right, left); // BIT_OR is commutative. |
| - __ JumpIfNotSmi(right, ¬_smis); // Test delayed until after BIT_OR. |
| + __ SmiOrIfSmis(right, right, left, ¬_smis); // BIT_OR is commutative. |
| break; |
| } |
| case Token::BIT_XOR: |
| @@ -1233,17 +1252,22 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
| __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
| __ movq(rax, rcx); |
| __ ret(0); |
| + } else { |
| + __ jmp(&fail); |
| } |
| } |
| // 7. Non-smi operands reach the end of the code generated by |
| // GenerateSmiCode, and fall through to subsequent code, |
| // with the operands in rdx and rax. |
| - Comment done_comment(masm, "-- Enter non-smi code"); |
| + // But first we check if non-smi values are HeapNumbers holding |
| + // values that could be smi. |
| __ bind(¬_smis); |
| - if (op_ == Token::BIT_OR) { |
| - __ movq(right, rcx); |
| - } |
| + Comment done_comment(masm, "-- Enter non-smi code"); |
| + FloatingPointHelper::NumbersToSmis(masm, left, right, rbx, rdi, rcx, |
| + &smi_values, &fail); |
| + __ jmp(&smi_values); |
| + __ bind(&fail); |
| } |
| @@ -2065,6 +2089,55 @@ void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, |
| } |
| +void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm, |
| + Register first, |
| + Register second, |
| + Register scratch1, |
| + Register scratch2, |
| + Register scratch3, |
| + Label* on_success, |
| + Label* on_not_smis) { |
| + Register heap_number_root = scratch3; |
| + Register smi_result = scratch1; |
| + __ LoadRoot(heap_number_root, Heap::kHeapNumberMapRootIndex); |
|
William Hesse
2011/04/08 12:01:27
Shouldn't this be called heap_number_map?
Lasse Reichstein
2011/04/08 12:07:46
Absolutely.
|
| + |
| + NearLabel first_smi, check_second; |
| + __ JumpIfSmi(first, &first_smi); |
| + __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_root); |
| + __ j(not_equal, on_not_smis); |
| + // Convert HeapNumber to smi if possible. |
| + __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset)); |
| + __ movq(scratch2, xmm0); |
| + __ cvttsd2siq(smi_result, xmm0); |
| + // Check if conversion was successful by converting back and |
| + // comparing to the original double's bits. |
| + __ cvtlsi2sd(xmm1, smi_result); |
| + __ movq(kScratchRegister, xmm1); |
| + __ cmpq(scratch2, kScratchRegister); |
| + __ j(not_equal, on_not_smis); |
| + __ Integer32ToSmi(first, smi_result); |
| + |
| + __ bind(&check_second); |
| + __ JumpIfSmi(second, on_success); |
| + __ bind(&first_smi); |
| + if (FLAG_debug_code) { |
| + // One of first or second should be non-smi if we get here. |
|
William Hesse
2011/04/08 12:01:27
Second should be non-smi if we get here.
Lasse Reichstein
2011/04/08 12:07:46
Done.
|
| + __ AbortIfSmi(second); |
| + } |
| + __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_root); |
| + __ j(not_equal, on_not_smis); |
| + // Convert second to smi, if possible. |
| + __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset)); |
| + __ movq(scratch2, xmm0); |
| + __ cvttsd2siq(smi_result, xmm0); |
| + __ cvtlsi2sd(xmm1, smi_result); |
| + __ movq(kScratchRegister, xmm1); |
| + __ cmpq(scratch2, kScratchRegister); |
| + __ j(not_equal, on_not_smis); |
| + __ Integer32ToSmi(second, smi_result); |
| +} |
| + |
| + |
| void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
| Label slow, done; |