| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 104 static bool HasImmediateInput(Instruction* instr, int index) { | 104 static bool HasImmediateInput(Instruction* instr, int index) { | 
| 105   return instr->InputAt(index)->IsImmediate(); | 105   return instr->InputAt(index)->IsImmediate(); | 
| 106 } | 106 } | 
| 107 | 107 | 
| 108 | 108 | 
| 109 // Assembles an instruction after register allocation, producing machine code. | 109 // Assembles an instruction after register allocation, producing machine code. | 
| 110 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 110 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 
| 111   IA32OperandConverter i(this, instr); | 111   IA32OperandConverter i(this, instr); | 
| 112 | 112 | 
| 113   switch (ArchOpcodeField::decode(instr->opcode())) { | 113   switch (ArchOpcodeField::decode(instr->opcode())) { | 
| 114     case kArchJmp: | 114     case kArchCallAddress: | 
| 115       __ jmp(code()->GetLabel(i.InputBlock(0))); | 115       if (HasImmediateInput(instr, 0)) { | 
|  | 116         // TODO(dcarney): wire up EXTERNAL_REFERENCE instead of RUNTIME_ENTRY. | 
|  | 117         __ call(reinterpret_cast<byte*>(i.InputInt32(0)), | 
|  | 118                 RelocInfo::RUNTIME_ENTRY); | 
|  | 119       } else { | 
|  | 120         __ call(i.InputRegister(0)); | 
|  | 121       } | 
| 116       break; | 122       break; | 
| 117     case kArchNop: | 123     case kArchCallCodeObject: { | 
| 118       // don't emit code for nops. | 124       if (HasImmediateInput(instr, 0)) { | 
|  | 125         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 
|  | 126         __ call(code, RelocInfo::CODE_TARGET); | 
|  | 127       } else { | 
|  | 128         Register reg = i.InputRegister(0); | 
|  | 129         __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag)); | 
|  | 130       } | 
|  | 131       AddSafepointAndDeopt(instr); | 
|  | 132       AddNopForSmiCodeInlining(); | 
| 119       break; | 133       break; | 
| 120     case kArchRet: | 134     } | 
| 121       AssembleReturn(); | 135     case kArchCallJSFunction: { | 
|  | 136       // TODO(jarin) The load of the context should be separated from the call. | 
|  | 137       Register func = i.InputRegister(0); | 
|  | 138       __ mov(esi, FieldOperand(func, JSFunction::kContextOffset)); | 
|  | 139       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 
|  | 140       AddSafepointAndDeopt(instr); | 
| 122       break; | 141       break; | 
|  | 142     } | 
| 123     case kArchDeoptimize: { | 143     case kArchDeoptimize: { | 
| 124       int deoptimization_id = MiscField::decode(instr->opcode()); | 144       int deoptimization_id = MiscField::decode(instr->opcode()); | 
| 125       BuildTranslation(instr, 0, deoptimization_id); | 145       BuildTranslation(instr, 0, deoptimization_id); | 
| 126 | 146 | 
| 127       Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 147       Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 
| 128           isolate(), deoptimization_id, Deoptimizer::LAZY); | 148           isolate(), deoptimization_id, Deoptimizer::LAZY); | 
| 129       __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 149       __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 
| 130       break; | 150       break; | 
| 131     } | 151     } | 
|  | 152     case kArchDrop: { | 
|  | 153       int words = MiscField::decode(instr->opcode()); | 
|  | 154       __ add(esp, Immediate(kPointerSize * words)); | 
|  | 155       break; | 
|  | 156     } | 
|  | 157     case kArchJmp: | 
|  | 158       __ jmp(code()->GetLabel(i.InputBlock(0))); | 
|  | 159       break; | 
|  | 160     case kArchNop: | 
|  | 161       // don't emit code for nops. | 
|  | 162       break; | 
|  | 163     case kArchRet: | 
|  | 164       AssembleReturn(); | 
|  | 165       break; | 
| 132     case kArchTruncateDoubleToI: | 166     case kArchTruncateDoubleToI: | 
| 133       __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 167       __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 
| 134       break; | 168       break; | 
| 135     case kIA32Add: | 169     case kIA32Add: | 
| 136       if (HasImmediateInput(instr, 1)) { | 170       if (HasImmediateInput(instr, 1)) { | 
| 137         __ add(i.InputOperand(0), i.InputImmediate(1)); | 171         __ add(i.InputOperand(0), i.InputImmediate(1)); | 
| 138       } else { | 172       } else { | 
| 139         __ add(i.InputRegister(0), i.InputOperand(1)); | 173         __ add(i.InputRegister(0), i.InputOperand(1)); | 
| 140       } | 174       } | 
| 141       break; | 175       break; | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 223         __ sar_cl(i.OutputRegister()); | 257         __ sar_cl(i.OutputRegister()); | 
| 224       } | 258       } | 
| 225       break; | 259       break; | 
| 226     case kIA32Ror: | 260     case kIA32Ror: | 
| 227       if (HasImmediateInput(instr, 1)) { | 261       if (HasImmediateInput(instr, 1)) { | 
| 228         __ ror(i.OutputRegister(), i.InputInt5(1)); | 262         __ ror(i.OutputRegister(), i.InputInt5(1)); | 
| 229       } else { | 263       } else { | 
| 230         __ ror_cl(i.OutputRegister()); | 264         __ ror_cl(i.OutputRegister()); | 
| 231       } | 265       } | 
| 232       break; | 266       break; | 
| 233     case kIA32Push: |  | 
| 234       if (HasImmediateInput(instr, 0)) { |  | 
| 235         __ push(i.InputImmediate(0)); |  | 
| 236       } else { |  | 
| 237         __ push(i.InputOperand(0)); |  | 
| 238       } |  | 
| 239       break; |  | 
| 240     case kIA32CallCodeObject: { |  | 
| 241       if (HasImmediateInput(instr, 0)) { |  | 
| 242         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |  | 
| 243         __ call(code, RelocInfo::CODE_TARGET); |  | 
| 244       } else { |  | 
| 245         Register reg = i.InputRegister(0); |  | 
| 246         int entry = Code::kHeaderSize - kHeapObjectTag; |  | 
| 247         __ call(Operand(reg, entry)); |  | 
| 248       } |  | 
| 249 |  | 
| 250       AddSafepointAndDeopt(instr); |  | 
| 251 |  | 
| 252       AddNopForSmiCodeInlining(); |  | 
| 253       break; |  | 
| 254     } |  | 
| 255     case kIA32CallAddress: |  | 
| 256       if (HasImmediateInput(instr, 0)) { |  | 
| 257         // TODO(dcarney): wire up EXTERNAL_REFERENCE instead of RUNTIME_ENTRY. |  | 
| 258         __ call(reinterpret_cast<byte*>(i.InputInt32(0)), |  | 
| 259                 RelocInfo::RUNTIME_ENTRY); |  | 
| 260       } else { |  | 
| 261         __ call(i.InputRegister(0)); |  | 
| 262       } |  | 
| 263       break; |  | 
| 264     case kPopStack: { |  | 
| 265       int words = MiscField::decode(instr->opcode()); |  | 
| 266       __ add(esp, Immediate(kPointerSize * words)); |  | 
| 267       break; |  | 
| 268     } |  | 
| 269     case kIA32CallJSFunction: { |  | 
| 270       Register func = i.InputRegister(0); |  | 
| 271 |  | 
| 272       // TODO(jarin) The load of the context should be separated from the call. |  | 
| 273       __ mov(esi, FieldOperand(func, JSFunction::kContextOffset)); |  | 
| 274       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |  | 
| 275 |  | 
| 276       AddSafepointAndDeopt(instr); |  | 
| 277       break; |  | 
| 278     } |  | 
| 279     case kSSEFloat64Cmp: | 267     case kSSEFloat64Cmp: | 
| 280       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1)); | 268       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1)); | 
| 281       break; | 269       break; | 
| 282     case kSSEFloat64Add: | 270     case kSSEFloat64Add: | 
| 283       __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); | 271       __ addsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); | 
| 284       break; | 272       break; | 
| 285     case kSSEFloat64Sub: | 273     case kSSEFloat64Sub: | 
| 286       __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); | 274       __ subsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); | 
| 287       break; | 275       break; | 
| 288     case kSSEFloat64Mul: | 276     case kSSEFloat64Mul: | 
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 393       if (instr->HasOutput()) { | 381       if (instr->HasOutput()) { | 
| 394         __ movss(i.OutputDoubleRegister(), i.MemoryOperand()); | 382         __ movss(i.OutputDoubleRegister(), i.MemoryOperand()); | 
| 395         __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister()); | 383         __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister()); | 
| 396       } else { | 384       } else { | 
| 397         int index = 0; | 385         int index = 0; | 
| 398         Operand operand = i.MemoryOperand(&index); | 386         Operand operand = i.MemoryOperand(&index); | 
| 399         __ cvtsd2ss(xmm0, i.InputDoubleRegister(index)); | 387         __ cvtsd2ss(xmm0, i.InputDoubleRegister(index)); | 
| 400         __ movss(operand, xmm0); | 388         __ movss(operand, xmm0); | 
| 401       } | 389       } | 
| 402       break; | 390       break; | 
|  | 391     case kIA32Push: | 
|  | 392       if (HasImmediateInput(instr, 0)) { | 
|  | 393         __ push(i.InputImmediate(0)); | 
|  | 394       } else { | 
|  | 395         __ push(i.InputOperand(0)); | 
|  | 396       } | 
|  | 397       break; | 
| 403     case kIA32StoreWriteBarrier: { | 398     case kIA32StoreWriteBarrier: { | 
| 404       Register object = i.InputRegister(0); | 399       Register object = i.InputRegister(0); | 
| 405       Register index = i.InputRegister(1); | 400       Register index = i.InputRegister(1); | 
| 406       Register value = i.InputRegister(2); | 401       Register value = i.InputRegister(2); | 
| 407       __ mov(Operand(object, index, times_1, 0), value); | 402       __ mov(Operand(object, index, times_1, 0), value); | 
| 408       __ lea(index, Operand(object, index, times_1, 0)); | 403       __ lea(index, Operand(object, index, times_1, 0)); | 
| 409       SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters() | 404       SaveFPRegsMode mode = code_->frame()->DidAllocateDoubleRegisters() | 
| 410                                 ? kSaveFPRegs | 405                                 ? kSaveFPRegs | 
| 411                                 : kDontSaveFPRegs; | 406                                 : kDontSaveFPRegs; | 
| 412       __ RecordWrite(object, index, value, mode); | 407       __ RecordWrite(object, index, value, mode); | 
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 949 } | 944 } | 
| 950 | 945 | 
| 951 | 946 | 
| 952 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); } | 947 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); } | 
| 953 | 948 | 
| 954 #undef __ | 949 #undef __ | 
| 955 | 950 | 
| 956 } | 951 } | 
| 957 } | 952 } | 
| 958 }  // namespace v8::internal::compiler | 953 }  // namespace v8::internal::compiler | 
| OLD | NEW | 
|---|