| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/arm64/macro-assembler-arm64.h" | 7 #include "src/arm64/macro-assembler-arm64.h" |
| 8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
| 9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| 11 #include "src/compiler/node-properties-inl.h" | 11 #include "src/compiler/node-properties-inl.h" |
| 12 #include "src/scopes.h" | 12 #include "src/scopes.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 namespace compiler { | 16 namespace compiler { |
| 17 | 17 |
| 18 #define __ masm()-> | 18 #define __ masm()-> |
| 19 | 19 |
| 20 | 20 |
| 21 // Adds Arm64-specific methods to convert InstructionOperands. | 21 // Adds Arm64-specific methods to convert InstructionOperands. |
| 22 class Arm64OperandConverter FINAL : public InstructionOperandConverter { | 22 class Arm64OperandConverter FINAL : public InstructionOperandConverter { |
| 23 public: | 23 public: |
| 24 Arm64OperandConverter(CodeGenerator* gen, Instruction* instr) | 24 Arm64OperandConverter(CodeGenerator* gen, Instruction* instr) |
| 25 : InstructionOperandConverter(gen, instr) {} | 25 : InstructionOperandConverter(gen, instr) {} |
| 26 | 26 |
| 27 DoubleRegister InputFloat32Register(int index) { |
| 28 return InputDoubleRegister(index).S(); |
| 29 } |
| 30 |
| 31 DoubleRegister InputFloat64Register(int index) { |
| 32 return InputDoubleRegister(index); |
| 33 } |
| 34 |
| 35 DoubleRegister OutputFloat32Register() { return OutputDoubleRegister().S(); } |
| 36 |
| 37 DoubleRegister OutputFloat64Register() { return OutputDoubleRegister(); } |
| 38 |
| 27 Register InputRegister32(int index) { | 39 Register InputRegister32(int index) { |
| 28 return ToRegister(instr_->InputAt(index)).W(); | 40 return ToRegister(instr_->InputAt(index)).W(); |
| 29 } | 41 } |
| 30 | 42 |
| 31 Register InputRegister64(int index) { return InputRegister(index); } | 43 Register InputRegister64(int index) { return InputRegister(index); } |
| 32 | 44 |
| 33 Operand InputImmediate(int index) { | 45 Operand InputImmediate(int index) { |
| 34 return ToImmediate(instr_->InputAt(index)); | 46 return ToImmediate(instr_->InputAt(index)); |
| 35 } | 47 } |
| 36 | 48 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 *first_index += 2; | 111 *first_index += 2; |
| 100 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); | 112 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); |
| 101 case kMode_MRR: | 113 case kMode_MRR: |
| 102 *first_index += 2; | 114 *first_index += 2; |
| 103 return MemOperand(InputRegister(index + 0), InputRegister(index + 1)); | 115 return MemOperand(InputRegister(index + 0), InputRegister(index + 1)); |
| 104 } | 116 } |
| 105 UNREACHABLE(); | 117 UNREACHABLE(); |
| 106 return MemOperand(no_reg); | 118 return MemOperand(no_reg); |
| 107 } | 119 } |
| 108 | 120 |
| 109 MemOperand MemoryOperand() { | 121 MemOperand MemoryOperand(int first_index = 0) { |
| 110 int index = 0; | 122 return MemoryOperand(&first_index); |
| 111 return MemoryOperand(&index); | |
| 112 } | 123 } |
| 113 | 124 |
| 114 Operand ToOperand(InstructionOperand* op) { | 125 Operand ToOperand(InstructionOperand* op) { |
| 115 if (op->IsRegister()) { | 126 if (op->IsRegister()) { |
| 116 return Operand(ToRegister(op)); | 127 return Operand(ToRegister(op)); |
| 117 } | 128 } |
| 118 return ToImmediate(op); | 129 return ToImmediate(op); |
| 119 } | 130 } |
| 120 | 131 |
| 121 Operand ToOperand32(InstructionOperand* op) { | 132 Operand ToOperand32(InstructionOperand* op) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 DCHECK(!op->IsDoubleRegister()); | 167 DCHECK(!op->IsDoubleRegister()); |
| 157 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 168 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
| 158 // The linkage computes where all spill slots are located. | 169 // The linkage computes where all spill slots are located. |
| 159 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); | 170 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); |
| 160 return MemOperand(offset.from_stack_pointer() ? masm->StackPointer() : fp, | 171 return MemOperand(offset.from_stack_pointer() ? masm->StackPointer() : fp, |
| 161 offset.offset()); | 172 offset.offset()); |
| 162 } | 173 } |
| 163 }; | 174 }; |
| 164 | 175 |
| 165 | 176 |
| 177 namespace { |
| 178 |
| 179 class OutOfLineLoadFloat32 FINAL : public OutOfLineCode { |
| 180 public: |
| 181 OutOfLineLoadFloat32(CodeGenerator* gen, DoubleRegister result) |
| 182 : OutOfLineCode(gen), result_(result) {} |
| 183 |
| 184 void Generate() FINAL { |
| 185 __ Fmov(result_, std::numeric_limits<float>::quiet_NaN()); |
| 186 } |
| 187 |
| 188 private: |
| 189 DoubleRegister const result_; |
| 190 }; |
| 191 |
| 192 |
| 193 class OutOfLineLoadFloat64 FINAL : public OutOfLineCode { |
| 194 public: |
| 195 OutOfLineLoadFloat64(CodeGenerator* gen, DoubleRegister result) |
| 196 : OutOfLineCode(gen), result_(result) {} |
| 197 |
| 198 void Generate() FINAL { |
| 199 __ Fmov(result_, std::numeric_limits<double>::quiet_NaN()); |
| 200 } |
| 201 |
| 202 private: |
| 203 DoubleRegister const result_; |
| 204 }; |
| 205 |
| 206 |
| 207 class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
| 208 public: |
| 209 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
| 210 : OutOfLineCode(gen), result_(result) {} |
| 211 |
| 212 void Generate() FINAL { __ Mov(result_, 0); } |
| 213 |
| 214 private: |
| 215 Register const result_; |
| 216 }; |
| 217 |
| 218 } // namespace |
| 219 |
| 220 |
| 221 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width) \ |
| 222 do { \ |
| 223 auto result = i.OutputFloat##width##Register(); \ |
| 224 auto offset = i.InputRegister32(0); \ |
| 225 auto length = i.InputOperand32(1); \ |
| 226 __ Cmp(offset, length); \ |
| 227 auto ool = new (zone()) OutOfLineLoadFloat##width(this, result); \ |
| 228 __ B(hs, ool->entry()); \ |
| 229 __ Ldr(result, i.MemoryOperand(2)); \ |
| 230 __ Bind(ool->exit()); \ |
| 231 } while (0) |
| 232 |
| 233 |
| 234 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
| 235 do { \ |
| 236 auto result = i.OutputRegister32(); \ |
| 237 auto offset = i.InputRegister32(0); \ |
| 238 auto length = i.InputOperand32(1); \ |
| 239 __ Cmp(offset, length); \ |
| 240 auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
| 241 __ B(hs, ool->entry()); \ |
| 242 __ asm_instr(result, i.MemoryOperand(2)); \ |
| 243 __ Bind(ool->exit()); \ |
| 244 } while (0) |
| 245 |
| 246 |
| 247 #define ASSEMBLE_CHECKED_STORE_FLOAT(width) \ |
| 248 do { \ |
| 249 auto offset = i.InputRegister32(0); \ |
| 250 auto length = i.InputOperand32(1); \ |
| 251 __ Cmp(offset, length); \ |
| 252 Label done; \ |
| 253 __ B(hs, &done); \ |
| 254 __ Str(i.InputFloat##width##Register(2), i.MemoryOperand(3)); \ |
| 255 __ Bind(&done); \ |
| 256 } while (0) |
| 257 |
| 258 |
| 259 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 260 do { \ |
| 261 auto offset = i.InputRegister32(0); \ |
| 262 auto length = i.InputOperand32(1); \ |
| 263 __ Cmp(offset, length); \ |
| 264 Label done; \ |
| 265 __ B(hs, &done); \ |
| 266 __ asm_instr(i.InputRegister32(2), i.MemoryOperand(3)); \ |
| 267 __ Bind(&done); \ |
| 268 } while (0) |
| 269 |
| 270 |
| 166 #define ASSEMBLE_SHIFT(asm_instr, width) \ | 271 #define ASSEMBLE_SHIFT(asm_instr, width) \ |
| 167 do { \ | 272 do { \ |
| 168 if (instr->InputAt(1)->IsRegister()) { \ | 273 if (instr->InputAt(1)->IsRegister()) { \ |
| 169 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), \ | 274 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), \ |
| 170 i.InputRegister##width(1)); \ | 275 i.InputRegister##width(1)); \ |
| 171 } else { \ | 276 } else { \ |
| 172 int64_t imm = i.InputOperand##width(1).immediate().value(); \ | 277 int64_t imm = i.InputOperand##width(1).immediate().value(); \ |
| 173 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), imm); \ | 278 __ asm_instr(i.OutputRegister##width(), i.InputRegister##width(0), imm); \ |
| 174 } \ | 279 } \ |
| 175 } while (0) | 280 } while (0) |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 temp = scope.AcquireX(); | 714 temp = scope.AcquireX(); |
| 610 lr_status = kLRHasBeenSaved; | 715 lr_status = kLRHasBeenSaved; |
| 611 __ Push(lr, temp); // Need to push a pair | 716 __ Push(lr, temp); // Need to push a pair |
| 612 } | 717 } |
| 613 __ RecordWrite(object, index, value, lr_status, mode); | 718 __ RecordWrite(object, index, value, lr_status, mode); |
| 614 if (csp.is(masm()->StackPointer())) { | 719 if (csp.is(masm()->StackPointer())) { |
| 615 __ Pop(temp, lr); | 720 __ Pop(temp, lr); |
| 616 } | 721 } |
| 617 break; | 722 break; |
| 618 } | 723 } |
| 724 case kCheckedLoadInt8: |
| 725 ASSEMBLE_CHECKED_LOAD_INTEGER(Ldrsb); |
| 726 break; |
| 727 case kCheckedLoadUint8: |
| 728 ASSEMBLE_CHECKED_LOAD_INTEGER(Ldrb); |
| 729 break; |
| 730 case kCheckedLoadInt16: |
| 731 ASSEMBLE_CHECKED_LOAD_INTEGER(Ldrsh); |
| 732 break; |
| 733 case kCheckedLoadUint16: |
| 734 ASSEMBLE_CHECKED_LOAD_INTEGER(Ldrh); |
| 735 break; |
| 736 case kCheckedLoadWord32: |
| 737 ASSEMBLE_CHECKED_LOAD_INTEGER(Ldr); |
| 738 break; |
| 739 case kCheckedLoadFloat32: |
| 740 ASSEMBLE_CHECKED_LOAD_FLOAT(32); |
| 741 break; |
| 742 case kCheckedLoadFloat64: |
| 743 ASSEMBLE_CHECKED_LOAD_FLOAT(64); |
| 744 break; |
| 745 case kCheckedStoreWord8: |
| 746 ASSEMBLE_CHECKED_STORE_INTEGER(Strb); |
| 747 break; |
| 748 case kCheckedStoreWord16: |
| 749 ASSEMBLE_CHECKED_STORE_INTEGER(Strh); |
| 750 break; |
| 751 case kCheckedStoreWord32: |
| 752 ASSEMBLE_CHECKED_STORE_INTEGER(Str); |
| 753 break; |
| 754 case kCheckedStoreFloat32: |
| 755 ASSEMBLE_CHECKED_STORE_FLOAT(32); |
| 756 break; |
| 757 case kCheckedStoreFloat64: |
| 758 ASSEMBLE_CHECKED_STORE_FLOAT(64); |
| 759 break; |
| 619 } | 760 } |
| 620 } | 761 } |
| 621 | 762 |
| 622 | 763 |
| 623 // Assemble branches after this instruction. | 764 // Assemble branches after this instruction. |
| 624 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 765 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 625 Arm64OperandConverter i(this, instr); | 766 Arm64OperandConverter i(this, instr); |
| 626 Label* tlabel = branch->true_label; | 767 Label* tlabel = branch->true_label; |
| 627 Label* flabel = branch->false_label; | 768 Label* flabel = branch->false_label; |
| 628 switch (branch->condition) { | 769 switch (branch->condition) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 case kUnsignedGreaterThan: | 904 case kUnsignedGreaterThan: |
| 764 cc = hi; | 905 cc = hi; |
| 765 break; | 906 break; |
| 766 case kOverflow: | 907 case kOverflow: |
| 767 cc = vs; | 908 cc = vs; |
| 768 break; | 909 break; |
| 769 case kNotOverflow: | 910 case kNotOverflow: |
| 770 cc = vc; | 911 cc = vc; |
| 771 break; | 912 break; |
| 772 } | 913 } |
| 773 __ bind(&check); | 914 __ Bind(&check); |
| 774 __ Cset(reg, cc); | 915 __ Cset(reg, cc); |
| 775 __ Bind(&done); | 916 __ Bind(&done); |
| 776 } | 917 } |
| 777 | 918 |
| 778 | 919 |
| 779 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { | 920 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { |
| 780 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 921 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
| 781 isolate(), deoptimization_id, Deoptimizer::LAZY); | 922 isolate(), deoptimization_id, Deoptimizer::LAZY); |
| 782 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 923 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
| 783 } | 924 } |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 } | 1157 } |
| 1017 } | 1158 } |
| 1018 MarkLazyDeoptSite(); | 1159 MarkLazyDeoptSite(); |
| 1019 } | 1160 } |
| 1020 | 1161 |
| 1021 #undef __ | 1162 #undef __ |
| 1022 | 1163 |
| 1023 } // namespace compiler | 1164 } // namespace compiler |
| 1024 } // namespace internal | 1165 } // namespace internal |
| 1025 } // namespace v8 | 1166 } // namespace v8 |
| OLD | NEW |