1/*
2 * Copyright (C) 2010, 2013 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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27#ifndef StackBounds_h
28#define StackBounds_h
29
30#include <algorithm>
31
32namespace WTF {
33
34class StackBounds {
35 // This 64k number was picked because a sampling of stack usage differences
36 // between consecutive entries into one of the Interpreter::execute...()
37 // functions was seen to be as high as 27k. Hence, 64k is chosen as a
38 // conservative availability value that is not too large but comfortably
39 // exceeds 27k with some buffer for error.
40 const static size_t s_defaultAvailabilityDelta = 64 * 1024;
41
42public:
43 static StackBounds currentThreadStackBounds()
44 {
45 StackBounds bounds;
46 bounds.initialize();
47 bounds.checkConsistency();
48 return bounds;
49 }
50
51 void* origin() const
52 {
53 ASSERT(m_origin);
54 return m_origin;
55 }
56
57 void* end() const
58 {
59 ASSERT(m_bound);
60 return m_bound;
61 }
62
63 size_t size() const
64 {
65 if (isGrowingDownward())
66 return static_cast<char*>(m_origin) - static_cast<char*>(m_bound);
67 return static_cast<char*>(m_bound) - static_cast<char*>(m_origin);
68 }
69
70 void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
71 {
72 checkConsistency();
73 if (isGrowingDownward())
74 return static_cast<char*>(m_bound) + minAvailableDelta;
75 return static_cast<char*>(m_bound) - minAvailableDelta;
76 }
77
78 void* recursionLimit(char* startOfUserStack, size_t maxUserStack, size_t reservedZoneSize) const
79 {
80 checkConsistency();
81 if (maxUserStack < reservedZoneSize)
82 reservedZoneSize = maxUserStack;
83 size_t maxUserStackWithReservedZone = maxUserStack - reservedZoneSize;
84
85 if (isGrowingDownward()) {
86 char* endOfStackWithReservedZone = reinterpret_cast<char*>(m_bound) + reservedZoneSize;
87 if (startOfUserStack < endOfStackWithReservedZone)
88 return endOfStackWithReservedZone;
89 size_t availableUserStack = startOfUserStack - endOfStackWithReservedZone;
90 if (maxUserStackWithReservedZone > availableUserStack)
91 maxUserStackWithReservedZone = availableUserStack;
92 return startOfUserStack - maxUserStackWithReservedZone;
93 }
94
95 char* endOfStackWithReservedZone = reinterpret_cast<char*>(m_bound) - reservedZoneSize;
96 if (startOfUserStack > endOfStackWithReservedZone)
97 return endOfStackWithReservedZone;
98 size_t availableUserStack = endOfStackWithReservedZone - startOfUserStack;
99 if (maxUserStackWithReservedZone > availableUserStack)
100 maxUserStackWithReservedZone = availableUserStack;
101 return startOfUserStack + maxUserStackWithReservedZone;
102 }
103
104 bool isGrowingDownward() const
105 {
106 ASSERT(m_origin && m_bound);
107 return true;
108 }
109
110private:
111 StackBounds()
112 : m_origin(0)
113 , m_bound(0)
114 {
115 }
116
117 WTF_EXPORT_PRIVATE void initialize();
118
119 void checkConsistency() const
120 {
121#if !ASSERT_DISABLED
122 void* currentPosition = &currentPosition;
123 ASSERT(m_origin != m_bound);
124 ASSERT(isGrowingDownward()
125 ? (currentPosition < m_origin && currentPosition > m_bound)
126 : (currentPosition > m_origin && currentPosition < m_bound));
127#endif
128 }
129
130 void* m_origin;
131 void* m_bound;
132
133 friend class StackStats;
134};
135
136} // namespace WTF
137
138using WTF::StackBounds;
139
140#endif
141