1/* 2 * Copyright (C) 2008, 2009, 2013, 2014 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 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 38namespace JSC { 39 40 class CodeBlockSet; 41 class ConservativeRoots; 42 class ExecState; 43 class JITStubRoutineSet; 44 class VM; 45 class LLIntOffsetsExtractor; 46 47 struct Instruction; 48 typedef ExecState CallFrame; 49 50 struct CallerFrameAndPC { 51 CallFrame* callerFrame; 52 Instruction* pc; 53 }; 54 55 class JSStack { 56 WTF_MAKE_NONCOPYABLE(JSStack); 57 public: 58 enum CallFrameHeaderEntry { 59 CallerFrameAndPCSize = sizeof(CallerFrameAndPC) / sizeof(Register), 60 CodeBlock = CallerFrameAndPCSize, 61 ScopeChain, 62 Callee, 63 ArgumentCount, 64 CallFrameHeaderSize, 65 66 // The following entries are not part of the CallFrameHeader but are provided here as a convenience: 67 ThisArgument = CallFrameHeaderSize, 68 FirstArgument, 69 }; 70 71 static const size_t commitSize = 16 * 1024; 72 // Allow 8k of excess registers before we start trying to reap the stack 73 static const ptrdiff_t maxExcessCapacity = 8 * 1024; 74 75 JSStack(VM&); 76 77 bool ensureCapacityFor(Register* newTopOfStack); 78 79 bool containsAddress(Register* address) { return (lowAddress() <= address && address < highAddress()); } 80 static size_t committedByteCount(); 81 82#if ENABLE(JIT) 83 void gatherConservativeRoots(ConservativeRoots&) { } 84 void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&) { } 85 void sanitizeStack() { } 86 static void initializeThreading() { } 87#else 88 ~JSStack(); 89 90 void gatherConservativeRoots(ConservativeRoots&); 91 void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&); 92 void sanitizeStack(); 93 94 Register* baseOfStack() const 95 { 96 return highAddress() - 1; 97 } 98 99 size_t size() const { return highAddress() - lowAddress(); } 100 101 static void initializeThreading(); 102 103 void setReservedZoneSize(size_t); 104 105 inline Register* topOfStack(); 106#endif // ENABLE(JIT) 107 108 private: 109 110#if !ENABLE(JIT) 111 Register* lowAddress() const 112 { 113 return m_end + 1; 114 } 115 116 Register* highAddress() const 117 { 118 return reinterpret_cast_ptr<Register*>(static_cast<char*>(m_reservation.base()) + m_reservation.size()); 119 } 120#else 121 Register* lowAddress() const; 122 Register* highAddress() const; 123#endif // !ENABLE(JIT) 124 125#if !ENABLE(JIT) 126 inline Register* topOfFrameFor(CallFrame*); 127 128 Register* reservationTop() const 129 { 130 char* reservationTop = static_cast<char*>(m_reservation.base()); 131 return reinterpret_cast_ptr<Register*>(reservationTop); 132 } 133 134 bool grow(Register* newTopOfStack); 135 bool growSlowCase(Register* newTopOfStack); 136 void shrink(Register* newTopOfStack); 137 void releaseExcessCapacity(); 138 void addToCommittedByteCount(long); 139 140 void setStackLimit(Register* newTopOfStack); 141#endif // !ENABLE(JIT) 142 143 VM& m_vm; 144 CallFrame*& m_topCallFrame; 145#if !ENABLE(JIT) 146 Register* m_end; 147 Register* m_commitTop; 148 PageReservation m_reservation; 149 Register* m_lastStackTop; 150 ptrdiff_t m_reservedZoneSizeInRegisters; 151#endif // !ENABLE(JIT) 152 153 friend class LLIntOffsetsExtractor; 154 }; 155 156} // namespace JSC 157 158#endif // JSStack_h 159