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

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, 8 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 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::AssembleSetupStackPointer() {}
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 658 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 // TODO(turbofan): We should be able to generate better code by sharing the 1259 // 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 1260 // actual final call site and just bl'ing to it here, similar to what we do
1254 // in the lithium backend. 1261 // in the lithium backend.
1255 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); 1262 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1256 __ CheckConstPool(false, false); 1263 __ CheckConstPool(false, false);
1257 } 1264 }
1258 1265
1259 1266
1260 void CodeGenerator::AssemblePrologue() { 1267 void CodeGenerator::AssemblePrologue() {
1261 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1268 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1262 if (frame()->needs_frame()) { 1269 if (frame_access_state()->has_frame()) {
1263 if (descriptor->IsCFunctionCall()) { 1270 if (descriptor->IsCFunctionCall()) {
1264 if (FLAG_enable_embedded_constant_pool) { 1271 if (FLAG_enable_embedded_constant_pool) {
1265 __ Push(lr, fp, pp); 1272 __ Push(lr, fp, pp);
1266 // Adjust FP to point to saved FP. 1273 // Adjust FP to point to saved FP.
1267 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); 1274 __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
1268 } else { 1275 } else {
1269 __ Push(lr, fp); 1276 __ Push(lr, fp);
1270 __ mov(fp, sp); 1277 __ mov(fp, sp);
1271 } 1278 }
1272 } else if (descriptor->IsJSFunctionCall()) { 1279 } else if (descriptor->IsJSFunctionCall()) {
1273 __ Prologue(this->info()->GeneratePreagedPrologue()); 1280 __ Prologue(this->info()->GeneratePreagedPrologue());
1274 } else { 1281 } else {
1275 __ StubPrologue(info()->GetOutputStackFrameType()); 1282 __ StubPrologue(info()->GetOutputStackFrameType());
1276 } 1283 }
1277 } else {
1278 frame()->SetElidedFrameSizeInSlots(0);
1279 } 1284 }
1280 frame_access_state()->SetFrameAccessToDefault();
1281 1285
1282 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1286 int stack_shrink_slots = frame()->GetSpillSlotCount();
1283 if (info()->is_osr()) { 1287 if (info()->is_osr()) {
1284 // TurboFan OSR-compiled functions cannot be entered directly. 1288 // TurboFan OSR-compiled functions cannot be entered directly.
1285 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1289 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1286 1290
1287 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1291 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1288 // frame is still on the stack. Optimized code uses OSR values directly from 1292 // 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 1293 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1290 // remaining stack slots. 1294 // remaining stack slots.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); 1344 const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
1341 if (saves_fp != 0) { 1345 if (saves_fp != 0) {
1342 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32); 1346 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
1343 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1; 1347 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
1344 uint32_t first = base::bits::CountTrailingZeros32(saves_fp); 1348 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
1345 __ vldm(ia_w, sp, DwVfpRegister::from_code(first), 1349 __ vldm(ia_w, sp, DwVfpRegister::from_code(first),
1346 DwVfpRegister::from_code(last)); 1350 DwVfpRegister::from_code(last));
1347 } 1351 }
1348 1352
1349 if (descriptor->IsCFunctionCall()) { 1353 if (descriptor->IsCFunctionCall()) {
1350 __ LeaveFrame(StackFrame::MANUAL); 1354 AssembleDeconstructFrame();
1351 } else if (frame()->needs_frame()) { 1355 } else if (frame_access_state()->has_frame()) {
1352 // Canonicalize JSFunction return sites for now. 1356 // Canonicalize JSFunction return sites for now.
1353 if (return_label_.is_bound()) { 1357 if (return_label_.is_bound()) {
1354 __ b(&return_label_); 1358 __ b(&return_label_);
1355 return; 1359 return;
1356 } else { 1360 } else {
1357 __ bind(&return_label_); 1361 __ bind(&return_label_);
1358 __ LeaveFrame(StackFrame::MANUAL); 1362 AssembleDeconstructFrame();
1359 } 1363 }
1360 } 1364 }
1361 __ Ret(pop_count); 1365 __ Ret(pop_count);
1362 } 1366 }
1363 1367
1364 1368
1365 void CodeGenerator::AssembleMove(InstructionOperand* source, 1369 void CodeGenerator::AssembleMove(InstructionOperand* source,
1366 InstructionOperand* destination) { 1370 InstructionOperand* destination) {
1367 ArmOperandConverter g(this, nullptr); 1371 ArmOperandConverter g(this, nullptr);
1368 // Dispatch on the source and destination operand kinds. Not all 1372 // Dispatch on the source and destination operand kinds. Not all
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1567 padding_size -= v8::internal::Assembler::kInstrSize; 1571 padding_size -= v8::internal::Assembler::kInstrSize;
1568 } 1572 }
1569 } 1573 }
1570 } 1574 }
1571 1575
1572 #undef __ 1576 #undef __
1573 1577
1574 } // namespace compiler 1578 } // namespace compiler
1575 } // namespace internal 1579 } // namespace internal
1576 } // namespace v8 1580 } // 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