Bug 989344 part 1 - Extract LRecoverInfo from LSnapshot. r=jandem

This commit is contained in:
Nicolas B. Pierron 2014-03-31 09:39:45 -07:00
Родитель f83d83e539
Коммит e0b778bf68
9 изменённых файлов: 175 добавлений и 95 удалений

Просмотреть файл

@ -14,6 +14,7 @@
namespace js {
namespace jit {
typedef uint32_t RecoverOffset;
typedef uint32_t SnapshotOffset;
typedef uint32_t BailoutId;
@ -25,6 +26,7 @@ static const uint32_t MAX_BUFFER_SIZE = (1 << 30) - 1;
// Maximum number of scripted arg slots.
static const uint32_t SNAPSHOT_MAX_NARGS = 127;
static const SnapshotOffset INVALID_RECOVER_OFFSET = uint32_t(-1);
static const SnapshotOffset INVALID_SNAPSHOT_OFFSET = uint32_t(-1);
// Different kinds of bailouts. When extending this enum, make sure to check

Просмотреть файл

@ -119,10 +119,28 @@ TotalOperandCount(MResumePoint *mir)
return accum;
}
LSnapshot::LSnapshot(MResumePoint *mir, BailoutKind kind)
: numSlots_(TotalOperandCount(mir) * BOX_PIECES),
LRecoverInfo::LRecoverInfo(MResumePoint *mir)
: mir_(mir),
recoverOffset_(INVALID_RECOVER_OFFSET)
{ }
LRecoverInfo *
LRecoverInfo::New(MIRGenerator *gen, MResumePoint *mir)
{
LRecoverInfo *recover = new(gen->alloc()) LRecoverInfo(mir);
if (!recover)
return nullptr;
IonSpew(IonSpew_Snapshots, "Generating LIR recover %p from MIR (%p)",
(void *)recover, (void *)mir);
return recover;
}
LSnapshot::LSnapshot(LRecoverInfo *recover, BailoutKind kind)
: numSlots_(TotalOperandCount(recover->mir()) * BOX_PIECES),
slots_(nullptr),
mir_(mir),
recoverInfo_(recover),
snapshotOffset_(INVALID_SNAPSHOT_OFFSET),
bailoutId_(INVALID_BAILOUT_ID),
bailoutKind_(kind)
@ -136,14 +154,14 @@ LSnapshot::init(MIRGenerator *gen)
}
LSnapshot *
LSnapshot::New(MIRGenerator *gen, MResumePoint *mir, BailoutKind kind)
LSnapshot::New(MIRGenerator *gen, LRecoverInfo *recover, BailoutKind kind)
{
LSnapshot *snapshot = new(gen->alloc()) LSnapshot(mir, kind);
if (!snapshot->init(gen))
LSnapshot *snapshot = new(gen->alloc()) LSnapshot(recover, kind);
if (!snapshot || !snapshot->init(gen))
return nullptr;
IonSpew(IonSpew_Snapshots, "Generating LIR snapshot %p from MIR (%p)",
(void *)snapshot, (void *)mir);
IonSpew(IonSpew_Snapshots, "Generating LIR snapshot %p from recover (%p)",
(void *)snapshot, (void *)recover);
return snapshot;
}

Просмотреть файл

