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/ast/scopes.h" | 7 #include "src/ast/scopes.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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 __ fstp_d(Operand(esp, 0)); \ | 393 __ fstp_d(Operand(esp, 0)); \ |
394 __ movsd(i.OutputDoubleRegister(), Operand(esp, 0)); \ | 394 __ movsd(i.OutputDoubleRegister(), Operand(esp, 0)); \ |
395 __ add(esp, Immediate(kDoubleSize)); \ | 395 __ add(esp, Immediate(kDoubleSize)); \ |
396 } while (false) | 396 } while (false) |
397 | 397 |
398 void CodeGenerator::AssembleDeconstructFrame() { | 398 void CodeGenerator::AssembleDeconstructFrame() { |
399 __ mov(esp, ebp); | 399 __ mov(esp, ebp); |
400 __ pop(ebp); | 400 __ pop(ebp); |
401 } | 401 } |
402 | 402 |
403 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 403 void CodeGenerator::AssemblePrepareTailCall() { |
404 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
405 if (sp_slot_delta > 0) { | |
406 __ add(esp, Immediate(sp_slot_delta * kPointerSize)); | |
407 } | |
408 frame_access_state()->SetFrameAccessToDefault(); | |
409 } | |
410 | |
411 | |
412 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
413 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
414 if (sp_slot_delta < 0) { | |
415 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); | |
416 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
417 } | |
418 if (frame_access_state()->has_frame()) { | 404 if (frame_access_state()->has_frame()) { |
419 __ mov(ebp, MemOperand(ebp, 0)); | 405 __ mov(ebp, MemOperand(ebp, 0)); |
420 } | 406 } |
421 frame_access_state()->SetFrameAccessToSP(); | 407 frame_access_state()->SetFrameAccessToSP(); |
422 } | 408 } |
423 | 409 |
424 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 410 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
425 Register, Register, | 411 Register, Register, |
426 Register) { | 412 Register) { |
427 // There are not enough temp registers left on ia32 for a call instruction | 413 // There are not enough temp registers left on ia32 for a call instruction |
(...skipping 24 matching lines...) Expand all Loading... |
452 ParameterCount callee_args_count(args_reg); | 438 ParameterCount callee_args_count(args_reg); |
453 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 439 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
454 scratch3, ReturnAddressState::kOnStack, scratch_count); | 440 scratch3, ReturnAddressState::kOnStack, scratch_count); |
455 __ pop(scratch3); | 441 __ pop(scratch3); |
456 __ pop(scratch2); | 442 __ pop(scratch2); |
457 __ pop(scratch1); | 443 __ pop(scratch1); |
458 | 444 |
459 __ bind(&done); | 445 __ bind(&done); |
460 } | 446 } |
461 | 447 |
| 448 namespace { |
| 449 |
| 450 void AdjustStackPointerForTailCall(MacroAssembler* masm, |
| 451 FrameAccessState* state, |
| 452 int new_slot_above_sp, |
| 453 bool allow_shrinkage = true) { |
| 454 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 455 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 456 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 457 if (stack_slot_delta > 0) { |
| 458 masm->sub(esp, Immediate(stack_slot_delta * kPointerSize)); |
| 459 state->IncreaseSPDelta(stack_slot_delta); |
| 460 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 461 masm->add(esp, Immediate(-stack_slot_delta * kPointerSize)); |
| 462 state->IncreaseSPDelta(stack_slot_delta); |
| 463 } |
| 464 } |
| 465 |
| 466 } // namespace |
| 467 |
| 468 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr, |
| 469 int first_unused_stack_slot) { |
| 470 CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush); |
| 471 ZoneVector<MoveOperands*> pushes(zone()); |
| 472 GetPushCompatibleMoves(instr, flags, &pushes); |
| 473 |
| 474 if (!pushes.empty() && |
| 475 (LocationOperand::cast(pushes.back()->destination()).index() + 1 == |
| 476 first_unused_stack_slot)) { |
| 477 IA32OperandConverter g(this, instr); |
| 478 for (auto move : pushes) { |
| 479 LocationOperand destination_location( |
| 480 LocationOperand::cast(move->destination())); |
| 481 InstructionOperand source(move->source()); |
| 482 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 483 destination_location.index()); |
| 484 if (source.IsStackSlot()) { |
| 485 LocationOperand source_location(LocationOperand::cast(source)); |
| 486 __ push(g.SlotToOperand(source_location.index())); |
| 487 } else if (source.IsRegister()) { |
| 488 LocationOperand source_location(LocationOperand::cast(source)); |
| 489 __ push(source_location.GetRegister()); |
| 490 } else if (source.IsImmediate()) { |
| 491 __ push(Immediate(ImmediateOperand::cast(source).inline_value())); |
| 492 } else { |
| 493 // Pushes of non-scalar data types is not supported. |
| 494 UNIMPLEMENTED(); |
| 495 } |
| 496 frame_access_state()->IncreaseSPDelta(1); |
| 497 move->Eliminate(); |
| 498 } |
| 499 } |
| 500 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 501 first_unused_stack_slot, false); |
| 502 } |
| 503 |
| 504 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr, |
| 505 int first_unused_stack_slot) { |
| 506 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 507 first_unused_stack_slot); |
| 508 } |
| 509 |
462 // Assembles an instruction after register allocation, producing machine code. | 510 // Assembles an instruction after register allocation, producing machine code. |
463 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 511 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
464 Instruction* instr) { | 512 Instruction* instr) { |
465 IA32OperandConverter i(this, instr); | 513 IA32OperandConverter i(this, instr); |
466 InstructionCode opcode = instr->opcode(); | 514 InstructionCode opcode = instr->opcode(); |
467 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 515 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
468 switch (arch_opcode) { | 516 switch (arch_opcode) { |
469 case kArchCallCodeObject: { | 517 case kArchCallCodeObject: { |
470 EnsureSpaceForLazyDeopt(); | 518 EnsureSpaceForLazyDeopt(); |
471 if (HasImmediateInput(instr, 0)) { | 519 if (HasImmediateInput(instr, 0)) { |
472 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 520 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
473 __ call(code, RelocInfo::CODE_TARGET); | 521 __ call(code, RelocInfo::CODE_TARGET); |
474 } else { | 522 } else { |
475 Register reg = i.InputRegister(0); | 523 Register reg = i.InputRegister(0); |
476 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 524 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
477 __ call(reg); | 525 __ call(reg); |
478 } | 526 } |
479 RecordCallPosition(instr); | 527 RecordCallPosition(instr); |
480 frame_access_state()->ClearSPDelta(); | 528 frame_access_state()->ClearSPDelta(); |
481 break; | 529 break; |
482 } | 530 } |
483 case kArchTailCallCodeObjectFromJSFunction: | 531 case kArchTailCallCodeObjectFromJSFunction: |
484 case kArchTailCallCodeObject: { | 532 case kArchTailCallCodeObject: { |
485 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
486 AssembleDeconstructActivationRecord(stack_param_delta); | |
487 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 533 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
488 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 534 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
489 no_reg, no_reg, no_reg); | 535 no_reg, no_reg, no_reg); |
490 } | 536 } |
491 if (HasImmediateInput(instr, 0)) { | 537 if (HasImmediateInput(instr, 0)) { |
492 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 538 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
493 __ jmp(code, RelocInfo::CODE_TARGET); | 539 __ jmp(code, RelocInfo::CODE_TARGET); |
494 } else { | 540 } else { |
495 Register reg = i.InputRegister(0); | 541 Register reg = i.InputRegister(0); |
496 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 542 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
497 __ jmp(reg); | 543 __ jmp(reg); |
498 } | 544 } |
499 frame_access_state()->ClearSPDelta(); | 545 frame_access_state()->ClearSPDelta(); |
| 546 frame_access_state()->SetFrameAccessToDefault(); |
500 break; | 547 break; |
501 } | 548 } |
502 case kArchTailCallAddress: { | 549 case kArchTailCallAddress: { |
503 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
504 AssembleDeconstructActivationRecord(stack_param_delta); | |
505 CHECK(!HasImmediateInput(instr, 0)); | 550 CHECK(!HasImmediateInput(instr, 0)); |
506 Register reg = i.InputRegister(0); | 551 Register reg = i.InputRegister(0); |
507 __ jmp(reg); | 552 __ jmp(reg); |
508 frame_access_state()->ClearSPDelta(); | 553 frame_access_state()->ClearSPDelta(); |
| 554 frame_access_state()->SetFrameAccessToDefault(); |
509 break; | 555 break; |
510 } | 556 } |
511 case kArchCallJSFunction: { | 557 case kArchCallJSFunction: { |
512 EnsureSpaceForLazyDeopt(); | 558 EnsureSpaceForLazyDeopt(); |
513 Register func = i.InputRegister(0); | 559 Register func = i.InputRegister(0); |
514 if (FLAG_debug_code) { | 560 if (FLAG_debug_code) { |
515 // Check the function's context matches the context argument. | 561 // Check the function's context matches the context argument. |
516 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 562 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
517 __ Assert(equal, kWrongFunctionContext); | 563 __ Assert(equal, kWrongFunctionContext); |
518 } | 564 } |
519 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 565 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
520 RecordCallPosition(instr); | 566 RecordCallPosition(instr); |
521 frame_access_state()->ClearSPDelta(); | 567 frame_access_state()->ClearSPDelta(); |
522 break; | 568 break; |
523 } | 569 } |
524 case kArchTailCallJSFunctionFromJSFunction: | 570 case kArchTailCallJSFunctionFromJSFunction: |
525 case kArchTailCallJSFunction: { | 571 case kArchTailCallJSFunction: { |
526 Register func = i.InputRegister(0); | 572 Register func = i.InputRegister(0); |
527 if (FLAG_debug_code) { | 573 if (FLAG_debug_code) { |
528 // Check the function's context matches the context argument. | 574 // Check the function's context matches the context argument. |
529 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 575 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
530 __ Assert(equal, kWrongFunctionContext); | 576 __ Assert(equal, kWrongFunctionContext); |
531 } | 577 } |
532 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
533 AssembleDeconstructActivationRecord(stack_param_delta); | |
534 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 578 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
535 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 579 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
536 no_reg, no_reg, no_reg); | 580 no_reg, no_reg, no_reg); |
537 } | 581 } |
538 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 582 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
539 frame_access_state()->ClearSPDelta(); | 583 frame_access_state()->ClearSPDelta(); |
| 584 frame_access_state()->SetFrameAccessToDefault(); |
540 break; | 585 break; |
541 } | 586 } |
542 case kArchPrepareCallCFunction: { | 587 case kArchPrepareCallCFunction: { |
543 // Frame alignment requires using FP-relative frame addressing. | 588 // Frame alignment requires using FP-relative frame addressing. |
544 frame_access_state()->SetFrameAccessToFP(); | 589 frame_access_state()->SetFrameAccessToFP(); |
545 int const num_parameters = MiscField::decode(instr->opcode()); | 590 int const num_parameters = MiscField::decode(instr->opcode()); |
546 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); | 591 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); |
547 break; | 592 break; |
548 } | 593 } |
549 case kArchPrepareTailCall: | 594 case kArchPrepareTailCall: |
550 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 595 AssemblePrepareTailCall(); |
551 break; | 596 break; |
552 case kArchCallCFunction: { | 597 case kArchCallCFunction: { |
553 int const num_parameters = MiscField::decode(instr->opcode()); | 598 int const num_parameters = MiscField::decode(instr->opcode()); |
554 if (HasImmediateInput(instr, 0)) { | 599 if (HasImmediateInput(instr, 0)) { |
555 ExternalReference ref = i.InputExternalReference(0); | 600 ExternalReference ref = i.InputExternalReference(0); |
556 __ CallCFunction(ref, num_parameters); | 601 __ CallCFunction(ref, num_parameters); |
557 } else { | 602 } else { |
558 Register func = i.InputRegister(0); | 603 Register func = i.InputRegister(0); |
559 __ CallCFunction(func, num_parameters); | 604 __ CallCFunction(func, num_parameters); |
560 } | 605 } |
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2106 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2062 __ Nop(padding_size); | 2107 __ Nop(padding_size); |
2063 } | 2108 } |
2064 } | 2109 } |
2065 | 2110 |
2066 #undef __ | 2111 #undef __ |
2067 | 2112 |
2068 } // namespace compiler | 2113 } // namespace compiler |
2069 } // namespace internal | 2114 } // namespace internal |
2070 } // namespace v8 | 2115 } // namespace v8 |
OLD | NEW |