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 |