Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(972)

Side by Side Diff: Source/wtf/StackStats.cpp

Issue 23668002: Avoid leaking ThreadingPrimitives.h from StackStats.h when collection is off. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/wtf/StackStats.h ('k') | Source/wtf/ThreadingPthreads.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2012 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 #include "config.h"
27 #include "StackStats.h"
28
29 #if ENABLE(STACK_STATS)
30
31 #include "Assertions.h"
32 #include "DataLog.h"
33 #include "WTFThreadData.h"
34
35 // Define the following flag if you want to collect stats on every single
36 // checkpoint. By default, we only log checkpoints that establish new
37 // max values.
38
39 // #define ENABLE_VERBOSE_STACK_STATS 1
40
41
42 namespace WTF {
43
44 // CheckPoint management:
45 Mutex* StackStats::s_sharedLock = 0;
46 StackStats::CheckPoint* StackStats::s_topCheckPoint = 0;
47 StackStats::LayoutCheckPoint* StackStats::s_firstLayoutCheckPoint = 0;
48 StackStats::LayoutCheckPoint* StackStats::s_topLayoutCheckPoint = 0;
49
50 // High watermark stats:
51 int StackStats::s_maxCheckPointDiff = 0;
52 int StackStats::s_maxStackHeight = 0;
53 int StackStats::s_maxReentryDepth = 0;
54
55 int StackStats::s_maxLayoutCheckPointDiff = 0;
56 int StackStats::s_maxTotalLayoutCheckPointDiff = 0;
57 int StackStats::s_maxLayoutReentryDepth = 0;
58
59
60 // Initializes locks and the log. Should only be called once.
61 void StackStats::initialize()
62 {
63 s_sharedLock = new Mutex();
64 dataLogF(" === LOG new stack stats ========\n");
65 }
66
67 StackStats::PerThreadStats::PerThreadStats()
68 {
69 const StackBounds& stack = wtfThreadData().stack();
70 m_reentryDepth = 0;
71 m_stackStart = (char*)stack.origin();
72 m_currentCheckPoint = 0;
73
74 dataLogF(" === THREAD new stackStart %p ========\n", m_stackStart);
75 }
76
77 StackStats::CheckPoint::CheckPoint()
78 {
79 MutexLocker locker(*StackStats::s_sharedLock);
80 WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
81 StackStats::PerThreadStats& t = threadData->stackStats();
82 const StackBounds& stack = threadData->stack();
83
84 bool needToLog = false;
85 char* current = reinterpret_cast<char*>(this);
86 char* last = reinterpret_cast<char*>(t.m_currentCheckPoint);
87
88 // If there was no previous checkpoint, measure from the start of the stack:
89 if (!last)
90 last = t.m_stackStart;
91
92 // Update the reentry depth stats:
93 t.m_reentryDepth++;
94 if (t.m_reentryDepth > StackStats::s_maxReentryDepth) {
95 StackStats::s_maxReentryDepth = t.m_reentryDepth;
96 needToLog = true;
97 }
98
99 // Update the stack height stats:
100 int height = t.m_stackStart - current;
101 if (height > StackStats::s_maxStackHeight) {
102 StackStats::s_maxStackHeight = height;
103 needToLog = true;
104 }
105
106 // Update the checkpoint diff stats:
107 int diff = last - current;
108 if (diff > StackStats::s_maxCheckPointDiff) {
109 StackStats::s_maxCheckPointDiff = diff;
110 needToLog = true;
111 }
112
113 // Push this checkpoint:
114 m_prev = t.m_currentCheckPoint;
115 t.m_currentCheckPoint = this;
116
117 #if ENABLE(VERBOSE_STACK_STATS)
118 needToLog = true; // always log.
119 #endif
120
121 // Log this checkpoint if needed:
122 if (needToLog)
123 dataLogF(" CHECKPOINT %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | h eight %.1fk/max %.1fk | stack %p size %.1fk\n",
124 this, diff, diff / 1024.0, StackStats::s_maxCheckPointDiff / 1024.0,
125 t.m_reentryDepth, StackStats::s_maxReentryDepth,
126 height / 1024.0, StackStats::s_maxStackHeight / 1024.0,
127 stack.origin(), stack.size() / 1024.0);
128 }
129
130 StackStats::CheckPoint::~CheckPoint()
131 {
132 MutexLocker locker(*StackStats::s_sharedLock);
133 WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
134 StackStats::PerThreadStats& t = threadData->stackStats();
135
136 // Pop to previous checkpoint:
137 t.m_currentCheckPoint = m_prev;
138 --t.m_reentryDepth;
139
140 // Log this checkpoint if needed:
141 #if ENABLE(VERBOSE_STACK_STATS)
142 if (!m_prev) {
143 const StackBounds& stack = threadData->stack();
144
145 char* current = reinterpret_cast<char*>(this);
146 int height = t.m_stackStart - current;
147
148 dataLogF(" POP to %p diff max %.1fk | reentry %d/%d max | height %.1fk/m ax %.1fk | stack %p size %.1fk)\n",
149 this, StackStats::s_maxCheckPointDiff / 1024.0,
150 t.m_reentryDepth, StackStats::s_maxReentryDepth,
151 height / 1024.0, StackStats::s_maxStackHeight / 1024.0,
152 stack.origin(), stack.size() / 1024.0);
153 }
154 #endif
155 }
156
157 void StackStats::probe()
158 {
159 MutexLocker locker(*StackStats::s_sharedLock);
160 WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
161 StackStats::PerThreadStats& t = threadData->stackStats();
162 const StackBounds& stack = threadData->stack();
163
164 bool needToLog = false;
165
166 int dummy;
167 char* current = reinterpret_cast<char*>(&dummy);
168 char* last = reinterpret_cast<char*>(t.m_currentCheckPoint);
169
170 // If there was no previous checkpoint, measure from the start of the stack:
171 if (!last)
172 last = t.m_stackStart;
173
174 // We did not reach another checkpoint yet. Hence, we do not touch the
175 // reentry stats.
176
177 // Update the stack height stats:
178 int height = t.m_stackStart - current;
179 if (height > StackStats::s_maxStackHeight) {
180 StackStats::s_maxStackHeight = height;
181 needToLog = true;
182 }
183
184 // Update the checkpoint diff stats:
185 int diff = last - current;
186 if (diff > StackStats::s_maxCheckPointDiff) {
187 StackStats::s_maxCheckPointDiff = diff;
188 needToLog = true;
189 }
190
191 #if ENABLE(VERBOSE_STACK_STATS)
192 needToLog = true; // always log.
193 #endif
194
195 if (needToLog)
196 dataLogF(" PROBE %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | height %.1fk/max %.1fk | stack %p size %.1fk\n",
197 current, diff, diff / 1024.0, StackStats::s_maxCheckPointDiff / 1024 .0,
198 t.m_reentryDepth, StackStats::s_maxReentryDepth,
199 height / 1024.0, StackStats::s_maxStackHeight / 1024.0,
200 stack.origin(), stack.size() / 1024.0);
201 }
202
203 StackStats::LayoutCheckPoint::LayoutCheckPoint()
204 {
205 // While a layout checkpoint is not necessarily a checkpoint where we
206 // we will do a recursion check, it is a convenient spot for doing a
207 // probe to measure the height of stack usage.
208 //
209 // We'll do this probe before we commence with the layout checkpoint.
210 // This is because the probe also locks the sharedLock. By calling the
211 // probe first, we can avoid re-entering the lock.
212 StackStats::probe();
213
214 MutexLocker locker(*StackStats::s_sharedLock);
215 WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
216 StackStats::PerThreadStats& t = threadData->stackStats();
217 const StackBounds& stack = threadData->stack();
218
219 // Push this checkpoint:
220 m_prev = StackStats::s_topLayoutCheckPoint;
221 if (m_prev)
222 m_depth = m_prev->m_depth + 1;
223 else {
224 StackStats::s_firstLayoutCheckPoint = this;
225 m_depth = 0;
226 }
227 StackStats::s_topLayoutCheckPoint = this;
228
229 //
230 char* current = reinterpret_cast<char*>(this);
231 char* last = reinterpret_cast<char*>(m_prev);
232 char* root = reinterpret_cast<char*>(StackStats::s_firstLayoutCheckPoint);
233 bool needToLog = false;
234
235 int diff = last - current;
236 if (!last)
237 diff = 0;
238 int totalDiff = root - current;
239 if (!root)
240 totalDiff = 0;
241
242 // Update the stack height stats:
243 int height = t.m_stackStart - current;
244 if (height > StackStats::s_maxStackHeight) {
245 StackStats::s_maxStackHeight = height;
246 needToLog = true;
247 }
248
249 // Update the layout checkpoint diff stats:
250 if (diff > StackStats::s_maxLayoutCheckPointDiff) {
251 StackStats::s_maxLayoutCheckPointDiff = diff;
252 needToLog = true;
253 }
254
255 // Update the total layout checkpoint diff stats:
256 if (totalDiff > StackStats::s_maxTotalLayoutCheckPointDiff) {
257 StackStats::s_maxTotalLayoutCheckPointDiff = totalDiff;
258 needToLog = true;
259 }
260
261 #if ENABLE(VERBOSE_STACK_STATS)
262 needToLog = true; // always log.
263 #endif
264
265 if (needToLog)
266 dataLogF(" LAYOUT %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | heigh t %.1fk/max %.1fk | stack %p size %.1fk\n",
267 current, diff, diff / 1024.0, StackStats::s_maxLayoutCheckPointDiff / 1024.0,
268 m_depth, StackStats::s_maxLayoutReentryDepth,
269 totalDiff / 1024.0, StackStats::s_maxTotalLayoutCheckPointDiff / 102 4.0,
270 stack.origin(), stack.size() / 1024.0);
271 }
272
273 StackStats::LayoutCheckPoint::~LayoutCheckPoint()
274 {
275 MutexLocker locker(*StackStats::s_sharedLock);
276
277 // Pop to the previous layout checkpoint:
278 StackStats::s_topLayoutCheckPoint = m_prev;
279 if (!m_depth)
280 StackStats::s_firstLayoutCheckPoint = 0;
281 }
282
283 } // namespace WTF
284
285 #endif // ENABLE(STACK_STATS)
286
OLDNEW
« no previous file with comments | « Source/wtf/StackStats.h ('k') | Source/wtf/ThreadingPthreads.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698