@ -876,6 +876,30 @@ class LCallInstructionHelper : public LInstructionHelper<Defs, Operands, Temps>
}
};
class LRecoverInfo : public TempObject
{
MResumePoint *mir_;
// Cached offset where this resume point is encoded.
RecoverOffset recoverOffset_;
LRecoverInfo(MResumePoint *mir);
public:
static LRecoverInfo *New(MIRGenerator *gen, MResumePoint *mir);
MResumePoint *mir() const {
return mir_;
}
RecoverOffset recoverOffset() const {
return recoverOffset_;
}
void setRecoverOffset(RecoverOffset offset) {
JS_ASSERT(recoverOffset_ == INVALID_RECOVER_OFFSET);
recoverOffset_ = offset;
}
};
// An LSnapshot is the reflection of an MResumePoint in LIR. Unlike MResumePoints,
// they cannot be shared, as they are filled in by the register allocator in
// order to capture the precise low-level stack state in between an
@ -886,16 +910,16 @@ class LSnapshot : public TempObject
private:
uint32_t numSlots_;
LAllocation *slots_;
MResumePoint *mir_;
LRecoverInfo *recoverInfo_;
SnapshotOffset snapshotOffset_;
BailoutId bailoutId_;
BailoutKind bailoutKind_;
LSnapshot(MResumePoint *mir, BailoutKind kind);
LSnapshot(LRecoverInfo *recover, BailoutKind kind);
bool init(MIRGenerator *gen);
public:
static LSnapshot *New(MIRGenerator *gen, MResumePoint *snapshot, BailoutKind kind);
static LSnapshot *New(MIRGenerator *gen, LRecoverInfo *recover, BailoutKind kind);
size_t numEntries() const {
return numSlots_;
@ -923,8 +947,11 @@ class LSnapshot : public TempObject
JS_ASSERT(i < numSlots_);
slots_[i] = alloc;
}
LRecoverInfo *recoverInfo() const {
return recoverInfo_;
}
MResumePoint *mir() const {
return mir_;
return recoverInfo()->mir();
}
SnapshotOffset snapshotOffset() const {
return snapshotOffset_;

Просмотреть файл

@ -594,6 +594,10 @@ SnapshotOffset
SnapshotWriter::startSnapshot(RecoverOffset recoverOffset, BailoutKind kind)
{
lastStart_ = writer_.length();
allocWritten_ = 0;
IonSpew(IonSpew_Snapshots, "starting snapshot with recover offset %u, bailout kind %u",
recoverOffset, kind);
JS_ASSERT(uint32_t(kind) < (1 << SNAPSHOT_BAILOUTKIND_BITS));
JS_ASSERT(recoverOffset < (1 << SNAPSHOT_ROFFSET_BITS));
@ -658,20 +662,15 @@ SnapshotWriter::endSnapshot()
uint32_t(writer_.length() - lastStart_), lastStart_);
}
RecoverWriter::RecoverWriter(SnapshotWriter &snapshot)
: snapshot_(snapshot)
{
}
SnapshotOffset
RecoverWriter::startRecover(uint32_t frameCount, BailoutKind kind, bool resumeAfter)
RecoverOffset
RecoverWriter::startRecover(uint32_t frameCount, bool resumeAfter)
{
MOZ_ASSERT(frameCount);
nframes_ = frameCount;
framesWritten_ = 0;
IonSpew(IonSpew_Snapshots, "starting snapshot with frameCount %u, bailout kind %u",
frameCount, kind);
IonSpew(IonSpew_Snapshots, "starting recover with frameCount %u",
frameCount);
MOZ_ASSERT(!(uint32_t(resumeAfter) &~ RECOVER_RESUMEAFTER_MASK));
MOZ_ASSERT(frameCount < uint32_t(1 << RECOVER_FRAMECOUNT_BITS));
@ -680,13 +679,12 @@ RecoverWriter::startRecover(uint32_t frameCount, BailoutKind kind, bool resumeAf
(frameCount << RECOVER_FRAMECOUNT_SHIFT);
RecoverOffset recoverOffset = writer_.length();
SnapshotOffset snapshotOffset = snapshot_.startSnapshot(recoverOffset, kind);
writer_.writeUnsigned(bits);
return snapshotOffset;
return recoverOffset;
}
void
RecoverWriter::startFrame(JSFunction *fun, JSScript *script,
RecoverWriter::writeFrame(JSFunction *fun, JSScript *script,
jsbytecode *pc, uint32_t exprStack)
{
// Test if we honor the maximum of arguments at all times.
@ -696,30 +694,20 @@ RecoverWriter::startFrame(JSFunction *fun, JSScript *script,
uint32_t implicit = StartArgSlot(script);
uint32_t formalArgs = CountArgSlots(script, fun);
nallocs_ = formalArgs + script->nfixed() + exprStack;
snapshot_.allocWritten_ = 0;
uint32_t nallocs = formalArgs + script->nfixed() + exprStack;
IonSpew(IonSpew_Snapshots, "Starting frame; implicit %u, formals %u, fixed %u, exprs %u",
implicit, formalArgs - implicit, script->nfixed(), exprStack);
uint32_t pcoff = script->pcToOffset(pc);
IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nallocs_);
IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nallocs);
writer_.writeUnsigned(pcoff);
writer_.writeUnsigned(nallocs_);
}
void
RecoverWriter::endFrame()
{
MOZ_ASSERT(snapshot_.allocWritten_ == nallocs_);
nallocs_ = snapshot_.allocWritten_ = 0;
writer_.writeUnsigned(nallocs);
framesWritten_++;
}
void
RecoverWriter::endRecover()
{
snapshot_.endSnapshot();
JS_ASSERT(nframes_ == framesWritten_);
}

Просмотреть файл

@ -302,8 +302,6 @@ class RValueAllocation
};
};
typedef uint32_t RecoverOffset;
class RecoverWriter;
// Collects snapshots in a contiguous buffer, which is copied into IonScript
@ -336,6 +334,9 @@ class SnapshotWriter
#endif
bool add(const RValueAllocation &slot);
uint32_t allocWritten() const {
return allocWritten_;
}
void endSnapshot();
bool oom() const {
@ -361,20 +362,14 @@ class SnapshotWriter
class RecoverWriter
{
CompactBufferWriter writer_;
SnapshotWriter &snapshot_;
uint32_t nallocs_;
uint32_t nframes_;
uint32_t framesWritten_;
public:
RecoverWriter(SnapshotWriter &snapshot);
SnapshotOffset startRecover(uint32_t frameCount, bool resumeAfter);
SnapshotOffset startRecover(uint32_t frameCount, BailoutKind kind, bool resumeAfter);
void startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack);
void endFrame();
void writeFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack);
void endRecover();

