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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 __ Dsubu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); | 494 __ Dsubu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); |
495 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 495 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
496 } | 496 } |
497 if (frame()->needs_frame()) { | 497 if (frame()->needs_frame()) { |
498 __ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 498 __ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
499 __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 499 __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
500 } | 500 } |
501 frame_access_state()->SetFrameAccessToSP(); | 501 frame_access_state()->SetFrameAccessToSP(); |
502 } | 502 } |
503 | 503 |
| 504 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 505 Register scratch1, |
| 506 Register scratch2, |
| 507 Register scratch3) { |
| 508 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 509 Label done; |
| 510 |
| 511 // Check if current frame is an arguments adaptor frame. |
| 512 __ ld(scratch3, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 513 __ Branch(&done, ne, scratch3, |
| 514 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 515 |
| 516 // Load arguments count from current arguments adaptor frame (note, it |
| 517 // does not include receiver). |
| 518 Register caller_args_count_reg = scratch1; |
| 519 __ ld(caller_args_count_reg, |
| 520 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 521 __ SmiUntag(caller_args_count_reg); |
| 522 |
| 523 ParameterCount callee_args_count(args_reg); |
| 524 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 525 scratch3); |
| 526 __ bind(&done); |
| 527 } |
504 | 528 |
505 // Assembles an instruction after register allocation, producing machine code. | 529 // Assembles an instruction after register allocation, producing machine code. |
506 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 530 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
507 MipsOperandConverter i(this, instr); | 531 MipsOperandConverter i(this, instr); |
508 InstructionCode opcode = instr->opcode(); | 532 InstructionCode opcode = instr->opcode(); |
509 | 533 |
510 switch (ArchOpcodeField::decode(opcode)) { | 534 switch (ArchOpcodeField::decode(opcode)) { |
511 case kArchCallCodeObject: { | 535 case kArchCallCodeObject: { |
512 EnsureSpaceForLazyDeopt(); | 536 EnsureSpaceForLazyDeopt(); |
513 if (instr->InputAt(0)->IsImmediate()) { | 537 if (instr->InputAt(0)->IsImmediate()) { |
514 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 538 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
515 RelocInfo::CODE_TARGET); | 539 RelocInfo::CODE_TARGET); |
516 } else { | 540 } else { |
517 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 541 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
518 __ Call(at); | 542 __ Call(at); |
519 } | 543 } |
520 RecordCallPosition(instr); | 544 RecordCallPosition(instr); |
521 frame_access_state()->ClearSPDelta(); | 545 frame_access_state()->ClearSPDelta(); |
522 break; | 546 break; |
523 } | 547 } |
| 548 case kArchTailCallCodeObjectFromJSFunction: { |
| 549 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 550 AssembleDeconstructActivationRecord(stack_param_delta); |
| 551 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 552 i.TempRegister(0), i.TempRegister(1), |
| 553 i.TempRegister(2)); |
| 554 if (instr->InputAt(0)->IsImmediate()) { |
| 555 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 556 RelocInfo::CODE_TARGET); |
| 557 } else { |
| 558 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
| 559 __ Jump(at); |
| 560 } |
| 561 frame_access_state()->ClearSPDelta(); |
| 562 break; |
| 563 } |
524 case kArchTailCallCodeObject: { | 564 case kArchTailCallCodeObject: { |
525 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 565 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
526 AssembleDeconstructActivationRecord(stack_param_delta); | 566 AssembleDeconstructActivationRecord(stack_param_delta); |
527 if (instr->InputAt(0)->IsImmediate()) { | 567 if (instr->InputAt(0)->IsImmediate()) { |
528 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 568 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
529 RelocInfo::CODE_TARGET); | 569 RelocInfo::CODE_TARGET); |
530 } else { | 570 } else { |
531 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 571 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
532 __ Jump(at); | 572 __ Jump(at); |
533 } | 573 } |
534 frame_access_state()->ClearSPDelta(); | 574 frame_access_state()->ClearSPDelta(); |
535 break; | 575 break; |
536 } | 576 } |
537 case kArchCallJSFunction: { | 577 case kArchCallJSFunction: { |
538 EnsureSpaceForLazyDeopt(); | 578 EnsureSpaceForLazyDeopt(); |
539 Register func = i.InputRegister(0); | 579 Register func = i.InputRegister(0); |
540 if (FLAG_debug_code) { | 580 if (FLAG_debug_code) { |
541 // Check the function's context matches the context argument. | 581 // Check the function's context matches the context argument. |
542 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 582 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
543 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 583 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
544 } | 584 } |
545 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 585 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
546 __ Call(at); | 586 __ Call(at); |
547 RecordCallPosition(instr); | 587 RecordCallPosition(instr); |
548 frame_access_state()->ClearSPDelta(); | 588 frame_access_state()->ClearSPDelta(); |
549 break; | 589 break; |
550 } | 590 } |
| 591 case kArchTailCallJSFunctionFromJSFunction: { |
| 592 Register func = i.InputRegister(0); |
| 593 if (FLAG_debug_code) { |
| 594 // Check the function's context matches the context argument. |
| 595 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 596 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
| 597 } |
| 598 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 599 AssembleDeconstructActivationRecord(stack_param_delta); |
| 600 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 601 i.TempRegister(0), i.TempRegister(1), |
| 602 i.TempRegister(2)); |
| 603 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 604 __ Jump(at); |
| 605 frame_access_state()->ClearSPDelta(); |
| 606 break; |
| 607 } |
551 case kArchTailCallJSFunction: { | 608 case kArchTailCallJSFunction: { |
552 Register func = i.InputRegister(0); | 609 Register func = i.InputRegister(0); |
553 if (FLAG_debug_code) { | 610 if (FLAG_debug_code) { |
554 // Check the function's context matches the context argument. | 611 // Check the function's context matches the context argument. |
555 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 612 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
556 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 613 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
557 } | 614 } |
558 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 615 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
559 AssembleDeconstructActivationRecord(stack_param_delta); | 616 AssembleDeconstructActivationRecord(stack_param_delta); |
560 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 617 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
(...skipping 1567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2128 padding_size -= v8::internal::Assembler::kInstrSize; | 2185 padding_size -= v8::internal::Assembler::kInstrSize; |
2129 } | 2186 } |
2130 } | 2187 } |
2131 } | 2188 } |
2132 | 2189 |
2133 #undef __ | 2190 #undef __ |
2134 | 2191 |
2135 } // namespace compiler | 2192 } // namespace compiler |
2136 } // namespace internal | 2193 } // namespace internal |
2137 } // namespace v8 | 2194 } // namespace v8 |
OLD | NEW |