Bug 989667 - Add writes of recovery meta-data to the MResumePoint. r=h4writer

This commit is contained in:
Nicolas B. Pierron 2014-04-08 07:21:17 -07:00
parent 5add17a7cf
commit 982506d574
6 changed files with 96 additions and 70 deletions

View File

@ -9425,6 +9425,8 @@ class MResumePoint MOZ_FINAL : public MNode, public InlineForwardListNode<MResum
operands_[i].producer()->removeUse(&operands_[i]);
}
}
bool writeRecoverData(CompactBufferWriter &writer) const;
};
class MIsCallable

82
js/src/jit/Recover.cpp Normal file
View File

@ -0,0 +1,82 @@
/* -*- 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/. */
#include "jit/IonSpewer.h"
#include "jit/MIR.h"
#include "jit/MIRGraph.h"
using namespace js;
using namespace js::jit;
bool
MResumePoint::writeRecoverData(CompactBufferWriter &writer) const
{
MBasicBlock *bb = block();
JSFunction *fun = bb->info().funMaybeLazy();
JSScript *script = bb->info().script();
uint32_t exprStack = stackDepth() - bb->info().ninvoke();
#ifdef DEBUG
// Ensure that all snapshot which are encoded can safely be used for
// bailouts.
if (GetIonContext()->cx) {
uint32_t stackDepth;
bool reachablePC;
jsbytecode *bailPC = pc();
if (mode() == MResumePoint::ResumeAfter)
bailPC = GetNextPc(pc());
if (!ReconstructStackDepth(GetIonContext()->cx, script,
bailPC, &stackDepth, &reachablePC))
{
return false;
}
if (reachablePC) {
if (JSOp(*bailPC) == JSOP_FUNCALL) {
// For fun.call(this, ...); the reconstructStackDepth will
// include the this. When inlining that is not included. So the
// exprStackSlots will be one less.
MOZ_ASSERT(stackDepth - exprStack <= 1);
} else if (JSOp(*bailPC) != JSOP_FUNAPPLY &&
!IsGetPropPC(bailPC) && !IsSetPropPC(bailPC))
{
// For fun.apply({}, arguments) the reconstructStackDepth will
// have stackdepth 4, but it could be that we inlined the
// funapply. In that case exprStackSlots, will have the real
// arguments in the slots and not be 4.
// With accessors, we have different stack depths depending on
// whether or not we inlined the accessor, as the inlined stack
// contains a callee function that should never have been there
// and we might just be capturing an uneventful property site,
// in which case there won't have been any violence.
MOZ_ASSERT(exprStack == stackDepth);
}
}
}
#endif
// Test if we honor the maximum of arguments at all times. This is a sanity
// check and not an algorithm limit. So check might be a bit too loose. +4
// to account for scope chain, return value, this value and maybe
// arguments_object.
MOZ_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
uint32_t implicit = StartArgSlot(script);
uint32_t formalArgs = CountArgSlots(script, fun);
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);
writer.writeUnsigned(pcoff);
writer.writeUnsigned(nallocs);
return true;
}

View File

@ -12,8 +12,8 @@
#include "jit/IonSpewer.h"
#ifdef TRACK_SNAPSHOTS
# include "jit/LIR.h"
# include "jit/MIR.h"
#endif
#include "jit/MIR.h"
using namespace js;
using namespace js::jit;
@ -683,27 +683,13 @@ RecoverWriter::startRecover(uint32_t frameCount, bool resumeAfter)
return recoverOffset;
}
void
RecoverWriter::writeFrame(JSFunction *fun, JSScript *script,
jsbytecode *pc, uint32_t exprStack)
bool
RecoverWriter::writeFrame(const MResumePoint *rp)
{
// Test if we honor the maximum of arguments at all times.
// This is a sanity check and not an algorithm limit. So check might be a bit too loose.
// +4 to account for scope chain, return value, this value and maybe arguments_object.
JS_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
uint32_t implicit = StartArgSlot(script);
uint32_t formalArgs = CountArgSlots(script, fun);
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);
writer_.writeUnsigned(pcoff);
writer_.writeUnsigned(nallocs);
if (!rp->writeRecoverData(writer_))
return false;
framesWritten_++;
return true;
}
void

View File

@ -359,6 +359,8 @@ class SnapshotWriter
}
};
class MResumePoint;
class RecoverWriter
{
CompactBufferWriter writer_;
@ -369,7 +371,7 @@ class RecoverWriter
public:
SnapshotOffset startRecover(uint32_t frameCount, bool resumeAfter);
void writeFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack);
bool writeFrame(const MResumePoint *rp);
void endRecover();

View File

@ -254,55 +254,8 @@ CodeGeneratorShared::encode(LRecoverInfo *recover)
it != end;
++it)
{
MResumePoint *mir = *it;
MBasicBlock *block = mir->block();
JSFunction *fun = block->info().funMaybeLazy();
JSScript *script = block->info().script();
jsbytecode *pc = mir->pc();
uint32_t exprStack = mir->stackDepth() - block->info().ninvoke();
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;
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) {
// For fun.call(this, ...); the reconstructStackDepth will
// include the this. When inlining that is not included.
// So the exprStackSlots will be one less.
JS_ASSERT(stackDepth - exprStack <= 1);
} else if (JSOp(*bailPC) != JSOP_FUNAPPLY &&
!IsGetPropPC(bailPC) && !IsSetPropPC(bailPC))
{
// For fun.apply({}, arguments) the reconstructStackDepth will
// have stackdepth 4, but it could be that we inlined the
// funapply. In that case exprStackSlots, will have the real
// arguments in the slots and not be 4.
// With accessors, we have different stack depths depending on
// whether or not we inlined the accessor, as the inlined stack
// contains a callee function that should never have been there
// and we might just be capturing an uneventful property site, in
// which case there won't have been any violence.
JS_ASSERT(exprStack == stackDepth);
}
}
}
#endif
if (!recovers_.writeFrame(*it))
return false;
}
recovers_.endRecover();

View File

@ -281,6 +281,7 @@ if CONFIG['ENABLE_ION']:
'jit/ParallelSafetyAnalysis.cpp',
'jit/PerfSpewer.cpp',
'jit/RangeAnalysis.cpp',
'jit/Recover.cpp',
'jit/RegisterAllocator.cpp',
'jit/Safepoints.cpp',
'jit/shared/BaselineCompiler-shared.cpp',