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

Side by Side Diff: src/frames.cc

Issue 50052: Support profiler stack sampling in any situation. (Closed)
Patch Set: Fixes according to comments Created 11 years, 9 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
« no previous file with comments | « src/frames.h ('k') | src/frames-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 StackHandler* handler_; 59 StackHandler* handler_;
60 }; 60 };
61 61
62 62
63 // ------------------------------------------------------------------------- 63 // -------------------------------------------------------------------------
64 64
65 65
66 #define INITIALIZE_SINGLETON(type, field) field##_(this), 66 #define INITIALIZE_SINGLETON(type, field) field##_(this),
67 StackFrameIterator::StackFrameIterator() 67 StackFrameIterator::StackFrameIterator()
68 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 68 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
69 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) { 69 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
70 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
70 Reset(); 71 Reset();
71 } 72 }
72 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) 73 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
73 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 74 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
74 frame_(NULL), handler_(NULL), thread_(t) { 75 frame_(NULL), handler_(NULL), thread_(t),
76 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
75 Reset(); 77 Reset();
76 } 78 }
77 StackFrameIterator::StackFrameIterator(bool reset) 79 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
78 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 80 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
79 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) { 81 frame_(NULL), handler_(NULL),
80 if (reset) Reset(); 82 thread_(use_top ? Top::GetCurrentThread() : NULL),
83 fp_(use_top ? NULL : fp), sp_(sp),
84 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
85 &StackFrameIterator::AdvanceWithoutHandler) {
86 if (use_top || fp != NULL) {
87 Reset();
88 }
81 } 89 }
90
82 #undef INITIALIZE_SINGLETON 91 #undef INITIALIZE_SINGLETON
83 92
84 93
85 void StackFrameIterator::Advance() { 94 void StackFrameIterator::AdvanceWithHandler() {
86 ASSERT(!done()); 95 ASSERT(!done());
87 // Compute the state of the calling frame before restoring 96 // Compute the state of the calling frame before restoring
88 // callee-saved registers and unwinding handlers. This allows the 97 // callee-saved registers and unwinding handlers. This allows the
89 // frame code that computes the caller state to access the top 98 // frame code that computes the caller state to access the top
90 // handler and the value of any callee-saved register if needed. 99 // handler and the value of any callee-saved register if needed.
91 StackFrame::State state; 100 StackFrame::State state;
92 StackFrame::Type type = frame_->GetCallerState(&state); 101 StackFrame::Type type = frame_->GetCallerState(&state);
93 102
94 // Unwind handlers corresponding to the current frame. 103 // Unwind handlers corresponding to the current frame.
95 StackHandlerIterator it(frame_, handler_); 104 StackHandlerIterator it(frame_, handler_);
96 while (!it.done()) it.Advance(); 105 while (!it.done()) it.Advance();
97 handler_ = it.handler(); 106 handler_ = it.handler();
98 107
99 // Advance to the calling frame. 108 // Advance to the calling frame.
100 frame_ = SingletonFor(type, &state); 109 frame_ = SingletonFor(type, &state);
101 110
102 // When we're done iterating over the stack frames, the handler 111 // When we're done iterating over the stack frames, the handler
103 // chain must have been completely unwound. 112 // chain must have been completely unwound.
104 ASSERT(!done() || handler_ == NULL); 113 ASSERT(!done() || handler_ == NULL);
105 } 114 }
106 115
107 116
117 void StackFrameIterator::AdvanceWithoutHandler() {
118 // A simpler version of Advance which doesn't care about handler.
119 ASSERT(!done());
120 StackFrame::State state;
121 StackFrame::Type type = frame_->GetCallerState(&state);
122 frame_ = SingletonFor(type, &state);
123 }
124
125
108 void StackFrameIterator::Reset() { 126 void StackFrameIterator::Reset() {
109 Address fp = Top::c_entry_fp(thread_);
110 StackFrame::State state; 127 StackFrame::State state;
111 StackFrame::Type type = ExitFrame::GetStateForFramePointer(fp, &state); 128 StackFrame::Type type;
129 if (thread_ != NULL) {
130 type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
131 handler_ = StackHandler::FromAddress(Top::handler(thread_));
132 } else {
133 ASSERT(fp_ != NULL);
134 state.fp = fp_;
135 state.sp = sp_;
136 state.pc_address =
137 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
138 type = StackFrame::ComputeType(&state);
139 if (SingletonFor(type) == NULL) return;
140 }
112 frame_ = SingletonFor(type, &state); 141 frame_ = SingletonFor(type, &state);
113 handler_ = StackHandler::FromAddress(Top::handler(thread_));
114 } 142 }
115 143
116 144
117 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, 145 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
118 StackFrame::State* state) { 146 StackFrame::State* state) {
147 if (type == StackFrame::NONE) return NULL;
148 StackFrame* result = SingletonFor(type);
149 ASSERT(result != NULL);
150 result->state_ = *state;
151 return result;
152 }
153
154
155 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
119 #define FRAME_TYPE_CASE(type, field) \ 156 #define FRAME_TYPE_CASE(type, field) \
120 case StackFrame::type: result = &field##_; break; 157 case StackFrame::type: result = &field##_; break;
121 158
122 StackFrame* result = NULL; 159 StackFrame* result = NULL;
123 switch (type) { 160 switch (type) {
124 case StackFrame::NONE: return NULL; 161 case StackFrame::NONE: return NULL;
125 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 162 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
126 default: break; 163 default: break;
127 } 164 }
128 ASSERT(result != NULL);
129 result->state_ = *state;
130 return result; 165 return result;
131 166
132 #undef FRAME_TYPE_CASE 167 #undef FRAME_TYPE_CASE
133 } 168 }
134 169
135 170
136 // ------------------------------------------------------------------------- 171 // -------------------------------------------------------------------------
137 172
138 173
139 StackTraceFrameIterator::StackTraceFrameIterator() { 174 StackTraceFrameIterator::StackTraceFrameIterator() {
140 if (!done() && !frame()->function()->IsJSFunction()) Advance(); 175 if (!done() && !frame()->function()->IsJSFunction()) Advance();
141 } 176 }
142 177
143 178
144 void StackTraceFrameIterator::Advance() { 179 void StackTraceFrameIterator::Advance() {
145 while (true) { 180 while (true) {
146 JavaScriptFrameIterator::Advance(); 181 JavaScriptFrameIterator::Advance();
147 if (done()) return; 182 if (done()) return;
148 if (frame()->function()->IsJSFunction()) return; 183 if (frame()->function()->IsJSFunction()) return;
149 } 184 }
150 } 185 }
151 186
152 187
153 // ------------------------------------------------------------------------- 188 // -------------------------------------------------------------------------
154 189
155 190
156 SafeStackFrameIterator::SafeStackFrameIterator( 191 SafeStackFrameIterator::SafeStackFrameIterator(
157 Address low_bound, Address high_bound) : 192 Address fp, Address sp, Address low_bound, Address high_bound) :
158 low_bound_(low_bound), high_bound_(high_bound), 193 low_bound_(low_bound), high_bound_(high_bound),
159 is_working_iterator_(IsInBounds(low_bound, high_bound, 194 is_valid_top_(
160 Top::c_entry_fp(Top::GetCurrentThread()))), 195 IsWithinBounds(low_bound, high_bound,
161 iteration_done_(!is_working_iterator_), iterator_(is_working_iterator_) { 196 Top::c_entry_fp(Top::GetCurrentThread())) &&
197 Top::handler(Top::GetCurrentThread()) != NULL),
198 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
199 is_working_iterator_(is_valid_top_ || is_valid_fp_),
200 iteration_done_(!is_working_iterator_),
201 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
162 } 202 }
163 203
164 204
165 void SafeStackFrameIterator::Advance() { 205 void SafeStackFrameIterator::Advance() {
166 ASSERT(is_working_iterator_); 206 ASSERT(is_working_iterator_);
167 ASSERT(!done()); 207 ASSERT(!done());
168 StackFrame* frame = iterator_.frame(); 208 StackFrame* last_frame = iterator_.frame();
169 iteration_done_ = 209 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
170 !IsGoodStackAddress(frame->sp()) || !IsGoodStackAddress(frame->fp()); 210 // Before advancing to the next stack frame, perform pointer validity tests
171 if (!iteration_done_) { 211 iteration_done_ = !IsValidFrame(last_frame) || !IsValidCaller(last_frame);
172 iterator_.Advance(); 212 if (iteration_done_) return;
173 if (!iterator_.done()) { 213
174 // Check that we have actually moved to the previous frame in the stack 214 iterator_.Advance();
175 StackFrame* prev_frame = iterator_.frame(); 215 if (iterator_.done()) return;
176 iteration_done_ = 216 // Check that we have actually moved to the previous frame in the stack
177 prev_frame->sp() < frame->sp() || prev_frame->fp() < frame->fp(); 217 StackFrame* prev_frame = iterator_.frame();
178 } 218 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
179 }
180 } 219 }
181 220
182 221
222 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
223 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()) &&
224 // JavaScriptFrame uses function shared info to advance, hence it must
225 // point to a valid function object.
226 (!frame->is_java_script() ||
227 reinterpret_cast<JavaScriptFrame*>(frame)->is_at_function());
228 }
229
230
231 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
232 StackFrame::State state;
233 frame->ComputeCallerState(&state);
234 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
235 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
236 }
237
238
183 void SafeStackFrameIterator::Reset() { 239 void SafeStackFrameIterator::Reset() {
184 if (is_working_iterator_) { 240 if (is_working_iterator_) {
185 iterator_.Reset(); 241 iterator_.Reset();
186 iteration_done_ = false; 242 iteration_done_ = false;
187 } 243 }
188 } 244 }
189 245
190 246
191 // ------------------------------------------------------------------------- 247 // -------------------------------------------------------------------------
192 248
193 249
194 #ifdef ENABLE_LOGGING_AND_PROFILING 250 #ifdef ENABLE_LOGGING_AND_PROFILING
195 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( 251 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
196 Address low_bound, Address high_bound) : 252 Address fp, Address sp, Address low_bound, Address high_bound) :
197 SafeJavaScriptFrameIterator(low_bound, high_bound) { 253 SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
198 if (!done() && !frame()->function()->IsJSFunction()) Advance(); 254 if (!done() && !frame()->is_at_function()) Advance();
199 } 255 }
200 256
201 257
202 void SafeStackTraceFrameIterator::Advance() { 258 void SafeStackTraceFrameIterator::Advance() {
203 while (true) { 259 while (true) {
204 SafeJavaScriptFrameIterator::Advance(); 260 SafeJavaScriptFrameIterator::Advance();
205 if (done()) return; 261 if (done()) return;
206 if (frame()->function()->IsJSFunction()) return; 262 if (frame()->is_at_function()) return;
207 } 263 }
208 } 264 }
209 #endif 265 #endif
210 266
211 267
212 // ------------------------------------------------------------------------- 268 // -------------------------------------------------------------------------
213 269
214 270
215 void StackHandler::Cook(Code* code) { 271 void StackHandler::Cook(Code* code) {
216 ASSERT(MarkCompactCollector::IsCompacting()); 272 ASSERT(MarkCompactCollector::IsCompacting());
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 void StackFrame::Uncook() { 328 void StackFrame::Uncook() {
273 Code* code = this->code(); 329 Code* code = this->code();
274 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { 330 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
275 it.handler()->Uncook(code); 331 it.handler()->Uncook(code);
276 } 332 }
277 set_pc(code->instruction_start() + OffsetFrom(pc())); 333 set_pc(code->instruction_start() + OffsetFrom(pc()));
278 ASSERT(code->contains(pc())); 334 ASSERT(code->contains(pc()));
279 } 335 }
280 336
281 337
338 StackFrame::Type StackFrame::GetCallerState(State* state) const {
339 ComputeCallerState(state);
340 return ComputeType(state);
341 }
342
343
282 Code* EntryFrame::code() const { 344 Code* EntryFrame::code() const {
283 return Heap::js_entry_code(); 345 return Heap::js_entry_code();
284 } 346 }
285 347
286 348
349 void EntryFrame::ComputeCallerState(State* state) const {
350 GetCallerState(state);
351 }
352
353
287 StackFrame::Type EntryFrame::GetCallerState(State* state) const { 354 StackFrame::Type EntryFrame::GetCallerState(State* state) const {
288 const int offset = EntryFrameConstants::kCallerFPOffset; 355 const int offset = EntryFrameConstants::kCallerFPOffset;
289 Address fp = Memory::Address_at(this->fp() + offset); 356 Address fp = Memory::Address_at(this->fp() + offset);
290 return ExitFrame::GetStateForFramePointer(fp, state); 357 return ExitFrame::GetStateForFramePointer(fp, state);
291 } 358 }
292 359
293 360
294 Code* EntryConstructFrame::code() const { 361 Code* EntryConstructFrame::code() const {
295 return Heap::js_construct_entry_code(); 362 return Heap::js_construct_entry_code();
296 } 363 }
297 364
298 365
299 Code* ExitFrame::code() const { 366 Code* ExitFrame::code() const {
300 return Heap::c_entry_code(); 367 return Heap::c_entry_code();
301 } 368 }
302 369
303 370
304 StackFrame::Type ExitFrame::GetCallerState(State* state) const { 371 void ExitFrame::ComputeCallerState(State* state) const {
305 // Setup the caller state. 372 // Setup the caller state.
306 state->sp = pp(); 373 state->sp = pp();
307 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); 374 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
308 state->pc_address 375 state->pc_address
309 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); 376 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
310 return ComputeType(state);
311 } 377 }
312 378
313 379
314 Address ExitFrame::GetCallerStackPointer() const { 380 Address ExitFrame::GetCallerStackPointer() const {
315 return fp() + ExitFrameConstants::kPPDisplacement; 381 return fp() + ExitFrameConstants::kPPDisplacement;
316 } 382 }
317 383
318 384
319 Code* ExitDebugFrame::code() const { 385 Code* ExitDebugFrame::code() const {
320 return Heap::c_entry_debug_break_code(); 386 return Heap::c_entry_debug_break_code();
(...skipping 10 matching lines...) Expand all
331 const int offset = 397 const int offset =
332 StandardFrameConstants::kExpressionsOffset + kPointerSize; 398 StandardFrameConstants::kExpressionsOffset + kPointerSize;
333 Address base = fp() + offset; 399 Address base = fp() + offset;
334 Address limit = sp(); 400 Address limit = sp();
335 ASSERT(base >= limit); // stack grows downwards 401 ASSERT(base >= limit); // stack grows downwards
336 // Include register-allocated locals in number of expressions. 402 // Include register-allocated locals in number of expressions.
337 return (base - limit) / kPointerSize; 403 return (base - limit) / kPointerSize;
338 } 404 }
339 405
340 406
341 StackFrame::Type StandardFrame::GetCallerState(State* state) const { 407 void StandardFrame::ComputeCallerState(State* state) const {
342 state->sp = caller_sp(); 408 state->sp = caller_sp();
343 state->fp = caller_fp(); 409 state->fp = caller_fp();
344 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp())); 410 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
345 return ComputeType(state);
346 } 411 }
347 412
348 413
349 bool StandardFrame::IsExpressionInsideHandler(int n) const { 414 bool StandardFrame::IsExpressionInsideHandler(int n) const {
350 Address address = GetExpressionAddress(n); 415 Address address = GetExpressionAddress(n);
351 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { 416 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
352 if (it.handler()->includes(address)) return true; 417 if (it.handler()->includes(address)) return true;
353 } 418 }
354 return false; 419 return false;
355 } 420 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 reg_code[i++] = r; 704 reg_code[i++] = r;
640 705
641 ASSERT(i == kNumJSCallerSaved); 706 ASSERT(i == kNumJSCallerSaved);
642 } 707 }
643 ASSERT(0 <= n && n < kNumJSCallerSaved); 708 ASSERT(0 <= n && n < kNumJSCallerSaved);
644 return reg_code[n]; 709 return reg_code[n];
645 } 710 }
646 711
647 712
648 } } // namespace v8::internal 713 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/frames-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698