Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(774)

Side by Side Diff: src/compiler/arm/code-generator-arm.cc

Issue 2082263002: [turbofan]: Support using push instructions for setting up tail call parameters (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/compiler/code-generator.h" 5 #include "src/compiler/code-generator.h"
6 6
7 #include "src/arm/macro-assembler-arm.h" 7 #include "src/arm/macro-assembler-arm.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/compiler/code-generator-impl.h" 9 #include "src/compiler/code-generator-impl.h"
10 #include "src/compiler/gap-resolver.h" 10 #include "src/compiler/gap-resolver.h"
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 0, 1); \ 408 0, 1); \
409 /* Move the result in the double result register. */ \ 409 /* Move the result in the double result register. */ \
410 __ MovFromFloatResult(i.OutputDoubleRegister()); \ 410 __ MovFromFloatResult(i.OutputDoubleRegister()); \
411 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 411 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
412 } while (0) 412 } while (0)
413 413
414 void CodeGenerator::AssembleDeconstructFrame() { 414 void CodeGenerator::AssembleDeconstructFrame() {
415 __ LeaveFrame(StackFrame::MANUAL); 415 __ LeaveFrame(StackFrame::MANUAL);
416 } 416 }
417 417
418 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 418 void CodeGenerator::AssemblePrepareTailCall() {
419 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
420 if (sp_slot_delta > 0) {
421 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize));
422 }
423 frame_access_state()->SetFrameAccessToDefault();
424 }
425
426
427 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
428 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
429 if (sp_slot_delta < 0) {
430 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
431 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
432 }
433 if (frame_access_state()->has_frame()) { 419 if (frame_access_state()->has_frame()) {
434 if (FLAG_enable_embedded_constant_pool) { 420 if (FLAG_enable_embedded_constant_pool) {
435 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); 421 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
436 } 422 }
437 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); 423 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
438 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 424 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
439 } 425 }
440 frame_access_state()->SetFrameAccessToSP(); 426 frame_access_state()->SetFrameAccessToSP();
441 } 427 }
442 428
(...skipping 15 matching lines...) Expand all
458 __ ldr(caller_args_count_reg, 444 __ ldr(caller_args_count_reg,
459 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 445 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
460 __ SmiUntag(caller_args_count_reg); 446 __ SmiUntag(caller_args_count_reg);
461 447
462 ParameterCount callee_args_count(args_reg); 448 ParameterCount callee_args_count(args_reg);
463 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, 449 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
464 scratch3); 450 scratch3);
465 __ bind(&done); 451 __ bind(&done);
466 } 452 }
467 453
454 namespace {
455
456 void FlushPendingPushRegisters(MacroAssembler* masm,
457 FrameAccessState* frame_access_state,
458 ZoneVector<Register>* pending_pushes) {
459 switch (pending_pushes->size()) {
460 case 0:
461 break;
462 case 1:
463 masm->push((*pending_pushes)[0]);
464 break;
465 case 2:
466 masm->Push((*pending_pushes)[0], (*pending_pushes)[1]);
467 break;
468 case 3:
469 masm->Push((*pending_pushes)[0], (*pending_pushes)[1],
470 (*pending_pushes)[2]);
471 break;
472 default:
473 UNREACHABLE();
474 break;
475 }
476 frame_access_state->IncreaseSPDelta(pending_pushes->size());
477 pending_pushes->resize(0);
478 }
479
480 void AddPendingPushRegister(MacroAssembler* masm,
481 FrameAccessState* frame_access_state,
482 ZoneVector<Register>* pending_pushes,
483 Register reg) {
484 pending_pushes->push_back(reg);
485 if (pending_pushes->size() == 3 || reg.is(ip)) {
486 FlushPendingPushRegisters(masm, frame_access_state, pending_pushes);
487 }
488 }
489
490 void AdjustStackPointerForTailCall(
491 MacroAssembler* masm, FrameAccessState* state, int new_slot_above_sp,
492 ZoneVector<Register>* pending_pushes = nullptr,
493 bool allow_shrinkage = true) {
494 int current_sp_offset = state->GetSPToFPSlotCount() +
495 StandardFrameConstants::kFixedSlotCountAboveFp;
496 int stack_slot_delta = new_slot_above_sp - current_sp_offset;
497 if (stack_slot_delta > 0) {
498 if (pending_pushes != nullptr) {
499 FlushPendingPushRegisters(masm, state, pending_pushes);
500 }
501 masm->sub(sp, sp, Operand(stack_slot_delta * kPointerSize));
502 state->IncreaseSPDelta(stack_slot_delta);
503 } else if (allow_shrinkage && stack_slot_delta < 0) {
504 if (pending_pushes != nullptr) {
505 FlushPendingPushRegisters(masm, state, pending_pushes);
506 }
507 masm->add(sp, sp, Operand(-stack_slot_delta * kPointerSize));
508 state->IncreaseSPDelta(stack_slot_delta);
509 }
510 }
511
512 } // namespace
513
514 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
515 int first_unused_stack_slot) {
516 CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush);
517 ZoneVector<MoveOperands*> pushes(zone());
518 GetPushCompatibleMoves(instr, flags, &pushes);
519
520 if (!pushes.empty() &&
521 (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
522 first_unused_stack_slot)) {
523 ArmOperandConverter g(this, instr);
524 ZoneVector<Register> pending_pushes(zone());
525 for (auto move : pushes) {
526 LocationOperand destination_location(
527 LocationOperand::cast(move->destination()));
528 InstructionOperand source(move->source());
529 AdjustStackPointerForTailCall(
530 masm(), frame_access_state(),
531 destination_location.index() - pending_pushes.size(),
532 &pending_pushes);
533 if (source.IsStackSlot()) {
534 LocationOperand source_location(LocationOperand::cast(source));
535 __ ldr(ip, g.SlotToMemOperand(source_location.index()));
536 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
537 ip);
538 } else if (source.IsRegister()) {
539 LocationOperand source_location(LocationOperand::cast(source));
540 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
541 source_location.GetRegister());
542 } else if (source.IsImmediate()) {
543 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
544 ip);
545 } else {
546 // Pushes of non-scalar data types is not supported.
547 UNIMPLEMENTED();
548 }
549 move->Eliminate();
550 }
551 FlushPendingPushRegisters(masm(), frame_access_state(), &pending_pushes);
552 }
553 AdjustStackPointerForTailCall(masm(), frame_access_state(),
554 first_unused_stack_slot, nullptr, false);
555 }
556
557 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
558 int first_unused_stack_slot) {
559 AdjustStackPointerForTailCall(masm(), frame_access_state(),
560 first_unused_stack_slot);
561 }
562
468 // Assembles an instruction after register allocation, producing machine code. 563 // Assembles an instruction after register allocation, producing machine code.
469 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( 564 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
470 Instruction* instr) { 565 Instruction* instr) {
471 ArmOperandConverter i(this, instr); 566 ArmOperandConverter i(this, instr);
472 567
473 __ MaybeCheckConstPool(); 568 __ MaybeCheckConstPool();
474 InstructionCode opcode = instr->opcode(); 569 InstructionCode opcode = instr->opcode();
475 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); 570 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
476 switch (arch_opcode) { 571 switch (arch_opcode) {
477 case kArchCallCodeObject: { 572 case kArchCallCodeObject: {
478 EnsureSpaceForLazyDeopt(); 573 EnsureSpaceForLazyDeopt();
479 if (instr->InputAt(0)->IsImmediate()) { 574 if (instr->InputAt(0)->IsImmediate()) {
480 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), 575 __ Call(Handle<Code>::cast(i.InputHeapObject(0)),
481 RelocInfo::CODE_TARGET); 576 RelocInfo::CODE_TARGET);
482 } else { 577 } else {
483 __ add(ip, i.InputRegister(0), 578 __ add(ip, i.InputRegister(0),
484 Operand(Code::kHeaderSize - kHeapObjectTag)); 579 Operand(Code::kHeaderSize - kHeapObjectTag));
485 __ Call(ip); 580 __ Call(ip);
486 } 581 }
487 RecordCallPosition(instr); 582 RecordCallPosition(instr);
488 DCHECK_EQ(LeaveCC, i.OutputSBit()); 583 DCHECK_EQ(LeaveCC, i.OutputSBit());
489 frame_access_state()->ClearSPDelta(); 584 frame_access_state()->ClearSPDelta();
490 break; 585 break;
491 } 586 }
492 case kArchTailCallCodeObjectFromJSFunction: 587 case kArchTailCallCodeObjectFromJSFunction:
493 case kArchTailCallCodeObject: { 588 case kArchTailCallCodeObject: {
494 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
495 AssembleDeconstructActivationRecord(stack_param_delta);
496 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { 589 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
497 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 590 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
498 i.TempRegister(0), i.TempRegister(1), 591 i.TempRegister(0), i.TempRegister(1),
499 i.TempRegister(2)); 592 i.TempRegister(2));
500 } 593 }
501 if (instr->InputAt(0)->IsImmediate()) { 594 if (instr->InputAt(0)->IsImmediate()) {
502 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), 595 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
503 RelocInfo::CODE_TARGET); 596 RelocInfo::CODE_TARGET);
504 } else { 597 } else {
505 __ add(ip, i.InputRegister(0), 598 __ add(ip, i.InputRegister(0),
506 Operand(Code::kHeaderSize - kHeapObjectTag)); 599 Operand(Code::kHeaderSize - kHeapObjectTag));
507 __ Jump(ip); 600 __ Jump(ip);
508 } 601 }
509 DCHECK_EQ(LeaveCC, i.OutputSBit()); 602 DCHECK_EQ(LeaveCC, i.OutputSBit());
510 frame_access_state()->ClearSPDelta(); 603 frame_access_state()->ClearSPDelta();
604 frame_access_state()->SetFrameAccessToDefault();
511 break; 605 break;
512 } 606 }
513 case kArchTailCallAddress: { 607 case kArchTailCallAddress: {
514 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
515 AssembleDeconstructActivationRecord(stack_param_delta);
516 CHECK(!instr->InputAt(0)->IsImmediate()); 608 CHECK(!instr->InputAt(0)->IsImmediate());
517 __ Jump(i.InputRegister(0)); 609 __ Jump(i.InputRegister(0));
518 frame_access_state()->ClearSPDelta(); 610 frame_access_state()->ClearSPDelta();
611 frame_access_state()->SetFrameAccessToDefault();
519 break; 612 break;
520 } 613 }
521 case kArchCallJSFunction: { 614 case kArchCallJSFunction: {
522 EnsureSpaceForLazyDeopt(); 615 EnsureSpaceForLazyDeopt();
523 Register func = i.InputRegister(0); 616 Register func = i.InputRegister(0);
524 if (FLAG_debug_code) { 617 if (FLAG_debug_code) {
525 // Check the function's context matches the context argument. 618 // Check the function's context matches the context argument.
526 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); 619 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
527 __ cmp(cp, kScratchReg); 620 __ cmp(cp, kScratchReg);
528 __ Assert(eq, kWrongFunctionContext); 621 __ Assert(eq, kWrongFunctionContext);
529 } 622 }
530 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 623 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
531 __ Call(ip); 624 __ Call(ip);
532 RecordCallPosition(instr); 625 RecordCallPosition(instr);
533 DCHECK_EQ(LeaveCC, i.OutputSBit()); 626 DCHECK_EQ(LeaveCC, i.OutputSBit());
534 frame_access_state()->ClearSPDelta(); 627 frame_access_state()->ClearSPDelta();
535 break; 628 break;
536 } 629 }
537 case kArchTailCallJSFunctionFromJSFunction: 630 case kArchTailCallJSFunctionFromJSFunction:
538 case kArchTailCallJSFunction: { 631 case kArchTailCallJSFunction: {
539 Register func = i.InputRegister(0); 632 Register func = i.InputRegister(0);
540 if (FLAG_debug_code) { 633 if (FLAG_debug_code) {
541 // Check the function's context matches the context argument. 634 // Check the function's context matches the context argument.
542 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); 635 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
543 __ cmp(cp, kScratchReg); 636 __ cmp(cp, kScratchReg);
544 __ Assert(eq, kWrongFunctionContext); 637 __ Assert(eq, kWrongFunctionContext);
545 } 638 }
546 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
547 AssembleDeconstructActivationRecord(stack_param_delta);
548 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { 639 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) {
549 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 640 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
550 i.TempRegister(0), i.TempRegister(1), 641 i.TempRegister(0), i.TempRegister(1),
551 i.TempRegister(2)); 642 i.TempRegister(2));
552 } 643 }
553 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 644 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
554 __ Jump(ip); 645 __ Jump(ip);
555 DCHECK_EQ(LeaveCC, i.OutputSBit()); 646 DCHECK_EQ(LeaveCC, i.OutputSBit());
556 frame_access_state()->ClearSPDelta(); 647 frame_access_state()->ClearSPDelta();
648 frame_access_state()->SetFrameAccessToDefault();
557 break; 649 break;
558 } 650 }
559 case kArchPrepareCallCFunction: { 651 case kArchPrepareCallCFunction: {
560 int const num_parameters = MiscField::decode(instr->opcode()); 652 int const num_parameters = MiscField::decode(instr->opcode());
561 __ PrepareCallCFunction(num_parameters, kScratchReg); 653 __ PrepareCallCFunction(num_parameters, kScratchReg);
562 // Frame alignment requires using FP-relative frame addressing. 654 // Frame alignment requires using FP-relative frame addressing.
563 frame_access_state()->SetFrameAccessToFP(); 655 frame_access_state()->SetFrameAccessToFP();
564 break; 656 break;
565 } 657 }
566 case kArchPrepareTailCall: 658 case kArchPrepareTailCall:
567 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 659 AssemblePrepareTailCall();
568 break; 660 break;
569 case kArchCallCFunction: { 661 case kArchCallCFunction: {
570 int const num_parameters = MiscField::decode(instr->opcode()); 662 int const num_parameters = MiscField::decode(instr->opcode());
571 if (instr->InputAt(0)->IsImmediate()) { 663 if (instr->InputAt(0)->IsImmediate()) {
572 ExternalReference ref = i.InputExternalReference(0); 664 ExternalReference ref = i.InputExternalReference(0);
573 __ CallCFunction(ref, num_parameters); 665 __ CallCFunction(ref, num_parameters);
574 } else { 666 } else {
575 Register func = i.InputRegister(0); 667 Register func = i.InputRegister(0);
576 __ CallCFunction(func, num_parameters); 668 __ CallCFunction(func, num_parameters);
577 } 669 }
(...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 padding_size -= v8::internal::Assembler::kInstrSize; 1917 padding_size -= v8::internal::Assembler::kInstrSize;
1826 } 1918 }
1827 } 1919 }
1828 } 1920 }
1829 1921
1830 #undef __ 1922 #undef __
1831 1923
1832 } // namespace compiler 1924 } // namespace compiler
1833 } // namespace internal 1925 } // namespace internal
1834 } // namespace v8 1926 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698