Просмотреть файл

@ -42,7 +42,7 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, Mac
graph(*graph),
current(nullptr),
snapshots_(),
recovers_(snapshots_),
recovers_(),
deoptTable_(nullptr),
#ifdef DEBUG
pushedArgs_(0),
@ -235,48 +235,25 @@ CodeGeneratorShared::encodeAllocations(LSnapshot *snapshot, MResumePoint *resume
}
bool
CodeGeneratorShared::encode(LSnapshot *snapshot)
CodeGeneratorShared::encode(LRecoverInfo *recover)
{
if (snapshot->snapshotOffset() != INVALID_SNAPSHOT_OFFSET)
if (recover->recoverOffset() != INVALID_RECOVER_OFFSET)
return true;
uint32_t frameCount = snapshot->mir()->frameCount();
uint32_t frameCount = recover->mir()->frameCount();
IonSpew(IonSpew_Snapshots, "Encoding LRecoverInfo %p (frameCount %u)",
(void *)recover, frameCount);
IonSpew(IonSpew_Snapshots, "Encoding LSnapshot %p (frameCount %u)",
(void *)snapshot, frameCount);
MResumePoint::Mode mode = snapshot->mir()->mode();
MResumePoint::Mode mode = recover->mir()->mode();
JS_ASSERT(mode != MResumePoint::Outer);
bool resumeAfter = (mode == MResumePoint::ResumeAfter);
SnapshotOffset offset = recovers_.startRecover(frameCount, snapshot->bailoutKind(),
resumeAfter);
RecoverOffset offset = recovers_.startRecover(frameCount, resumeAfter);
#ifdef TRACK_SNAPSHOTS
uint32_t pcOpcode = 0;
uint32_t lirOpcode = 0;
uint32_t lirId = 0;
uint32_t mirOpcode = 0;
uint32_t mirId = 0;
if (LInstruction *ins = instruction()) {
lirOpcode = ins->op();
lirId = ins->id();
if (ins->mirRaw()) {
mirOpcode = ins->mirRaw()->op();
mirId = ins->mirRaw()->id();
if (ins->mirRaw()->trackedPc())
pcOpcode = *ins->mirRaw()->trackedPc();
}
}
snapshots_.trackSnapshot(pcOpcode, mirOpcode, mirId, lirOpcode, lirId);
#endif
FlattenedMResumePointIter mirOperandIter(snapshot->mir());
FlattenedMResumePointIter mirOperandIter(recover->mir());
if (!mirOperandIter.init())
return false;
uint32_t startIndex = 0;
for (MResumePoint **it = mirOperandIter.begin(), **end = mirOperandIter.end();
it != end;
++it)
@ -287,20 +264,24 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
JSScript *script = block->info().script();
jsbytecode *pc = mir->pc();
uint32_t exprStack = mir->stackDepth() - block->info().ninvoke();
recovers_.startFrame(fun, script, pc, exprStack);
// Ensure that all snapshot which are encoded can safely be used for
// bailouts.
DebugOnly<jsbytecode *> bailPC = pc;
if (mir->mode() == MResumePoint::ResumeAfter)
bailPC = GetNextPc(pc);
recovers_.writeFrame(fun, script, pc, exprStack);
#ifdef DEBUG
// Ensure that all snapshot which are encoded can safely be used for
// bailouts.
if (GetIonContext()->cx) {
uint32_t stackDepth;
bool reachablePC;
if (!ReconstructStackDepth(GetIonContext()->cx, script, bailPC, &stackDepth, &reachablePC))
jsbytecode *bailPC = pc;
if (mir->mode() == MResumePoint::ResumeAfter)
bailPC = GetNextPc(pc);
if (!ReconstructStackDepth(GetIonContext()->cx, script,
bailPC, &stackDepth, &reachablePC))
{
return false;
}
if (reachablePC) {
if (JSOp(*bailPC) == JSOP_FUNCALL) {
@ -326,16 +307,68 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
}
}
#endif
if (!encodeAllocations(snapshot, mir, &startIndex))
return false;
recovers_.endFrame();
}
recovers_.endRecover();
snapshot->setSnapshotOffset(offset);
recover->setRecoverOffset(offset);
return !recovers_.oom();
}
return !recovers_.oom() || !snapshots_.oom();
bool
CodeGeneratorShared::encode(LSnapshot *snapshot)
{
if (snapshot->snapshotOffset() != INVALID_SNAPSHOT_OFFSET)
return true;
if (!encode(snapshot->recoverInfo()))
return false;
RecoverOffset recoverOffset = snapshot->recoverInfo()->recoverOffset();
MOZ_ASSERT(recoverOffset != INVALID_RECOVER_OFFSET);
IonSpew(IonSpew_Snapshots, "Encoding LSnapshot %p (LRecoverInfo %p)",
(void *)snapshot, (void*) snapshot->recoverInfo());
SnapshotOffset offset = snapshots_.startSnapshot(recoverOffset, snapshot->bailoutKind());
#ifdef TRACK_SNAPSHOTS
uint32_t pcOpcode = 0;
uint32_t lirOpcode = 0;
uint32_t lirId = 0;
uint32_t mirOpcode = 0;
uint32_t mirId = 0;
if (LInstruction *ins = instruction()) {
lirOpcode = ins->op();
lirId = ins->id();
if (ins->mirRaw()) {
mirOpcode = ins->mirRaw()->op();
mirId = ins->mirRaw()->id();
if (ins->mirRaw()->trackedPc())
pcOpcode = *ins->mirRaw()->trackedPc();
}
}
snapshots_.trackSnapshot(pcOpcode, mirOpcode, mirId, lirOpcode, lirId);
#endif
FlattenedMResumePointIter mirOperandIter(snapshot->recoverInfo()->mir());
if (!mirOperandIter.init())
return false;
uint32_t startIndex = 0;
for (MResumePoint **it = mirOperandIter.begin(), **end = mirOperandIter.end();
it != end;
++it)
{
MResumePoint *mir = *it;
if (!encodeAllocations(snapshot, mir, &startIndex))
return false;
}
MOZ_ASSERT(snapshots_.allocWritten() == snapshot->numSlots());
snapshots_.endSnapshot();
snapshot->setSnapshotOffset(offset);
return !snapshots_.oom();
}
bool

