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