mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Add IsConstructing and thisObject to Ion frames (Bug 744253, r=dvander)
This commit is contained in:
parent
0a66b9d72b
commit
2a49f16bc0
@ -1022,7 +1022,7 @@ InvalidateActivation(FreeOp *fop, uint8 *ionTop, bool invalidateAll)
|
||||
|
||||
size_t frameno = 1;
|
||||
|
||||
for (IonFrameIterator it(ionTop); it.more(); ++it, ++frameno) {
|
||||
for (IonFrameIterator it(ionTop); !it.done(); ++it, ++frameno) {
|
||||
JS_ASSERT_IF(frameno == 1, it.type() == IonFrame_Exit);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -113,6 +113,8 @@ class IonFrameIterator
|
||||
}
|
||||
bool isFunctionFrame() const;
|
||||
|
||||
bool isConstructing(IonActivation *activation) const;
|
||||
|
||||
void *calleeToken() const;
|
||||
JSFunction *callee() const;
|
||||
JSFunction *maybeCallee() const;
|
||||
@ -135,8 +137,8 @@ class IonFrameIterator
|
||||
|
||||
// Functions used to iterate on frames. When prevType is IonFrame_Entry,
|
||||
// the current frame is the last frame.
|
||||
inline bool more() const {
|
||||
return type_ != IonFrame_Entry;
|
||||
inline bool done() const {
|
||||
return type_ == IonFrame_Entry;
|
||||
}
|
||||
IonFrameIterator &operator++();
|
||||
|
||||
@ -165,7 +167,7 @@ class IonActivationIterator
|
||||
|
||||
IonActivationIterator &operator++();
|
||||
|
||||
IonActivation *activation() {
|
||||
IonActivation *activation() const {
|
||||
return activation_;
|
||||
}
|
||||
uint8 *top() const {
|
||||
@ -240,6 +242,8 @@ class InlineFrameIterator
|
||||
return si_;
|
||||
}
|
||||
bool isFunctionFrame() const;
|
||||
bool isConstructing(IonActivation *activation) const;
|
||||
JSObject *thisObject() const;
|
||||
InlineFrameIterator operator++();
|
||||
};
|
||||
|
||||
|
@ -451,7 +451,7 @@ MarkIonJSFrame(JSTracer *trc, const IonFrameIterator &frame)
|
||||
static void
|
||||
MarkIonActivation(JSTracer *trc, uint8 *top)
|
||||
{
|
||||
for (IonFrameIterator frames(top); frames.more(); ++frames) {
|
||||
for (IonFrameIterator frames(top); !frames.done(); ++frames) {
|
||||
switch (frames.type()) {
|
||||
case IonFrame_Exit:
|
||||
// The exit frame gets ignored.
|
||||
@ -730,3 +730,57 @@ MachineState::FromBailout(uintptr_t regs[Registers::Total],
|
||||
return machine;
|
||||
}
|
||||
|
||||
bool
|
||||
InlineFrameIterator::isConstructing(IonActivation *activation) const
|
||||
{
|
||||
// Skip the current frame and look at the caller's.
|
||||
if (more()) {
|
||||
InlineFrameIterator parent(*this);
|
||||
++parent;
|
||||
|
||||
// In the case of a JS frame, look up the pc from the snapshot.
|
||||
JS_ASSERT(js_CodeSpec[*parent.pc()].format & JOF_INVOKE);
|
||||
|
||||
return (JSOp)*parent.pc() == JSOP_NEW;
|
||||
}
|
||||
|
||||
return frame_->isConstructing(activation);
|
||||
}
|
||||
|
||||
bool
|
||||
IonFrameIterator::isConstructing(IonActivation *activation) const
|
||||
{
|
||||
IonFrameIterator parent(*this);
|
||||
|
||||
// Skip the current frame and look at the caller's.
|
||||
do {
|
||||
++parent;
|
||||
} while (!parent.done() && !parent.isScripted());
|
||||
|
||||
if (parent.isScripted()) {
|
||||
// In the case of a JS frame, look up the pc from the snapshot.
|
||||
InlineFrameIterator inlinedParent(&parent);
|
||||
JS_ASSERT(js_CodeSpec[*inlinedParent.pc()].format & JOF_INVOKE);
|
||||
|
||||
return (JSOp)*inlinedParent.pc() == JSOP_NEW;
|
||||
}
|
||||
|
||||
JS_ASSERT(parent.done());
|
||||
return activation->entryfp()->isConstructing();
|
||||
}
|
||||
|
||||
JSObject *
|
||||
InlineFrameIterator::thisObject() const
|
||||
{
|
||||
// JS_ASSERT(isConstructing(...));
|
||||
SnapshotIterator s(si_);
|
||||
|
||||
// scopeChain
|
||||
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();
|
||||
}
|
||||
|
@ -158,9 +158,6 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
StackIter prev(iter);
|
||||
++prev;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) {
|
||||
/*
|
||||
|
@ -1119,7 +1119,7 @@ MarkRangeConservativelyAndSkipIon(JSTracer *trc, JSRuntime *rt, const uintptr_t
|
||||
// that the conservative scanner will still see them.
|
||||
for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
|
||||
ion::IonFrameIterator frames(ion.top());
|
||||
while (frames.more())
|
||||
while (!frames.done())
|
||||
++frames;
|
||||
|
||||
uintptr_t *ionMin = (uintptr_t *)ion.top();
|
||||
|
@ -3082,11 +3082,10 @@ TypeObject::clearNewScript(JSContext *cx)
|
||||
pcOffsets.append(uint32_t(iter.pc() - iter.script()->code));
|
||||
if (iter.isConstructing() &&
|
||||
iter.callee() == newScript->fun &&
|
||||
iter.thisv().isObject() &&
|
||||
!iter.thisv().toObject().hasLazyType() &&
|
||||
iter.thisv().toObject().type() == this)
|
||||
!iter.thisObject()->hasLazyType() &&
|
||||
iter.thisObject()->type() == this)
|
||||
{
|
||||
JSObject *obj = &iter.thisv().toObject();
|
||||
JSObject *obj = iter.thisObject();
|
||||
|
||||
/* Whether all identified 'new' properties have been initialized. */
|
||||
bool finished = false;
|
||||
|
@ -6307,7 +6307,7 @@ js_DumpBacktrace(JSContext *cx)
|
||||
const char *filename = JS_GetScriptFilename(cx, i.script());
|
||||
unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc());
|
||||
sprinter.printf("#%d %14p %s:%d (%p @ %d)\n",
|
||||
depth, i.fp(), filename, line,
|
||||
depth, (i.isIon() ? 0 : i.fp()), filename, line,
|
||||
i.script(), i.pc() - i.script()->code);
|
||||
} else {
|
||||
sprinter.printf("#%d ???\n", depth);
|
||||
|
@ -1176,10 +1176,10 @@ StackIter::settleOnNewState()
|
||||
if (fp_->runningInIon()) {
|
||||
ionFrames_ = ion::IonFrameIterator(ionActivations_.top());
|
||||
|
||||
while (ionFrames_.more() && !ionFrames_.isScripted())
|
||||
while (!ionFrames_.done() && !ionFrames_.isScripted())
|
||||
++ionFrames_;
|
||||
|
||||
if (!ionFrames_.more()) {
|
||||
if (ionFrames_.done()) {
|
||||
// In this case, we bailed out the last frame, so we
|
||||
// shouldn't really transition to Ion code.
|
||||
++ionActivations_;
|
||||
@ -1273,9 +1273,7 @@ StackIter::StackIter(JSContext *cx, SavedOption savedOption)
|
||||
#endif
|
||||
{
|
||||
#ifdef JS_METHODJIT
|
||||
CompartmentVector &v = cx->runtime->compartments;
|
||||
for (size_t i = 0; i < v.length(); i++)
|
||||
mjit::ExpandInlineFrames(v[i]);
|
||||
mjit::ExpandInlineFrames(cx->compartment);
|
||||
#endif
|
||||
|
||||
if (StackSegment *seg = cx->stack.seg_) {
|
||||
@ -1298,10 +1296,10 @@ StackIter::popIonFrame()
|
||||
script_ = ionInlineFrames_.script();
|
||||
} else {
|
||||
++ionFrames_;
|
||||
while (ionFrames_.more() && !ionFrames_.isScripted())
|
||||
while (!ionFrames_.done() && !ionFrames_.isScripted())
|
||||
++ionFrames_;
|
||||
|
||||
if (ionFrames_.more()) {
|
||||
if (!ionFrames_.done()) {
|
||||
ionInlineFrames_ = ion::InlineFrameIterator(&ionFrames_);
|
||||
pc_ = ionInlineFrames_.pc();
|
||||
script_ = ionInlineFrames_.script();
|
||||
@ -1410,6 +1408,8 @@ StackIter::isConstructing() const
|
||||
case DONE:
|
||||
JS_NOT_REACHED("Unexpected state");
|
||||
return false;
|
||||
case ION:
|
||||
return ionInlineFrames_.isConstructing(ionActivations_.activation());
|
||||
case SCRIPTED:
|
||||
case NATIVE:
|
||||
case IMPLICIT_NATIVE:
|
||||
@ -1456,20 +1456,21 @@ StackIter::calleev() const
|
||||
return Value();
|
||||
}
|
||||
|
||||
Value
|
||||
StackIter::thisv() const
|
||||
JSObject *
|
||||
StackIter::thisObject() const
|
||||
{
|
||||
switch (state_) {
|
||||
case DONE:
|
||||
MOZ_NOT_REACHED("Unexpected state");
|
||||
return Value();
|
||||
break;
|
||||
case ION:
|
||||
return ionInlineFrames_.thisObject();
|
||||
case SCRIPTED:
|
||||
case NATIVE:
|
||||
case IMPLICIT_NATIVE:
|
||||
return fp()->thisValue();
|
||||
return &fp()->thisValue().toObject();
|
||||
}
|
||||
MOZ_NOT_REACHED("unexpected state");
|
||||
return Value();
|
||||
JS_NOT_REACHED("Unexpected state");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -1838,11 +1838,7 @@ class StackIter
|
||||
private:
|
||||
SavedOption savedOption_;
|
||||
|
||||
enum State { DONE, SCRIPTED, NATIVE, IMPLICIT_NATIVE
|
||||
#ifdef JS_ION
|
||||
, ION
|
||||
#endif
|
||||
};
|
||||
enum State { DONE, SCRIPTED, NATIVE, IMPLICIT_NATIVE, ION };
|
||||
|
||||
State state_;
|
||||
|
||||
@ -1881,6 +1877,7 @@ class StackIter
|
||||
bool operator!=(const StackIter &rhs) const { return !(*this == rhs); }
|
||||
|
||||
bool isScript() const { JS_ASSERT(!done()); return state_ == SCRIPTED || state_ == ION; }
|
||||
bool isIon() const { JS_ASSERT(!done()); return state_ == ION; }
|
||||
bool isImplicitNativeCall() const {
|
||||
JS_ASSERT(!done());
|
||||
return state_ == IMPLICIT_NATIVE;
|
||||
@ -1895,13 +1892,14 @@ class StackIter
|
||||
bool isNonEvalFunctionFrame() const;
|
||||
bool isConstructing() const;
|
||||
|
||||
// :TODO: Add && !isIon() in JS_ASSERT of fp() and sp().
|
||||
StackFrame *fp() const { JS_ASSERT(isScript()); return fp_; }
|
||||
Value *sp() const { JS_ASSERT(isScript()); return sp_; }
|
||||
jsbytecode *pc() const { JS_ASSERT(isScript()); return pc_; }
|
||||
JSScript *script() const { JS_ASSERT(isScript()); return script_; }
|
||||
JSFunction *callee() const;
|
||||
Value calleev() const;
|
||||
Value thisv() const;
|
||||
JSObject *thisObject() const;
|
||||
|
||||
CallArgs nativeArgs() const { JS_ASSERT(isNativeCall()); return args_; }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user