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

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

Issue 1460183002: [turbofan] Add general support for sp-based frame access (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix arm64 Created 5 years, 1 month 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/arm64/frames-arm64.h" 7 #include "src/arm64/frames-arm64.h"
8 #include "src/arm64/macro-assembler-arm64.h" 8 #include "src/arm64/macro-assembler-arm64.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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 UNREACHABLE(); // TODO(dcarney): RPO immediates on arm64. 198 UNREACHABLE(); // TODO(dcarney): RPO immediates on arm64.
199 break; 199 break;
200 } 200 }
201 UNREACHABLE(); 201 UNREACHABLE();
202 return Operand(-1); 202 return Operand(-1);
203 } 203 }
204 204
205 MemOperand ToMemOperand(InstructionOperand* op, MacroAssembler* masm) const { 205 MemOperand ToMemOperand(InstructionOperand* op, MacroAssembler* masm) const {
206 DCHECK(op != NULL); 206 DCHECK(op != NULL);
207 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); 207 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
208 FrameOffset offset = 208 FrameOffset offset = linkage()->GetFrameOffset(
209 linkage()->GetFrameOffset(AllocatedOperand::cast(op)->index(), frame()); 209 AllocatedOperand::cast(op)->index(), frame_access_state());
210 if (offset.from_frame_pointer()) { 210 if (offset.from_frame_pointer()) {
211 int from_sp = 211 int from_sp =
212 offset.offset() + (frame()->GetSpToFpSlotCount() * kPointerSize); 212 offset.offset() +
213 ((frame()->GetSpToFpSlotCount() + frame_access_state()->sp_delta()) *
214 kPointerSize);
213 // Convert FP-offsets to SP-offsets if it results in better code. 215 // Convert FP-offsets to SP-offsets if it results in better code.
214 if (Assembler::IsImmLSUnscaled(from_sp) || 216 if (Assembler::IsImmLSUnscaled(from_sp) ||
215 Assembler::IsImmLSScaled(from_sp, LSDoubleWord)) { 217 Assembler::IsImmLSScaled(from_sp, LSDoubleWord)) {
216 offset = FrameOffset::FromStackPointer(from_sp); 218 offset = FrameOffset::FromStackPointer(from_sp);
217 } 219 }
218 } 220 }
219 return MemOperand(offset.from_stack_pointer() ? masm->StackPointer() : fp, 221 return MemOperand(offset.from_stack_pointer() ? masm->StackPointer() : fp,
220 offset.offset()); 222 offset.offset());
221 } 223 }
222 }; 224 };
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 // Discard only slots that won't be used by new parameters. 472 // Discard only slots that won't be used by new parameters.
471 total_discarded_slots -= stack_param_delta; 473 total_discarded_slots -= stack_param_delta;
472 if (total_discarded_slots > 0) { 474 if (total_discarded_slots > 0) {
473 __ Add(jssp, jssp, Operand(total_discarded_slots * kPointerSize)); 475 __ Add(jssp, jssp, Operand(total_discarded_slots * kPointerSize));
474 } 476 }
475 } else { 477 } else {
476 __ Mov(jssp, fp); 478 __ Mov(jssp, fp);
477 } 479 }
478 __ Pop(fp, lr); 480 __ Pop(fp, lr);
479 } 481 }
482 frame_access_state()->UseDefaultFrameAccess();
480 } 483 }
481 484
482 485
483 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { 486 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
484 if (stack_param_delta > 0) { 487 if (stack_param_delta > 0) {
485 int total_discarded_slots = frame()->GetTotalFrameSlotCount(); 488 int total_discarded_slots = frame()->GetTotalFrameSlotCount();
486 // Leave the PC and saved frame pointer on the stack. 489 // Leave the PC and saved frame pointer on the stack.
487 total_discarded_slots -= 490 total_discarded_slots -=
488 StandardFrameConstants::kFixedFrameSizeFromFp / kPointerSize; 491 StandardFrameConstants::kFixedFrameSizeFromFp / kPointerSize;
489 // Discard only slots that won't be used by new parameters. 492 // Discard only slots that won't be used by new parameters.
490 total_discarded_slots -= stack_param_delta; 493 total_discarded_slots -= stack_param_delta;
491 if (total_discarded_slots < 0) { 494 if (total_discarded_slots < 0) {
492 __ Sub(jssp, jssp, Operand(-total_discarded_slots * kPointerSize)); 495 __ Sub(jssp, jssp, Operand(-total_discarded_slots * kPointerSize));
496 frame_access_state()->IncreaseSPDelta(-total_discarded_slots);
493 } 497 }
494 } 498 }
499 frame_access_state()->UseSPToAccessFrame();
495 } 500 }
496 501
497 502
498 // Assembles an instruction after register allocation, producing machine code. 503 // Assembles an instruction after register allocation, producing machine code.
499 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { 504 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
500 Arm64OperandConverter i(this, instr); 505 Arm64OperandConverter i(this, instr);
501 InstructionCode opcode = instr->opcode(); 506 InstructionCode opcode = instr->opcode();
502 switch (ArchOpcodeField::decode(opcode)) { 507 switch (ArchOpcodeField::decode(opcode)) {
503 case kArchCallCodeObject: { 508 case kArchCallCodeObject: {
504 EnsureSpaceForLazyDeopt(); 509 EnsureSpaceForLazyDeopt();
505 if (instr->InputAt(0)->IsImmediate()) { 510 if (instr->InputAt(0)->IsImmediate()) {
506 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), 511 __ Call(Handle<Code>::cast(i.InputHeapObject(0)),
507 RelocInfo::CODE_TARGET); 512 RelocInfo::CODE_TARGET);
508 } else { 513 } else {
509 Register target = i.InputRegister(0); 514 Register target = i.InputRegister(0);
510 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); 515 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag);
511 __ Call(target); 516 __ Call(target);
512 } 517 }
513 frame()->ClearOutgoingParameterSlots(); 518 frame_access_state()->ClearSPDelta();
514 RecordCallPosition(instr); 519 RecordCallPosition(instr);
515 break; 520 break;
516 } 521 }
517 case kArchTailCallCodeObject: { 522 case kArchTailCallCodeObject: {
518 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); 523 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
519 AssembleDeconstructActivationRecord(stack_param_delta); 524 AssembleDeconstructActivationRecord(stack_param_delta);
520 if (instr->InputAt(0)->IsImmediate()) { 525 if (instr->InputAt(0)->IsImmediate()) {
521 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), 526 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
522 RelocInfo::CODE_TARGET); 527 RelocInfo::CODE_TARGET);
523 } else { 528 } else {
524 Register target = i.InputRegister(0); 529 Register target = i.InputRegister(0);
525 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); 530 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag);
526 __ Jump(target); 531 __ Jump(target);
527 } 532 }
528 frame()->ClearOutgoingParameterSlots(); 533 frame_access_state()->ClearSPDelta();
529 break; 534 break;
530 } 535 }
531 case kArchCallJSFunction: { 536 case kArchCallJSFunction: {
532 EnsureSpaceForLazyDeopt(); 537 EnsureSpaceForLazyDeopt();
533 Register func = i.InputRegister(0); 538 Register func = i.InputRegister(0);
534 if (FLAG_debug_code) { 539 if (FLAG_debug_code) {
535 // Check the function's context matches the context argument. 540 // Check the function's context matches the context argument.
536 UseScratchRegisterScope scope(masm()); 541 UseScratchRegisterScope scope(masm());
537 Register temp = scope.AcquireX(); 542 Register temp = scope.AcquireX();
538 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); 543 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset));
539 __ cmp(cp, temp); 544 __ cmp(cp, temp);
540 __ Assert(eq, kWrongFunctionContext); 545 __ Assert(eq, kWrongFunctionContext);
541 } 546 }
542 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 547 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
543 __ Call(x10); 548 __ Call(x10);
544 frame()->ClearOutgoingParameterSlots(); 549 frame_access_state()->ClearSPDelta();
545 RecordCallPosition(instr); 550 RecordCallPosition(instr);
546 break; 551 break;
547 } 552 }
548 case kArchTailCallJSFunction: { 553 case kArchTailCallJSFunction: {
549 Register func = i.InputRegister(0); 554 Register func = i.InputRegister(0);
550 if (FLAG_debug_code) { 555 if (FLAG_debug_code) {
551 // Check the function's context matches the context argument. 556 // Check the function's context matches the context argument.
552 UseScratchRegisterScope scope(masm()); 557 UseScratchRegisterScope scope(masm());
553 Register temp = scope.AcquireX(); 558 Register temp = scope.AcquireX();
554 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); 559 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset));
555 __ cmp(cp, temp); 560 __ cmp(cp, temp);
556 __ Assert(eq, kWrongFunctionContext); 561 __ Assert(eq, kWrongFunctionContext);
557 } 562 }
558 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); 563 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
559 AssembleDeconstructActivationRecord(stack_param_delta); 564 AssembleDeconstructActivationRecord(stack_param_delta);
560 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 565 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
561 __ Jump(x10); 566 __ Jump(x10);
562 frame()->ClearOutgoingParameterSlots(); 567 frame_access_state()->ClearSPDelta();
563 break; 568 break;
564 } 569 }
565 case kArchLazyBailout: { 570 case kArchLazyBailout: {
566 EnsureSpaceForLazyDeopt(); 571 EnsureSpaceForLazyDeopt();
567 RecordCallPosition(instr); 572 RecordCallPosition(instr);
568 break; 573 break;
569 } 574 }
570 case kArchPrepareCallCFunction: 575 case kArchPrepareCallCFunction:
571 // We don't need kArchPrepareCallCFunction on arm64 as the instruction 576 // We don't need kArchPrepareCallCFunction on arm64 as the instruction
572 // selector already perform a Claim to reserve space on the stack and 577 // selector already perform a Claim to reserve space on the stack and
573 // guarantee correct alignment of stack pointer. 578 // guarantee correct alignment of stack pointer.
574 UNREACHABLE(); 579 UNREACHABLE();
575 break; 580 break;
576 case kArchPrepareTailCall: 581 case kArchPrepareTailCall:
577 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 582 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
578 break; 583 break;
579 case kArchCallCFunction: { 584 case kArchCallCFunction: {
580 int const num_parameters = MiscField::decode(instr->opcode()); 585 int const num_parameters = MiscField::decode(instr->opcode());
581 if (instr->InputAt(0)->IsImmediate()) { 586 if (instr->InputAt(0)->IsImmediate()) {
582 ExternalReference ref = i.InputExternalReference(0); 587 ExternalReference ref = i.InputExternalReference(0);
583 __ CallCFunction(ref, num_parameters, 0); 588 __ CallCFunction(ref, num_parameters, 0);
584 } else { 589 } else {
585 Register func = i.InputRegister(0); 590 Register func = i.InputRegister(0);
586 __ CallCFunction(func, num_parameters, 0); 591 __ CallCFunction(func, num_parameters, 0);
587 } 592 }
588 // CallCFunction only supports register arguments so we never need to call 593 // CallCFunction only supports register arguments so we never need to call
589 // frame()->ClearOutgoingParameterSlots() here. 594 // frame()->ClearOutgoingParameterSlots() here.
590 DCHECK(frame()->GetOutgoingParameterSlotCount() == 0); 595 DCHECK(frame_access_state()->sp_delta() == 0);
591 break; 596 break;
592 } 597 }
593 case kArchJmp: 598 case kArchJmp:
594 AssembleArchJump(i.InputRpo(0)); 599 AssembleArchJump(i.InputRpo(0));
595 break; 600 break;
596 case kArchTableSwitch: 601 case kArchTableSwitch:
597 AssembleArchTableSwitch(instr); 602 AssembleArchTableSwitch(instr);
598 break; 603 break;
599 case kArchLookupSwitch: 604 case kArchLookupSwitch:
600 AssembleArchLookupSwitch(instr); 605 AssembleArchLookupSwitch(instr);
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 break; 871 break;
867 case kArm64TestAndBranch32: 872 case kArm64TestAndBranch32:
868 case kArm64TestAndBranch: 873 case kArm64TestAndBranch:
869 // Pseudo instructions turned into tbz/tbnz in AssembleArchBranch. 874 // Pseudo instructions turned into tbz/tbnz in AssembleArchBranch.
870 break; 875 break;
871 case kArm64CompareAndBranch32: 876 case kArm64CompareAndBranch32:
872 // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch. 877 // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch.
873 break; 878 break;
874 case kArm64ClaimForCallArguments: { 879 case kArm64ClaimForCallArguments: {
875 __ Claim(i.InputInt32(0)); 880 __ Claim(i.InputInt32(0));
876 frame()->AllocateOutgoingParameterSlots(i.InputInt32(0)); 881 frame_access_state()->IncreaseSPDelta(i.InputInt32(0));
877 break; 882 break;
878 } 883 }
879 case kArm64Poke: { 884 case kArm64Poke: {
880 Operand operand(i.InputInt32(1) * kPointerSize); 885 Operand operand(i.InputInt32(1) * kPointerSize);
881 __ Poke(i.InputRegister(0), operand); 886 __ Poke(i.InputRegister(0), operand);
882 break; 887 break;
883 } 888 }
884 case kArm64PokePair: { 889 case kArm64PokePair: {
885 int slot = i.InputInt32(2) - 1; 890 int slot = i.InputInt32(2) - 1;
886 __ PokePair(i.InputRegister(1), i.InputRegister(0), slot * kPointerSize); 891 __ PokePair(i.InputRegister(1), i.InputRegister(0), slot * kPointerSize);
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 void CodeGenerator::AssemblePrologue() { 1281 void CodeGenerator::AssemblePrologue() {
1277 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1282 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1278 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1283 if (descriptor->kind() == CallDescriptor::kCallAddress) {
1279 __ SetStackPointer(csp); 1284 __ SetStackPointer(csp);
1280 __ Push(lr, fp); 1285 __ Push(lr, fp);
1281 __ Mov(fp, csp); 1286 __ Mov(fp, csp);
1282 } else if (descriptor->IsJSFunctionCall()) { 1287 } else if (descriptor->IsJSFunctionCall()) {
1283 CompilationInfo* info = this->info(); 1288 CompilationInfo* info = this->info();
1284 __ SetStackPointer(jssp); 1289 __ SetStackPointer(jssp);
1285 __ Prologue(info->IsCodePreAgingActive()); 1290 __ Prologue(info->IsCodePreAgingActive());
1286 } else if (needs_frame_) { 1291 } else if (frame()->needs_frame()) {
1287 __ SetStackPointer(jssp); 1292 __ SetStackPointer(jssp);
1288 __ StubPrologue(); 1293 __ StubPrologue();
1289 } else { 1294 } else {
1290 frame()->SetElidedFrameSizeInSlots(0); 1295 frame()->SetElidedFrameSizeInSlots(0);
1291 } 1296 }
1297 frame_access_state()->UseDefaultFrameAccess();
1292 1298
1293 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1299 int stack_shrink_slots = frame()->GetSpillSlotCount();
1294 if (info()->is_osr()) { 1300 if (info()->is_osr()) {
1295 // TurboFan OSR-compiled functions cannot be entered directly. 1301 // TurboFan OSR-compiled functions cannot be entered directly.
1296 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1302 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1297 1303
1298 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1304 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1299 // frame is still on the stack. Optimized code uses OSR values directly from 1305 // frame is still on the stack. Optimized code uses OSR values directly from
1300 // the unoptimized frame. Thus, all that needs to be done is to allocate the 1306 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1301 // remaining stack slots. 1307 // remaining stack slots.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits, 1357 CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
1352 descriptor->CalleeSavedFPRegisters()); 1358 descriptor->CalleeSavedFPRegisters());
1353 if (saves_fp.Count() != 0) { 1359 if (saves_fp.Count() != 0) {
1354 __ PopCPURegList(saves_fp); 1360 __ PopCPURegList(saves_fp);
1355 } 1361 }
1356 1362
1357 int pop_count = static_cast<int>(descriptor->StackParameterCount()); 1363 int pop_count = static_cast<int>(descriptor->StackParameterCount());
1358 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1364 if (descriptor->kind() == CallDescriptor::kCallAddress) {
1359 __ Mov(csp, fp); 1365 __ Mov(csp, fp);
1360 __ Pop(fp, lr); 1366 __ Pop(fp, lr);
1361 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { 1367 } else if (descriptor->IsJSFunctionCall() || frame()->needs_frame()) {
1362 // Canonicalize JSFunction return sites for now. 1368 // Canonicalize JSFunction return sites for now.
1363 if (return_label_.is_bound()) { 1369 if (return_label_.is_bound()) {
1364 __ B(&return_label_); 1370 __ B(&return_label_);
1365 return; 1371 return;
1366 } else { 1372 } else {
1367 __ Bind(&return_label_); 1373 __ Bind(&return_label_);
1368 __ Mov(jssp, fp); 1374 __ Mov(jssp, fp);
1369 __ Pop(fp, lr); 1375 __ Pop(fp, lr);
1370 } 1376 }
1371 } 1377 }
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 padding_size -= kInstructionSize; 1562 padding_size -= kInstructionSize;
1557 } 1563 }
1558 } 1564 }
1559 } 1565 }
1560 1566
1561 #undef __ 1567 #undef __
1562 1568
1563 } // namespace compiler 1569 } // namespace compiler
1564 } // namespace internal 1570 } // namespace internal
1565 } // namespace v8 1571 } // namespace v8
OLDNEW
« no previous file with comments | « BUILD.gn ('k') | src/compiler/code-generator.h » ('j') | src/compiler/linkage.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698