1/* 2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#ifndef JSStack_h 30#define JSStack_h 31 32#include "ExecutableAllocator.h" 33#include "Register.h" 34#include <wtf/Noncopyable.h> 35#include <wtf/PageReservation.h> 36#include <wtf/VMTags.h> 37 38#if !defined(NDEBUG) && !defined(ENABLE_DEBUG_JSSTACK) 39#define ENABLE_DEBUG_JSSTACK 1 40#endif 41 42namespace JSC { 43 44 class ConservativeRoots; 45 class DFGCodeBlocks; 46 class ExecState; 47 class JITStubRoutineSet; 48 class VM; 49 class LLIntOffsetsExtractor; 50 51 class JSStack { 52 WTF_MAKE_NONCOPYABLE(JSStack); 53 public: 54 enum CallFrameHeaderEntry { 55 CallFrameHeaderSize = 6, 56 57 ArgumentCount = -6, 58 CallerFrame = -5, 59 Callee = -4, 60 ScopeChain = -3, 61 ReturnPC = -2, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. 62 CodeBlock = -1, 63 }; 64 65 static const size_t defaultCapacity = 512 * 1024; 66 static const size_t commitSize = 16 * 1024; 67 // Allow 8k of excess registers before we start trying to reap the stack 68 static const ptrdiff_t maxExcessCapacity = 8 * 1024; 69 70 JSStack(VM&, size_t capacity = defaultCapacity); 71 ~JSStack(); 72 73 void gatherConservativeRoots(ConservativeRoots&); 74 void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, DFGCodeBlocks&); 75 76 Register* begin() const { return static_cast<Register*>(m_reservation.base()); } 77 Register* end() const { return m_end; } 78 size_t size() const { return end() - begin(); } 79 80 bool grow(Register*); 81 82 static size_t committedByteCount(); 83 static void initializeThreading(); 84 85 Register* const * addressOfEnd() const 86 { 87 return &m_end; 88 } 89 90 Register* getTopOfFrame(CallFrame*); 91 Register* getStartOfFrame(CallFrame*); 92 Register* getTopOfStack(); 93 94 CallFrame* pushFrame(CallFrame* callerFrame, class CodeBlock*, 95 JSScope*, int argsCount, JSObject* callee); 96 97 void popFrame(CallFrame*); 98 99 void enableErrorStackReserve(); 100 void disableErrorStackReserve(); 101 102#if ENABLE(DEBUG_JSSTACK) 103 void installFence(CallFrame*, const char *function = "", int lineNo = 0); 104 void validateFence(CallFrame*, const char *function = "", int lineNo = 0); 105 static const int FenceSize = 4; 106#else // !ENABLE(DEBUG_JSSTACK) 107 void installFence(CallFrame*, const char* = "", int = 0) { } 108 void validateFence(CallFrame*, const char* = "", int = 0) { } 109#endif // !ENABLE(DEBUG_JSSTACK) 110 111 private: 112 Register* reservationEnd() const 113 { 114 char* base = static_cast<char*>(m_reservation.base()); 115 char* reservationEnd = base + m_reservation.size(); 116 return reinterpret_cast_ptr<Register*>(reservationEnd); 117 } 118 119#if ENABLE(DEBUG_JSSTACK) 120 static JSValue generateFenceValue(size_t argIndex); 121 void installTrapsAfterFrame(CallFrame*); 122#else 123 void installTrapsAfterFrame(CallFrame*) { } 124#endif 125 126 bool growSlowCase(Register*); 127 void shrink(Register*); 128 void releaseExcessCapacity(); 129 void addToCommittedByteCount(long); 130 131 Register* m_end; 132 Register* m_commitEnd; 133 Register* m_useableEnd; 134 PageReservation m_reservation; 135 CallFrame*& m_topCallFrame; 136 137 friend class LLIntOffsetsExtractor; 138 }; 139 140 inline void JSStack::shrink(Register* newEnd) 141 { 142 if (newEnd >= m_end) 143 return; 144 m_end = newEnd; 145 if (m_end == m_reservation.base() && (m_commitEnd - begin()) >= maxExcessCapacity) 146 releaseExcessCapacity(); 147 } 148 149 inline bool JSStack::grow(Register* newEnd) 150 { 151 if (newEnd <= m_end) 152 return true; 153 return growSlowCase(newEnd); 154 } 155 156} // namespace JSC 157 158#endif // JSStack_h 159