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/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.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" |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 *first_index += 2; | 135 *first_index += 2; |
136 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); | 136 return MemOperand(InputRegister(index + 0), InputInt32(index + 1)); |
137 case kMode_Offset_RR: | 137 case kMode_Offset_RR: |
138 *first_index += 2; | 138 *first_index += 2; |
139 return MemOperand(InputRegister(index + 0), InputRegister(index + 1)); | 139 return MemOperand(InputRegister(index + 0), InputRegister(index + 1)); |
140 } | 140 } |
141 UNREACHABLE(); | 141 UNREACHABLE(); |
142 return MemOperand(r0); | 142 return MemOperand(r0); |
143 } | 143 } |
144 | 144 |
145 MemOperand InputOffset() { | 145 MemOperand InputOffset(int first_index = 0) { |
146 int index = 0; | 146 return InputOffset(&first_index); |
147 return InputOffset(&index); | |
148 } | 147 } |
149 | 148 |
150 MemOperand ToMemOperand(InstructionOperand* op) const { | 149 MemOperand ToMemOperand(InstructionOperand* op) const { |
151 DCHECK(op != NULL); | 150 DCHECK(op != NULL); |
152 DCHECK(!op->IsRegister()); | 151 DCHECK(!op->IsRegister()); |
153 DCHECK(!op->IsDoubleRegister()); | 152 DCHECK(!op->IsDoubleRegister()); |
154 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 153 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
155 // The linkage computes where all spill slots are located. | 154 // The linkage computes where all spill slots are located. |
156 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); | 155 FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0); |
157 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); | 156 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); |
158 } | 157 } |
159 }; | 158 }; |
160 | 159 |
161 | 160 |
| 161 namespace { |
| 162 |
| 163 class OutOfLineLoadFloat32 FINAL : public OutOfLineCode { |
| 164 public: |
| 165 OutOfLineLoadFloat32(CodeGenerator* gen, SwVfpRegister result) |
| 166 : OutOfLineCode(gen), result_(result) {} |
| 167 |
| 168 void Generate() FINAL { |
| 169 __ vmov(result_, std::numeric_limits<float>::quiet_NaN()); |
| 170 } |
| 171 |
| 172 private: |
| 173 SwVfpRegister const result_; |
| 174 }; |
| 175 |
| 176 |
| 177 class OutOfLineLoadFloat64 FINAL : public OutOfLineCode { |
| 178 public: |
| 179 OutOfLineLoadFloat64(CodeGenerator* gen, DwVfpRegister result) |
| 180 : OutOfLineCode(gen), result_(result) {} |
| 181 |
| 182 void Generate() FINAL { |
| 183 __ vmov(result_, std::numeric_limits<double>::quiet_NaN(), kScratchReg); |
| 184 } |
| 185 |
| 186 private: |
| 187 DwVfpRegister const result_; |
| 188 }; |
| 189 |
| 190 |
| 191 class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
| 192 public: |
| 193 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
| 194 : OutOfLineCode(gen), result_(result) {} |
| 195 |
| 196 void Generate() FINAL { __ mov(result_, Operand::Zero()); } |
| 197 |
| 198 private: |
| 199 Register const result_; |
| 200 }; |
| 201 |
| 202 } // namespace |
| 203 |
| 204 |
| 205 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width) \ |
| 206 do { \ |
| 207 auto result = i.OutputFloat##width##Register(); \ |
| 208 auto offset = i.InputRegister(0); \ |
| 209 if (instr->InputAt(1)->IsRegister()) { \ |
| 210 __ cmp(offset, i.InputRegister(1)); \ |
| 211 } else { \ |
| 212 __ cmp(offset, i.InputImmediate(1)); \ |
| 213 } \ |
| 214 auto ool = new (zone()) OutOfLineLoadFloat##width(this, result); \ |
| 215 __ b(hs, ool->entry()); \ |
| 216 __ vldr(result, i.InputOffset(2)); \ |
| 217 __ bind(ool->exit()); \ |
| 218 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
| 219 } while (0) |
| 220 |
| 221 |
| 222 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
| 223 do { \ |
| 224 auto result = i.OutputRegister(); \ |
| 225 auto offset = i.InputRegister(0); \ |
| 226 if (instr->InputAt(1)->IsRegister()) { \ |
| 227 __ cmp(offset, i.InputRegister(1)); \ |
| 228 } else { \ |
| 229 __ cmp(offset, i.InputImmediate(1)); \ |
| 230 } \ |
| 231 auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
| 232 __ b(hs, ool->entry()); \ |
| 233 __ asm_instr(result, i.InputOffset(2)); \ |
| 234 __ bind(ool->exit()); \ |
| 235 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
| 236 } while (0) |
| 237 |
| 238 |
| 239 #define ASSEMBLE_CHECKED_STORE_FLOAT(width) \ |
| 240 do { \ |
| 241 auto offset = i.InputRegister(0); \ |
| 242 if (instr->InputAt(1)->IsRegister()) { \ |
| 243 __ cmp(offset, i.InputRegister(1)); \ |
| 244 } else { \ |
| 245 __ cmp(offset, i.InputImmediate(1)); \ |
| 246 } \ |
| 247 auto value = i.InputFloat##width##Register(2); \ |
| 248 __ vstr(value, i.InputOffset(3), lo); \ |
| 249 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
| 250 } while (0) |
| 251 |
| 252 |
| 253 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 254 do { \ |
| 255 auto offset = i.InputRegister(0); \ |
| 256 if (instr->InputAt(1)->IsRegister()) { \ |
| 257 __ cmp(offset, i.InputRegister(1)); \ |
| 258 } else { \ |
| 259 __ cmp(offset, i.InputImmediate(1)); \ |
| 260 } \ |
| 261 auto value = i.InputRegister(2); \ |
| 262 __ asm_instr(value, i.InputOffset(3), lo); \ |
| 263 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
| 264 } while (0) |
| 265 |
| 266 |
162 // Assembles an instruction after register allocation, producing machine code. | 267 // Assembles an instruction after register allocation, producing machine code. |
163 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 268 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
164 ArmOperandConverter i(this, instr); | 269 ArmOperandConverter i(this, instr); |
165 | 270 |
166 switch (ArchOpcodeField::decode(instr->opcode())) { | 271 switch (ArchOpcodeField::decode(instr->opcode())) { |
167 case kArchCallCodeObject: { | 272 case kArchCallCodeObject: { |
168 EnsureSpaceForLazyDeopt(); | 273 EnsureSpaceForLazyDeopt(); |
169 if (instr->InputAt(0)->IsImmediate()) { | 274 if (instr->InputAt(0)->IsImmediate()) { |
170 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 275 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
171 RelocInfo::CODE_TARGET); | 276 RelocInfo::CODE_TARGET); |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 Register value = i.InputRegister(2); | 633 Register value = i.InputRegister(2); |
529 __ add(index, object, index); | 634 __ add(index, object, index); |
530 __ str(value, MemOperand(index)); | 635 __ str(value, MemOperand(index)); |
531 SaveFPRegsMode mode = | 636 SaveFPRegsMode mode = |
532 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 637 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
533 LinkRegisterStatus lr_status = kLRHasNotBeenSaved; | 638 LinkRegisterStatus lr_status = kLRHasNotBeenSaved; |
534 __ RecordWrite(object, index, value, lr_status, mode); | 639 __ RecordWrite(object, index, value, lr_status, mode); |
535 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 640 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
536 break; | 641 break; |
537 } | 642 } |
| 643 case kCheckedLoadInt8: |
| 644 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsb); |
| 645 break; |
| 646 case kCheckedLoadUint8: |
| 647 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrb); |
| 648 break; |
| 649 case kCheckedLoadInt16: |
| 650 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsh); |
| 651 break; |
| 652 case kCheckedLoadUint16: |
| 653 ASSEMBLE_CHECKED_LOAD_INTEGER(ldrh); |
| 654 break; |
| 655 case kCheckedLoadWord32: |
| 656 ASSEMBLE_CHECKED_LOAD_INTEGER(ldr); |
| 657 break; |
| 658 case kCheckedLoadFloat32: |
| 659 ASSEMBLE_CHECKED_LOAD_FLOAT(32); |
| 660 break; |
| 661 case kCheckedLoadFloat64: |
| 662 ASSEMBLE_CHECKED_LOAD_FLOAT(64); |
| 663 break; |
| 664 case kCheckedStoreWord8: |
| 665 ASSEMBLE_CHECKED_STORE_INTEGER(strb); |
| 666 break; |
| 667 case kCheckedStoreWord16: |
| 668 ASSEMBLE_CHECKED_STORE_INTEGER(strh); |
| 669 break; |
| 670 case kCheckedStoreWord32: |
| 671 ASSEMBLE_CHECKED_STORE_INTEGER(str); |
| 672 break; |
| 673 case kCheckedStoreFloat32: |
| 674 ASSEMBLE_CHECKED_STORE_FLOAT(32); |
| 675 break; |
| 676 case kCheckedStoreFloat64: |
| 677 ASSEMBLE_CHECKED_STORE_FLOAT(64); |
| 678 break; |
538 } | 679 } |
539 } | 680 } |
540 | 681 |
541 | 682 |
542 // Assembles branches after an instruction. | 683 // Assembles branches after an instruction. |
543 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 684 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
544 ArmOperandConverter i(this, instr); | 685 ArmOperandConverter i(this, instr); |
545 Label* tlabel = branch->true_label; | 686 Label* tlabel = branch->true_label; |
546 Label* flabel = branch->false_label; | 687 Label* flabel = branch->false_label; |
547 switch (branch->condition) { | 688 switch (branch->condition) { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 break; | 962 break; |
822 case Constant::kHeapObject: | 963 case Constant::kHeapObject: |
823 __ Move(dst, src.ToHeapObject()); | 964 __ Move(dst, src.ToHeapObject()); |
824 break; | 965 break; |
825 case Constant::kRpoNumber: | 966 case Constant::kRpoNumber: |
826 UNREACHABLE(); // TODO(dcarney): loading RPO constants on arm. | 967 UNREACHABLE(); // TODO(dcarney): loading RPO constants on arm. |
827 break; | 968 break; |
828 } | 969 } |
829 if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination)); | 970 if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination)); |
830 } else if (src.type() == Constant::kFloat32) { | 971 } else if (src.type() == Constant::kFloat32) { |
831 SwVfpRegister dst = destination->IsDoubleRegister() | |
832 ? g.ToFloat32Register(destination) | |
833 : kScratchDoubleReg.low(); | |
834 // TODO(turbofan): Can we do better here? | |
835 __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32()))); | |
836 __ vmov(dst, ip); | |
837 if (destination->IsDoubleStackSlot()) { | 972 if (destination->IsDoubleStackSlot()) { |
838 __ vstr(dst, g.ToMemOperand(destination)); | 973 MemOperand dst = g.ToMemOperand(destination); |
| 974 __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
| 975 __ str(ip, dst); |
| 976 } else { |
| 977 SwVfpRegister dst = g.ToFloat32Register(destination); |
| 978 __ vmov(dst, src.ToFloat32()); |
839 } | 979 } |
840 } else { | 980 } else { |
841 DCHECK_EQ(Constant::kFloat64, src.type()); | 981 DCHECK_EQ(Constant::kFloat64, src.type()); |
842 DwVfpRegister dst = destination->IsDoubleRegister() | 982 DwVfpRegister dst = destination->IsDoubleRegister() |
843 ? g.ToFloat64Register(destination) | 983 ? g.ToFloat64Register(destination) |
844 : kScratchDoubleReg; | 984 : kScratchDoubleReg; |
845 __ vmov(dst, src.ToFloat64()); | 985 __ vmov(dst, src.ToFloat64(), kScratchReg); |
846 if (destination->IsDoubleStackSlot()) { | 986 if (destination->IsDoubleStackSlot()) { |
847 __ vstr(dst, g.ToMemOperand(destination)); | 987 __ vstr(dst, g.ToMemOperand(destination)); |
848 } | 988 } |
849 } | 989 } |
850 } else if (source->IsDoubleRegister()) { | 990 } else if (source->IsDoubleRegister()) { |
851 DwVfpRegister src = g.ToDoubleRegister(source); | 991 DwVfpRegister src = g.ToDoubleRegister(source); |
852 if (destination->IsDoubleRegister()) { | 992 if (destination->IsDoubleRegister()) { |
853 DwVfpRegister dst = g.ToDoubleRegister(destination); | 993 DwVfpRegister dst = g.ToDoubleRegister(destination); |
854 __ Move(dst, src); | 994 __ Move(dst, src); |
855 } else { | 995 } else { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 } | 1102 } |
963 } | 1103 } |
964 MarkLazyDeoptSite(); | 1104 MarkLazyDeoptSite(); |
965 } | 1105 } |
966 | 1106 |
967 #undef __ | 1107 #undef __ |
968 | 1108 |
969 } // namespace compiler | 1109 } // namespace compiler |
970 } // namespace internal | 1110 } // namespace internal |
971 } // namespace v8 | 1111 } // namespace v8 |
OLD | NEW |