| 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 |