| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
| 8 #include "src/arm64/assembler-arm64-inl.h" | 8 #include "src/arm64/assembler-arm64-inl.h" |
| 9 #include "src/arm64/frames-arm64.h" | 9 #include "src/arm64/frames-arm64.h" |
| 10 #include "src/arm64/macro-assembler-arm64-inl.h" | 10 #include "src/arm64/macro-assembler-arm64-inl.h" |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 __ Pop(double_scratch); | 140 __ Pop(double_scratch); |
| 141 } | 141 } |
| 142 __ Pop(scratch2, scratch1); | 142 __ Pop(scratch2, scratch1); |
| 143 __ Ret(); | 143 __ Ret(); |
| 144 } | 144 } |
| 145 | 145 |
| 146 | 146 |
| 147 // See call site for description. | 147 // See call site for description. |
| 148 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Register left, | 148 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Register left, |
| 149 Register right, Register scratch, | 149 Register right, Register scratch, |
| 150 VRegister double_scratch, Label* slow, | 150 FPRegister double_scratch, |
| 151 Condition cond) { | 151 Label* slow, Condition cond) { |
| 152 DCHECK(!AreAliased(left, right, scratch)); | 152 DCHECK(!AreAliased(left, right, scratch)); |
| 153 Label not_identical, return_equal, heap_number; | 153 Label not_identical, return_equal, heap_number; |
| 154 Register result = x0; | 154 Register result = x0; |
| 155 | 155 |
| 156 __ Cmp(right, left); | 156 __ Cmp(right, left); |
| 157 __ B(ne, ¬_identical); | 157 __ B(ne, ¬_identical); |
| 158 | 158 |
| 159 // Test for NaN. Sadly, we can't just compare to factory::nan_value(), | 159 // Test for NaN. Sadly, we can't just compare to factory::nan_value(), |
| 160 // so we do the second best thing - test it ourselves. | 160 // so we do the second best thing - test it ourselves. |
| 161 // They are both equal and they are not both Smis so both of them are not | 161 // They are both equal and they are not both Smis so both of them are not |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 // same object. We have already tested that case, so if left and right are | 285 // same object. We have already tested that case, so if left and right are |
| 286 // both internalized strings, they cannot be equal. | 286 // both internalized strings, they cannot be equal. |
| 287 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); | 287 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
| 288 __ Orr(scratch, left_type, right_type); | 288 __ Orr(scratch, left_type, right_type); |
| 289 __ TestAndBranchIfAllClear( | 289 __ TestAndBranchIfAllClear( |
| 290 scratch, kIsNotStringMask | kIsNotInternalizedMask, &return_not_equal); | 290 scratch, kIsNotStringMask | kIsNotInternalizedMask, &return_not_equal); |
| 291 } | 291 } |
| 292 | 292 |
| 293 | 293 |
| 294 // See call site for description. | 294 // See call site for description. |
| 295 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register left, | 295 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
| 296 Register right, VRegister left_d, | 296 Register left, |
| 297 VRegister right_d, Label* slow, | 297 Register right, |
| 298 FPRegister left_d, |
| 299 FPRegister right_d, |
| 300 Label* slow, |
| 298 bool strict) { | 301 bool strict) { |
| 299 DCHECK(!AreAliased(left_d, right_d)); | 302 DCHECK(!AreAliased(left_d, right_d)); |
| 300 DCHECK((left.is(x0) && right.is(x1)) || | 303 DCHECK((left.is(x0) && right.is(x1)) || |
| 301 (right.is(x0) && left.is(x1))); | 304 (right.is(x0) && left.is(x1))); |
| 302 Register result = x0; | 305 Register result = x0; |
| 303 | 306 |
| 304 Label right_is_smi, done; | 307 Label right_is_smi, done; |
| 305 __ JumpIfSmi(right, &right_is_smi); | 308 __ JumpIfSmi(right, &right_is_smi); |
| 306 | 309 |
| 307 // Left is the smi. Check whether right is a heap number. | 310 // Left is the smi. Check whether right is a heap number. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 __ JumpIfBothNotSmi(lhs, rhs, ¬_smis); | 469 __ JumpIfBothNotSmi(lhs, rhs, ¬_smis); |
| 467 | 470 |
| 468 // Exactly one operand is a smi. EmitSmiNonsmiComparison generates code that | 471 // Exactly one operand is a smi. EmitSmiNonsmiComparison generates code that |
| 469 // can: | 472 // can: |
| 470 // 1) Return the answer. | 473 // 1) Return the answer. |
| 471 // 2) Branch to the slow case. | 474 // 2) Branch to the slow case. |
| 472 // 3) Fall through to both_loaded_as_doubles. | 475 // 3) Fall through to both_loaded_as_doubles. |
| 473 // In case 3, we have found out that we were dealing with a number-number | 476 // In case 3, we have found out that we were dealing with a number-number |
| 474 // comparison. The double values of the numbers have been loaded, right into | 477 // comparison. The double values of the numbers have been loaded, right into |
| 475 // rhs_d, left into lhs_d. | 478 // rhs_d, left into lhs_d. |
| 476 VRegister rhs_d = d0; | 479 FPRegister rhs_d = d0; |
| 477 VRegister lhs_d = d1; | 480 FPRegister lhs_d = d1; |
| 478 EmitSmiNonsmiComparison(masm, lhs, rhs, lhs_d, rhs_d, &slow, strict()); | 481 EmitSmiNonsmiComparison(masm, lhs, rhs, lhs_d, rhs_d, &slow, strict()); |
| 479 | 482 |
| 480 __ Bind(&both_loaded_as_doubles); | 483 __ Bind(&both_loaded_as_doubles); |
| 481 // The arguments have been converted to doubles and stored in rhs_d and | 484 // The arguments have been converted to doubles and stored in rhs_d and |
| 482 // lhs_d. | 485 // lhs_d. |
| 483 Label nan; | 486 Label nan; |
| 484 __ Fcmp(lhs_d, rhs_d); | 487 __ Fcmp(lhs_d, rhs_d); |
| 485 __ B(vs, &nan); // Overflow flag set if either is NaN. | 488 __ B(vs, &nan); // Overflow flag set if either is NaN. |
| 486 STATIC_ASSERT((LESS == -1) && (EQUAL == 0) && (GREATER == 1)); | 489 STATIC_ASSERT((LESS == -1) && (EQUAL == 0) && (GREATER == 1)); |
| 487 __ Cset(result, gt); // gt => 1, otherwise (lt, eq) => 0 (EQUAL). | 490 __ Cset(result, gt); // gt => 1, otherwise (lt, eq) => 0 (EQUAL). |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 __ TailCallRuntime(Runtime::kCompare); | 606 __ TailCallRuntime(Runtime::kCompare); |
| 604 } | 607 } |
| 605 | 608 |
| 606 __ Bind(&miss); | 609 __ Bind(&miss); |
| 607 GenerateMiss(masm); | 610 GenerateMiss(masm); |
| 608 } | 611 } |
| 609 | 612 |
| 610 | 613 |
| 611 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 614 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 612 CPURegList saved_regs = kCallerSaved; | 615 CPURegList saved_regs = kCallerSaved; |
| 613 CPURegList saved_fp_regs = kCallerSavedV; | 616 CPURegList saved_fp_regs = kCallerSavedFP; |
| 614 | 617 |
| 615 // We don't allow a GC during a store buffer overflow so there is no need to | 618 // We don't allow a GC during a store buffer overflow so there is no need to |
| 616 // store the registers in any particular way, but we do have to store and | 619 // store the registers in any particular way, but we do have to store and |
| 617 // restore them. | 620 // restore them. |
| 618 | 621 |
| 619 // We don't care if MacroAssembler scratch registers are corrupted. | 622 // We don't care if MacroAssembler scratch registers are corrupted. |
| 620 saved_regs.Remove(*(masm->TmpList())); | 623 saved_regs.Remove(*(masm->TmpList())); |
| 621 saved_fp_regs.Remove(*(masm->FPTmpList())); | 624 saved_fp_regs.Remove(*(masm->FPTmpList())); |
| 622 | 625 |
| 623 __ PushCPURegList(saved_regs); | 626 __ PushCPURegList(saved_regs); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 // jssp[0]: Exponent (as a tagged value). | 679 // jssp[0]: Exponent (as a tagged value). |
| 677 // jssp[1]: Base (as a tagged value). | 680 // jssp[1]: Base (as a tagged value). |
| 678 // | 681 // |
| 679 // The (tagged) result will be returned in x0, as a heap number. | 682 // The (tagged) result will be returned in x0, as a heap number. |
| 680 | 683 |
| 681 Register exponent_tagged = MathPowTaggedDescriptor::exponent(); | 684 Register exponent_tagged = MathPowTaggedDescriptor::exponent(); |
| 682 DCHECK(exponent_tagged.is(x11)); | 685 DCHECK(exponent_tagged.is(x11)); |
| 683 Register exponent_integer = MathPowIntegerDescriptor::exponent(); | 686 Register exponent_integer = MathPowIntegerDescriptor::exponent(); |
| 684 DCHECK(exponent_integer.is(x12)); | 687 DCHECK(exponent_integer.is(x12)); |
| 685 Register saved_lr = x19; | 688 Register saved_lr = x19; |
| 686 VRegister result_double = d0; | 689 FPRegister result_double = d0; |
| 687 VRegister base_double = d0; | 690 FPRegister base_double = d0; |
| 688 VRegister exponent_double = d1; | 691 FPRegister exponent_double = d1; |
| 689 VRegister base_double_copy = d2; | 692 FPRegister base_double_copy = d2; |
| 690 VRegister scratch1_double = d6; | 693 FPRegister scratch1_double = d6; |
| 691 VRegister scratch0_double = d7; | 694 FPRegister scratch0_double = d7; |
| 692 | 695 |
| 693 // A fast-path for integer exponents. | 696 // A fast-path for integer exponents. |
| 694 Label exponent_is_smi, exponent_is_integer; | 697 Label exponent_is_smi, exponent_is_integer; |
| 695 // Allocate a heap number for the result, and return it. | 698 // Allocate a heap number for the result, and return it. |
| 696 Label done; | 699 Label done; |
| 697 | 700 |
| 698 // Unpack the inputs. | 701 // Unpack the inputs. |
| 699 if (exponent_type() == TAGGED) { | 702 if (exponent_type() == TAGGED) { |
| 700 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); | 703 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); |
| 701 __ Ldr(exponent_double, | 704 __ Ldr(exponent_double, |
| (...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1639 DCHECK(state() == CompareICState::NUMBER); | 1642 DCHECK(state() == CompareICState::NUMBER); |
| 1640 ASM_LOCATION("CompareICStub[HeapNumbers]"); | 1643 ASM_LOCATION("CompareICStub[HeapNumbers]"); |
| 1641 | 1644 |
| 1642 Label unordered, maybe_undefined1, maybe_undefined2; | 1645 Label unordered, maybe_undefined1, maybe_undefined2; |
| 1643 Label miss, handle_lhs, values_in_d_regs; | 1646 Label miss, handle_lhs, values_in_d_regs; |
| 1644 Label untag_rhs, untag_lhs; | 1647 Label untag_rhs, untag_lhs; |
| 1645 | 1648 |
| 1646 Register result = x0; | 1649 Register result = x0; |
| 1647 Register rhs = x0; | 1650 Register rhs = x0; |
| 1648 Register lhs = x1; | 1651 Register lhs = x1; |
| 1649 VRegister rhs_d = d0; | 1652 FPRegister rhs_d = d0; |
| 1650 VRegister lhs_d = d1; | 1653 FPRegister lhs_d = d1; |
| 1651 | 1654 |
| 1652 if (left() == CompareICState::SMI) { | 1655 if (left() == CompareICState::SMI) { |
| 1653 __ JumpIfNotSmi(lhs, &miss); | 1656 __ JumpIfNotSmi(lhs, &miss); |
| 1654 } | 1657 } |
| 1655 if (right() == CompareICState::SMI) { | 1658 if (right() == CompareICState::SMI) { |
| 1656 __ JumpIfNotSmi(rhs, &miss); | 1659 __ JumpIfNotSmi(rhs, &miss); |
| 1657 } | 1660 } |
| 1658 | 1661 |
| 1659 __ SmiUntagToDouble(rhs_d, rhs, kSpeculativeUntag); | 1662 __ SmiUntagToDouble(rhs_d, rhs, kSpeculativeUntag); |
| 1660 __ SmiUntagToDouble(lhs_d, lhs, kSpeculativeUntag); | 1663 __ SmiUntagToDouble(lhs_d, lhs, kSpeculativeUntag); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2099 __ TailCallStub(&stub); | 2102 __ TailCallStub(&stub); |
| 2100 } | 2103 } |
| 2101 | 2104 |
| 2102 RecordWriteStub::RegisterAllocation::RegisterAllocation(Register object, | 2105 RecordWriteStub::RegisterAllocation::RegisterAllocation(Register object, |
| 2103 Register address, | 2106 Register address, |
| 2104 Register scratch) | 2107 Register scratch) |
| 2105 : object_(object), | 2108 : object_(object), |
| 2106 address_(address), | 2109 address_(address), |
| 2107 scratch0_(scratch), | 2110 scratch0_(scratch), |
| 2108 saved_regs_(kCallerSaved), | 2111 saved_regs_(kCallerSaved), |
| 2109 saved_fp_regs_(kCallerSavedV) { | 2112 saved_fp_regs_(kCallerSavedFP) { |
| 2110 DCHECK(!AreAliased(scratch, object, address)); | 2113 DCHECK(!AreAliased(scratch, object, address)); |
| 2111 | 2114 |
| 2112 // The SaveCallerSaveRegisters method needs to save caller-saved | 2115 // The SaveCallerSaveRegisters method needs to save caller-saved |
| 2113 // registers, but we don't bother saving MacroAssembler scratch registers. | 2116 // registers, but we don't bother saving MacroAssembler scratch registers. |
| 2114 saved_regs_.Remove(MacroAssembler::DefaultTmpList()); | 2117 saved_regs_.Remove(MacroAssembler::DefaultTmpList()); |
| 2115 saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList()); | 2118 saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList()); |
| 2116 | 2119 |
| 2117 // We would like to require more scratch registers for this stub, | 2120 // We would like to require more scratch registers for this stub, |
| 2118 // but the number of registers comes down to the ones used in | 2121 // but the number of registers comes down to the ones used in |
| 2119 // FullCodeGen::SetVar(), which is architecture independent. | 2122 // FullCodeGen::SetVar(), which is architecture independent. |
| (...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3227 kStackUnwindSpace, NULL, spill_offset, | 3230 kStackUnwindSpace, NULL, spill_offset, |
| 3228 return_value_operand, NULL); | 3231 return_value_operand, NULL); |
| 3229 } | 3232 } |
| 3230 | 3233 |
| 3231 #undef __ | 3234 #undef __ |
| 3232 | 3235 |
| 3233 } // namespace internal | 3236 } // namespace internal |
| 3234 } // namespace v8 | 3237 } // namespace v8 |
| 3235 | 3238 |
| 3236 #endif // V8_TARGET_ARCH_ARM64 | 3239 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |