зеркало из https://github.com/mozilla/gecko-dev.git
Bug 989344 part 1 - Extract LRecoverInfo from LSnapshot. r=jandem
This commit is contained in:
Родитель
f83d83e539
Коммит
e0b778bf68
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче