blob: 67d87eaaf6125ba634479b9133ea55c2de7df2e5 [file] [log] [blame]
/* -*- 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/. */
#ifndef jit_IonFrameIterator_h
#define jit_IonFrameIterator_h
#ifdef JS_ION
#include "jstypes.h"
#include "IonCode.h"
#include "SnapshotReader.h"
class JSFunction;
class JSScript;
namespace js {
class ActivationIterator;
};
namespace js {
namespace jit {
enum FrameType
{
// A JS frame is analagous to a js::StackFrame, representing one scripted
// functon activation. OptimizedJS frames are used by the optimizing compiler.
IonFrame_OptimizedJS,
// JS frame used by the baseline JIT.
IonFrame_BaselineJS,
// Frame pushed for baseline JIT stubs that make non-tail calls, so that the
// return address -> ICEntry mapping works.
IonFrame_BaselineStub,
// The entry frame is the initial prologue block transitioning from the VM
// into the Ion world.
IonFrame_Entry,
// A rectifier frame sits in between two JS frames, adapting argc != nargs
// mismatches in calls.
IonFrame_Rectifier,
// An unwound JS frame is a JS frame signalling that its callee frame has been
// turned into an exit frame (see EnsureExitFrame). Used by Ion bailouts and
// Baseline exception unwinding.
IonFrame_Unwound_OptimizedJS,
// Like Unwound_OptimizedJS, but the caller is a baseline stub frame.
IonFrame_Unwound_BaselineStub,
// An unwound rectifier frame is a rectifier frame signalling that its callee
// frame has been turned into an exit frame (see EnsureExitFrame).
IonFrame_Unwound_Rectifier,
// An exit frame is necessary for transitioning from a JS frame into C++.
// From within C++, an exit frame is always the last frame in any
// JitActivation.
IonFrame_Exit,
// An OSR frame is added when performing OSR from within a bailout. It
// looks like a JS frame, but does not push scripted arguments, as OSR
// reads arguments from a js::StackFrame.
IonFrame_Osr
};
class IonCommonFrameLayout;
class IonJSFrameLayout;
class IonExitFrameLayout;
class BaselineFrame;
class JitActivation;
class IonFrameIterator
{
protected:
uint8_t *current_;
FrameType type_;
uint8_t *returnAddressToFp_;
size_t frameSize_;
private:
mutable const SafepointIndex *cachedSafepointIndex_;
const JitActivation *activation_;
void dumpBaseline() const;
public:
IonFrameIterator(uint8_t *top)
: current_(top),
type_(IonFrame_Exit),
returnAddressToFp_(NULL),
frameSize_(0),
cachedSafepointIndex_(NULL),
activation_(NULL)
{ }
IonFrameIterator(const ActivationIterator &activations);
IonFrameIterator(IonJSFrameLayout *fp);
// Current frame information.
FrameType type() const {
return type_;
}
uint8_t *fp() const {
return current_;
}
inline IonCommonFrameLayout *current() const;
inline uint8_t *returnAddress() const;
IonJSFrameLayout *jsFrame() const {
JS_ASSERT(isScripted());
return (IonJSFrameLayout *) fp();
}
// Returns true iff this exit frame was created using EnsureExitFrame.
inline bool isFakeExitFrame() const;
inline IonExitFrameLayout *exitFrame() const;
// Returns whether the JS frame has been invalidated and, if so,
// places the invalidated Ion script in |ionScript|.
bool checkInvalidation(IonScript **ionScript) const;
bool checkInvalidation() const;
bool isScripted() const {
return type_ == IonFrame_BaselineJS || type_ == IonFrame_OptimizedJS;
}
bool isBaselineJS() const {
return type_ == IonFrame_BaselineJS;
}
bool isOptimizedJS() const {
return type_ == IonFrame_OptimizedJS;
}
bool isBaselineStub() const {
return type_ == IonFrame_BaselineStub;
}
bool isNative() const;
bool isOOLNativeGetter() const;
bool isOOLPropertyOp() const;
bool isOOLProxyGet() const;
bool isDOMExit() const;
bool isEntry() const {
return type_ == IonFrame_Entry;
}
bool isFunctionFrame() const;
bool isParallelFunctionFrame() const;
bool isConstructing() const;
bool isEntryJSFrame() const;
void *calleeToken() const;
JSFunction *callee() const;
JSFunction *maybeCallee() const;
unsigned numActualArgs() const;
JSScript *script() const;
void baselineScriptAndPc(JSScript **scriptRes, jsbytecode **pcRes) const;
Value *nativeVp() const;
Value *actualArgs() const;
// Returns the return address of the frame above this one (that is, the
// return address that returns back to the current frame).
uint8_t *returnAddressToFp() const {
return returnAddressToFp_;
}
// Previous frame information extracted from the current frame.
inline size_t prevFrameLocalSize() const;
inline FrameType prevType() const;
uint8_t *prevFp() const;
// Returns the stack space used by the current frame, in bytes. This does
// not include the size of its fixed header.
inline size_t frameSize() const;
// Functions used to iterate on frames. When prevType is IonFrame_Entry,
// the current frame is the last frame.
inline bool done() const {
return type_ == IonFrame_Entry;
}
IonFrameIterator &operator++();
// Returns the IonScript associated with this JS frame.
IonScript *ionScript() const;
// Returns the Safepoint associated with this JS frame. Incurs a lookup
// overhead.
const SafepointIndex *safepoint() const;
// Returns the OSI index associated with this JS frame. Incurs a lookup
// overhead.
const OsiIndex *osiIndex() const;
uintptr_t *spillBase() const;
MachineState machineState() const;
template <class Op>
inline void forEachCanonicalActualArg(Op op, unsigned start, unsigned count) const;
void dump() const;
inline BaselineFrame *baselineFrame() const;
};
class IonJSFrameLayout;
class IonBailoutIterator;
// Reads frame information in snapshot-encoding order (that is, outermost frame
// to innermost frame).
class SnapshotIterator : public SnapshotReader
{
IonJSFrameLayout *fp_;
MachineState machine_;
IonScript *ionScript_;
private:
bool hasLocation(const SnapshotReader::Location &loc);
uintptr_t fromLocation(const SnapshotReader::Location &loc);
static Value FromTypedPayload(JSValueType type, uintptr_t payload);
Value slotValue(const Slot &slot);
bool slotReadable(const Slot &slot);
void warnUnreadableSlot();
public:
SnapshotIterator(IonScript *ionScript, SnapshotOffset snapshotOffset,
IonJSFrameLayout *fp, const MachineState &machine);
SnapshotIterator(const IonFrameIterator &iter);
SnapshotIterator(const IonBailoutIterator &iter);
SnapshotIterator();
Value read() {
return slotValue(readSlot());
}
Value maybeRead(bool silentFailure = false) {
Slot s = readSlot();
if (slotReadable(s))
return slotValue(s);
if (!silentFailure)
warnUnreadableSlot();
return UndefinedValue();
}
template <class Op>
inline void readFrameArgs(Op &op, const Value *argv, Value *scopeChain, Value *thisv,
unsigned start, unsigned formalEnd, unsigned iterEnd,
JSScript *script);
Value maybeReadSlotByIndex(size_t index) {
while (index--) {
JS_ASSERT(moreSlots());
skip();
}
Value s = maybeRead(true);
while (moreSlots())
skip();
return s;
}
};
// Reads frame information in callstack order (that is, innermost frame to
// outermost frame).
template <AllowGC allowGC=CanGC>
class InlineFrameIteratorMaybeGC
{
const IonFrameIterator *frame_;
SnapshotIterator start_;
SnapshotIterator si_;
unsigned framesRead_;
typename MaybeRooted<JSFunction*, allowGC>::RootType callee_;
typename MaybeRooted<JSScript*, allowGC>::RootType script_;
jsbytecode *pc_;
uint32_t numActualArgs_;
private:
void findNextFrame();
public:
inline InlineFrameIteratorMaybeGC(JSContext *cx, const IonFrameIterator *iter);
inline InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter);
inline InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter);
bool more() const {
return frame_ && framesRead_ < start_.frameCount();
}
JSFunction *callee() const {
JS_ASSERT(callee_);
return callee_;
}
JSFunction *maybeCallee() const {
return callee_;
}
inline unsigned numActualArgs() const;
template <class Op>
inline void forEachCanonicalActualArg(JSContext *cx, Op op, unsigned start, unsigned count) const;
JSScript *script() const {
return script_;
}
jsbytecode *pc() const {
return pc_;
}
SnapshotIterator snapshotIterator() const {
return si_;
}
bool isFunctionFrame() const;
bool isConstructing() const;
inline JSObject *scopeChain() const;
inline JSObject *thisObject() const;
inline InlineFrameIteratorMaybeGC &operator++();
void dump() const;
void resetOn(const IonFrameIterator *iter);
private:
InlineFrameIteratorMaybeGC() MOZ_DELETE;
InlineFrameIteratorMaybeGC(const InlineFrameIteratorMaybeGC &iter) MOZ_DELETE;
};
typedef InlineFrameIteratorMaybeGC<CanGC> InlineFrameIterator;
typedef InlineFrameIteratorMaybeGC<NoGC> InlineFrameIteratorNoGC;
} // namespace jit
} // namespace js
#endif // JS_ION
#endif /* jit_IonFrameIterator_h */