| 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 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state, |
| 562 int new_slot_above_sp, |
| 563 bool allow_shrinkage = true) { |
| 564 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 565 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 566 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 567 if (stack_slot_delta > 0) { |
| 568 masm->Dsubu(sp, sp, stack_slot_delta * kPointerSize); |
| 569 state->IncreaseSPDelta(stack_slot_delta); |
| 570 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 571 masm->Daddu(sp, sp, stack_slot_delta * kPointerSize); |
| 572 state->IncreaseSPDelta(stack_slot_delta); |
| 573 } |
| 574 } |
| 575 } // namespace |
| 576 |
| 577 void CodeGenerator::AssemblePreGaps(Instruction* instr) { |
| 578 int first_unused_stack_slot; |
| 579 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 580 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 581 first_unused_stack_slot, false); |
| 582 } |
| 583 |
| 584 void CodeGenerator::AssemblePostGaps(Instruction* instr) { |
| 585 int first_unused_stack_slot; |
| 586 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; |
| 587 AdjustStackPointerForGap(masm(), frame_access_state(), |
| 588 first_unused_stack_slot); |
| 589 } |
| 590 |
| 574 // Assembles an instruction after register allocation, producing machine code. | 591 // Assembles an instruction after register allocation, producing machine code. |
| 575 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 592 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
| 576 Instruction* instr) { | 593 Instruction* instr) { |
| 577 MipsOperandConverter i(this, instr); | 594 MipsOperandConverter i(this, instr); |
| 578 InstructionCode opcode = instr->opcode(); | 595 InstructionCode opcode = instr->opcode(); |
| 579 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 596 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 580 switch (arch_opcode) { | 597 switch (arch_opcode) { |
| 581 case kArchCallCodeObject: { | 598 case kArchCallCodeObject: { |
| 582 EnsureSpaceForLazyDeopt(); | 599 EnsureSpaceForLazyDeopt(); |
| 583 if (instr->InputAt(0)->IsImmediate()) { | 600 if (instr->InputAt(0)->IsImmediate()) { |
| 584 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 601 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
| 585 RelocInfo::CODE_TARGET); | 602 RelocInfo::CODE_TARGET); |
| 586 } else { | 603 } else { |
| 587 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 604 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
| 588 __ Call(at); | 605 __ Call(at); |
| 589 } | 606 } |
| 590 RecordCallPosition(instr); | 607 RecordCallPosition(instr); |
| 591 frame_access_state()->ClearSPDelta(); | 608 frame_access_state()->ClearSPDelta(); |
| 592 break; | 609 break; |
| 593 } | 610 } |
| 594 case kArchTailCallCodeObjectFromJSFunction: | 611 case kArchTailCallCodeObjectFromJSFunction: |
| 595 case kArchTailCallCodeObject: { | 612 case kArchTailCallCodeObject: { |
| 596 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 597 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 598 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 613 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 599 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 614 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 600 i.TempRegister(0), i.TempRegister(1), | 615 i.TempRegister(0), i.TempRegister(1), |
| 601 i.TempRegister(2)); | 616 i.TempRegister(2)); |
| 602 } | 617 } |
| 603 if (instr->InputAt(0)->IsImmediate()) { | 618 if (instr->InputAt(0)->IsImmediate()) { |
| 604 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 619 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 605 RelocInfo::CODE_TARGET); | 620 RelocInfo::CODE_TARGET); |
| 606 } else { | 621 } else { |
| 607 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 622 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
| 608 __ Jump(at); | 623 __ Jump(at); |
| 609 } | 624 } |
| 610 frame_access_state()->ClearSPDelta(); | 625 frame_access_state()->ClearSPDelta(); |
| 626 frame_access_state()->SetFrameAccessToDefault(); |
| 611 break; | 627 break; |
| 612 } | 628 } |
| 613 case kArchTailCallAddress: { | 629 case kArchTailCallAddress: { |
| 614 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 615 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 616 CHECK(!instr->InputAt(0)->IsImmediate()); | 630 CHECK(!instr->InputAt(0)->IsImmediate()); |
| 617 __ Jump(i.InputRegister(0)); | 631 __ Jump(i.InputRegister(0)); |
| 618 frame_access_state()->ClearSPDelta(); | 632 frame_access_state()->ClearSPDelta(); |
| 633 frame_access_state()->SetFrameAccessToDefault(); |
| 619 break; | 634 break; |
| 620 } | 635 } |
| 621 case kArchCallJSFunction: { | 636 case kArchCallJSFunction: { |
| 622 EnsureSpaceForLazyDeopt(); | 637 EnsureSpaceForLazyDeopt(); |
| 623 Register func = i.InputRegister(0); | 638 Register func = i.InputRegister(0); |
| 624 if (FLAG_debug_code) { | 639 if (FLAG_debug_code) { |
| 625 // Check the function's context matches the context argument. | 640 // Check the function's context matches the context argument. |
| 626 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 641 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 627 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 642 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
| 628 } | 643 } |
| 629 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 644 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 630 __ Call(at); | 645 __ Call(at); |
| 631 RecordCallPosition(instr); | 646 RecordCallPosition(instr); |
| 632 frame_access_state()->ClearSPDelta(); | 647 frame_access_state()->ClearSPDelta(); |
| 633 break; | 648 break; |
| 634 } | 649 } |
| 635 case kArchTailCallJSFunctionFromJSFunction: | 650 case kArchTailCallJSFunctionFromJSFunction: |
| 636 case kArchTailCallJSFunction: { | 651 case kArchTailCallJSFunction: { |
| 637 Register func = i.InputRegister(0); | 652 Register func = i.InputRegister(0); |
| 638 if (FLAG_debug_code) { | 653 if (FLAG_debug_code) { |
| 639 // Check the function's context matches the context argument. | 654 // Check the function's context matches the context argument. |
| 640 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 655 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 641 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 656 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
| 642 } | 657 } |
| 643 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 644 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 645 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 658 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 646 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 659 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 647 i.TempRegister(0), i.TempRegister(1), | 660 i.TempRegister(0), i.TempRegister(1), |
| 648 i.TempRegister(2)); | 661 i.TempRegister(2)); |
| 649 } | 662 } |
| 650 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 663 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 651 __ Jump(at); | 664 __ Jump(at); |
| 652 frame_access_state()->ClearSPDelta(); | 665 frame_access_state()->ClearSPDelta(); |
| 666 frame_access_state()->SetFrameAccessToDefault(); |
| 653 break; | 667 break; |
| 654 } | 668 } |
| 655 case kArchPrepareCallCFunction: { | 669 case kArchPrepareCallCFunction: { |
| 656 int const num_parameters = MiscField::decode(instr->opcode()); | 670 int const num_parameters = MiscField::decode(instr->opcode()); |
| 657 __ PrepareCallCFunction(num_parameters, kScratchReg); | 671 __ PrepareCallCFunction(num_parameters, kScratchReg); |
| 658 // Frame alignment requires using FP-relative frame addressing. | 672 // Frame alignment requires using FP-relative frame addressing. |
| 659 frame_access_state()->SetFrameAccessToFP(); | 673 frame_access_state()->SetFrameAccessToFP(); |
| 660 break; | 674 break; |
| 661 } | 675 } |
| 662 case kArchPrepareTailCall: | 676 case kArchPrepareTailCall: |
| 663 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 677 AssemblePrepareTailCall(); |
| 664 break; | 678 break; |
| 665 case kArchCallCFunction: { | 679 case kArchCallCFunction: { |
| 666 int const num_parameters = MiscField::decode(instr->opcode()); | 680 int const num_parameters = MiscField::decode(instr->opcode()); |
| 667 if (instr->InputAt(0)->IsImmediate()) { | 681 if (instr->InputAt(0)->IsImmediate()) { |
| 668 ExternalReference ref = i.InputExternalReference(0); | 682 ExternalReference ref = i.InputExternalReference(0); |
| 669 __ CallCFunction(ref, num_parameters); | 683 __ CallCFunction(ref, num_parameters); |
| 670 } else { | 684 } else { |
| 671 Register func = i.InputRegister(0); | 685 Register func = i.InputRegister(0); |
| 672 __ CallCFunction(func, num_parameters); | 686 __ CallCFunction(func, num_parameters); |
| 673 } | 687 } |
| (...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2336 padding_size -= v8::internal::Assembler::kInstrSize; | 2350 padding_size -= v8::internal::Assembler::kInstrSize; |
| 2337 } | 2351 } |
| 2338 } | 2352 } |
| 2339 } | 2353 } |
| 2340 | 2354 |
| 2341 #undef __ | 2355 #undef __ |
| 2342 | 2356 |
| 2343 } // namespace compiler | 2357 } // namespace compiler |
| 2344 } // namespace internal | 2358 } // namespace internal |
| 2345 } // namespace v8 | 2359 } // namespace v8 |
| OLD | NEW |