Просмотреть файл

@ -258,6 +258,7 @@ class CodeGeneratorShared : public LInstructionVisitor
protected:
// Encodes an LSnapshot into the compressed snapshot buffer, returning
// false on failure.
bool encode(LRecoverInfo *recover);
bool encode(LSnapshot *snapshot);
bool encodeAllocations(LSnapshot *snapshot, MResumePoint *resumePoint, uint32_t *startIndex);

Просмотреть файл

@ -56,11 +56,22 @@ LIRGeneratorShared::lowerTypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock
lir->setOperand(inputPosition, LUse(operand->virtualRegister(), LUse::ANY));
}
LRecoverInfo *
LIRGeneratorShared::buildRecover(MResumePoint *rp)
{
LRecoverInfo *recover = LRecoverInfo::New(gen, rp);
return recover;
}
#ifdef JS_NUNBOX32
LSnapshot *
LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
{
LSnapshot *snapshot = LSnapshot::New(gen, rp, kind);
LRecoverInfo *recover = buildRecover(rp);
if (!recover)
return nullptr;
LSnapshot *snapshot = LSnapshot::New(gen, recover, kind);
if (!snapshot)
return nullptr;
@ -114,7 +125,11 @@ LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKi
LSnapshot *
LIRGeneratorShared::buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind)
{
LSnapshot *snapshot = LSnapshot::New(gen, rp, kind);
LRecoverInfo *recover = buildRecover(rp);
if (!recover)
return nullptr;
LSnapshot *snapshot = LSnapshot::New(gen, recover, kind);
if (!snapshot)
return nullptr;

Просмотреть файл

@ -160,6 +160,7 @@ class LIRGeneratorShared : public MInstructionVisitorWithDefaults
return tmp;
}
LRecoverInfo *buildRecover(MResumePoint *rp);
LSnapshot *buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind);
bool assignPostSnapshot(MInstruction *mir, LInstruction *ins);