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

Side by Side Diff: src/frames.cc

Issue 17819003: Extract StackFrameIteratorBase (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 7 years, 5 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 | « src/frames.h ('k') | src/frames-inl.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 private: 81 private:
82 const Address limit_; 82 const Address limit_;
83 StackHandler* handler_; 83 StackHandler* handler_;
84 }; 84 };
85 85
86 86
87 // ------------------------------------------------------------------------- 87 // -------------------------------------------------------------------------
88 88
89 89
90 #define INITIALIZE_SINGLETON(type, field) field##_(this), 90 #define INITIALIZE_SINGLETON(type, field) field##_(this),
91 StackFrameIterator::StackFrameIterator(Isolate* isolate) 91 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
92 bool can_access_heap_objects)
92 : isolate_(isolate), 93 : isolate_(isolate),
93 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 94 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
94 frame_(NULL), handler_(NULL), 95 frame_(NULL), handler_(NULL),
95 thread_(isolate_->thread_local_top()), 96 can_access_heap_objects_(can_access_heap_objects) {
96 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler),
97 can_access_heap_objects_(true) {
98 Reset();
99 } 97 }
100 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
101 : isolate_(isolate),
102 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
103 frame_(NULL), handler_(NULL), thread_(t),
104 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler),
105 can_access_heap_objects_(true) {
106 Reset();
107 }
108 StackFrameIterator::StackFrameIterator(Isolate* isolate,
109 bool use_top, Address fp, Address sp)
110 : isolate_(isolate),
111 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
112 frame_(NULL), handler_(NULL),
113 thread_(use_top ? isolate_->thread_local_top() : NULL),
114 fp_(use_top ? NULL : fp), sp_(sp),
115 advance_(&StackFrameIterator::AdvanceWithoutHandler),
116 can_access_heap_objects_(false) {
117 if (use_top || fp != NULL) {
118 Reset();
119 }
120 }
121
122 #undef INITIALIZE_SINGLETON 98 #undef INITIALIZE_SINGLETON
123 99
124 100
125 void StackFrameIterator::AdvanceWithHandler() { 101 StackFrameIterator::StackFrameIterator(Isolate* isolate)
102 : StackFrameIteratorBase(isolate, true) {
103 Reset(isolate->thread_local_top());
104 }
105
106
107 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
108 : StackFrameIteratorBase(isolate, true) {
109 Reset(t);
110 }
111
112
113 void StackFrameIterator::Advance() {
126 ASSERT(!done()); 114 ASSERT(!done());
127 // Compute the state of the calling frame before restoring 115 // Compute the state of the calling frame before restoring
128 // callee-saved registers and unwinding handlers. This allows the 116 // callee-saved registers and unwinding handlers. This allows the
129 // frame code that computes the caller state to access the top 117 // frame code that computes the caller state to access the top
130 // handler and the value of any callee-saved register if needed. 118 // handler and the value of any callee-saved register if needed.
131 StackFrame::State state; 119 StackFrame::State state;
132 StackFrame::Type type = frame_->GetCallerState(&state); 120 StackFrame::Type type = frame_->GetCallerState(&state);
133 121
134 // Unwind handlers corresponding to the current frame. 122 // Unwind handlers corresponding to the current frame.
135 StackHandlerIterator it(frame_, handler_); 123 StackHandlerIterator it(frame_, handler_);
136 while (!it.done()) it.Advance(); 124 while (!it.done()) it.Advance();
137 handler_ = it.handler(); 125 handler_ = it.handler();
138 126
139 // Advance to the calling frame. 127 // Advance to the calling frame.
140 frame_ = SingletonFor(type, &state); 128 frame_ = SingletonFor(type, &state);
141 129
142 // When we're done iterating over the stack frames, the handler 130 // When we're done iterating over the stack frames, the handler
143 // chain must have been completely unwound. 131 // chain must have been completely unwound.
144 ASSERT(!done() || handler_ == NULL); 132 ASSERT(!done() || handler_ == NULL);
145 } 133 }
146 134
147 135
148 void StackFrameIterator::AdvanceWithoutHandler() { 136 void StackFrameIterator::Reset(ThreadLocalTop* top) {
149 // A simpler version of Advance which doesn't care about handler.
150 ASSERT(!done());
151 StackFrame::State state; 137 StackFrame::State state;
152 StackFrame::Type type = frame_->GetCallerState(&state); 138 StackFrame::Type type = ExitFrame::GetStateForFramePointer(
153 frame_ = SingletonFor(type, &state); 139 Isolate::c_entry_fp(top), &state);
154 } 140 handler_ = StackHandler::FromAddress(Isolate::handler(top));
155
156
157 void StackFrameIterator::Reset() {
158 StackFrame::State state;
159 StackFrame::Type type;
160 if (thread_ != NULL) {
161 type = ExitFrame::GetStateForFramePointer(
162 Isolate::c_entry_fp(thread_), &state);
163 handler_ = StackHandler::FromAddress(
164 Isolate::handler(thread_));
165 } else {
166 ASSERT(fp_ != NULL);
167 state.fp = fp_;
168 state.sp = sp_;
169 state.pc_address = ResolveReturnAddressLocation(
170 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
171 type = StackFrame::ComputeType(this, &state);
172 }
173 if (SingletonFor(type) == NULL) return; 141 if (SingletonFor(type) == NULL) return;
174 frame_ = SingletonFor(type, &state); 142 frame_ = SingletonFor(type, &state);
175 } 143 }
176 144
177 145
178 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, 146 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
179 StackFrame::State* state) { 147 StackFrame::State* state) {
180 if (type == StackFrame::NONE) return NULL; 148 if (type == StackFrame::NONE) return NULL;
181 StackFrame* result = SingletonFor(type); 149 StackFrame* result = SingletonFor(type);
182 ASSERT(result != NULL); 150 ASSERT(result != NULL);
183 result->state_ = *state; 151 result->state_ = *state;
184 return result; 152 return result;
185 } 153 }
186 154
187 155
188 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) { 156 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
189 #define FRAME_TYPE_CASE(type, field) \ 157 #define FRAME_TYPE_CASE(type, field) \
190 case StackFrame::type: result = &field##_; break; 158 case StackFrame::type: result = &field##_; break;
191 159
192 StackFrame* result = NULL; 160 StackFrame* result = NULL;
193 switch (type) { 161 switch (type) {
194 case StackFrame::NONE: return NULL; 162 case StackFrame::NONE: return NULL;
195 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 163 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
196 default: break; 164 default: break;
197 } 165 }
198 return result; 166 return result;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 Object* script = JSFunction::cast(frame()->function())->shared()->script(); 218 Object* script = JSFunction::cast(frame()->function())->shared()->script();
251 // Don't show functions from native scripts to user. 219 // Don't show functions from native scripts to user.
252 return (script->IsScript() && 220 return (script->IsScript() &&
253 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); 221 Script::TYPE_NATIVE != Script::cast(script)->type()->value());
254 } 222 }
255 223
256 224
257 // ------------------------------------------------------------------------- 225 // -------------------------------------------------------------------------
258 226
259 227
260 bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
261 if (!validator_.IsValid(fp)) return false;
262 Address sp = ExitFrame::ComputeStackPointer(fp);
263 if (!validator_.IsValid(sp)) return false;
264 StackFrame::State state;
265 ExitFrame::FillState(fp, sp, &state);
266 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
267 return false;
268 }
269 return *state.pc_address != NULL;
270 }
271
272
273 SafeStackFrameIterator::SafeStackFrameIterator( 228 SafeStackFrameIterator::SafeStackFrameIterator(
274 Isolate* isolate, 229 Isolate* isolate,
275 Address fp, Address sp, Address low_bound, Address high_bound) : 230 Address fp, Address sp, Address low_bound, Address high_bound) :
276 stack_validator_(low_bound, high_bound), 231 StackFrameIteratorBase(isolate, false),
277 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)), 232 low_bound_(low_bound), high_bound_(high_bound) {
278 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), 233 StackFrame::State state;
279 iteration_done_(!is_valid_top_ && !is_valid_fp_), 234 StackFrame::Type type;
280 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { 235 ThreadLocalTop* top = isolate->thread_local_top();
236 if (IsValidTop(top)) {
237 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
238 } else if (IsValidStackAddress(fp)) {
239 ASSERT(fp != NULL);
240 state.fp = fp;
241 state.sp = sp;
242 state.pc_address = ResolveReturnAddressLocation(
243 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
244 type = StackFrame::ComputeType(this, &state);
245 } else {
246 return;
247 }
248 if (SingletonFor(type) == NULL) return;
249 frame_ = SingletonFor(type, &state);
250
281 if (!done()) Advance(); 251 if (!done()) Advance();
282 } 252 }
283 253
284 254
285 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate, 255 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
286 Address low_bound, Address high_bound) {
287 ThreadLocalTop* top = isolate->thread_local_top();
288 Address fp = Isolate::c_entry_fp(top); 256 Address fp = Isolate::c_entry_fp(top);
289 ExitFrameValidator validator(low_bound, high_bound); 257 if (!IsValidExitFrame(fp)) return false;
290 if (!validator.IsValidFP(fp)) return false; 258 // There should be at least one JS_ENTRY stack handler.
291 return Isolate::handler(top) != NULL; 259 return Isolate::handler(top) != NULL;
292 } 260 }
293 261
294 262
295 void SafeStackFrameIterator::AdvanceOneFrame() { 263 void SafeStackFrameIterator::AdvanceOneFrame() {
296 ASSERT(!done()); 264 ASSERT(!done());
297 StackFrame* last_frame = iterator_.frame(); 265 StackFrame* last_frame = frame_;
298 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); 266 Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
299 // Before advancing to the next stack frame, perform pointer validity tests 267 // Before advancing to the next stack frame, perform pointer validity tests.
300 iteration_done_ = !IsValidFrame(last_frame) || 268 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
301 !IsValidCaller(last_frame); 269 frame_ = NULL;
302 if (iteration_done_) return; 270 return;
271 }
303 272
304 iterator_.Advance(); 273 // Advance to the previous frame.
305 if (iterator_.done()) return; 274 StackFrame::State state;
306 // Check that we have actually moved to the previous frame in the stack 275 StackFrame::Type type = frame_->GetCallerState(&state);
307 StackFrame* prev_frame = iterator_.frame(); 276 frame_ = SingletonFor(type, &state);
308 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp; 277 if (frame_ == NULL) return;
278
279 // Check that we have actually moved to the previous frame in the stack.
280 if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
281 frame_ = NULL;
282 }
309 } 283 }
310 284
311 285
312 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { 286 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
313 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); 287 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
314 } 288 }
315 289
316 290
317 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { 291 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
318 StackFrame::State state; 292 StackFrame::State state;
319 if (frame->is_entry() || frame->is_entry_construct()) { 293 if (frame->is_entry() || frame->is_entry_construct()) {
320 // See EntryFrame::GetCallerState. It computes the caller FP address 294 // See EntryFrame::GetCallerState. It computes the caller FP address
321 // and calls ExitFrame::GetStateForFramePointer on it. We need to be 295 // and calls ExitFrame::GetStateForFramePointer on it. We need to be
322 // sure that caller FP address is valid. 296 // sure that caller FP address is valid.
323 Address caller_fp = Memory::Address_at( 297 Address caller_fp = Memory::Address_at(
324 frame->fp() + EntryFrameConstants::kCallerFPOffset); 298 frame->fp() + EntryFrameConstants::kCallerFPOffset);
325 ExitFrameValidator validator(stack_validator_); 299 if (!IsValidExitFrame(caller_fp)) return false;
326 if (!validator.IsValidFP(caller_fp)) return false;
327 } else if (frame->is_arguments_adaptor()) { 300 } else if (frame->is_arguments_adaptor()) {
328 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that 301 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
329 // the number of arguments is stored on stack as Smi. We need to check 302 // the number of arguments is stored on stack as Smi. We need to check
330 // that it really an Smi. 303 // that it really an Smi.
331 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> 304 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
332 GetExpression(0); 305 GetExpression(0);
333 if (!number_of_args->IsSmi()) { 306 if (!number_of_args->IsSmi()) {
334 return false; 307 return false;
335 } 308 }
336 } 309 }
337 frame->ComputeCallerState(&state); 310 frame->ComputeCallerState(&state);
338 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && 311 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
339 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL; 312 SingletonFor(frame->GetCallerState(&state)) != NULL;
340 } 313 }
341 314
342 315
316 bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
317 if (!IsValidStackAddress(fp)) return false;
318 Address sp = ExitFrame::ComputeStackPointer(fp);
319 if (!IsValidStackAddress(sp)) return false;
320 StackFrame::State state;
321 ExitFrame::FillState(fp, sp, &state);
322 if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) {
323 return false;
324 }
325 return *state.pc_address != NULL;
326 }
327
328
343 void SafeStackFrameIterator::Advance() { 329 void SafeStackFrameIterator::Advance() {
344 while (true) { 330 while (true) {
345 AdvanceOneFrame(); 331 AdvanceOneFrame();
346 if (done()) return; 332 if (done()) return;
347 if (iterator_.frame()->is_java_script()) return; 333 if (frame_->is_java_script()) return;
348 } 334 }
349 } 335 }
350 336
351 337
352 // ------------------------------------------------------------------------- 338 // -------------------------------------------------------------------------
353 339
354 340
355 Code* StackFrame::GetSafepointData(Isolate* isolate, 341 Code* StackFrame::GetSafepointData(Isolate* isolate,
356 Address inner_pointer, 342 Address inner_pointer,
357 SafepointEntry* safepoint_entry, 343 SafepointEntry* safepoint_entry,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 } 387 }
402 388
403 389
404 void StackFrame::SetReturnAddressLocationResolver( 390 void StackFrame::SetReturnAddressLocationResolver(
405 ReturnAddressLocationResolver resolver) { 391 ReturnAddressLocationResolver resolver) {
406 ASSERT(return_address_location_resolver == NULL); 392 ASSERT(return_address_location_resolver == NULL);
407 return_address_location_resolver = resolver; 393 return_address_location_resolver = resolver;
408 } 394 }
409 395
410 396
411 StackFrame::Type StackFrame::ComputeType(const StackFrameIterator* iterator, 397 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
412 State* state) { 398 State* state) {
413 ASSERT(state->fp != NULL); 399 ASSERT(state->fp != NULL);
414 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 400 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
415 return ARGUMENTS_ADAPTOR; 401 return ARGUMENTS_ADAPTOR;
416 } 402 }
417 // The marker and function offsets overlap. If the marker isn't a 403 // The marker and function offsets overlap. If the marker isn't a
418 // smi then the frame is a JavaScript frame -- and the marker is 404 // smi then the frame is a JavaScript frame -- and the marker is
419 // really the function. 405 // really the function.
420 const int offset = StandardFrameConstants::kMarkerOffset; 406 const int offset = StandardFrameConstants::kMarkerOffset;
421 Object* marker = Memory::Object_at(state->fp + offset); 407 Object* marker = Memory::Object_at(state->fp + offset);
(...skipping 1188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 ZoneList<StackFrame*> list(10, zone); 1596 ZoneList<StackFrame*> list(10, zone);
1611 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { 1597 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1612 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); 1598 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1613 list.Add(frame, zone); 1599 list.Add(frame, zone);
1614 } 1600 }
1615 return list.ToVector(); 1601 return list.ToVector();
1616 } 1602 }
1617 1603
1618 1604
1619 } } // namespace v8::internal 1605 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/frames-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698