OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |