зеркало из https://github.com/mozilla/gecko-dev.git
Bug 891215 (part 9) - Slim down IonFrameIterator-inl.h. r=terrence.
--HG-- extra : rebase_source : 9857155ba2628a7319e9d712116eba4839689be1
This commit is contained in:
Родитель
68a1ab8034
Коммит
6f9ec4ba7d
|
@ -12,181 +12,10 @@
|
||||||
#include "ion/BaselineFrame.h"
|
#include "ion/BaselineFrame.h"
|
||||||
#include "ion/IonFrameIterator.h"
|
#include "ion/IonFrameIterator.h"
|
||||||
#include "ion/Bailouts.h"
|
#include "ion/Bailouts.h"
|
||||||
#include "ion/Ion.h"
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace ion {
|
namespace ion {
|
||||||
|
|
||||||
template <class Op>
|
|
||||||
inline void
|
|
||||||
SnapshotIterator::readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Value *thisv,
|
|
||||||
unsigned start, unsigned formalEnd, unsigned iterEnd,
|
|
||||||
JSScript *script)
|
|
||||||
{
|
|
||||||
if (scopeChain)
|
|
||||||
*scopeChain = read();
|
|
||||||
else
|
|
||||||
skip();
|
|
||||||
|
|
||||||
// Skip slot for arguments object.
|
|
||||||
if (script->argumentsHasVarBinding())
|
|
||||||
skip();
|
|
||||||
|
|
||||||
if (thisv)
|
|
||||||
*thisv = read();
|
|
||||||
else
|
|
||||||
skip();
|
|
||||||
|
|
||||||
unsigned i = 0;
|
|
||||||
if (formalEnd < start)
|
|
||||||
i = start;
|
|
||||||
|
|
||||||
for (; i < start; i++)
|
|
||||||
skip();
|
|
||||||
for (; i < formalEnd && i < iterEnd; i++) {
|
|
||||||
// We are not always able to read values from the snapshots, some values
|
|
||||||
// such as non-gc things may still be live in registers and cause an
|
|
||||||
// error while reading the machine state.
|
|
||||||
Value v = maybeRead();
|
|
||||||
op(v);
|
|
||||||
}
|
|
||||||
if (iterEnd >= formalEnd) {
|
|
||||||
for (; i < iterEnd; i++)
|
|
||||||
op(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(
|
|
||||||
JSContext *cx, const IonFrameIterator *iter)
|
|
||||||
: callee_(cx),
|
|
||||||
script_(cx)
|
|
||||||
{
|
|
||||||
resetOn(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(
|
|
||||||
JSContext *cx,
|
|
||||||
const InlineFrameIteratorMaybeGC<allowGC> *iter)
|
|
||||||
: frame_(iter ? iter->frame_ : NULL),
|
|
||||||
framesRead_(0),
|
|
||||||
callee_(cx),
|
|
||||||
script_(cx)
|
|
||||||
{
|
|
||||||
if (frame_) {
|
|
||||||
start_ = SnapshotIterator(*frame_);
|
|
||||||
// findNextFrame will iterate to the next frame and init. everything.
|
|
||||||
// Therefore to settle on the same frame, we report one frame less readed.
|
|
||||||
framesRead_ = iter->framesRead_ - 1;
|
|
||||||
findNextFrame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
template <class Op>
|
|
||||||
inline void
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::forEachCanonicalActualArg(
|
|
||||||
JSContext *cx, Op op, unsigned start, unsigned count) const
|
|
||||||
{
|
|
||||||
unsigned nactual = numActualArgs();
|
|
||||||
if (count == unsigned(-1))
|
|
||||||
count = nactual - start;
|
|
||||||
|
|
||||||
unsigned end = start + count;
|
|
||||||
unsigned nformal = callee()->nargs;
|
|
||||||
|
|
||||||
JS_ASSERT(start <= end && end <= nactual);
|
|
||||||
|
|
||||||
if (more()) {
|
|
||||||
// There is still a parent frame of this inlined frame.
|
|
||||||
// The not overflown arguments are taken from the inlined frame,
|
|
||||||
// because it will have the updated value when JSOP_SETARG is done.
|
|
||||||
// All arguments (also the overflown) are the last pushed values in the parent frame.
|
|
||||||
// To get the overflown arguments, we need to take them from there.
|
|
||||||
|
|
||||||
// Get the non overflown arguments
|
|
||||||
unsigned formal_end = (end < nformal) ? end : nformal;
|
|
||||||
SnapshotIterator s(si_);
|
|
||||||
s.readFrameArgs(op, NULL, NULL, NULL, start, nformal, formal_end, script());
|
|
||||||
|
|
||||||
// The overflown arguments are not available in current frame.
|
|
||||||
// They are the last pushed arguments in the parent frame of this inlined frame.
|
|
||||||
InlineFrameIteratorMaybeGC it(cx, this);
|
|
||||||
++it;
|
|
||||||
unsigned argsObjAdj = it.script()->argumentsHasVarBinding() ? 1 : 0;
|
|
||||||
SnapshotIterator parent_s(it.snapshotIterator());
|
|
||||||
|
|
||||||
// Skip over all slots untill we get to the last slots (= arguments slots of callee)
|
|
||||||
// the +2 is for [this] and [scopechain], and maybe +1 for [argsObj]
|
|
||||||
JS_ASSERT(parent_s.slots() >= nactual + 2 + argsObjAdj);
|
|
||||||
unsigned skip = parent_s.slots() - nactual - 2 - argsObjAdj;
|
|
||||||
for (unsigned j = 0; j < skip; j++)
|
|
||||||
parent_s.skip();
|
|
||||||
|
|
||||||
// Get the overflown arguments
|
|
||||||
parent_s.readFrameArgs(op, NULL, NULL, NULL, nformal, nactual, end, it.script());
|
|
||||||
} else {
|
|
||||||
SnapshotIterator s(si_);
|
|
||||||
Value *argv = frame_->actualArgs();
|
|
||||||
s.readFrameArgs(op, argv, NULL, NULL, start, nformal, end, script());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline JSObject *
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::scopeChain() const
|
|
||||||
{
|
|
||||||
SnapshotIterator s(si_);
|
|
||||||
|
|
||||||
// scopeChain
|
|
||||||
Value v = s.read();
|
|
||||||
if (v.isObject()) {
|
|
||||||
JS_ASSERT_IF(script()->hasAnalysis(), script()->analysis()->usesScopeChain());
|
|
||||||
return &v.toObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
return callee()->environment();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline JSObject *
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::thisObject() const
|
|
||||||
{
|
|
||||||
// JS_ASSERT(isConstructing(...));
|
|
||||||
SnapshotIterator s(si_);
|
|
||||||
|
|
||||||
// scopeChain
|
|
||||||
s.skip();
|
|
||||||
|
|
||||||
// Arguments object.
|
|
||||||
if (script()->argumentsHasVarBinding())
|
|
||||||
s.skip();
|
|
||||||
|
|
||||||
// In strict modes, |this| may not be an object and thus may not be
|
|
||||||
// readable which can either segv in read or trigger the assertion.
|
|
||||||
Value v = s.read();
|
|
||||||
JS_ASSERT(v.isObject());
|
|
||||||
return &v.toObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline unsigned
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::numActualArgs() const
|
|
||||||
{
|
|
||||||
// The number of actual arguments of inline frames is recovered by the
|
|
||||||
// iteration process. It is recovered from the bytecode because this
|
|
||||||
// property still hold since the for inlined frames. This property does not
|
|
||||||
// hold for the parent frame because it can have optimize a call to
|
|
||||||
// js_fun_call or js_fun_apply.
|
|
||||||
if (more())
|
|
||||||
return numActualArgs_;
|
|
||||||
|
|
||||||
return frame_->numActualArgs();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline
|
inline
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(
|
InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(
|
||||||
|
@ -202,32 +31,6 @@ InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline InlineFrameIteratorMaybeGC<allowGC> &
|
|
||||||
InlineFrameIteratorMaybeGC<allowGC>::operator++()
|
|
||||||
{
|
|
||||||
findNextFrame();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Op>
|
|
||||||
inline void
|
|
||||||
IonFrameIterator::forEachCanonicalActualArg(Op op, unsigned start, unsigned count) const
|
|
||||||
{
|
|
||||||
JS_ASSERT(isBaselineJS());
|
|
||||||
|
|
||||||
unsigned nactual = numActualArgs();
|
|
||||||
if (count == unsigned(-1))
|
|
||||||
count = nactual - start;
|
|
||||||
|
|
||||||
unsigned end = start + count;
|
|
||||||
JS_ASSERT(start <= end && end <= nactual);
|
|
||||||
|
|
||||||
Value *argv = actualArgs();
|
|
||||||
for (unsigned i = start; i < end; i++)
|
|
||||||
op(argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BaselineFrame *
|
inline BaselineFrame *
|
||||||
IonFrameIterator::baselineFrame() const
|
IonFrameIterator::baselineFrame() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -201,7 +201,20 @@ class IonFrameIterator
|
||||||
MachineState machineState() const;
|
MachineState machineState() const;
|
||||||
|
|
||||||
template <class Op>
|
template <class Op>
|
||||||
inline void forEachCanonicalActualArg(Op op, unsigned start, unsigned count) const;
|
void forEachCanonicalActualArg(Op op, unsigned start, unsigned count) const {
|
||||||
|
JS_ASSERT(isBaselineJS());
|
||||||
|
|
||||||
|
unsigned nactual = numActualArgs();
|
||||||
|
if (count == unsigned(-1))
|
||||||
|
count = nactual - start;
|
||||||
|
|
||||||
|
unsigned end = start + count;
|
||||||
|
JS_ASSERT(start <= end && end <= nactual);
|
||||||
|
|
||||||
|
Value *argv = actualArgs();
|
||||||
|
for (unsigned i = start; i < end; i++)
|
||||||
|
op(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
|
||||||
|
@ -248,9 +261,41 @@ class SnapshotIterator : public SnapshotReader
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Op>
|
template <class Op>
|
||||||
inline void readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Value *thisv,
|
void readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Value *thisv,
|
||||||
unsigned start, unsigned formalEnd, unsigned iterEnd,
|
unsigned start, unsigned formalEnd, unsigned iterEnd, JSScript *script)
|
||||||
JSScript *script);
|
{
|
||||||
|
if (scopeChain)
|
||||||
|
*scopeChain = read();
|
||||||
|
else
|
||||||
|
skip();
|
||||||
|
|
||||||
|
// Skip slot for arguments object.
|
||||||
|
if (script->argumentsHasVarBinding())
|
||||||
|
skip();
|
||||||
|
|
||||||
|
if (thisv)
|
||||||
|
*thisv = read();
|
||||||
|
else
|
||||||
|
skip();
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
if (formalEnd < start)
|
||||||
|
i = start;
|
||||||
|
|
||||||
|
for (; i < start; i++)
|
||||||
|
skip();
|
||||||
|
for (; i < formalEnd && i < iterEnd; i++) {
|
||||||
|
// We are not always able to read values from the snapshots, some values
|
||||||
|
// such as non-gc things may still be live in registers and cause an
|
||||||
|
// error while reading the machine state.
|
||||||
|
Value v = maybeRead();
|
||||||
|
op(v);
|
||||||
|
}
|
||||||
|
if (iterEnd >= formalEnd) {
|
||||||
|
for (; i < iterEnd; i++)
|
||||||
|
op(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Value maybeReadSlotByIndex(size_t index) {
|
Value maybeReadSlotByIndex(size_t index) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
|
@ -285,9 +330,29 @@ class InlineFrameIteratorMaybeGC
|
||||||
void findNextFrame();
|
void findNextFrame();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline InlineFrameIteratorMaybeGC(JSContext *cx, const IonFrameIterator *iter);
|
InlineFrameIteratorMaybeGC(JSContext *cx, const IonFrameIterator *iter)
|
||||||
inline InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter);
|
: callee_(cx),
|
||||||
inline InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter);
|
script_(cx)
|
||||||
|
{
|
||||||
|
resetOn(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter);
|
||||||
|
|
||||||
|
InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter)
|
||||||
|
: frame_(iter ? iter->frame_ : NULL),
|
||||||
|
framesRead_(0),
|
||||||
|
callee_(cx),
|
||||||
|
script_(cx)
|
||||||
|
{
|
||||||
|
if (frame_) {
|
||||||
|
start_ = SnapshotIterator(*frame_);
|
||||||
|
// findNextFrame will iterate to the next frame and init. everything.
|
||||||
|
// Therefore to settle on the same frame, we report one frame less readed.
|
||||||
|
framesRead_ = iter->framesRead_ - 1;
|
||||||
|
findNextFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool more() const {
|
bool more() const {
|
||||||
return frame_ && framesRead_ < start_.frameCount();
|
return frame_ && framesRead_ < start_.frameCount();
|
||||||
|
@ -299,10 +364,64 @@ class InlineFrameIteratorMaybeGC
|
||||||
JSFunction *maybeCallee() const {
|
JSFunction *maybeCallee() const {
|
||||||
return callee_;
|
return callee_;
|
||||||
}
|
}
|
||||||
inline unsigned numActualArgs() const;
|
|
||||||
|
unsigned numActualArgs() const {
|
||||||
|
// The number of actual arguments of inline frames is recovered by the
|
||||||
|
// iteration process. It is recovered from the bytecode because this
|
||||||
|
// property still hold since the for inlined frames. This property does not
|
||||||
|
// hold for the parent frame because it can have optimize a call to
|
||||||
|
// js_fun_call or js_fun_apply.
|
||||||
|
if (more())
|
||||||
|
return numActualArgs_;
|
||||||
|
|
||||||
|
return frame_->numActualArgs();
|
||||||
|
}
|
||||||
|
|
||||||
template <class Op>
|
template <class Op>
|
||||||
inline void forEachCanonicalActualArg(JSContext *cx, Op op, unsigned start, unsigned count) const;
|
void forEachCanonicalActualArg(JSContext *cx, Op op, unsigned start, unsigned count) const {
|
||||||
|
unsigned nactual = numActualArgs();
|
||||||
|
if (count == unsigned(-1))
|
||||||
|
count = nactual - start;
|
||||||
|
|
||||||
|
unsigned end = start + count;
|
||||||
|
unsigned nformal = callee()->nargs;
|
||||||
|
|
||||||
|
JS_ASSERT(start <= end && end <= nactual);
|
||||||
|
|
||||||
|
if (more()) {
|
||||||
|
// There is still a parent frame of this inlined frame.
|
||||||
|
// The not overflown arguments are taken from the inlined frame,
|
||||||
|
// because it will have the updated value when JSOP_SETARG is done.
|
||||||
|
// All arguments (also the overflown) are the last pushed values in the parent frame.
|
||||||
|
// To get the overflown arguments, we need to take them from there.
|
||||||
|
|
||||||
|
// Get the non overflown arguments
|
||||||
|
unsigned formal_end = (end < nformal) ? end : nformal;
|
||||||
|
SnapshotIterator s(si_);
|
||||||
|
s.readFrameArgs(op, NULL, NULL, NULL, start, nformal, formal_end, script());
|
||||||
|
|
||||||
|
// The overflown arguments are not available in current frame.
|
||||||
|
// They are the last pushed arguments in the parent frame of this inlined frame.
|
||||||
|
InlineFrameIteratorMaybeGC it(cx, this);
|
||||||
|
++it;
|
||||||
|
unsigned argsObjAdj = it.script()->argumentsHasVarBinding() ? 1 : 0;
|
||||||
|
SnapshotIterator parent_s(it.snapshotIterator());
|
||||||
|
|
||||||
|
// Skip over all slots untill we get to the last slots (= arguments slots of callee)
|
||||||
|
// the +2 is for [this] and [scopechain], and maybe +1 for [argsObj]
|
||||||
|
JS_ASSERT(parent_s.slots() >= nactual + 2 + argsObjAdj);
|
||||||
|
unsigned skip = parent_s.slots() - nactual - 2 - argsObjAdj;
|
||||||
|
for (unsigned j = 0; j < skip; j++)
|
||||||
|
parent_s.skip();
|
||||||
|
|
||||||
|
// Get the overflown arguments
|
||||||
|
parent_s.readFrameArgs(op, NULL, NULL, NULL, nformal, nactual, end, it.script());
|
||||||
|
} else {
|
||||||
|
SnapshotIterator s(si_);
|
||||||
|
Value *argv = frame_->actualArgs();
|
||||||
|
s.readFrameArgs(op, argv, NULL, NULL, start, nformal, end, script());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JSScript *script() const {
|
JSScript *script() const {
|
||||||
return script_;
|
return script_;
|
||||||
|
@ -315,9 +434,42 @@ class InlineFrameIteratorMaybeGC
|
||||||
}
|
}
|
||||||
bool isFunctionFrame() const;
|
bool isFunctionFrame() const;
|
||||||
bool isConstructing() const;
|
bool isConstructing() const;
|
||||||
inline JSObject *scopeChain() const;
|
|
||||||
inline JSObject *thisObject() const;
|
JSObject *scopeChain() const {
|
||||||
inline InlineFrameIteratorMaybeGC &operator++();
|
SnapshotIterator s(si_);
|
||||||
|
|
||||||
|
// scopeChain
|
||||||
|
Value v = s.read();
|
||||||
|
if (v.isObject()) {
|
||||||
|
JS_ASSERT_IF(script()->hasAnalysis(), script()->analysis()->usesScopeChain());
|
||||||
|
return &v.toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return callee()->environment();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *thisObject() const {
|
||||||
|
// JS_ASSERT(isConstructing(...));
|
||||||
|
SnapshotIterator s(si_);
|
||||||
|
|
||||||
|
// scopeChain
|
||||||
|
s.skip();
|
||||||
|
|
||||||
|
// Arguments object.
|
||||||
|
if (script()->argumentsHasVarBinding())
|
||||||
|
s.skip();
|
||||||
|
|
||||||
|
// In strict modes, |this| may not be an object and thus may not be
|
||||||
|
// readable which can either segv in read or trigger the assertion.
|
||||||
|
Value v = s.read();
|
||||||
|
JS_ASSERT(v.isObject());
|
||||||
|
return &v.toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
InlineFrameIteratorMaybeGC &operator++() {
|
||||||
|
findNextFrame();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче