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 |