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

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

Issue 1775323002: [turbofan] Frame elision for code stubs (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index, 223 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index,
224 Register value, Register scratch0, Register scratch1, 224 Register value, Register scratch0, Register scratch1,
225 RecordWriteMode mode) 225 RecordWriteMode mode)
226 : OutOfLineCode(gen), 226 : OutOfLineCode(gen),
227 object_(object), 227 object_(object),
228 index_(no_reg), 228 index_(no_reg),
229 index_immediate_(index), 229 index_immediate_(index),
230 value_(value), 230 value_(value),
231 scratch0_(scratch0), 231 scratch0_(scratch0),
232 scratch1_(scratch1), 232 scratch1_(scratch1),
233 mode_(mode) {} 233 mode_(mode),
234 must_save_lr_(!gen->frame_access_state()->has_frame()) {}
234 235
235 void Generate() final { 236 void Generate() final {
236 if (mode_ > RecordWriteMode::kValueIsPointer) { 237 if (mode_ > RecordWriteMode::kValueIsPointer) {
237 __ JumpIfSmi(value_, exit()); 238 __ JumpIfSmi(value_, exit());
238 } 239 }
239 __ CheckPageFlag(value_, scratch0_, 240 __ CheckPageFlag(value_, scratch0_,
240 MemoryChunk::kPointersToHereAreInterestingMask, eq, 241 MemoryChunk::kPointersToHereAreInterestingMask, eq,
241 exit()); 242 exit());
242 RememberedSetAction const remembered_set_action = 243 RememberedSetAction const remembered_set_action =
243 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET 244 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
244 : OMIT_REMEMBERED_SET; 245 : OMIT_REMEMBERED_SET;
245 SaveFPRegsMode const save_fp_mode = 246 SaveFPRegsMode const save_fp_mode =
246 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; 247 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
247 if (!frame()->needs_frame()) { 248 if (must_save_lr_) {
248 // We need to save and restore lr if the frame was elided. 249 // We need to save and restore lr if the frame was elided.
249 __ Push(lr); 250 __ Push(lr);
250 } 251 }
251 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, 252 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
252 remembered_set_action, save_fp_mode); 253 remembered_set_action, save_fp_mode);
253 if (index_.is(no_reg)) { 254 if (index_.is(no_reg)) {
254 __ add(scratch1_, object_, Operand(index_immediate_)); 255 __ add(scratch1_, object_, Operand(index_immediate_));
255 } else { 256 } else {
256 DCHECK_EQ(0, index_immediate_); 257 DCHECK_EQ(0, index_immediate_);
257 __ add(scratch1_, object_, Operand(index_)); 258 __ add(scratch1_, object_, Operand(index_));
258 } 259 }
259 __ CallStub(&stub); 260 __ CallStub(&stub);
260 if (!frame()->needs_frame()) { 261 if (must_save_lr_) {
261 __ Pop(lr); 262 __ Pop(lr);
262 } 263 }
263 } 264 }
264 265
265 private: 266 private:
266 Register const object_; 267 Register const object_;
267 Register const index_; 268 Register const index_;
268 int32_t const index_immediate_; // Valid if index_.is(no_reg). 269 int32_t const index_immediate_; // Valid if index_.is(no_reg).
269 Register const value_; 270 Register const value_;
270 Register const scratch0_; 271 Register const scratch0_;
271 Register const scratch1_; 272 Register const scratch1_;
272 RecordWriteMode const mode_; 273 RecordWriteMode const mode_;
274 bool must_save_lr_;
273 }; 275 };
274 276
275 277
276 Condition FlagsConditionToCondition(FlagsCondition condition) { 278 Condition FlagsConditionToCondition(FlagsCondition condition) {
277 switch (condition) { 279 switch (condition) {
278 case kEqual: 280 case kEqual:
279 return eq; 281 return eq;
280 case kNotEqual: 282 case kNotEqual:
281 return ne; 283 return ne;
282 case kSignedLessThan: 284 case kSignedLessThan:
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 if (instr->InputAt(1)->IsRegister()) { \ 381 if (instr->InputAt(1)->IsRegister()) { \
380 __ cmp(offset, i.InputRegister(1)); \ 382 __ cmp(offset, i.InputRegister(1)); \
381 } else { \ 383 } else { \
382 __ cmp(offset, i.InputImmediate(1)); \ 384 __ cmp(offset, i.InputImmediate(1)); \
383 } \ 385 } \
384 auto value = i.InputRegister(2); \ 386 auto value = i.InputRegister(2); \
385 __ asm_instr(value, i.InputOffset(3), lo); \ 387 __ asm_instr(value, i.InputOffset(3), lo); \
386 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 388 DCHECK_EQ(LeaveCC, i.OutputSBit()); \
387 } while (0) 389 } while (0)
388 390
391 void CodeGenerator::AssembleDeconstructFrame() {
392 __ LeaveFrame(StackFrame::MANUAL);
393 }
394
395 void CodeGenerator::SetupStackPointer() {}
389 396
390 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 397 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
391 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 398 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
392 if (sp_slot_delta > 0) { 399 if (sp_slot_delta > 0) {
393 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize)); 400 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize));
394 } 401 }
395 frame_access_state()->SetFrameAccessToDefault(); 402 frame_access_state()->SetFrameAccessToDefault();
396 } 403 }
397 404
398 405
399 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { 406 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
400 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 407 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
401 if (sp_slot_delta < 0) { 408 if (sp_slot_delta < 0) {
402 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize)); 409 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize));
403 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); 410 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
404 } 411 }
405 if (frame()->needs_frame()) { 412 if (frame_access_state()->has_frame()) {
406 if (FLAG_enable_embedded_constant_pool) { 413 if (FLAG_enable_embedded_constant_pool) {
407 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); 414 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
408 } 415 }
409 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); 416 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
410 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 417 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
411 } 418 }
412 frame_access_state()->SetFrameAccessToSP(); 419 frame_access_state()->SetFrameAccessToSP();
413 } 420 }
414 421
415 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, 422 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 break; 580 break;
574 case kArchStackPointer: 581 case kArchStackPointer:
575 __ mov(i.OutputRegister(), sp); 582 __ mov(i.OutputRegister(), sp);
576 DCHECK_EQ(LeaveCC, i.OutputSBit()); 583 DCHECK_EQ(LeaveCC, i.OutputSBit());
577 break; 584 break;
578 case kArchFramePointer: 585 case kArchFramePointer:
579 __ mov(i.OutputRegister(), fp); 586 __ mov(i.OutputRegister(), fp);
580 DCHECK_EQ(LeaveCC, i.OutputSBit()); 587 DCHECK_EQ(LeaveCC, i.OutputSBit());
581 break; 588 break;
582 case kArchParentFramePointer: 589 case kArchParentFramePointer:
583 if (frame_access_state()->frame()->needs_frame()) { 590 if (frame_access_state()->has_frame()) {
584 __ ldr(i.OutputRegister(), MemOperand(fp, 0)); 591 __ ldr(i.OutputRegister(), MemOperand(fp, 0));
585 } else { 592 } else {
586 __ mov(i.OutputRegister(), fp); 593 __ mov(i.OutputRegister(), fp);
587 } 594 }
588 break; 595 break;
589 case kArchTruncateDoubleToI: 596 case kArchTruncateDoubleToI:
590 __ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0)); 597 __ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0));
591 DCHECK_EQ(LeaveCC, i.OutputSBit()); 598 DCHECK_EQ(LeaveCC, i.OutputSBit());
592 break; 599 break;
593 case kArchStoreWithWriteBarrier: { 600 case kArchStoreWithWriteBarrier: {
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 case kCheckedLoadWord64: 1189 case kCheckedLoadWord64:
1183 case kCheckedStoreWord64: 1190 case kCheckedStoreWord64:
1184 UNREACHABLE(); // currently unsupported checked int64 load/store. 1191 UNREACHABLE(); // currently unsupported checked int64 load/store.
1185 break; 1192 break;
1186 } 1193 }
1187 } // NOLINT(readability/fn_size) 1194 } // NOLINT(readability/fn_size)
1188 1195
1189 1196
1190 // Assembles branches after an instruction. 1197 // Assembles branches after an instruction.
1191 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { 1198 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
1199 AssembleDeconstructFrameIfNeeded();
1192 ArmOperandConverter i(this, instr); 1200 ArmOperandConverter i(this, instr);
1193 Label* tlabel = branch->true_label; 1201 Label* tlabel = branch->true_label;
1194 Label* flabel = branch->false_label; 1202 Label* flabel = branch->false_label;
1195 Condition cc = FlagsConditionToCondition(branch->condition); 1203 Condition cc = FlagsConditionToCondition(branch->condition);
1196 __ b(cc, tlabel); 1204 __ b(cc, tlabel);
1197 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel. 1205 if (!branch->fallthru) __ b(flabel); // no fallthru to flabel.
1198 } 1206 }
1199 1207
1200 1208
1201 void CodeGenerator::AssembleArchJump(RpoNumber target) { 1209 void CodeGenerator::AssembleArchJump(RpoNumber target) {
1210 AssembleDeconstructFrameIfNeeded();
1202 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); 1211 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target));
1203 } 1212 }
1204 1213
1205 1214
1206 // Assembles boolean materializations after an instruction. 1215 // Assembles boolean materializations after an instruction.
1207 void CodeGenerator::AssembleArchBoolean(Instruction* instr, 1216 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
1208 FlagsCondition condition) { 1217 FlagsCondition condition) {
1209 ArmOperandConverter i(this, instr); 1218 ArmOperandConverter i(this, instr);
1210 1219
1211 // Materialize a full 32-bit 1 or 0 value. The result register is always the 1220 // Materialize a full 32-bit 1 or 0 value. The result register is always the
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 // TODO(turbofan): We should be able to generate better code by sharing the 1261 // TODO(turbofan): We should be able to generate better code by sharing the
1253 // actual final call site and just bl'ing to it here, similar to what we do 1262 // actual final call site and just bl'ing to it here, similar to what we do
1254 // in the lithium backend. 1263 // in the lithium backend.
1255 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); 1264 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1256 __ CheckConstPool(false, false); 1265 __ CheckConstPool(false, false);
1257 } 1266 }
1258 1267
1259 1268
1260 void CodeGenerator::AssemblePrologue() { 1269 void CodeGenerator::AssemblePrologue() {
1261 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1270 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1262 if (frame()->needs_frame()) { 1271 if (frame_access_state()->has_frame()) {
1263 if (descriptor->IsCFunctionCall()) { 1272 if (descriptor->IsCFunctionCall()) {
1264 if (FLAG_enable_embedded_constant_pool) { 1273 if (FLAG_enable_embedded_constant_pool) {
1265 __ Push(lr, fp, pp); 1274 __ Push(lr, fp, pp);
1266 // Adjust FP to point to saved FP. 1275 // Adjust FP to point to saved FP.
1267 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); 1276 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
1268 } else { 1277 } else {
1269 __ Push(lr, fp); 1278 __ Push(lr, fp);
1270 __ mov(fp, sp); 1279 __ mov(fp, sp);
1271 } 1280 }
1272 } else if (descriptor->IsJSFunctionCall()) { 1281 } else if (descriptor->IsJSFunctionCall()) {
1273 __ Prologue(this->info()->GeneratePreagedPrologue()); 1282 __ Prologue(this->info()->GeneratePreagedPrologue());
1274 } else { 1283 } else {
1275 __ StubPrologue(info()->GetOutputStackFrameType()); 1284 __ StubPrologue(info()->GetOutputStackFrameType());
1276 } 1285 }
1277 } else {
1278 frame()->SetElidedFrameSizeInSlots(0);
1279 } 1286 }
1280 frame_access_state()->SetFrameAccessToDefault();
1281 1287
1282 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1288 int stack_shrink_slots = frame()->GetSpillSlotCount();
1283 if (info()->is_osr()) { 1289 if (info()->is_osr()) {
1284 // TurboFan OSR-compiled functions cannot be entered directly. 1290 // TurboFan OSR-compiled functions cannot be entered directly.
1285 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1291 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1286 1292
1287 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1293 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1288 // frame is still on the stack. Optimized code uses OSR values directly from 1294 // frame is still on the stack. Optimized code uses OSR values directly from
1289 // the unoptimized frame. Thus, all that needs to be done is to allocate the 1295 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1290 // remaining stack slots. 1296 // remaining stack slots.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); 1346 const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
1341 if (saves_fp != 0) { 1347 if (saves_fp != 0) {
1342 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32); 1348 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
1343 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1; 1349 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
1344 uint32_t first = base::bits::CountTrailingZeros32(saves_fp); 1350 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
1345 __ vldm(ia_w, sp, DwVfpRegister::from_code(first), 1351 __ vldm(ia_w, sp, DwVfpRegister::from_code(first),
1346 DwVfpRegister::from_code(last)); 1352 DwVfpRegister::from_code(last));
1347 } 1353 }
1348 1354
1349 if (descriptor->IsCFunctionCall()) { 1355 if (descriptor->IsCFunctionCall()) {
1350 __ LeaveFrame(StackFrame::MANUAL); 1356 AssembleDeconstructFrameIfNeeded();
1351 } else if (frame()->needs_frame()) { 1357 } else if (frame_access_state()->has_frame()) {
1352 // Canonicalize JSFunction return sites for now. 1358 if (AssembleDeconstructFrameUsingReturnLabel()) return;
1353 if (return_label_.is_bound()) {
1354 __ b(&return_label_);
1355 return;
1356 } else {
1357 __ bind(&return_label_);
1358 __ LeaveFrame(StackFrame::MANUAL);
1359 }
1360 } 1359 }
1361 __ Ret(pop_count); 1360 __ Ret(pop_count);
1362 } 1361 }
1363 1362
1364 1363
1365 void CodeGenerator::AssembleMove(InstructionOperand* source, 1364 void CodeGenerator::AssembleMove(InstructionOperand* source,
1366 InstructionOperand* destination) { 1365 InstructionOperand* destination) {
1367 ArmOperandConverter g(this, nullptr); 1366 ArmOperandConverter g(this, nullptr);
1368 // Dispatch on the source and destination operand kinds. Not all 1367 // Dispatch on the source and destination operand kinds. Not all
1369 // combinations are possible. 1368 // combinations are possible.
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1567 padding_size -= v8::internal::Assembler::kInstrSize; 1566 padding_size -= v8::internal::Assembler::kInstrSize;
1568 } 1567 }
1569 } 1568 }
1570 } 1569 }
1571 1570
1572 #undef __ 1571 #undef __
1573 1572
1574 } // namespace compiler 1573 } // namespace compiler
1575 } // namespace internal 1574 } // namespace internal
1576 } // namespace v8 1575 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/arm64/code-generator-arm64.cc » ('j') | src/compiler/code-generator.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698