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()); | |
Rodolph Perfetta
2014/12/01 15:16:34
This won't do what you expect. Since result is a d
Benedikt Meurer
2014/12/01 17:58:39
Yeah the arm64 macro assembler can be quite confus
| |
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()); \ | |
Rodolph Perfetta
2014/12/01 15:16:34
nit, use the upper case variant: Bind. Same below.
Benedikt Meurer
2014/12/01 17:58:39
Done.
| |
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 387 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 |