| 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 FPRegister double_scratch, | 150 VRegister double_scratch, Label* slow, |
| 151 Label* slow, Condition cond) { | 151 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, | 295 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register left, |
| 296 Register left, | 296 Register right, VRegister left_d, |
| 297 Register right, | 297 VRegister right_d, Label* slow, |
| 298 FPRegister left_d, | |
| 299 FPRegister right_d, | |
| 300 Label* slow, | |
| 301 bool strict) { | 298 bool strict) { |
| 302 DCHECK(!AreAliased(left_d, right_d)); | 299 DCHECK(!AreAliased(left_d, right_d)); |
| 303 DCHECK((left.is(x0) && right.is(x1)) || | 300 DCHECK((left.is(x0) && right.is(x1)) || |
| 304 (right.is(x0) && left.is(x1))); | 301 (right.is(x0) && left.is(x1))); |
| 305 Register result = x0; | 302 Register result = x0; |
| 306 | 303 |
| 307 Label right_is_smi, done; | 304 Label right_is_smi, done; |
| 308 __ JumpIfSmi(right, &right_is_smi); | 305 __ JumpIfSmi(right, &right_is_smi); |
| 309 | 306 |
| 310 // Left is the smi. Check whether right is a heap number. | 307 // Left is the smi. Check whether right is a heap number. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 __ JumpIfBothNotSmi(lhs, rhs, ¬_smis); | 466 __ JumpIfBothNotSmi(lhs, rhs, ¬_smis); |
| 470 | 467 |
| 471 // Exactly one operand is a smi. EmitSmiNonsmiComparison generates code that | 468 // Exactly one operand is a smi. EmitSmiNonsmiComparison generates code that |
| 472 // can: | 469 // can: |
| 473 // 1) Return the answer. | 470 // 1) Return the answer. |
| 474 // 2) Branch to the slow case. | 471 // 2) Branch to the slow case. |
| 475 // 3) Fall through to both_loaded_as_doubles. | 472 // 3) Fall through to both_loaded_as_doubles. |
| 476 // In case 3, we have found out that we were dealing with a number-number | 473 // In case 3, we have found out that we were dealing with a number-number |
| 477 // comparison. The double values of the numbers have been loaded, right into | 474 // comparison. The double values of the numbers have been loaded, right into |
| 478 // rhs_d, left into lhs_d. | 475 // rhs_d, left into lhs_d. |
| 479 FPRegister rhs_d = d0; | 476 VRegister rhs_d = d0; |
| 480 FPRegister lhs_d = d1; | 477 VRegister lhs_d = d1; |
| 481 EmitSmiNonsmiComparison(masm, lhs, rhs, lhs_d, rhs_d, &slow, strict()); | 478 EmitSmiNonsmiComparison(masm, lhs, rhs, lhs_d, rhs_d, &slow, strict()); |
| 482 | 479 |
| 483 __ Bind(&both_loaded_as_doubles); | 480 __ Bind(&both_loaded_as_doubles); |
| 484 // The arguments have been converted to doubles and stored in rhs_d and | 481 // The arguments have been converted to doubles and stored in rhs_d and |
| 485 // lhs_d. | 482 // lhs_d. |
| 486 Label nan; | 483 Label nan; |
| 487 __ Fcmp(lhs_d, rhs_d); | 484 __ Fcmp(lhs_d, rhs_d); |
| 488 __ B(vs, &nan); // Overflow flag set if either is NaN. | 485 __ B(vs, &nan); // Overflow flag set if either is NaN. |
| 489 STATIC_ASSERT((LESS == -1) && (EQUAL == 0) && (GREATER == 1)); | 486 STATIC_ASSERT((LESS == -1) && (EQUAL == 0) && (GREATER == 1)); |
| 490 __ Cset(result, gt); // gt => 1, otherwise (lt, eq) => 0 (EQUAL). | 487 __ Cset(result, gt); // gt => 1, otherwise (lt, eq) => 0 (EQUAL). |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 __ TailCallRuntime(Runtime::kCompare); | 603 __ TailCallRuntime(Runtime::kCompare); |
| 607 } | 604 } |
| 608 | 605 |
| 609 __ Bind(&miss); | 606 __ Bind(&miss); |
| 610 GenerateMiss(masm); | 607 GenerateMiss(masm); |
| 611 } | 608 } |
| 612 | 609 |
| 613 | 610 |
| 614 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 611 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 615 CPURegList saved_regs = kCallerSaved; | 612 CPURegList saved_regs = kCallerSaved; |
| 616 CPURegList saved_fp_regs = kCallerSavedFP; | 613 CPURegList saved_fp_regs = kCallerSavedV; |
| 617 | 614 |
| 618 // We don't allow a GC during a store buffer overflow so there is no need to | 615 // We don't allow a GC during a store buffer overflow so there is no need to |
| 619 // store the registers in any particular way, but we do have to store and | 616 // store the registers in any particular way, but we do have to store and |
| 620 // restore them. | 617 // restore them. |
| 621 | 618 |
| 622 // We don't care if MacroAssembler scratch registers are corrupted. | 619 // We don't care if MacroAssembler scratch registers are corrupted. |
| 623 saved_regs.Remove(*(masm->TmpList())); | 620 saved_regs.Remove(*(masm->TmpList())); |
| 624 saved_fp_regs.Remove(*(masm->FPTmpList())); | 621 saved_fp_regs.Remove(*(masm->FPTmpList())); |
| 625 | 622 |
| 626 __ PushCPURegList(saved_regs); | 623 __ PushCPURegList(saved_regs); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 // jssp[0]: Exponent (as a tagged value). | 676 // jssp[0]: Exponent (as a tagged value). |
| 680 // jssp[1]: Base (as a tagged value). | 677 // jssp[1]: Base (as a tagged value). |
| 681 // | 678 // |
| 682 // The (tagged) result will be returned in x0, as a heap number. | 679 // The (tagged) result will be returned in x0, as a heap number. |
| 683 | 680 |
| 684 Register exponent_tagged = MathPowTaggedDescriptor::exponent(); | 681 Register exponent_tagged = MathPowTaggedDescriptor::exponent(); |
| 685 DCHECK(exponent_tagged.is(x11)); | 682 DCHECK(exponent_tagged.is(x11)); |
| 686 Register exponent_integer = MathPowIntegerDescriptor::exponent(); | 683 Register exponent_integer = MathPowIntegerDescriptor::exponent(); |
| 687 DCHECK(exponent_integer.is(x12)); | 684 DCHECK(exponent_integer.is(x12)); |
| 688 Register saved_lr = x19; | 685 Register saved_lr = x19; |
| 689 FPRegister result_double = d0; | 686 VRegister result_double = d0; |
| 690 FPRegister base_double = d0; | 687 VRegister base_double = d0; |
| 691 FPRegister exponent_double = d1; | 688 VRegister exponent_double = d1; |
| 692 FPRegister base_double_copy = d2; | 689 VRegister base_double_copy = d2; |
| 693 FPRegister scratch1_double = d6; | 690 VRegister scratch1_double = d6; |
| 694 FPRegister scratch0_double = d7; | 691 VRegister scratch0_double = d7; |
| 695 | 692 |
| 696 // A fast-path for integer exponents. | 693 // A fast-path for integer exponents. |
| 697 Label exponent_is_smi, exponent_is_integer; | 694 Label exponent_is_smi, exponent_is_integer; |
| 698 // Allocate a heap number for the result, and return it. | 695 // Allocate a heap number for the result, and return it. |
| 699 Label done; | 696 Label done; |
| 700 | 697 |
| 701 // Unpack the inputs. | 698 // Unpack the inputs. |
| 702 if (exponent_type() == TAGGED) { | 699 if (exponent_type() == TAGGED) { |
| 703 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); | 700 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); |
| 704 __ Ldr(exponent_double, | 701 __ Ldr(exponent_double, |
| (...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1575 DCHECK(state() == CompareICState::NUMBER); | 1572 DCHECK(state() == CompareICState::NUMBER); |
| 1576 ASM_LOCATION("CompareICStub[HeapNumbers]"); | 1573 ASM_LOCATION("CompareICStub[HeapNumbers]"); |
| 1577 | 1574 |
| 1578 Label unordered, maybe_undefined1, maybe_undefined2; | 1575 Label unordered, maybe_undefined1, maybe_undefined2; |
| 1579 Label miss, handle_lhs, values_in_d_regs; | 1576 Label miss, handle_lhs, values_in_d_regs; |
| 1580 Label untag_rhs, untag_lhs; | 1577 Label untag_rhs, untag_lhs; |
| 1581 | 1578 |
| 1582 Register result = x0; | 1579 Register result = x0; |
| 1583 Register rhs = x0; | 1580 Register rhs = x0; |
| 1584 Register lhs = x1; | 1581 Register lhs = x1; |
| 1585 FPRegister rhs_d = d0; | 1582 VRegister rhs_d = d0; |
| 1586 FPRegister lhs_d = d1; | 1583 VRegister lhs_d = d1; |
| 1587 | 1584 |
| 1588 if (left() == CompareICState::SMI) { | 1585 if (left() == CompareICState::SMI) { |
| 1589 __ JumpIfNotSmi(lhs, &miss); | 1586 __ JumpIfNotSmi(lhs, &miss); |
| 1590 } | 1587 } |
| 1591 if (right() == CompareICState::SMI) { | 1588 if (right() == CompareICState::SMI) { |
| 1592 __ JumpIfNotSmi(rhs, &miss); | 1589 __ JumpIfNotSmi(rhs, &miss); |
| 1593 } | 1590 } |
| 1594 | 1591 |
| 1595 __ SmiUntagToDouble(rhs_d, rhs, kSpeculativeUntag); | 1592 __ SmiUntagToDouble(rhs_d, rhs, kSpeculativeUntag); |
| 1596 __ SmiUntagToDouble(lhs_d, lhs, kSpeculativeUntag); | 1593 __ SmiUntagToDouble(lhs_d, lhs, kSpeculativeUntag); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2035 __ TailCallStub(&stub); | 2032 __ TailCallStub(&stub); |
| 2036 } | 2033 } |
| 2037 | 2034 |
| 2038 RecordWriteStub::RegisterAllocation::RegisterAllocation(Register object, | 2035 RecordWriteStub::RegisterAllocation::RegisterAllocation(Register object, |
| 2039 Register address, | 2036 Register address, |
| 2040 Register scratch) | 2037 Register scratch) |
| 2041 : object_(object), | 2038 : object_(object), |
| 2042 address_(address), | 2039 address_(address), |
| 2043 scratch0_(scratch), | 2040 scratch0_(scratch), |
| 2044 saved_regs_(kCallerSaved), | 2041 saved_regs_(kCallerSaved), |
| 2045 saved_fp_regs_(kCallerSavedFP) { | 2042 saved_fp_regs_(kCallerSavedV) { |
| 2046 DCHECK(!AreAliased(scratch, object, address)); | 2043 DCHECK(!AreAliased(scratch, object, address)); |
| 2047 | 2044 |
| 2048 // The SaveCallerSaveRegisters method needs to save caller-saved | 2045 // The SaveCallerSaveRegisters method needs to save caller-saved |
| 2049 // registers, but we don't bother saving MacroAssembler scratch registers. | 2046 // registers, but we don't bother saving MacroAssembler scratch registers. |
| 2050 saved_regs_.Remove(MacroAssembler::DefaultTmpList()); | 2047 saved_regs_.Remove(MacroAssembler::DefaultTmpList()); |
| 2051 saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList()); | 2048 saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList()); |
| 2052 | 2049 |
| 2053 // We would like to require more scratch registers for this stub, | 2050 // We would like to require more scratch registers for this stub, |
| 2054 // but the number of registers comes down to the ones used in | 2051 // but the number of registers comes down to the ones used in |
| 2055 // FullCodeGen::SetVar(), which is architecture independent. | 2052 // FullCodeGen::SetVar(), which is architecture independent. |
| (...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3161 kStackUnwindSpace, NULL, spill_offset, | 3158 kStackUnwindSpace, NULL, spill_offset, |
| 3162 return_value_operand, NULL); | 3159 return_value_operand, NULL); |
| 3163 } | 3160 } |
| 3164 | 3161 |
| 3165 #undef __ | 3162 #undef __ |
| 3166 | 3163 |
| 3167 } // namespace internal | 3164 } // namespace internal |
| 3168 } // namespace v8 | 3165 } // namespace v8 |
| 3169 | 3166 |
| 3170 #endif // V8_TARGET_ARCH_ARM64 | 3167 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |