#ifndef JSStack_h
#define JSStack_h
#include "ExecutableAllocator.h"
#include "Register.h"
#include <wtf/Noncopyable.h>
#include <wtf/PageReservation.h>
#include <wtf/VMTags.h>
namespace JSC {
class CodeBlockSet;
class ConservativeRoots;
class ExecState;
class JITStubRoutineSet;
class VM;
class LLIntOffsetsExtractor;
struct Instruction;
typedef ExecState CallFrame;
struct CallerFrameAndPC {
CallFrame* callerFrame;
Instruction* pc;
};
class JSStack {
WTF_MAKE_NONCOPYABLE(JSStack);
public:
enum CallFrameHeaderEntry {
CallerFrameAndPCSize = sizeof(CallerFrameAndPC) / sizeof(Register),
CodeBlock = CallerFrameAndPCSize,
ScopeChain,
Callee,
ArgumentCount,
CallFrameHeaderSize,
ThisArgument = CallFrameHeaderSize,
FirstArgument,
};
static const size_t commitSize = 16 * 1024;
static const ptrdiff_t maxExcessCapacity = 8 * 1024;
JSStack(VM&);
bool ensureCapacityFor(Register* newTopOfStack);
bool containsAddress(Register* address) { return (lowAddress() <= address && address < highAddress()); }
static size_t committedByteCount();
#if ENABLE(JIT)
void gatherConservativeRoots(ConservativeRoots&) { }
void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&) { }
void sanitizeStack() { }
static void initializeThreading() { }
#else
~JSStack();
void gatherConservativeRoots(ConservativeRoots&);
void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&);
void sanitizeStack();
Register* baseOfStack() const
{
return highAddress() - 1;
}
size_t size() const { return highAddress() - lowAddress(); }
static void initializeThreading();
void setReservedZoneSize(size_t);
inline Register* topOfStack();
#endif // ENABLE(JIT)
private:
#if !ENABLE(JIT)
Register* lowAddress() const
{
return m_end + 1;
}
Register* highAddress() const
{
return reinterpret_cast_ptr<Register*>(static_cast<char*>(m_reservation.base()) + m_reservation.size());
}
#else
Register* lowAddress() const;
Register* highAddress() const;
#endif // !ENABLE(JIT)
#if !ENABLE(JIT)
inline Register* topOfFrameFor(CallFrame*);
Register* reservationTop() const
{
char* reservationTop = static_cast<char*>(m_reservation.base());
return reinterpret_cast_ptr<Register*>(reservationTop);
}
bool grow(Register* newTopOfStack);
bool growSlowCase(Register* newTopOfStack);
void shrink(Register* newTopOfStack);
void releaseExcessCapacity();
void addToCommittedByteCount(long);
void setStackLimit(Register* newTopOfStack);
#endif // !ENABLE(JIT)
VM& m_vm;
CallFrame*& m_topCallFrame;
#if !ENABLE(JIT)
Register* m_end;
Register* m_commitTop;
PageReservation m_reservation;
Register* m_lastStackTop;
ptrdiff_t m_reservedZoneSizeInRegisters;
#endif // !ENABLE(JIT)
friend class LLIntOffsetsExtractor;
};
}
#endif // JSStack_h