| 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 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
| 8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
| 9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
| 10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 return Operand(Immediate(disp)); | 148 return Operand(Immediate(disp)); |
| 149 } | 149 } |
| 150 case kMode_None: | 150 case kMode_None: |
| 151 UNREACHABLE(); | 151 UNREACHABLE(); |
| 152 return Operand(no_reg, 0); | 152 return Operand(no_reg, 0); |
| 153 } | 153 } |
| 154 UNREACHABLE(); | 154 UNREACHABLE(); |
| 155 return Operand(no_reg, 0); | 155 return Operand(no_reg, 0); |
| 156 } | 156 } |
| 157 | 157 |
| 158 Operand MemoryOperand() { | 158 Operand MemoryOperand(int first_input = 0) { |
| 159 int first_input = 0; | |
| 160 return MemoryOperand(&first_input); | 159 return MemoryOperand(&first_input); |
| 161 } | 160 } |
| 162 }; | 161 }; |
| 163 | 162 |
| 164 | 163 |
| 165 static bool HasImmediateInput(Instruction* instr, int index) { | 164 namespace { |
| 165 |
| 166 bool HasImmediateInput(Instruction* instr, int index) { |
| 166 return instr->InputAt(index)->IsImmediate(); | 167 return instr->InputAt(index)->IsImmediate(); |
| 167 } | 168 } |
| 168 | 169 |
| 169 | 170 |
| 171 class OutOfLineLoadInteger FINAL : public OutOfLineCode { |
| 172 public: |
| 173 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
| 174 : OutOfLineCode(gen), result_(result) {} |
| 175 |
| 176 void Generate() FINAL { __ xor_(result_, result_); } |
| 177 |
| 178 private: |
| 179 Register const result_; |
| 180 }; |
| 181 |
| 182 |
| 183 class OutOfLineLoadFloat FINAL : public OutOfLineCode { |
| 184 public: |
| 185 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result) |
| 186 : OutOfLineCode(gen), result_(result) {} |
| 187 |
| 188 void Generate() FINAL { __ pcmpeqd(result_, result_); } |
| 189 |
| 190 private: |
| 191 XMMRegister const result_; |
| 192 }; |
| 193 |
| 194 } // namespace |
| 195 |
| 196 |
| 197 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
| 198 do { \ |
| 199 auto result = i.OutputDoubleRegister(); \ |
| 200 auto offset = i.InputRegister(0); \ |
| 201 if (instr->InputAt(1)->IsRegister()) { \ |
| 202 __ cmp(offset, i.InputRegister(1)); \ |
| 203 } else { \ |
| 204 __ cmp(offset, i.InputImmediate(1)); \ |
| 205 } \ |
| 206 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ |
| 207 __ j(above_equal, ool->entry()); \ |
| 208 __ asm_instr(result, i.MemoryOperand(2)); \ |
| 209 __ bind(ool->exit()); \ |
| 210 } while (false) |
| 211 |
| 212 |
| 213 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
| 214 do { \ |
| 215 auto result = i.OutputRegister(); \ |
| 216 auto offset = i.InputRegister(0); \ |
| 217 if (instr->InputAt(1)->IsRegister()) { \ |
| 218 __ cmp(offset, i.InputRegister(1)); \ |
| 219 } else { \ |
| 220 __ cmp(offset, i.InputImmediate(1)); \ |
| 221 } \ |
| 222 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
| 223 __ j(above_equal, ool->entry()); \ |
| 224 __ asm_instr(result, i.MemoryOperand(2)); \ |
| 225 __ bind(ool->exit()); \ |
| 226 } while (false) |
| 227 |
| 228 |
| 229 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ |
| 230 do { \ |
| 231 auto offset = i.InputRegister(0); \ |
| 232 if (instr->InputAt(1)->IsRegister()) { \ |
| 233 __ cmp(offset, i.InputRegister(1)); \ |
| 234 } else { \ |
| 235 __ cmp(offset, i.InputImmediate(1)); \ |
| 236 } \ |
| 237 Label done; \ |
| 238 __ j(above_equal, &done, Label::kNear); \ |
| 239 __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \ |
| 240 __ bind(&done); \ |
| 241 } while (false) |
| 242 |
| 243 |
| 244 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 245 do { \ |
| 246 auto offset = i.InputRegister(0); \ |
| 247 if (instr->InputAt(1)->IsRegister()) { \ |
| 248 __ cmp(offset, i.InputRegister(1)); \ |
| 249 } else { \ |
| 250 __ cmp(offset, i.InputImmediate(1)); \ |
| 251 } \ |
| 252 Label done; \ |
| 253 __ j(above_equal, &done, Label::kNear); \ |
| 254 if (instr->InputAt(2)->IsRegister()) { \ |
| 255 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ |
| 256 } else { \ |
| 257 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ |
| 258 } \ |
| 259 __ bind(&done); \ |
| 260 } while (false) |
| 261 |
| 262 |
| 170 // Assembles an instruction after register allocation, producing machine code. | 263 // Assembles an instruction after register allocation, producing machine code. |
| 171 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 264 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| 172 IA32OperandConverter i(this, instr); | 265 IA32OperandConverter i(this, instr); |
| 173 | 266 |
| 174 switch (ArchOpcodeField::decode(instr->opcode())) { | 267 switch (ArchOpcodeField::decode(instr->opcode())) { |
| 175 case kArchCallCodeObject: { | 268 case kArchCallCodeObject: { |
| 176 EnsureSpaceForLazyDeopt(); | 269 EnsureSpaceForLazyDeopt(); |
| 177 if (HasImmediateInput(instr, 0)) { | 270 if (HasImmediateInput(instr, 0)) { |
| 178 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 271 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
| 179 __ call(code, RelocInfo::CODE_TARGET); | 272 __ call(code, RelocInfo::CODE_TARGET); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 Register object = i.InputRegister(0); | 569 Register object = i.InputRegister(0); |
| 477 Register index = i.InputRegister(1); | 570 Register index = i.InputRegister(1); |
| 478 Register value = i.InputRegister(2); | 571 Register value = i.InputRegister(2); |
| 479 __ mov(Operand(object, index, times_1, 0), value); | 572 __ mov(Operand(object, index, times_1, 0), value); |
| 480 __ lea(index, Operand(object, index, times_1, 0)); | 573 __ lea(index, Operand(object, index, times_1, 0)); |
| 481 SaveFPRegsMode mode = | 574 SaveFPRegsMode mode = |
| 482 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 575 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
| 483 __ RecordWrite(object, index, value, mode); | 576 __ RecordWrite(object, index, value, mode); |
| 484 break; | 577 break; |
| 485 } | 578 } |
| 579 case kCheckedLoadInt8: |
| 580 ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b); |
| 581 break; |
| 582 case kCheckedLoadUint8: |
| 583 ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_b); |
| 584 break; |
| 585 case kCheckedLoadInt16: |
| 586 ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_w); |
| 587 break; |
| 588 case kCheckedLoadUint16: |
| 589 ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_w); |
| 590 break; |
| 591 case kCheckedLoadWord32: |
| 592 ASSEMBLE_CHECKED_LOAD_INTEGER(mov); |
| 593 break; |
| 594 case kCheckedLoadFloat32: |
| 595 ASSEMBLE_CHECKED_LOAD_FLOAT(movss); |
| 596 break; |
| 597 case kCheckedLoadFloat64: |
| 598 ASSEMBLE_CHECKED_LOAD_FLOAT(movsd); |
| 599 break; |
| 600 case kCheckedStoreWord8: |
| 601 ASSEMBLE_CHECKED_STORE_INTEGER(mov_b); |
| 602 break; |
| 603 case kCheckedStoreWord16: |
| 604 ASSEMBLE_CHECKED_STORE_INTEGER(mov_w); |
| 605 break; |
| 606 case kCheckedStoreWord32: |
| 607 ASSEMBLE_CHECKED_STORE_INTEGER(mov); |
| 608 break; |
| 609 case kCheckedStoreFloat32: |
| 610 ASSEMBLE_CHECKED_STORE_FLOAT(movss); |
| 611 break; |
| 612 case kCheckedStoreFloat64: |
| 613 ASSEMBLE_CHECKED_STORE_FLOAT(movsd); |
| 614 break; |
| 486 } | 615 } |
| 487 } | 616 } |
| 488 | 617 |
| 489 | 618 |
| 490 // Assembles a branch after an instruction. | 619 // Assembles a branch after an instruction. |
| 491 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 620 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 492 IA32OperandConverter i(this, instr); | 621 IA32OperandConverter i(this, instr); |
| 493 Label::Distance flabel_distance = | 622 Label::Distance flabel_distance = |
| 494 branch->fallthru ? Label::kNear : Label::kFar; | 623 branch->fallthru ? Label::kNear : Label::kFar; |
| 495 Label* tlabel = branch->true_label; | 624 Label* tlabel = branch->true_label; |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 } | 1163 } |
| 1035 } | 1164 } |
| 1036 MarkLazyDeoptSite(); | 1165 MarkLazyDeoptSite(); |
| 1037 } | 1166 } |
| 1038 | 1167 |
| 1039 #undef __ | 1168 #undef __ |
| 1040 | 1169 |
| 1041 } // namespace compiler | 1170 } // namespace compiler |
| 1042 } // namespace internal | 1171 } // namespace internal |
| 1043 } // namespace v8 | 1172 } // namespace v8 |
| OLD | NEW |