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 |