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