void FrameElider::MarkBlocks() {
for (auto block : instruction_blocks()) {
+ if (block->needs_frame()) continue;
for (auto i = block->code_start(); i < block->code_end(); ++i) {
if (InstructionAt(i)->IsCall()) {
block->mark_needs_frame();
}
-const InstructionBlock* InstructionSequence::GetInstructionBlock(
+InstructionBlock* InstructionSequence::GetInstructionBlock(
int instruction_index) const {
DCHECK(instruction_blocks_->size() == block_starts_.size());
auto begin = block_starts_.begin();
os << "B" << block->rpo_number();
os << ": AO#" << block->ao_number();
if (block->IsDeferred()) os << " (deferred)";
+ if (!block->needs_frame()) os << " (no frame)";
+ if (block->must_construct_frame()) os << " (construct frame)";
+ if (block->must_deconstruct_frame()) os << " (deconstruct frame)";
if (block->IsLoopHeader()) {
os << " loop blocks: [" << block->rpo_number() << ", "
<< block->loop_end() << ")";
return instruction_blocks_->at(rpo_number.ToSize());
}
- const InstructionBlock* GetInstructionBlock(int instruction_index) const;
+ InstructionBlock* GetInstructionBlock(int instruction_index) const;
static MachineType DefaultRepresentation() {
return kPointerSize == 8 ? kRepWord64 : kRepWord32;
};
+struct LocateSpillSlotsPhase {
+ static const char* phase_name() { return "locate spill slots"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ SpillSlotLocator locator(data->register_allocation_data());
+ locator.LocateSpillSlots();
+ }
+};
+
+
struct AssignSpillSlotsPhase {
static const char* phase_name() { return "assign spill slots"; }
return Handle<Code>();
}
- if (FLAG_turbo_frame_elision) {
- Run<FrameElisionPhase>();
- }
-
BeginPhaseKind("code generation");
// Optimimize jumps.
Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>();
Run<AllocateDoubleRegistersPhase<LinearScanAllocator>>();
}
+
+ if (FLAG_turbo_frame_elision) {
+ Run<LocateSpillSlotsPhase>();
+ Run<FrameElisionPhase>();
+ }
+
Run<AssignSpillSlotsPhase>();
Run<CommitAssignmentPhase>();
}
+SpillSlotLocator::SpillSlotLocator(RegisterAllocationData* data)
+ : data_(data) {}
+
+
+void SpillSlotLocator::LocateSpillSlots() {
+ auto code = data()->code();
+ for (auto range : data()->live_ranges()) {
+ if (range == nullptr || range->IsEmpty() || range->IsChild()) continue;
+ // We care only about ranges which spill in the frame.
+ if (!range->HasSpillRange()) continue;
+ auto spills = range->spills_at_definition();
+ DCHECK_NOT_NULL(spills);
+ for (; spills != nullptr; spills = spills->next) {
+ code->GetInstructionBlock(spills->gap_index)->mark_needs_frame();
+ }
+ }
+}
+
+
OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {}
void SetUseHints(int register_index);
void UnsetUseHints() { SetUseHints(kUnassignedRegister); }
- private:
struct SpillAtDefinitionList;
+ SpillAtDefinitionList* spills_at_definition() const {
+ return spills_at_definition_;
+ }
+
+ private:
void set_spill_type(SpillType value) {
bits_ = SpillTypeField::update(bits_, value);
}
};
+class SpillSlotLocator final : public ZoneObject {
+ public:
+ explicit SpillSlotLocator(RegisterAllocationData* data);
+
+ void LocateSpillSlots();
+
+ private:
+ RegisterAllocationData* data() const { return data_; }
+
+ RegisterAllocationData* const data_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpillSlotLocator);
+};
+
+
class OperandAssigner final : public ZoneObject {
public:
explicit OperandAssigner(RegisterAllocationData* data);