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

Side by Side Diff: src/compiler/arm/code-generator-arm.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: Last comment addressed Created 5 years 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/compiler/code-generator-impl.h" 8 #include "src/compiler/code-generator-impl.h"
9 #include "src/compiler/gap-resolver.h" 9 #include "src/compiler/gap-resolver.h"
10 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 return MemOperand(r0); 142 return MemOperand(r0);
143 } 143 }
144 144
145 MemOperand InputOffset(size_t first_index = 0) { 145 MemOperand InputOffset(size_t first_index = 0) {
146 return InputOffset(&first_index); 146 return InputOffset(&first_index);
147 } 147 }
148 148
149 MemOperand ToMemOperand(InstructionOperand* op) const { 149 MemOperand ToMemOperand(InstructionOperand* op) const {
150 DCHECK(op != NULL); 150 DCHECK(op != NULL);
151 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); 151 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
152 FrameOffset offset = 152 FrameOffset offset = frame_access_state()->GetFrameOffset(
153 linkage()->GetFrameOffset(AllocatedOperand::cast(op)->index(), frame()); 153 AllocatedOperand::cast(op)->index());
154 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); 154 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
155 } 155 }
156 }; 156 };
157 157
158 158
159 namespace { 159 namespace {
160 160
161 class OutOfLineLoadFloat32 final : public OutOfLineCode { 161 class OutOfLineLoadFloat32 final : public OutOfLineCode {
162 public: 162 public:
163 OutOfLineLoadFloat32(CodeGenerator* gen, SwVfpRegister result) 163 OutOfLineLoadFloat32(CodeGenerator* gen, SwVfpRegister result)
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 __ asm_instr(value, i.InputOffset(3), lo); \ 352 __ asm_instr(value, i.InputOffset(3), lo); \
353 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 353 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
354 } while (0) 354 } while (0)
355 355
356 356
357 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 357 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
358 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 358 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
359 if (sp_slot_delta > 0) { 359 if (sp_slot_delta > 0) {
360 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize)); 360 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize));
361 } 361 }
362 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 362 if (frame()->needs_frame()) {
363 int spill_slots = frame()->GetSpillSlotCount();
364 bool has_frame = descriptor->IsJSFunctionCall() || spill_slots > 0;
365 if (has_frame) {
366 if (FLAG_enable_embedded_constant_pool) { 363 if (FLAG_enable_embedded_constant_pool) {
367 __ ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit()); 364 __ ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
368 } else { 365 } else {
369 __ ldm(ia_w, sp, fp.bit() | lr.bit()); 366 __ ldm(ia_w, sp, fp.bit() | lr.bit());
370 } 367 }
371 } 368 }
369 frame_access_state()->SetFrameAccessToDefault();
372 } 370 }
373 371
374 372
375 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { 373 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
376 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 374 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
377 if (sp_slot_delta < 0) { 375 if (sp_slot_delta < 0) {
378 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize)); 376 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
377 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
379 } 378 }
379 frame_access_state()->SetFrameAccessToSP();
380 } 380 }
381 381
382 382
383 // Assembles an instruction after register allocation, producing machine code. 383 // Assembles an instruction after register allocation, producing machine code.
384 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { 384 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
385 ArmOperandConverter i(this, instr); 385 ArmOperandConverter i(this, instr);
386 386
387 masm()->MaybeCheckConstPool(); 387 masm()->MaybeCheckConstPool();
388 388
389 switch (ArchOpcodeField::decode(instr->opcode())) { 389 switch (ArchOpcodeField::decode(instr->opcode())) {
390 case kArchCallCodeObject: { 390 case kArchCallCodeObject: {
391 EnsureSpaceForLazyDeopt(); 391 EnsureSpaceForLazyDeopt();
392 if (instr->InputAt(0)->IsImmediate()) { 392 if (instr->InputAt(0)->IsImmediate()) {
393 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), 393 __ Call(Handle<Code>::cast(i.InputHeapObject(0)),
394 RelocInfo::CODE_TARGET); 394 RelocInfo::CODE_TARGET);
395 } else { 395 } else {
396 __ add(ip, i.InputRegister(0), 396 __ add(ip, i.InputRegister(0),
397 Operand(Code::kHeaderSize - kHeapObjectTag)); 397 Operand(Code::kHeaderSize - kHeapObjectTag));
398 __ Call(ip); 398 __ Call(ip);
399 } 399 }
400 RecordCallPosition(instr); 400 RecordCallPosition(instr);
401 DCHECK_EQ(LeaveCC, i.OutputSBit()); 401 DCHECK_EQ(LeaveCC, i.OutputSBit());
402 frame_access_state()->ClearSPDelta();
402 break; 403 break;
403 } 404 }
404 case kArchTailCallCodeObject: { 405 case kArchTailCallCodeObject: {
405 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); 406 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
406 AssembleDeconstructActivationRecord(stack_param_delta); 407 AssembleDeconstructActivationRecord(stack_param_delta);
407 if (instr->InputAt(0)->IsImmediate()) { 408 if (instr->InputAt(0)->IsImmediate()) {
408 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), 409 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
409 RelocInfo::CODE_TARGET); 410 RelocInfo::CODE_TARGET);
410 } else { 411 } else {
411 __ add(ip, i.InputRegister(0), 412 __ add(ip, i.InputRegister(0),
412 Operand(Code::kHeaderSize - kHeapObjectTag)); 413 Operand(Code::kHeaderSize - kHeapObjectTag));
413 __ Jump(ip); 414 __ Jump(ip);
414 } 415 }
415 DCHECK_EQ(LeaveCC, i.OutputSBit()); 416 DCHECK_EQ(LeaveCC, i.OutputSBit());
417 frame_access_state()->ClearSPDelta();
416 break; 418 break;
417 } 419 }
418 case kArchCallJSFunction: { 420 case kArchCallJSFunction: {
419 EnsureSpaceForLazyDeopt(); 421 EnsureSpaceForLazyDeopt();
420 Register func = i.InputRegister(0); 422 Register func = i.InputRegister(0);
421 if (FLAG_debug_code) { 423 if (FLAG_debug_code) {
422 // Check the function's context matches the context argument. 424 // Check the function's context matches the context argument.
423 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); 425 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
424 __ cmp(cp, kScratchReg); 426 __ cmp(cp, kScratchReg);
425 __ Assert(eq, kWrongFunctionContext); 427 __ Assert(eq, kWrongFunctionContext);
426 } 428 }
427 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 429 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
428 __ Call(ip); 430 __ Call(ip);
429 RecordCallPosition(instr); 431 RecordCallPosition(instr);
430 DCHECK_EQ(LeaveCC, i.OutputSBit()); 432 DCHECK_EQ(LeaveCC, i.OutputSBit());
433 frame_access_state()->ClearSPDelta();
431 break; 434 break;
432 } 435 }
433 case kArchTailCallJSFunction: { 436 case kArchTailCallJSFunction: {
434 Register func = i.InputRegister(0); 437 Register func = i.InputRegister(0);
435 if (FLAG_debug_code) { 438 if (FLAG_debug_code) {
436 // Check the function's context matches the context argument. 439 // Check the function's context matches the context argument.
437 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); 440 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
438 __ cmp(cp, kScratchReg); 441 __ cmp(cp, kScratchReg);
439 __ Assert(eq, kWrongFunctionContext); 442 __ Assert(eq, kWrongFunctionContext);
440 } 443 }
441 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); 444 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
442 AssembleDeconstructActivationRecord(stack_param_delta); 445 AssembleDeconstructActivationRecord(stack_param_delta);
443 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); 446 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
444 __ Jump(ip); 447 __ Jump(ip);
445 DCHECK_EQ(LeaveCC, i.OutputSBit()); 448 DCHECK_EQ(LeaveCC, i.OutputSBit());
449 frame_access_state()->ClearSPDelta();
446 break; 450 break;
447 } 451 }
448 case kArchLazyBailout: { 452 case kArchLazyBailout: {
449 EnsureSpaceForLazyDeopt(); 453 EnsureSpaceForLazyDeopt();
450 RecordCallPosition(instr); 454 RecordCallPosition(instr);
451 break; 455 break;
452 } 456 }
453 case kArchPrepareCallCFunction: { 457 case kArchPrepareCallCFunction: {
454 int const num_parameters = MiscField::decode(instr->opcode()); 458 int const num_parameters = MiscField::decode(instr->opcode());
455 __ PrepareCallCFunction(num_parameters, kScratchReg); 459 __ PrepareCallCFunction(num_parameters, kScratchReg);
460 // Frame alignment requires using FP-relative frame addressing.
461 frame_access_state()->SetFrameAccessToFP();
456 break; 462 break;
457 } 463 }
458 case kArchPrepareTailCall: 464 case kArchPrepareTailCall:
459 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 465 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
460 break; 466 break;
461 case kArchCallCFunction: { 467 case kArchCallCFunction: {
462 int const num_parameters = MiscField::decode(instr->opcode()); 468 int const num_parameters = MiscField::decode(instr->opcode());
463 if (instr->InputAt(0)->IsImmediate()) { 469 if (instr->InputAt(0)->IsImmediate()) {
464 ExternalReference ref = i.InputExternalReference(0); 470 ExternalReference ref = i.InputExternalReference(0);
465 __ CallCFunction(ref, num_parameters); 471 __ CallCFunction(ref, num_parameters);
466 } else { 472 } else {
467 Register func = i.InputRegister(0); 473 Register func = i.InputRegister(0);
468 __ CallCFunction(func, num_parameters); 474 __ CallCFunction(func, num_parameters);
469 } 475 }
476 frame_access_state()->SetFrameAccessToDefault();
477 frame_access_state()->ClearSPDelta();
470 break; 478 break;
471 } 479 }
472 case kArchJmp: 480 case kArchJmp:
473 AssembleArchJump(i.InputRpo(0)); 481 AssembleArchJump(i.InputRpo(0));
474 DCHECK_EQ(LeaveCC, i.OutputSBit()); 482 DCHECK_EQ(LeaveCC, i.OutputSBit());
475 break; 483 break;
476 case kArchLookupSwitch: 484 case kArchLookupSwitch:
477 AssembleArchLookupSwitch(instr); 485 AssembleArchLookupSwitch(instr);
478 DCHECK_EQ(LeaveCC, i.OutputSBit()); 486 DCHECK_EQ(LeaveCC, i.OutputSBit());
479 break; 487 break;
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 case kArmVstrF64: { 922 case kArmVstrF64: {
915 size_t index = 0; 923 size_t index = 0;
916 MemOperand operand = i.InputOffset(&index); 924 MemOperand operand = i.InputOffset(&index);
917 __ vstr(i.InputFloat64Register(index), operand); 925 __ vstr(i.InputFloat64Register(index), operand);
918 DCHECK_EQ(LeaveCC, i.OutputSBit()); 926 DCHECK_EQ(LeaveCC, i.OutputSBit());
919 break; 927 break;
920 } 928 }
921 case kArmPush: 929 case kArmPush:
922 if (instr->InputAt(0)->IsDoubleRegister()) { 930 if (instr->InputAt(0)->IsDoubleRegister()) {
923 __ vpush(i.InputDoubleRegister(0)); 931 __ vpush(i.InputDoubleRegister(0));
932 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
924 } else { 933 } else {
925 __ push(i.InputRegister(0)); 934 __ push(i.InputRegister(0));
935 frame_access_state()->IncreaseSPDelta(1);
926 } 936 }
927 DCHECK_EQ(LeaveCC, i.OutputSBit()); 937 DCHECK_EQ(LeaveCC, i.OutputSBit());
928 break; 938 break;
929 case kArmPoke: { 939 case kArmPoke: {
930 int const slot = MiscField::decode(instr->opcode()); 940 int const slot = MiscField::decode(instr->opcode());
931 __ str(i.InputRegister(0), MemOperand(sp, slot * kPointerSize)); 941 __ str(i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
932 DCHECK_EQ(LeaveCC, i.OutputSBit()); 942 DCHECK_EQ(LeaveCC, i.OutputSBit());
933 break; 943 break;
934 } 944 }
935 case kCheckedLoadInt8: 945 case kCheckedLoadInt8:
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 void CodeGenerator::AssembleDeoptimizerCall( 1047 void CodeGenerator::AssembleDeoptimizerCall(
1038 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { 1048 int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
1039 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( 1049 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
1040 isolate(), deoptimization_id, bailout_type); 1050 isolate(), deoptimization_id, bailout_type);
1041 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); 1051 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1042 } 1052 }
1043 1053
1044 1054
1045 void CodeGenerator::AssemblePrologue() { 1055 void CodeGenerator::AssemblePrologue() {
1046 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1056 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1047 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1057 if (descriptor->IsCFunctionCall()) {
1048 if (FLAG_enable_embedded_constant_pool) { 1058 if (FLAG_enable_embedded_constant_pool) {
1049 __ Push(lr, fp, pp); 1059 __ Push(lr, fp, pp);
1050 // Adjust FP to point to saved FP. 1060 // Adjust FP to point to saved FP.
1051 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); 1061 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
1052 } else { 1062 } else {
1053 __ Push(lr, fp); 1063 __ Push(lr, fp);
1054 __ mov(fp, sp); 1064 __ mov(fp, sp);
1055 } 1065 }
1056 } else if (descriptor->IsJSFunctionCall()) { 1066 } else if (descriptor->IsJSFunctionCall()) {
1057 CompilationInfo* info = this->info(); 1067 CompilationInfo* info = this->info();
1058 __ Prologue(info->IsCodePreAgingActive()); 1068 __ Prologue(info->IsCodePreAgingActive());
1059 } else if (needs_frame_) { 1069 } else if (frame()->needs_frame()) {
1060 __ StubPrologue(); 1070 __ StubPrologue();
1061 } else { 1071 } else {
1062 frame()->SetElidedFrameSizeInSlots(0); 1072 frame()->SetElidedFrameSizeInSlots(0);
1063 } 1073 }
1074 frame_access_state()->SetFrameAccessToDefault();
1064 1075
1065 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1076 int stack_shrink_slots = frame()->GetSpillSlotCount();
1066 if (info()->is_osr()) { 1077 if (info()->is_osr()) {
1067 // TurboFan OSR-compiled functions cannot be entered directly. 1078 // TurboFan OSR-compiled functions cannot be entered directly.
1068 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1079 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1069 1080
1070 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1081 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1071 // frame is still on the stack. Optimized code uses OSR values directly from 1082 // frame is still on the stack. Optimized code uses OSR values directly from
1072 // the unoptimized frame. Thus, all that needs to be done is to allocate the 1083 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1073 // remaining stack slots. 1084 // remaining stack slots.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 // Restore FP registers. 1135 // Restore FP registers.
1125 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); 1136 const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
1126 if (saves_fp != 0) { 1137 if (saves_fp != 0) {
1127 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32); 1138 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
1128 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1; 1139 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
1129 uint32_t first = base::bits::CountTrailingZeros32(saves_fp); 1140 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
1130 __ vldm(ia_w, sp, DwVfpRegister::from_code(first), 1141 __ vldm(ia_w, sp, DwVfpRegister::from_code(first),
1131 DwVfpRegister::from_code(last)); 1142 DwVfpRegister::from_code(last));
1132 } 1143 }
1133 1144
1134 if (descriptor->kind() == CallDescriptor::kCallAddress) { 1145 if (descriptor->IsCFunctionCall()) {
1135 __ LeaveFrame(StackFrame::MANUAL); 1146 __ LeaveFrame(StackFrame::MANUAL);
1136 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { 1147 } else if (frame()->needs_frame()) {
1137 // Canonicalize JSFunction return sites for now. 1148 // Canonicalize JSFunction return sites for now.
1138 if (return_label_.is_bound()) { 1149 if (return_label_.is_bound()) {
1139 __ b(&return_label_); 1150 __ b(&return_label_);
1140 return; 1151 return;
1141 } else { 1152 } else {
1142 __ bind(&return_label_); 1153 __ bind(&return_label_);
1143 __ LeaveFrame(StackFrame::MANUAL); 1154 __ LeaveFrame(StackFrame::MANUAL);
1144 } 1155 }
1145 } 1156 }
1146 __ Ret(pop_count); 1157 __ Ret(pop_count);
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 padding_size -= v8::internal::Assembler::kInstrSize; 1363 padding_size -= v8::internal::Assembler::kInstrSize;
1353 } 1364 }
1354 } 1365 }
1355 } 1366 }
1356 1367
1357 #undef __ 1368 #undef __
1358 1369
1359 } // namespace compiler 1370 } // namespace compiler
1360 } // namespace internal 1371 } // namespace internal
1361 } // namespace v8 1372 } // 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