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/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
6 #include "src/compiler/code-generator.h" | 6 #include "src/compiler/code-generator.h" |
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/osr.h" | 10 #include "src/compiler/osr.h" |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 0, 1); \ | 517 0, 1); \ |
518 /* Move the result in the double result register. */ \ | 518 /* Move the result in the double result register. */ \ |
519 __ MovFromFloatResult(i.OutputDoubleRegister()); \ | 519 __ MovFromFloatResult(i.OutputDoubleRegister()); \ |
520 } while (0) | 520 } while (0) |
521 | 521 |
522 void CodeGenerator::AssembleDeconstructFrame() { | 522 void CodeGenerator::AssembleDeconstructFrame() { |
523 __ mov(sp, fp); | 523 __ mov(sp, fp); |
524 __ Pop(ra, fp); | 524 __ Pop(ra, fp); |
525 } | 525 } |
526 | 526 |
527 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 527 void CodeGenerator::AssemblePrepareTailCall() { |
528 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
529 if (sp_slot_delta > 0) { | |
530 __ daddiu(sp, sp, sp_slot_delta * kPointerSize); | |
531 } | |
532 frame_access_state()->SetFrameAccessToDefault(); | |
533 } | |
534 | |
535 | |
536 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
537 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
538 if (sp_slot_delta < 0) { | |
539 __ Dsubu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); | |
540 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
541 } | |
542 if (frame_access_state()->has_frame()) { | 528 if (frame_access_state()->has_frame()) { |
543 __ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 529 __ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
544 __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 530 __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
545 } | 531 } |
546 frame_access_state()->SetFrameAccessToSP(); | 532 frame_access_state()->SetFrameAccessToSP(); |
547 } | 533 } |
548 | 534 |
549 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 535 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
550 Register scratch1, | 536 Register scratch1, |
551 Register scratch2, | 537 Register scratch2, |
(...skipping 12 matching lines...) Expand all Loading... |
564 __ ld(caller_args_count_reg, | 550 __ ld(caller_args_count_reg, |
565 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 551 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
566 __ SmiUntag(caller_args_count_reg); | 552 __ SmiUntag(caller_args_count_reg); |
567 | 553 |
568 ParameterCount callee_args_count(args_reg); | 554 ParameterCount callee_args_count(args_reg); |
569 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 555 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
570 scratch3); | 556 scratch3); |
571 __ bind(&done); | 557 __ bind(&done); |
572 } | 558 } |
573 | 559 |
| 560 namespace { |
| 561 |
| 562 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state, |
| 563 int new_slot_above_sp, |
| 564 bool allow_shrinkage = true) { |
| 565 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 566 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 567 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 568 if (stack_slot_delta > 0) { |
| 569 masm->Dsubu(sp, sp, stack_slot_delta * kPointerSize); |
| 570 state->IncreaseSPDelta(stack_slot_delta); |
| 571 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 572 masm->Daddu(sp, sp, stack_slot_delta * kPointerSize); |
| 573 state->IncreaseSPDelta(stack_slot_delta); |
| 574 } |
| 575 } |
| 576 |
| 577 } // namespace |
| 578 |
| 579 void CodeGenerator::AssemblePreGaps(Instruction* instr) { |
| 580 int first_unused_stack_slot; |
| 581 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 582 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 583 first_unused_stack_slot, false); |
| 584 } |
| 585 |
| 586 void CodeGenerator::AssemblePostGaps(Instruction* instr) { |
| 587 int first_unused_stack_slot; |
| 588 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 589 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 590 first_unused_stack_slot); |
| 591 } |
| 592 |
574 // Assembles an instruction after register allocation, producing machine code. | 593 // Assembles an instruction after register allocation, producing machine code. |
575 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 594 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
576 Instruction* instr) { | 595 Instruction* instr) { |
577 MipsOperandConverter i(this, instr); | 596 MipsOperandConverter i(this, instr); |
578 InstructionCode opcode = instr->opcode(); | 597 InstructionCode opcode = instr->opcode(); |
579 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 598 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
580 switch (arch_opcode) { | 599 switch (arch_opcode) { |
581 case kArchCallCodeObject: { | 600 case kArchCallCodeObject: { |
582 EnsureSpaceForLazyDeopt(); | 601 EnsureSpaceForLazyDeopt(); |
583 if (instr->InputAt(0)->IsImmediate()) { | 602 if (instr->InputAt(0)->IsImmediate()) { |
584 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 603 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
585 RelocInfo::CODE_TARGET); | 604 RelocInfo::CODE_TARGET); |
586 } else { | 605 } else { |
587 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 606 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
588 __ Call(at); | 607 __ Call(at); |
589 } | 608 } |
590 RecordCallPosition(instr); | 609 RecordCallPosition(instr); |
591 frame_access_state()->ClearSPDelta(); | 610 frame_access_state()->ClearSPDelta(); |
592 break; | 611 break; |
593 } | 612 } |
594 case kArchTailCallCodeObjectFromJSFunction: | 613 case kArchTailCallCodeObjectFromJSFunction: |
595 case kArchTailCallCodeObject: { | 614 case kArchTailCallCodeObject: { |
596 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
597 AssembleDeconstructActivationRecord(stack_param_delta); | |
598 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 615 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
599 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 616 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
600 i.TempRegister(0), i.TempRegister(1), | 617 i.TempRegister(0), i.TempRegister(1), |
601 i.TempRegister(2)); | 618 i.TempRegister(2)); |
602 } | 619 } |
603 if (instr->InputAt(0)->IsImmediate()) { | 620 if (instr->InputAt(0)->IsImmediate()) { |
604 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 621 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
605 RelocInfo::CODE_TARGET); | 622 RelocInfo::CODE_TARGET); |
606 } else { | 623 } else { |
607 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 624 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
608 __ Jump(at); | 625 __ Jump(at); |
609 } | 626 } |
610 frame_access_state()->ClearSPDelta(); | 627 frame_access_state()->ClearSPDelta(); |
| 628 frame_access_state()->SetFrameAccessToDefault(); |
611 break; | 629 break; |
612 } | 630 } |
613 case kArchTailCallAddress: { | 631 case kArchTailCallAddress: { |
614 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
615 AssembleDeconstructActivationRecord(stack_param_delta); | |
616 CHECK(!instr->InputAt(0)->IsImmediate()); | 632 CHECK(!instr->InputAt(0)->IsImmediate()); |
617 __ Jump(i.InputRegister(0)); | 633 __ Jump(i.InputRegister(0)); |
618 frame_access_state()->ClearSPDelta(); | 634 frame_access_state()->ClearSPDelta(); |
| 635 frame_access_state()->SetFrameAccessToDefault(); |
619 break; | 636 break; |
620 } | 637 } |
621 case kArchCallJSFunction: { | 638 case kArchCallJSFunction: { |
622 EnsureSpaceForLazyDeopt(); | 639 EnsureSpaceForLazyDeopt(); |
623 Register func = i.InputRegister(0); | 640 Register func = i.InputRegister(0); |
624 if (FLAG_debug_code) { | 641 if (FLAG_debug_code) { |
625 // Check the function's context matches the context argument. | 642 // Check the function's context matches the context argument. |
626 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 643 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
627 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 644 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
628 } | 645 } |
629 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 646 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
630 __ Call(at); | 647 __ Call(at); |
631 RecordCallPosition(instr); | 648 RecordCallPosition(instr); |
632 frame_access_state()->ClearSPDelta(); | 649 frame_access_state()->ClearSPDelta(); |
633 break; | 650 break; |
634 } | 651 } |
635 case kArchTailCallJSFunctionFromJSFunction: | 652 case kArchTailCallJSFunctionFromJSFunction: |
636 case kArchTailCallJSFunction: { | 653 case kArchTailCallJSFunction: { |
637 Register func = i.InputRegister(0); | 654 Register func = i.InputRegister(0); |
638 if (FLAG_debug_code) { | 655 if (FLAG_debug_code) { |
639 // Check the function's context matches the context argument. | 656 // Check the function's context matches the context argument. |
640 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 657 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
641 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 658 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
642 } | 659 } |
643 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
644 AssembleDeconstructActivationRecord(stack_param_delta); | |
645 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 660 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
646 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 661 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
647 i.TempRegister(0), i.TempRegister(1), | 662 i.TempRegister(0), i.TempRegister(1), |
648 i.TempRegister(2)); | 663 i.TempRegister(2)); |
649 } | 664 } |
650 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 665 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
651 __ Jump(at); | 666 __ Jump(at); |
652 frame_access_state()->ClearSPDelta(); | 667 frame_access_state()->ClearSPDelta(); |
| 668 frame_access_state()->SetFrameAccessToDefault(); |
653 break; | 669 break; |
654 } | 670 } |
655 case kArchPrepareCallCFunction: { | 671 case kArchPrepareCallCFunction: { |
656 int const num_parameters = MiscField::decode(instr->opcode()); | 672 int const num_parameters = MiscField::decode(instr->opcode()); |
657 __ PrepareCallCFunction(num_parameters, kScratchReg); | 673 __ PrepareCallCFunction(num_parameters, kScratchReg); |
658 // Frame alignment requires using FP-relative frame addressing. | 674 // Frame alignment requires using FP-relative frame addressing. |
659 frame_access_state()->SetFrameAccessToFP(); | 675 frame_access_state()->SetFrameAccessToFP(); |
660 break; | 676 break; |
661 } | 677 } |
662 case kArchPrepareTailCall: | 678 case kArchPrepareTailCall: |
663 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 679 AssemblePrepareTailCall(); |
664 break; | 680 break; |
665 case kArchCallCFunction: { | 681 case kArchCallCFunction: { |
666 int const num_parameters = MiscField::decode(instr->opcode()); | 682 int const num_parameters = MiscField::decode(instr->opcode()); |
667 if (instr->InputAt(0)->IsImmediate()) { | 683 if (instr->InputAt(0)->IsImmediate()) { |
668 ExternalReference ref = i.InputExternalReference(0); | 684 ExternalReference ref = i.InputExternalReference(0); |
669 __ CallCFunction(ref, num_parameters); | 685 __ CallCFunction(ref, num_parameters); |
670 } else { | 686 } else { |
671 Register func = i.InputRegister(0); | 687 Register func = i.InputRegister(0); |
672 __ CallCFunction(func, num_parameters); | 688 __ CallCFunction(func, num_parameters); |
673 } | 689 } |
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2336 padding_size -= v8::internal::Assembler::kInstrSize; | 2352 padding_size -= v8::internal::Assembler::kInstrSize; |
2337 } | 2353 } |
2338 } | 2354 } |
2339 } | 2355 } |
2340 | 2356 |
2341 #undef __ | 2357 #undef __ |
2342 | 2358 |
2343 } // namespace compiler | 2359 } // namespace compiler |
2344 } // namespace internal | 2360 } // namespace internal |
2345 } // namespace v8 | 2361 } // namespace v8 |
OLD | NEW |