blob: 2d34b7d473f7e5c60898fa59ac3ec59088c9f360 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_LinearScan_h
#define jit_LinearScan_h
#include "LiveRangeAllocator.h"
#include "BitSet.h"
#include "js/Vector.h"
namespace js {
namespace jit {
class LinearScanVirtualRegister : public VirtualRegister
{
private:
LAllocation *canonicalSpill_;
CodePosition spillPosition_ ;
bool spillAtDefinition_ : 1;
// This bit is used to determine whether both halves of a nunbox have been
// processed by freeAllocation().
bool finished_ : 1;
public:
void setCanonicalSpill(LAllocation *alloc) {
canonicalSpill_ = alloc;
}
LAllocation *canonicalSpill() const {
return canonicalSpill_;
}
unsigned canonicalSpillSlot() const {
return canonicalSpill_->toStackSlot()->slot();
}
void setFinished() {
finished_ = true;
}
bool finished() const {
return finished_;
}
void setSpillAtDefinition(CodePosition pos) {
spillAtDefinition_ = true;
setSpillPosition(pos);
}
bool mustSpillAtDefinition() const {
return spillAtDefinition_;
}
CodePosition spillPosition() const {
return spillPosition_;
}
void setSpillPosition(CodePosition pos) {
spillPosition_ = pos;
}
};
class LinearScanAllocator : public LiveRangeAllocator<LinearScanVirtualRegister>
{
friend class C1Spewer;
friend class JSONSpewer;
// Work set of LiveIntervals, sorted by start() and then by priority,
// non-monotonically descending from tail to head.
class UnhandledQueue : public InlineList<LiveInterval>
{
public:
void enqueueForward(LiveInterval *after, LiveInterval *interval);
void enqueueBackward(LiveInterval *interval);
void enqueueAtHead(LiveInterval *interval);
void assertSorted();
LiveInterval *dequeue();
};
typedef Vector<LiveInterval *, 0, SystemAllocPolicy> SlotList;
SlotList finishedSlots_;
SlotList finishedDoubleSlots_;
#ifdef JS_NUNBOX32
SlotList finishedNunboxSlots_;
#endif
// Run-time state
UnhandledQueue unhandled;
InlineList<LiveInterval> active;
InlineList<LiveInterval> inactive;
InlineList<LiveInterval> fixed;
InlineList<LiveInterval> handled;
LiveInterval *current;
bool allocateRegisters();
bool resolveControlFlow();
bool reifyAllocations();
bool populateSafepoints();
// Optimization for the UnsortedQueue.
void enqueueVirtualRegisterIntervals();
uint32_t allocateSlotFor(const LiveInterval *interval);
bool splitInterval(LiveInterval *interval, CodePosition pos);
bool splitBlockingIntervals(LAllocation allocation);
bool assign(LAllocation allocation);
bool spill();
void freeAllocation(LiveInterval *interval, LAllocation *alloc);
void finishInterval(LiveInterval *interval);
AnyRegister::Code findBestFreeRegister(CodePosition *freeUntil);
AnyRegister::Code findBestBlockedRegister(CodePosition *nextUsed);
bool canCoexist(LiveInterval *a, LiveInterval *b);
bool moveInputAlloc(CodePosition pos, LAllocation *from, LAllocation *to);
void setIntervalRequirement(LiveInterval *interval);
bool isSpilledAt(LiveInterval *interval, CodePosition pos);
#ifdef DEBUG
void validateIntervals();
void validateAllocations();
#else
inline void validateIntervals() { }
inline void validateAllocations() { }
#endif
public:
LinearScanAllocator(MIRGenerator *mir, LIRGenerator *lir, LIRGraph &graph)
: LiveRangeAllocator<LinearScanVirtualRegister>(mir, lir, graph, /* forLSRA = */ true)
{
}
bool go();
};
} // namespace jit
} // namespace js
#endif /* jit_LinearScan_h */