OLD | NEW |
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/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
6 #include "src/compiler/code-generator.h" | 6 #include "src/compiler/code-generator.h" |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/osr.h" | 10 #include "src/compiler/osr.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 public: | 217 public: |
218 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index, | 218 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index, |
219 Register value, Register scratch0, Register scratch1, | 219 Register value, Register scratch0, Register scratch1, |
220 RecordWriteMode mode) | 220 RecordWriteMode mode) |
221 : OutOfLineCode(gen), | 221 : OutOfLineCode(gen), |
222 object_(object), | 222 object_(object), |
223 index_(index), | 223 index_(index), |
224 value_(value), | 224 value_(value), |
225 scratch0_(scratch0), | 225 scratch0_(scratch0), |
226 scratch1_(scratch1), | 226 scratch1_(scratch1), |
227 mode_(mode) {} | 227 mode_(mode), |
| 228 must_save_lr_(!gen->frame_access_state()->has_frame()) {} |
228 | 229 |
229 void Generate() final { | 230 void Generate() final { |
230 if (mode_ > RecordWriteMode::kValueIsPointer) { | 231 if (mode_ > RecordWriteMode::kValueIsPointer) { |
231 __ JumpIfSmi(value_, exit()); | 232 __ JumpIfSmi(value_, exit()); |
232 } | 233 } |
233 __ CheckPageFlag(value_, scratch0_, | 234 __ CheckPageFlag(value_, scratch0_, |
234 MemoryChunk::kPointersToHereAreInterestingMask, eq, | 235 MemoryChunk::kPointersToHereAreInterestingMask, eq, |
235 exit()); | 236 exit()); |
236 RememberedSetAction const remembered_set_action = | 237 RememberedSetAction const remembered_set_action = |
237 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET | 238 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET |
238 : OMIT_REMEMBERED_SET; | 239 : OMIT_REMEMBERED_SET; |
239 SaveFPRegsMode const save_fp_mode = | 240 SaveFPRegsMode const save_fp_mode = |
240 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 241 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
241 if (!frame()->needs_frame()) { | 242 if (must_save_lr_) { |
242 // We need to save and restore ra if the frame was elided. | 243 // We need to save and restore ra if the frame was elided. |
243 __ Push(ra); | 244 __ Push(ra); |
244 } | 245 } |
245 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, | 246 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, |
246 remembered_set_action, save_fp_mode); | 247 remembered_set_action, save_fp_mode); |
247 __ Addu(scratch1_, object_, index_); | 248 __ Addu(scratch1_, object_, index_); |
248 __ CallStub(&stub); | 249 __ CallStub(&stub); |
249 if (!frame()->needs_frame()) { | 250 if (must_save_lr_) { |
250 __ Pop(ra); | 251 __ Pop(ra); |
251 } | 252 } |
252 } | 253 } |
253 | 254 |
254 private: | 255 private: |
255 Register const object_; | 256 Register const object_; |
256 Register const index_; | 257 Register const index_; |
257 Register const value_; | 258 Register const value_; |
258 Register const scratch0_; | 259 Register const scratch0_; |
259 Register const scratch1_; | 260 Register const scratch1_; |
260 RecordWriteMode const mode_; | 261 RecordWriteMode const mode_; |
| 262 bool must_save_lr_; |
261 }; | 263 }; |
262 | 264 |
263 | 265 |
264 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { | 266 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { |
265 switch (condition) { | 267 switch (condition) { |
266 case kEqual: | 268 case kEqual: |
267 return eq; | 269 return eq; |
268 case kNotEqual: | 270 case kNotEqual: |
269 return ne; | 271 return ne; |
270 case kSignedLessThan: | 272 case kSignedLessThan: |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 Operand(kFloat32ExponentBias + kFloat32MantissaBits)); \ | 465 Operand(kFloat32ExponentBias + kFloat32MantissaBits)); \ |
464 __ mov_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ | 466 __ mov_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
465 __ mode##_w_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ | 467 __ mode##_w_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
466 __ mfc1(at, i.OutputDoubleRegister()); \ | 468 __ mfc1(at, i.OutputDoubleRegister()); \ |
467 __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ | 469 __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ |
468 __ cvt_s_w(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ | 470 __ cvt_s_w(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ |
469 __ bind(ool->exit()); \ | 471 __ bind(ool->exit()); \ |
470 __ bind(&done); \ | 472 __ bind(&done); \ |
471 } | 473 } |
472 | 474 |
| 475 void CodeGenerator::AssembleDeconstructFrame() { |
| 476 __ mov(sp, fp); |
| 477 __ Pop(ra, fp); |
| 478 } |
| 479 |
| 480 void CodeGenerator::SetupStackPointer() {} |
| 481 |
473 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 482 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { |
474 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 483 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
475 if (sp_slot_delta > 0) { | 484 if (sp_slot_delta > 0) { |
476 __ addiu(sp, sp, sp_slot_delta * kPointerSize); | 485 __ addiu(sp, sp, sp_slot_delta * kPointerSize); |
477 } | 486 } |
478 frame_access_state()->SetFrameAccessToDefault(); | 487 frame_access_state()->SetFrameAccessToDefault(); |
479 } | 488 } |
480 | 489 |
481 | 490 |
482 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | 491 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { |
483 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 492 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
484 if (sp_slot_delta < 0) { | 493 if (sp_slot_delta < 0) { |
485 __ Subu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); | 494 __ Subu(sp, sp, Operand(-sp_slot_delta * kPointerSize)); |
486 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 495 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
487 } | 496 } |
488 if (frame()->needs_frame()) { | 497 if (frame_access_state()->has_frame()) { |
489 __ lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 498 __ lw(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
490 __ lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 499 __ lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
491 } | 500 } |
492 frame_access_state()->SetFrameAccessToSP(); | 501 frame_access_state()->SetFrameAccessToSP(); |
493 } | 502 } |
494 | 503 |
495 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 504 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
496 Register scratch1, | 505 Register scratch1, |
497 Register scratch2, | 506 Register scratch2, |
498 Register scratch3) { | 507 Register scratch3) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 case kArchRet: | 647 case kArchRet: |
639 AssembleReturn(); | 648 AssembleReturn(); |
640 break; | 649 break; |
641 case kArchStackPointer: | 650 case kArchStackPointer: |
642 __ mov(i.OutputRegister(), sp); | 651 __ mov(i.OutputRegister(), sp); |
643 break; | 652 break; |
644 case kArchFramePointer: | 653 case kArchFramePointer: |
645 __ mov(i.OutputRegister(), fp); | 654 __ mov(i.OutputRegister(), fp); |
646 break; | 655 break; |
647 case kArchParentFramePointer: | 656 case kArchParentFramePointer: |
648 if (frame_access_state()->frame()->needs_frame()) { | 657 if (frame_access_state()->has_frame()) { |
649 __ lw(i.OutputRegister(), MemOperand(fp, 0)); | 658 __ lw(i.OutputRegister(), MemOperand(fp, 0)); |
650 } else { | 659 } else { |
651 __ mov(i.OutputRegister(), fp); | 660 __ mov(i.OutputRegister(), fp); |
652 } | 661 } |
653 break; | 662 break; |
654 case kArchTruncateDoubleToI: | 663 case kArchTruncateDoubleToI: |
655 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 664 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); |
656 break; | 665 break; |
657 case kArchStoreWithWriteBarrier: { | 666 case kArchStoreWithWriteBarrier: { |
658 RecordWriteMode mode = | 667 RecordWriteMode mode = |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 return true; | 1297 return true; |
1289 default: | 1298 default: |
1290 break; | 1299 break; |
1291 } | 1300 } |
1292 return false; | 1301 return false; |
1293 } | 1302 } |
1294 | 1303 |
1295 | 1304 |
1296 // Assembles branches after an instruction. | 1305 // Assembles branches after an instruction. |
1297 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 1306 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 1307 AssembleDeconstructFrameIfNeeded(); |
1298 MipsOperandConverter i(this, instr); | 1308 MipsOperandConverter i(this, instr); |
1299 Label* tlabel = branch->true_label; | 1309 Label* tlabel = branch->true_label; |
1300 Label* flabel = branch->false_label; | 1310 Label* flabel = branch->false_label; |
1301 Condition cc = kNoCondition; | 1311 Condition cc = kNoCondition; |
1302 // MIPS does not have condition code flags, so compare and branch are | 1312 // MIPS does not have condition code flags, so compare and branch are |
1303 // implemented differently than on the other arch's. The compare operations | 1313 // implemented differently than on the other arch's. The compare operations |
1304 // emit mips pseudo-instructions, which are handled here by branch | 1314 // emit mips pseudo-instructions, which are handled here by branch |
1305 // instructions that do the actual comparison. Essential that the input | 1315 // instructions that do the actual comparison. Essential that the input |
1306 // registers to compare pseudo-op are not modified before this branch op, as | 1316 // registers to compare pseudo-op are not modified before this branch op, as |
1307 // they are tested here. | 1317 // they are tested here. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 } else { | 1376 } else { |
1367 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", | 1377 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", |
1368 instr->arch_opcode()); | 1378 instr->arch_opcode()); |
1369 UNIMPLEMENTED(); | 1379 UNIMPLEMENTED(); |
1370 } | 1380 } |
1371 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. | 1381 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. |
1372 } | 1382 } |
1373 | 1383 |
1374 | 1384 |
1375 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 1385 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
| 1386 AssembleDeconstructFrameIfNeeded(); |
1376 if (!IsNextInAssemblyOrder(target)) __ Branch(GetLabel(target)); | 1387 if (!IsNextInAssemblyOrder(target)) __ Branch(GetLabel(target)); |
1377 } | 1388 } |
1378 | 1389 |
1379 | 1390 |
1380 // Assembles boolean materializations after an instruction. | 1391 // Assembles boolean materializations after an instruction. |
1381 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1392 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1382 FlagsCondition condition) { | 1393 FlagsCondition condition) { |
1383 MipsOperandConverter i(this, instr); | 1394 MipsOperandConverter i(this, instr); |
1384 Label done; | 1395 Label done; |
1385 | 1396 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { | 1568 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { |
1558 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 1569 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
1559 isolate(), deoptimization_id, bailout_type); | 1570 isolate(), deoptimization_id, bailout_type); |
1560 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 1571 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
1561 } | 1572 } |
1562 | 1573 |
1563 | 1574 |
1564 void CodeGenerator::AssemblePrologue() { | 1575 void CodeGenerator::AssemblePrologue() { |
1565 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1576 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1566 int stack_shrink_slots = frame()->GetSpillSlotCount(); | 1577 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
1567 if (frame()->needs_frame()) { | 1578 if (frame_access_state()->has_frame()) { |
1568 if (descriptor->IsCFunctionCall()) { | 1579 if (descriptor->IsCFunctionCall()) { |
1569 __ Push(ra, fp); | 1580 __ Push(ra, fp); |
1570 __ mov(fp, sp); | 1581 __ mov(fp, sp); |
1571 } else if (descriptor->IsJSFunctionCall()) { | 1582 } else if (descriptor->IsJSFunctionCall()) { |
1572 __ Prologue(this->info()->GeneratePreagedPrologue()); | 1583 __ Prologue(this->info()->GeneratePreagedPrologue()); |
1573 } else { | 1584 } else { |
1574 __ StubPrologue(info()->GetOutputStackFrameType()); | 1585 __ StubPrologue(info()->GetOutputStackFrameType()); |
1575 } | 1586 } |
1576 } else { | |
1577 frame()->SetElidedFrameSizeInSlots(0); | |
1578 } | 1587 } |
1579 frame_access_state()->SetFrameAccessToDefault(); | |
1580 | 1588 |
1581 if (info()->is_osr()) { | 1589 if (info()->is_osr()) { |
1582 // TurboFan OSR-compiled functions cannot be entered directly. | 1590 // TurboFan OSR-compiled functions cannot be entered directly. |
1583 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1591 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
1584 | 1592 |
1585 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1593 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
1586 // frame is still on the stack. Optimized code uses OSR values directly from | 1594 // frame is still on the stack. Optimized code uses OSR values directly from |
1587 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1595 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
1588 // remaining stack slots. | 1596 // remaining stack slots. |
1589 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1597 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 __ MultiPop(saves); | 1639 __ MultiPop(saves); |
1632 } | 1640 } |
1633 | 1641 |
1634 // Restore FPU registers. | 1642 // Restore FPU registers. |
1635 const RegList saves_fpu = descriptor->CalleeSavedFPRegisters(); | 1643 const RegList saves_fpu = descriptor->CalleeSavedFPRegisters(); |
1636 if (saves_fpu != 0) { | 1644 if (saves_fpu != 0) { |
1637 __ MultiPopFPU(saves_fpu); | 1645 __ MultiPopFPU(saves_fpu); |
1638 } | 1646 } |
1639 | 1647 |
1640 if (descriptor->IsCFunctionCall()) { | 1648 if (descriptor->IsCFunctionCall()) { |
1641 __ mov(sp, fp); | 1649 AssembleDeconstructFrameIfNeeded(); |
1642 __ Pop(ra, fp); | 1650 } else if (frame_access_state()->has_frame()) { |
1643 } else if (frame()->needs_frame()) { | 1651 if (AssembleDeconstructFrameUsingReturnLabel()) return; |
1644 // Canonicalize JSFunction return sites for now. | |
1645 if (return_label_.is_bound()) { | |
1646 __ Branch(&return_label_); | |
1647 return; | |
1648 } else { | |
1649 __ bind(&return_label_); | |
1650 __ mov(sp, fp); | |
1651 __ Pop(ra, fp); | |
1652 } | |
1653 } | 1652 } |
1654 if (pop_count != 0) { | 1653 if (pop_count != 0) { |
1655 __ DropAndRet(pop_count); | 1654 __ DropAndRet(pop_count); |
1656 } else { | 1655 } else { |
1657 __ Ret(); | 1656 __ Ret(); |
1658 } | 1657 } |
1659 } | 1658 } |
1660 | 1659 |
1661 | 1660 |
1662 void CodeGenerator::AssembleMove(InstructionOperand* source, | 1661 void CodeGenerator::AssembleMove(InstructionOperand* source, |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1865 padding_size -= v8::internal::Assembler::kInstrSize; | 1864 padding_size -= v8::internal::Assembler::kInstrSize; |
1866 } | 1865 } |
1867 } | 1866 } |
1868 } | 1867 } |
1869 | 1868 |
1870 #undef __ | 1869 #undef __ |
1871 | 1870 |
1872 } // namespace compiler | 1871 } // namespace compiler |
1873 } // namespace internal | 1872 } // namespace internal |
1874 } // namespace v8 | 1873 } // namespace v8 |
OLD | NEW |