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

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: Review feedback 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
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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 0, 1); \ 404 0, 1); \
405 /* Move the result in the double result register. */ \ 405 /* Move the result in the double result register. */ \
406 __ MovFromFloatResult(i.OutputDoubleRegister()); \ 406 __ MovFromFloatResult(i.OutputDoubleRegister()); \
407 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 407 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
408 } while (0) 408 } while (0)
409 409
410 void CodeGenerator::AssembleDeconstructFrame() { 410 void CodeGenerator::AssembleDeconstructFrame() {
411 __ LeaveFrame(StackFrame::MANUAL); 411 __ LeaveFrame(StackFrame::MANUAL);
412 } 412 }
413 413
414 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 414 void CodeGenerator::AssemblePrepareTailCall() {
415 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
416 if (sp_slot_delta > 0) {
417 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize));
418 }
419 frame_access_state()->SetFrameAccessToDefault();
420 }
421
422
423 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
424 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
425 if (sp_slot_delta < 0) {
426 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
427 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
428 }
429 if (frame_access_state()->has_frame()) { 415 if (frame_access_state()->has_frame()) {
430 if (FLAG_enable_embedded_constant_pool) { 416 if (FLAG_enable_embedded_constant_pool) {
431 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); 417 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
432 } 418 }
433 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); 419 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
434 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 420 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
435 } 421 }
436 frame_access_state()->SetFrameAccessToSP(); 422 frame_access_state()->SetFrameAccessToSP();
437 } 423 }
438 424
(...skipping 15 matching lines...) Expand all
454 __ ldr(caller_args_count_reg, 440 __ ldr(caller_args_count_reg,
455 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 441 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
456 __ SmiUntag(caller_args_count_reg); 442 __ SmiUntag(caller_args_count_reg);
457 443
458 ParameterCount callee_args_count(args_reg); 444 ParameterCount callee_args_count(args_reg);
459 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, 445 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
460 scratch3); 446 scratch3);
461 __ bind(&done); 447 __ bind(&done);
462 } 448 }
463 449
450 namespace {
451
452 void FlushPendingPushRegisters(MacroAssembler* masm,
453 FrameAccessState* frame_access_state,
454 ZoneVector<Register>* pending_pushes) {
455 switch (pending_pushes->size()) {
456 case 0:
457 break;
458 case 1:
459 masm->push((*pending_pushes)[0]);
Mircea Trofin 2016/06/30 15:32:34 pending_pushes->at(0) same further down and else
danno 2016/07/01 07:31:57 Done.
460 break;
461 case 2:
462 masm->Push((*pending_pushes)[0], (*pending_pushes)[1]);
463 break;
464 case 3:
465 masm->Push((*pending_pushes)[0], (*pending_pushes)[1],
466 (*pending_pushes)[2]);
467 break;
468 default:
469 UNREACHABLE();
470 break;
471 }
472 frame_access_state->IncreaseSPDelta(pending_pushes->size());
473 pending_pushes->resize(0);
474 }
475
476 void AddPendingPushRegister(MacroAssembler* masm,
477 FrameAccessState* frame_access_state,
478 ZoneVector<Register>* pending_pushes,
479 Register reg) {
480 pending_pushes->push_back(reg);
481 if (pending_pushes->size() == 3 || reg.is(ip)) {
482 FlushPendingPushRegisters(masm, frame_access_state, pending_pushes);
483 }
484 }
485
486 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state,
487 int new_slot_above_sp,
488 ZoneVector<Register>* pending_pushes = nullptr,
489 bool allow_shrinkage = true) {
490 int current_sp_offset = state->GetSPToFPSlotCount() +
491 StandardFrameConstants::kFixedSlotCountAboveFp;
492 int stack_slot_delta = new_slot_above_sp - current_sp_offset;
493 if (stack_slot_delta > 0) {
494 if (pending_pushes != nullptr) {
495 FlushPendingPushRegisters(masm, state, pending_pushes);
496 }
497 masm->sub(sp, sp, Operand(stack_slot_delta * kPointerSize));
498 state->IncreaseSPDelta(stack_slot_delta);
499 } else if (allow_shrinkage && stack_slot_delta < 0) {
500 if (pending_pushes != nullptr) {
501 FlushPendingPushRegisters(masm, state, pending_pushes);
502 }
503 masm->add(sp, sp, Operand(-stack_slot_delta * kPointerSize));
504 state->IncreaseSPDelta(stack_slot_delta);
505 }
506 }
507
508 } // namespace
509
510 void CodeGenerator::AssemblePreGaps(Instruction* instr) {
511 int first_unused_stack_slot;
512 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return;
513
514 GapResolver::PushTypeFlags flags(GapResolver::kImmediatePush |
515 GapResolver::kScalarPush);
516 ZoneVector<MoveOperands*> pushes(zone());
517 resolver()->GetPushCompatibleMoves(zone(), instr, flags, &pushes);
518
519 if (!pushes.empty() &&
520 (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
521 first_unused_stack_slot)) {
522 ArmOperandConverter g(this, instr);
523 ZoneVector<Register> pending_pushes(zone());
524 for (auto move : pushes) {
525 LocationOperand destination_location(
526 LocationOperand::cast(move->destination()));
527 InstructionOperand source(move->source());
528 AdjustStackPointerForGap(
529 masm(), frame_access_state(),
530 destination_location.index() - pending_pushes.size(),
531 &pending_pushes);
532 if (source.IsStackSlot()) {
533 LocationOperand source_location(LocationOperand::cast(source));
534 __ ldr(ip, g.SlotToMemOperand(source_location.index()));
535 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
536 ip);
537 } else if (source.IsRegister()) {
538 LocationOperand source_location(LocationOperand::cast(source));
539 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
540 source_location.GetRegister());
541 } else if (source.IsImmediate()) {
542 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes,
543 ip);
544 } else {
545 // Pushes of non-scalar data types is not supported.
546 UNIMPLEMENTED();
547 }
548 move->Eliminate();
549 }
550 FlushPendingPushRegisters(masm(), frame_access_state(), &pending_pushes);
551 }
552 AdjustStackPointerForGap(masm(), frame_access_state(),
553 first_unused_stack_slot, nullptr, false);
554 }
555
556 void CodeGenerator::AssemblePostGaps(Instruction* instr) {
557 int first_unused_stack_slot;
558 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return;
559 AdjustStackPointerForGap(masm(), frame_access_state(),
560 first_unused_stack_slot);
561 }
562
464 // Assembles an instruction after register allocation, producing machine code. 563 // Assembles an instruction after register allocation, producing machine code.
465 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( 564 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
466 Instruction* instr) { 565 Instruction* instr) {
467 ArmOperandConverter i(this, instr); 566 ArmOperandConverter i(this, instr);
468 567
469 __ MaybeCheckConstPool(); 568 __ MaybeCheckConstPool();
470 InstructionCode opcode = instr->opcode(); 569 InstructionCode opcode = instr->opcode();
471 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); 570 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
472 switch (arch_opcode) { 571 switch (arch_opcode) {
473 case kArchCallCodeObject: { 572 case kArchCallCodeObject: {
474 EnsureSpaceForLazyDeopt(); 573 EnsureSpaceForLazyDeopt();
475 if (instr->InputAt(0)->IsImmediate()) { 574 if (instr->InputAt(0)->IsImmediate()) {
476 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), 575 __ Call(Handle<Code>::cast(i.InputHeapObject(0)),
477 RelocInfo::CODE_TARGET); 576 RelocInfo::CODE_TARGET);
478 } else { 577 } else {
479 __ add(ip, i.InputRegister(0), 578 __ add(ip, i.InputRegister(0),
480 Operand(Code::kHeaderSize - kHeapObjectTag)); 579 Operand(Code::kHeaderSize - kHeapObjectTag));
481 __ Call(ip); 580 __ Call(ip);
482 } 581 }
483 RecordCallPosition(instr); 582 RecordCallPosition(instr);
484 DCHECK_EQ(LeaveCC, i.OutputSBit()); 583 DCHECK_EQ(LeaveCC, i.OutputSBit());
485 frame_access_state()->ClearSPDelta(); 584 frame_access_state()->ClearSPDelta();
486 break; 585 break;
487 } 586 }
488 case kArchTailCallCodeObjectFromJSFunction: 587 case kArchTailCallCodeObjectFromJSFunction:
489 case kArchTailCallCodeObject: { 588 case kArchTailCallCodeObject: {
490 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
491 AssembleDeconstructActivationRecord(stack_param_delta);
492 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { 589 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
493 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 590 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
494 i.TempRegister(0), i.TempRegister(1), 591 i.TempRegister(0), i.TempRegister(1),
495 i.TempRegister(2)); 592 i.TempRegister(2));
496 } 593 }
497 if (instr->InputAt(0)->IsImmediate()) { 594 if (instr->InputAt(0)->IsImmediate()) {
498 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), 595 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
499 RelocInfo::CODE_TARGET); 596 RelocInfo::CODE_TARGET);
500 } else { 597 } else {
501 __ add(ip, i.InputRegister(0), 598 __ add(ip, i.InputRegister(0),
502 Operand(Code::kHeaderSize - kHeapObjectTag)); 599 Operand(Code::kHeaderSize - kHeapObjectTag));
503 __ Jump(ip); 600 __ Jump(ip);
504 } 601 }
505 DCHECK_EQ(LeaveCC, i.OutputSBit()); 602 DCHECK_EQ(LeaveCC, i.OutputSBit());
506 frame_access_state()->ClearSPDelta(); 603 frame_access_state()->ClearSPDelta();
604 frame_access_state()->SetFrameAccessToDefault();
507 break; 605 break;
508 } 606 }
509 case kArchTailCallAddress: { 607 case kArchTailCallAddress: {
510 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
511 AssembleDeconstructActivationRecord(stack_param_delta);
512 CHECK(!instr->InputAt(0)->IsImmediate()); 608 CHECK(!instr->InputAt(0)->IsImmediate());
513 __ Jump(i.InputRegister(0)); 609 __ Jump(i.InputRegister(0));
514 frame_access_state()->ClearSPDelta(); 610 frame_access_state()->ClearSPDelta();
611 frame_access_state()->SetFrameAccessToDefault();
515 break; 612 break;
516 } 613 }
517 case kArchCallJSFunction: { 614 case kArchCallJSFunction: {
518 EnsureSpaceForLazyDeopt(); 615 EnsureSpaceForLazyDeopt();
519 Register func = i.InputRegister(0); 616 Register func = i.InputRegister(0);
520 if (FLAG_debug_code) { 617 if (FLAG_debug_code) {
521 // Check the function's context matches the context argument. 618 // Check the function's context matches the context argument.
522 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); 619 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
523 __ cmp(cp, kScratchReg); 620 __ cmp(cp, kScratchReg);
524 __ Assert(eq, kWrongFunctionContext); 621 __ Assert(eq, kWrongFunctionContext);
525 } 622 }
526 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 623 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
527 __ Call(ip); 624 __ Call(ip);
528 RecordCallPosition(instr); 625 RecordCallPosition(instr);
529 DCHECK_EQ(LeaveCC, i.OutputSBit()); 626 DCHECK_EQ(LeaveCC, i.OutputSBit());
530 frame_access_state()->ClearSPDelta(); 627 frame_access_state()->ClearSPDelta();
531 break; 628 break;
532 } 629 }
533 case kArchTailCallJSFunctionFromJSFunction: 630 case kArchTailCallJSFunctionFromJSFunction:
534 case kArchTailCallJSFunction: { 631 case kArchTailCallJSFunction: {
535 Register func = i.InputRegister(0); 632 Register func = i.InputRegister(0);
536 if (FLAG_debug_code) { 633 if (FLAG_debug_code) {
537 // Check the function's context matches the context argument. 634 // Check the function's context matches the context argument.
538 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); 635 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
539 __ cmp(cp, kScratchReg); 636 __ cmp(cp, kScratchReg);
540 __ Assert(eq, kWrongFunctionContext); 637 __ Assert(eq, kWrongFunctionContext);
541 } 638 }
542 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
543 AssembleDeconstructActivationRecord(stack_param_delta);
544 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { 639 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) {
545 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 640 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
546 i.TempRegister(0), i.TempRegister(1), 641 i.TempRegister(0), i.TempRegister(1),
547 i.TempRegister(2)); 642 i.TempRegister(2));
548 } 643 }
549 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 644 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
550 __ Jump(ip); 645 __ Jump(ip);
551 DCHECK_EQ(LeaveCC, i.OutputSBit()); 646 DCHECK_EQ(LeaveCC, i.OutputSBit());
552 frame_access_state()->ClearSPDelta(); 647 frame_access_state()->ClearSPDelta();
648 frame_access_state()->SetFrameAccessToDefault();
553 break; 649 break;
554 } 650 }
555 case kArchPrepareCallCFunction: { 651 case kArchPrepareCallCFunction: {
556 int const num_parameters = MiscField::decode(instr->opcode()); 652 int const num_parameters = MiscField::decode(instr->opcode());
557 __ PrepareCallCFunction(num_parameters, kScratchReg); 653 __ PrepareCallCFunction(num_parameters, kScratchReg);
558 // Frame alignment requires using FP-relative frame addressing. 654 // Frame alignment requires using FP-relative frame addressing.
559 frame_access_state()->SetFrameAccessToFP(); 655 frame_access_state()->SetFrameAccessToFP();
560 break; 656 break;
561 } 657 }
562 case kArchPrepareTailCall: 658 case kArchPrepareTailCall:
563 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 659 AssemblePrepareTailCall();
564 break; 660 break;
565 case kArchCallCFunction: { 661 case kArchCallCFunction: {
566 int const num_parameters = MiscField::decode(instr->opcode()); 662 int const num_parameters = MiscField::decode(instr->opcode());
567 if (instr->InputAt(0)->IsImmediate()) { 663 if (instr->InputAt(0)->IsImmediate()) {
568 ExternalReference ref = i.InputExternalReference(0); 664 ExternalReference ref = i.InputExternalReference(0);
569 __ CallCFunction(ref, num_parameters); 665 __ CallCFunction(ref, num_parameters);
570 } else { 666 } else {
571 Register func = i.InputRegister(0); 667 Register func = i.InputRegister(0);
572 __ CallCFunction(func, num_parameters); 668 __ CallCFunction(func, num_parameters);
573 } 669 }
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 padding_size -= v8::internal::Assembler::kInstrSize; 1908 padding_size -= v8::internal::Assembler::kInstrSize;
1813 } 1909 }
1814 } 1910 }
1815 } 1911 }
1816 1912
1817 #undef __ 1913 #undef __
1818 1914
1819 } // namespace compiler 1915 } // namespace compiler
1820 } // namespace internal 1916 } // namespace internal
1821 } // namespace v8 1917 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | src/compiler/code-generator.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698