OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/stack_frame.h" | 5 #include "vm/stack_frame.h" |
6 | 6 |
7 #include "platform/memory_sanitizer.h" | 7 #include "platform/memory_sanitizer.h" |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/deopt_instructions.h" | 9 #include "vm/deopt_instructions.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 #include "vm/object_store.h" | 12 #include "vm/object_store.h" |
13 #include "vm/os.h" | 13 #include "vm/os.h" |
14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
15 #include "vm/raw_object.h" | 15 #include "vm/raw_object.h" |
16 #include "vm/reusable_handles.h" | 16 #include "vm/reusable_handles.h" |
17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
18 #include "vm/visitor.h" | 18 #include "vm/visitor.h" |
19 | 19 |
20 namespace dart { | 20 namespace dart { |
21 | 21 |
22 | |
23 bool StackFrame::IsStubFrame() const { | 22 bool StackFrame::IsStubFrame() const { |
24 ASSERT(!(IsEntryFrame() || IsExitFrame())); | 23 ASSERT(!(IsEntryFrame() || IsExitFrame())); |
25 #if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA) | 24 #if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA) |
26 // On Windows and Fuchsia, the profiler calls this from a separate thread | 25 // On Windows and Fuchsia, the profiler calls this from a separate thread |
27 // where Thread::Current() is NULL, so we cannot create a NoSafepointScope. | 26 // where Thread::Current() is NULL, so we cannot create a NoSafepointScope. |
28 NoSafepointScope no_safepoint; | 27 NoSafepointScope no_safepoint; |
29 #endif | 28 #endif |
30 RawCode* code = GetCodeObject(); | 29 RawCode* code = GetCodeObject(); |
31 ASSERT(code != Object::null()); | 30 ASSERT(code != Object::null()); |
32 const intptr_t cid = code->ptr()->owner_->GetClassId(); | 31 const intptr_t cid = code->ptr()->owner_->GetClassId(); |
33 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); | 32 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); |
34 return cid == kNullCid || cid == kClassCid; | 33 return cid == kNullCid || cid == kClassCid; |
35 } | 34 } |
36 | 35 |
37 | |
38 const char* StackFrame::ToCString() const { | 36 const char* StackFrame::ToCString() const { |
39 ASSERT(thread_ == Thread::Current()); | 37 ASSERT(thread_ == Thread::Current()); |
40 Zone* zone = Thread::Current()->zone(); | 38 Zone* zone = Thread::Current()->zone(); |
41 if (IsDartFrame()) { | 39 if (IsDartFrame()) { |
42 const Code& code = Code::Handle(zone, LookupDartCode()); | 40 const Code& code = Code::Handle(zone, LookupDartCode()); |
43 ASSERT(!code.IsNull()); | 41 ASSERT(!code.IsNull()); |
44 const Object& owner = Object::Handle(zone, code.owner()); | 42 const Object& owner = Object::Handle(zone, code.owner()); |
45 ASSERT(!owner.IsNull()); | 43 ASSERT(!owner.IsNull()); |
46 if (owner.IsFunction()) { | 44 if (owner.IsFunction()) { |
47 const char* opt = code.is_optimized() ? "*" : ""; | 45 const char* opt = code.is_optimized() ? "*" : ""; |
48 const Function& function = Function::Cast(owner); | 46 const Function& function = Function::Cast(owner); |
49 return zone->PrintToString( | 47 return zone->PrintToString( |
50 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s%s ]", GetName(), | 48 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s%s ]", GetName(), |
51 sp(), fp(), pc(), opt, function.ToFullyQualifiedCString()); | 49 sp(), fp(), pc(), opt, function.ToFullyQualifiedCString()); |
52 } else { | 50 } else { |
53 return zone->PrintToString( | 51 return zone->PrintToString( |
54 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", GetName(), | 52 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", GetName(), |
55 sp(), fp(), pc(), owner.ToCString()); | 53 sp(), fp(), pc(), owner.ToCString()); |
56 } | 54 } |
57 } else { | 55 } else { |
58 return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px | 56 return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px |
59 ")]", | 57 ")]", |
60 GetName(), sp(), fp(), pc()); | 58 GetName(), sp(), fp(), pc()); |
61 } | 59 } |
62 } | 60 } |
63 | 61 |
64 | |
65 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 62 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
66 // There are no objects to visit in this frame. | 63 // There are no objects to visit in this frame. |
67 } | 64 } |
68 | 65 |
69 | |
70 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 66 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
71 // Visit objects between SP and (FP - callee_save_area). | 67 // Visit objects between SP and (FP - callee_save_area). |
72 ASSERT(visitor != NULL); | 68 ASSERT(visitor != NULL); |
73 #if !defined(TARGET_ARCH_DBC) | 69 #if !defined(TARGET_ARCH_DBC) |
74 RawObject** first = reinterpret_cast<RawObject**>(sp()); | 70 RawObject** first = reinterpret_cast<RawObject**>(sp()); |
75 RawObject** last = reinterpret_cast<RawObject**>( | 71 RawObject** last = reinterpret_cast<RawObject**>( |
76 fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize); | 72 fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize); |
77 visitor->VisitPointers(first, last); | 73 visitor->VisitPointers(first, last); |
78 #else | 74 #else |
79 // On DBC stack is growing upwards which implies fp() <= sp(). | 75 // On DBC stack is growing upwards which implies fp() <= sp(). |
80 RawObject** first = reinterpret_cast<RawObject**>(fp()); | 76 RawObject** first = reinterpret_cast<RawObject**>(fp()); |
81 RawObject** last = reinterpret_cast<RawObject**>(sp()); | 77 RawObject** last = reinterpret_cast<RawObject**>(sp()); |
82 visitor->VisitPointers(first, last); | 78 visitor->VisitPointers(first, last); |
83 #endif | 79 #endif |
84 } | 80 } |
85 | 81 |
86 | |
87 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 82 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
88 ASSERT(visitor != NULL); | 83 ASSERT(visitor != NULL); |
89 // NOTE: This code runs while GC is in progress and runs within | 84 // NOTE: This code runs while GC is in progress and runs within |
90 // a NoHandleScope block. Hence it is not ok to use regular Zone or | 85 // a NoHandleScope block. Hence it is not ok to use regular Zone or |
91 // Scope handles. We use direct stack handles, the raw pointers in | 86 // Scope handles. We use direct stack handles, the raw pointers in |
92 // these handles are not traversed. The use of handles is mainly to | 87 // these handles are not traversed. The use of handles is mainly to |
93 // be able to reuse the handle based code and avoid having to add | 88 // be able to reuse the handle based code and avoid having to add |
94 // helper functions to the raw object interface. | 89 // helper functions to the raw object interface. |
95 NoSafepointScope no_safepoint; | 90 NoSafepointScope no_safepoint; |
96 Code code; | 91 Code code; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 #else | 192 #else |
198 // On DBC stack grows upwards: fp() <= sp(). | 193 // On DBC stack grows upwards: fp() <= sp(). |
199 RawObject** first = reinterpret_cast<RawObject**>( | 194 RawObject** first = reinterpret_cast<RawObject**>( |
200 fp() + (kFirstObjectSlotFromFp * kWordSize)); | 195 fp() + (kFirstObjectSlotFromFp * kWordSize)); |
201 RawObject** last = reinterpret_cast<RawObject**>(sp()); | 196 RawObject** last = reinterpret_cast<RawObject**>(sp()); |
202 #endif // !defined(TARGET_ARCH_DBC) | 197 #endif // !defined(TARGET_ARCH_DBC) |
203 | 198 |
204 visitor->VisitPointers(first, last); | 199 visitor->VisitPointers(first, last); |
205 } | 200 } |
206 | 201 |
207 | |
208 RawFunction* StackFrame::LookupDartFunction() const { | 202 RawFunction* StackFrame::LookupDartFunction() const { |
209 const Code& code = Code::Handle(LookupDartCode()); | 203 const Code& code = Code::Handle(LookupDartCode()); |
210 if (!code.IsNull()) { | 204 if (!code.IsNull()) { |
211 return code.function(); | 205 return code.function(); |
212 } | 206 } |
213 return Function::null(); | 207 return Function::null(); |
214 } | 208 } |
215 | 209 |
216 | |
217 RawCode* StackFrame::LookupDartCode() const { | 210 RawCode* StackFrame::LookupDartCode() const { |
218 // We add a no gc scope to ensure that the code below does not trigger | 211 // We add a no gc scope to ensure that the code below does not trigger |
219 // a GC as we are handling raw object references here. It is possible | 212 // a GC as we are handling raw object references here. It is possible |
220 // that the code is called while a GC is in progress, that is ok. | 213 // that the code is called while a GC is in progress, that is ok. |
221 #if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA) | 214 #if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA) |
222 // On Windows and Fuchsia, the profiler calls this from a separate thread | 215 // On Windows and Fuchsia, the profiler calls this from a separate thread |
223 // where Thread::Current() is NULL, so we cannot create a NoSafepointScope. | 216 // where Thread::Current() is NULL, so we cannot create a NoSafepointScope. |
224 NoSafepointScope no_safepoint; | 217 NoSafepointScope no_safepoint; |
225 #endif | 218 #endif |
226 RawCode* code = GetCodeObject(); | 219 RawCode* code = GetCodeObject(); |
227 if ((code != Code::null()) && | 220 if ((code != Code::null()) && |
228 (code->ptr()->owner_->GetClassId() == kFunctionCid)) { | 221 (code->ptr()->owner_->GetClassId() == kFunctionCid)) { |
229 return code; | 222 return code; |
230 } | 223 } |
231 return Code::null(); | 224 return Code::null(); |
232 } | 225 } |
233 | 226 |
234 | |
235 RawCode* StackFrame::GetCodeObject() const { | 227 RawCode* StackFrame::GetCodeObject() const { |
236 const uword pc_marker = | 228 const uword pc_marker = |
237 *(reinterpret_cast<uword*>(fp() + (kPcMarkerSlotFromFp * kWordSize))); | 229 *(reinterpret_cast<uword*>(fp() + (kPcMarkerSlotFromFp * kWordSize))); |
238 ASSERT(pc_marker != 0); | 230 ASSERT(pc_marker != 0); |
239 ASSERT(reinterpret_cast<RawObject*>(pc_marker)->GetClassId() == kCodeCid || | 231 ASSERT(reinterpret_cast<RawObject*>(pc_marker)->GetClassId() == kCodeCid || |
240 reinterpret_cast<RawObject*>(pc_marker) == Object::null()); | 232 reinterpret_cast<RawObject*>(pc_marker) == Object::null()); |
241 return reinterpret_cast<RawCode*>(pc_marker); | 233 return reinterpret_cast<RawCode*>(pc_marker); |
242 } | 234 } |
243 | 235 |
244 | |
245 bool StackFrame::FindExceptionHandler(Thread* thread, | 236 bool StackFrame::FindExceptionHandler(Thread* thread, |
246 uword* handler_pc, | 237 uword* handler_pc, |
247 bool* needs_stacktrace, | 238 bool* needs_stacktrace, |
248 bool* has_catch_all, | 239 bool* has_catch_all, |
249 bool* is_optimized) const { | 240 bool* is_optimized) const { |
250 REUSABLE_CODE_HANDLESCOPE(thread); | 241 REUSABLE_CODE_HANDLESCOPE(thread); |
251 Code& code = reused_code_handle.Handle(); | 242 Code& code = reused_code_handle.Handle(); |
252 code = LookupDartCode(); | 243 code = LookupDartCode(); |
253 if (code.IsNull()) { | 244 if (code.IsNull()) { |
254 return false; // Stub frames do not have exception handlers. | 245 return false; // Stub frames do not have exception handlers. |
(...skipping 29 matching lines...) Expand all Loading... |
284 *handler_pc = code.PayloadStart() + handler_info.handler_pc_offset; | 275 *handler_pc = code.PayloadStart() + handler_info.handler_pc_offset; |
285 *needs_stacktrace = handler_info.needs_stacktrace; | 276 *needs_stacktrace = handler_info.needs_stacktrace; |
286 *has_catch_all = handler_info.has_catch_all; | 277 *has_catch_all = handler_info.has_catch_all; |
287 cache->Insert(pc(), handler_info); | 278 cache->Insert(pc(), handler_info); |
288 return true; | 279 return true; |
289 } | 280 } |
290 } | 281 } |
291 return false; | 282 return false; |
292 } | 283 } |
293 | 284 |
294 | |
295 TokenPosition StackFrame::GetTokenPos() const { | 285 TokenPosition StackFrame::GetTokenPos() const { |
296 const Code& code = Code::Handle(LookupDartCode()); | 286 const Code& code = Code::Handle(LookupDartCode()); |
297 if (code.IsNull()) { | 287 if (code.IsNull()) { |
298 return TokenPosition::kNoSource; // Stub frames do not have token_pos. | 288 return TokenPosition::kNoSource; // Stub frames do not have token_pos. |
299 } | 289 } |
300 uword pc_offset = pc() - code.PayloadStart(); | 290 uword pc_offset = pc() - code.PayloadStart(); |
301 const PcDescriptors& descriptors = | 291 const PcDescriptors& descriptors = |
302 PcDescriptors::Handle(code.pc_descriptors()); | 292 PcDescriptors::Handle(code.pc_descriptors()); |
303 ASSERT(!descriptors.IsNull()); | 293 ASSERT(!descriptors.IsNull()); |
304 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | 294 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
305 while (iter.MoveNext()) { | 295 while (iter.MoveNext()) { |
306 if (iter.PcOffset() == pc_offset) { | 296 if (iter.PcOffset() == pc_offset) { |
307 return TokenPosition(iter.TokenPos()); | 297 return TokenPosition(iter.TokenPos()); |
308 } | 298 } |
309 } | 299 } |
310 return TokenPosition::kNoSource; | 300 return TokenPosition::kNoSource; |
311 } | 301 } |
312 | 302 |
313 | |
314 bool StackFrame::IsValid() const { | 303 bool StackFrame::IsValid() const { |
315 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { | 304 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { |
316 return true; | 305 return true; |
317 } | 306 } |
318 return (LookupDartCode() != Code::null()); | 307 return (LookupDartCode() != Code::null()); |
319 } | 308 } |
320 | 309 |
321 | |
322 void StackFrameIterator::SetupLastExitFrameData() { | 310 void StackFrameIterator::SetupLastExitFrameData() { |
323 ASSERT(thread_ != NULL); | 311 ASSERT(thread_ != NULL); |
324 uword exit_marker = thread_->top_exit_frame_info(); | 312 uword exit_marker = thread_->top_exit_frame_info(); |
325 frames_.fp_ = exit_marker; | 313 frames_.fp_ = exit_marker; |
326 } | 314 } |
327 | 315 |
328 | |
329 void StackFrameIterator::SetupNextExitFrameData() { | 316 void StackFrameIterator::SetupNextExitFrameData() { |
330 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); | 317 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); |
331 uword exit_marker = *reinterpret_cast<uword*>(exit_address); | 318 uword exit_marker = *reinterpret_cast<uword*>(exit_address); |
332 frames_.fp_ = exit_marker; | 319 frames_.fp_ = exit_marker; |
333 frames_.sp_ = 0; | 320 frames_.sp_ = 0; |
334 frames_.pc_ = 0; | 321 frames_.pc_ = 0; |
335 } | 322 } |
336 | 323 |
337 | |
338 // Tell MemorySanitizer that generated code initializes part of the stack. | 324 // Tell MemorySanitizer that generated code initializes part of the stack. |
339 // TODO(koda): Limit to frames that are actually written by generated code. | 325 // TODO(koda): Limit to frames that are actually written by generated code. |
340 static void UnpoisonStack(uword fp) { | 326 static void UnpoisonStack(uword fp) { |
341 ASSERT(fp != 0); | 327 ASSERT(fp != 0); |
342 uword size = OSThread::GetSpecifiedStackSize(); | 328 uword size = OSThread::GetSpecifiedStackSize(); |
343 MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size); | 329 MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size); |
344 } | 330 } |
345 | 331 |
346 | |
347 StackFrameIterator::StackFrameIterator(ValidationPolicy validation_policy, | 332 StackFrameIterator::StackFrameIterator(ValidationPolicy validation_policy, |
348 Thread* thread, | 333 Thread* thread, |
349 CrossThreadPolicy cross_thread_policy) | 334 CrossThreadPolicy cross_thread_policy) |
350 : validate_(validation_policy == kValidateFrames), | 335 : validate_(validation_policy == kValidateFrames), |
351 entry_(thread), | 336 entry_(thread), |
352 exit_(thread), | 337 exit_(thread), |
353 frames_(thread), | 338 frames_(thread), |
354 current_frame_(NULL), | 339 current_frame_(NULL), |
355 thread_(thread) { | 340 thread_(thread) { |
356 ASSERT(cross_thread_policy == kAllowCrossThreadIteration || | 341 ASSERT(cross_thread_policy == kAllowCrossThreadIteration || |
357 thread_ == Thread::Current()); | 342 thread_ == Thread::Current()); |
358 SetupLastExitFrameData(); // Setup data for last exit frame. | 343 SetupLastExitFrameData(); // Setup data for last exit frame. |
359 } | 344 } |
360 | 345 |
361 | |
362 StackFrameIterator::StackFrameIterator(uword last_fp, | 346 StackFrameIterator::StackFrameIterator(uword last_fp, |
363 ValidationPolicy validation_policy, | 347 ValidationPolicy validation_policy, |
364 Thread* thread, | 348 Thread* thread, |
365 CrossThreadPolicy cross_thread_policy) | 349 CrossThreadPolicy cross_thread_policy) |
366 : validate_(validation_policy == kValidateFrames), | 350 : validate_(validation_policy == kValidateFrames), |
367 entry_(thread), | 351 entry_(thread), |
368 exit_(thread), | 352 exit_(thread), |
369 frames_(thread), | 353 frames_(thread), |
370 current_frame_(NULL), | 354 current_frame_(NULL), |
371 thread_(thread) { | 355 thread_(thread) { |
372 ASSERT(cross_thread_policy == kAllowCrossThreadIteration || | 356 ASSERT(cross_thread_policy == kAllowCrossThreadIteration || |
373 thread_ == Thread::Current()); | 357 thread_ == Thread::Current()); |
374 frames_.fp_ = last_fp; | 358 frames_.fp_ = last_fp; |
375 frames_.sp_ = 0; | 359 frames_.sp_ = 0; |
376 frames_.pc_ = 0; | 360 frames_.pc_ = 0; |
377 } | 361 } |
378 | 362 |
379 | |
380 #if !defined(TARGET_ARCH_DBC) | 363 #if !defined(TARGET_ARCH_DBC) |
381 StackFrameIterator::StackFrameIterator(uword fp, | 364 StackFrameIterator::StackFrameIterator(uword fp, |
382 uword sp, | 365 uword sp, |
383 uword pc, | 366 uword pc, |
384 ValidationPolicy validation_policy, | 367 ValidationPolicy validation_policy, |
385 Thread* thread, | 368 Thread* thread, |
386 CrossThreadPolicy cross_thread_policy) | 369 CrossThreadPolicy cross_thread_policy) |
387 : validate_(validation_policy == kValidateFrames), | 370 : validate_(validation_policy == kValidateFrames), |
388 entry_(thread), | 371 entry_(thread), |
389 exit_(thread), | 372 exit_(thread), |
390 frames_(thread), | 373 frames_(thread), |
391 current_frame_(NULL), | 374 current_frame_(NULL), |
392 thread_(thread) { | 375 thread_(thread) { |
393 ASSERT(cross_thread_policy == kAllowCrossThreadIteration || | 376 ASSERT(cross_thread_policy == kAllowCrossThreadIteration || |
394 thread_ == Thread::Current()); | 377 thread_ == Thread::Current()); |
395 frames_.fp_ = fp; | 378 frames_.fp_ = fp; |
396 frames_.sp_ = sp; | 379 frames_.sp_ = sp; |
397 frames_.pc_ = pc; | 380 frames_.pc_ = pc; |
398 } | 381 } |
399 #endif | 382 #endif |
400 | 383 |
401 | |
402 StackFrame* StackFrameIterator::NextFrame() { | 384 StackFrame* StackFrameIterator::NextFrame() { |
403 // When we are at the start of iteration after having created an | 385 // When we are at the start of iteration after having created an |
404 // iterator object, current_frame_ will be NULL as we haven't seen | 386 // iterator object, current_frame_ will be NULL as we haven't seen |
405 // any frames yet (unless we start iterating in the simulator from a given | 387 // any frames yet (unless we start iterating in the simulator from a given |
406 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries | 388 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries |
407 // to set up the next exit frame by reading the top_exit_frame_info | 389 // to set up the next exit frame by reading the top_exit_frame_info |
408 // from the isolate. If we do not have any dart invocations yet, | 390 // from the isolate. If we do not have any dart invocations yet, |
409 // top_exit_frame_info will be 0 and so we would return NULL. | 391 // top_exit_frame_info will be 0 and so we would return NULL. |
410 | 392 |
411 // current_frame_ will also be NULL, when we are at the end of having | 393 // current_frame_ will also be NULL, when we are at the end of having |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 current_frame_->IsStubFrame()); | 434 current_frame_->IsStubFrame()); |
453 | 435 |
454 // Consume dart/stub frames using StackFrameIterator::FrameSetIterator | 436 // Consume dart/stub frames using StackFrameIterator::FrameSetIterator |
455 // until we are out of dart/stub frames at which point we return the | 437 // until we are out of dart/stub frames at which point we return the |
456 // corresponding entry frame for that set of dart/stub frames. | 438 // corresponding entry frame for that set of dart/stub frames. |
457 current_frame_ = | 439 current_frame_ = |
458 (frames_.HasNext()) ? frames_.NextFrame(validate_) : NextEntryFrame(); | 440 (frames_.HasNext()) ? frames_.NextFrame(validate_) : NextEntryFrame(); |
459 return current_frame_; | 441 return current_frame_; |
460 } | 442 } |
461 | 443 |
462 | |
463 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { | 444 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) { |
464 StackFrame* frame; | 445 StackFrame* frame; |
465 ASSERT(HasNext()); | 446 ASSERT(HasNext()); |
466 frame = &stack_frame_; | 447 frame = &stack_frame_; |
467 frame->sp_ = sp_; | 448 frame->sp_ = sp_; |
468 frame->fp_ = fp_; | 449 frame->fp_ = fp_; |
469 frame->pc_ = pc_; | 450 frame->pc_ = pc_; |
470 sp_ = frame->GetCallerSp(); | 451 sp_ = frame->GetCallerSp(); |
471 fp_ = frame->GetCallerFp(); | 452 fp_ = frame->GetCallerFp(); |
472 pc_ = frame->GetCallerPc(); | 453 pc_ = frame->GetCallerPc(); |
473 ASSERT((validate == kDontValidateFrames) || frame->IsValid()); | 454 ASSERT((validate == kDontValidateFrames) || frame->IsValid()); |
474 return frame; | 455 return frame; |
475 } | 456 } |
476 | 457 |
477 | |
478 ExitFrame* StackFrameIterator::NextExitFrame() { | 458 ExitFrame* StackFrameIterator::NextExitFrame() { |
479 exit_.sp_ = frames_.sp_; | 459 exit_.sp_ = frames_.sp_; |
480 exit_.fp_ = frames_.fp_; | 460 exit_.fp_ = frames_.fp_; |
481 exit_.pc_ = frames_.pc_; | 461 exit_.pc_ = frames_.pc_; |
482 frames_.sp_ = exit_.GetCallerSp(); | 462 frames_.sp_ = exit_.GetCallerSp(); |
483 frames_.fp_ = exit_.GetCallerFp(); | 463 frames_.fp_ = exit_.GetCallerFp(); |
484 frames_.pc_ = exit_.GetCallerPc(); | 464 frames_.pc_ = exit_.GetCallerPc(); |
485 ASSERT(exit_.IsValid()); | 465 ASSERT(exit_.IsValid()); |
486 return &exit_; | 466 return &exit_; |
487 } | 467 } |
488 | 468 |
489 | |
490 EntryFrame* StackFrameIterator::NextEntryFrame() { | 469 EntryFrame* StackFrameIterator::NextEntryFrame() { |
491 ASSERT(!frames_.HasNext()); | 470 ASSERT(!frames_.HasNext()); |
492 entry_.sp_ = frames_.sp_; | 471 entry_.sp_ = frames_.sp_; |
493 entry_.fp_ = frames_.fp_; | 472 entry_.fp_ = frames_.fp_; |
494 entry_.pc_ = frames_.pc_; | 473 entry_.pc_ = frames_.pc_; |
495 SetupNextExitFrameData(); // Setup data for next exit frame in chain. | 474 SetupNextExitFrameData(); // Setup data for next exit frame in chain. |
496 ASSERT(entry_.IsValid()); | 475 ASSERT(entry_.IsValid()); |
497 return &entry_; | 476 return &entry_; |
498 } | 477 } |
499 | 478 |
500 | |
501 InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc) | 479 InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc) |
502 : index_(0), | 480 : index_(0), |
503 num_materializations_(0), | 481 num_materializations_(0), |
504 dest_frame_size_(0), | 482 dest_frame_size_(0), |
505 code_(Code::Handle(code.raw())), | 483 code_(Code::Handle(code.raw())), |
506 deopt_info_(TypedData::Handle()), | 484 deopt_info_(TypedData::Handle()), |
507 function_(Function::Handle()), | 485 function_(Function::Handle()), |
508 pc_(pc), | 486 pc_(pc), |
509 deopt_instructions_(), | 487 deopt_instructions_(), |
510 object_table_(ObjectPool::Handle()) { | 488 object_table_(ObjectPool::Handle()) { |
(...skipping 18 matching lines...) Expand all Loading... |
529 ASSERT(!deopt_table.IsNull()); | 507 ASSERT(!deopt_table.IsNull()); |
530 DeoptInfo::Unpack(deopt_table, deopt_info_, &deopt_instructions_); | 508 DeoptInfo::Unpack(deopt_table, deopt_info_, &deopt_instructions_); |
531 num_materializations_ = DeoptInfo::NumMaterializations(deopt_instructions_); | 509 num_materializations_ = DeoptInfo::NumMaterializations(deopt_instructions_); |
532 dest_frame_size_ = DeoptInfo::FrameSize(deopt_info_); | 510 dest_frame_size_ = DeoptInfo::FrameSize(deopt_info_); |
533 object_table_ = code_.GetObjectPool(); | 511 object_table_ = code_.GetObjectPool(); |
534 Advance(); | 512 Advance(); |
535 } | 513 } |
536 #endif // defined(DART_PRECOMPILED_RUNTIME) | 514 #endif // defined(DART_PRECOMPILED_RUNTIME) |
537 } | 515 } |
538 | 516 |
539 | |
540 void InlinedFunctionsIterator::Advance() { | 517 void InlinedFunctionsIterator::Advance() { |
541 // Iterate over the deopt instructions and determine the inlined | 518 // Iterate over the deopt instructions and determine the inlined |
542 // functions if any and iterate over them. | 519 // functions if any and iterate over them. |
543 ASSERT(!Done()); | 520 ASSERT(!Done()); |
544 | 521 |
545 #if defined(DART_PRECOMPILED_RUNTIME) | 522 #if defined(DART_PRECOMPILED_RUNTIME) |
546 ASSERT(deopt_info_.IsNull()); | 523 ASSERT(deopt_info_.IsNull()); |
547 SetDone(); | 524 SetDone(); |
548 return; | 525 return; |
549 #else | 526 #else |
550 if (deopt_info_.IsNull()) { | 527 if (deopt_info_.IsNull()) { |
551 SetDone(); | 528 SetDone(); |
552 return; | 529 return; |
553 } | 530 } |
554 | 531 |
555 ASSERT(deopt_instructions_.length() != 0); | 532 ASSERT(deopt_instructions_.length() != 0); |
556 while (index_ < deopt_instructions_.length()) { | 533 while (index_ < deopt_instructions_.length()) { |
557 DeoptInstr* deopt_instr = deopt_instructions_[index_++]; | 534 DeoptInstr* deopt_instr = deopt_instructions_[index_++]; |
558 if (deopt_instr->kind() == DeoptInstr::kRetAddress) { | 535 if (deopt_instr->kind() == DeoptInstr::kRetAddress) { |
559 pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &code_); | 536 pc_ = DeoptInstr::GetRetAddress(deopt_instr, object_table_, &code_); |
560 function_ = code_.function(); | 537 function_ = code_.function(); |
561 return; | 538 return; |
562 } | 539 } |
563 } | 540 } |
564 SetDone(); | 541 SetDone(); |
565 #endif // defined(DART_PRECOMPILED_RUNTIME) | 542 #endif // defined(DART_PRECOMPILED_RUNTIME) |
566 } | 543 } |
567 | 544 |
568 | |
569 // Finds the potential offset for the current function's FP if the | 545 // Finds the potential offset for the current function's FP if the |
570 // current frame were to be deoptimized. | 546 // current frame were to be deoptimized. |
571 intptr_t InlinedFunctionsIterator::GetDeoptFpOffset() const { | 547 intptr_t InlinedFunctionsIterator::GetDeoptFpOffset() const { |
572 ASSERT(deopt_instructions_.length() != 0); | 548 ASSERT(deopt_instructions_.length() != 0); |
573 for (intptr_t index = index_; index < deopt_instructions_.length(); index++) { | 549 for (intptr_t index = index_; index < deopt_instructions_.length(); index++) { |
574 DeoptInstr* deopt_instr = deopt_instructions_[index]; | 550 DeoptInstr* deopt_instr = deopt_instructions_[index]; |
575 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { | 551 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { |
576 intptr_t fp_offset = (index - num_materializations_); | 552 intptr_t fp_offset = (index - num_materializations_); |
577 #if defined(TARGET_ARCH_DBC) | 553 #if defined(TARGET_ARCH_DBC) |
578 // Stack on DBC is growing upwards but we record deopt commands | 554 // Stack on DBC is growing upwards but we record deopt commands |
579 // in the same order we record them on other architectures as if | 555 // in the same order we record them on other architectures as if |
580 // the stack was growing downwards. | 556 // the stack was growing downwards. |
581 fp_offset = dest_frame_size_ - fp_offset; | 557 fp_offset = dest_frame_size_ - fp_offset; |
582 #endif | 558 #endif |
583 return fp_offset; | 559 return fp_offset; |
584 } | 560 } |
585 } | 561 } |
586 UNREACHABLE(); | 562 UNREACHABLE(); |
587 return 0; | 563 return 0; |
588 } | 564 } |
589 | 565 |
590 | |
591 #if defined(DEBUG) | 566 #if defined(DEBUG) |
592 void ValidateFrames() { | 567 void ValidateFrames() { |
593 StackFrameIterator frames(StackFrameIterator::kValidateFrames, | 568 StackFrameIterator frames(StackFrameIterator::kValidateFrames, |
594 Thread::Current(), | 569 Thread::Current(), |
595 StackFrameIterator::kNoCrossThreadIteration); | 570 StackFrameIterator::kNoCrossThreadIteration); |
596 StackFrame* frame = frames.NextFrame(); | 571 StackFrame* frame = frames.NextFrame(); |
597 while (frame != NULL) { | 572 while (frame != NULL) { |
598 frame = frames.NextFrame(); | 573 frame = frames.NextFrame(); |
599 } | 574 } |
600 } | 575 } |
601 #endif | 576 #endif |
602 | 577 |
603 | |
604 } // namespace dart | 578 } // namespace dart |
OLD | NEW |