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