OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 __ cmp(offset, i.InputRegister(1)); \ | 292 __ cmp(offset, i.InputRegister(1)); \ |
293 } else { \ | 293 } else { \ |
294 __ cmp(offset, i.InputImmediate(1)); \ | 294 __ cmp(offset, i.InputImmediate(1)); \ |
295 } \ | 295 } \ |
296 auto value = i.InputRegister(2); \ | 296 auto value = i.InputRegister(2); \ |
297 __ asm_instr(value, i.InputOffset(3), lo); \ | 297 __ asm_instr(value, i.InputOffset(3), lo); \ |
298 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ | 298 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
299 } while (0) | 299 } while (0) |
300 | 300 |
301 | 301 |
| 302 void CodeGenerator::AssembleDeconstructActivationRecord() { |
| 303 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 304 int stack_slots = frame()->GetSpillSlotCount(); |
| 305 if (descriptor->IsJSFunctionCall() || stack_slots > 0) { |
| 306 __ LeaveFrame(StackFrame::MANUAL); |
| 307 int pop_count = descriptor->IsJSFunctionCall() |
| 308 ? static_cast<int>(descriptor->JSParameterCount()) |
| 309 : 0; |
| 310 __ Drop(pop_count); |
| 311 } |
| 312 } |
| 313 |
| 314 |
302 // Assembles an instruction after register allocation, producing machine code. | 315 // Assembles an instruction after register allocation, producing machine code. |
303 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 316 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
304 ArmOperandConverter i(this, instr); | 317 ArmOperandConverter i(this, instr); |
305 | 318 |
306 switch (ArchOpcodeField::decode(instr->opcode())) { | 319 switch (ArchOpcodeField::decode(instr->opcode())) { |
307 case kArchCallCodeObject: { | 320 case kArchCallCodeObject: { |
308 EnsureSpaceForLazyDeopt(); | 321 EnsureSpaceForLazyDeopt(); |
309 if (instr->InputAt(0)->IsImmediate()) { | 322 if (instr->InputAt(0)->IsImmediate()) { |
310 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 323 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
311 RelocInfo::CODE_TARGET); | 324 RelocInfo::CODE_TARGET); |
312 } else { | 325 } else { |
313 __ add(ip, i.InputRegister(0), | 326 __ add(ip, i.InputRegister(0), |
314 Operand(Code::kHeaderSize - kHeapObjectTag)); | 327 Operand(Code::kHeaderSize - kHeapObjectTag)); |
315 __ Call(ip); | 328 __ Call(ip); |
316 } | 329 } |
317 RecordCallPosition(instr); | 330 RecordCallPosition(instr); |
318 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 331 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
319 break; | 332 break; |
320 } | 333 } |
| 334 case kArchTailCallCodeObject: { |
| 335 AssembleDeconstructActivationRecord(); |
| 336 if (instr->InputAt(0)->IsImmediate()) { |
| 337 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 338 RelocInfo::CODE_TARGET); |
| 339 } else { |
| 340 __ add(ip, i.InputRegister(0), |
| 341 Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 342 __ Jump(ip); |
| 343 } |
| 344 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 345 break; |
| 346 } |
321 case kArchCallJSFunction: { | 347 case kArchCallJSFunction: { |
322 EnsureSpaceForLazyDeopt(); | 348 EnsureSpaceForLazyDeopt(); |
323 Register func = i.InputRegister(0); | 349 Register func = i.InputRegister(0); |
324 if (FLAG_debug_code) { | 350 if (FLAG_debug_code) { |
325 // Check the function's context matches the context argument. | 351 // Check the function's context matches the context argument. |
326 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 352 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
327 __ cmp(cp, kScratchReg); | 353 __ cmp(cp, kScratchReg); |
328 __ Assert(eq, kWrongFunctionContext); | 354 __ Assert(eq, kWrongFunctionContext); |
329 } | 355 } |
330 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 356 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
331 __ Call(ip); | 357 __ Call(ip); |
332 RecordCallPosition(instr); | 358 RecordCallPosition(instr); |
333 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 359 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
334 break; | 360 break; |
335 } | 361 } |
| 362 case kArchTailCallJSFunction: { |
| 363 Register func = i.InputRegister(0); |
| 364 if (FLAG_debug_code) { |
| 365 // Check the function's context matches the context argument. |
| 366 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 367 __ cmp(cp, kScratchReg); |
| 368 __ Assert(eq, kWrongFunctionContext); |
| 369 } |
| 370 AssembleDeconstructActivationRecord(); |
| 371 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 372 __ Jump(ip); |
| 373 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 374 break; |
| 375 } |
336 case kArchJmp: | 376 case kArchJmp: |
337 AssembleArchJump(i.InputRpo(0)); | 377 AssembleArchJump(i.InputRpo(0)); |
338 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 378 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
339 break; | 379 break; |
340 case kArchLookupSwitch: | 380 case kArchLookupSwitch: |
341 AssembleArchLookupSwitch(instr); | 381 AssembleArchLookupSwitch(instr); |
342 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 382 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
343 break; | 383 break; |
344 case kArchTableSwitch: | 384 case kArchTableSwitch: |
345 AssembleArchTableSwitch(instr); | 385 AssembleArchTableSwitch(instr); |
(...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 } | 1214 } |
1175 } | 1215 } |
1176 MarkLazyDeoptSite(); | 1216 MarkLazyDeoptSite(); |
1177 } | 1217 } |
1178 | 1218 |
1179 #undef __ | 1219 #undef __ |
1180 | 1220 |
1181 } // namespace compiler | 1221 } // namespace compiler |
1182 } // namespace internal | 1222 } // namespace internal |
1183 } // namespace v8 | 1223 } // namespace v8 |
OLD | NEW |