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" |
(...skipping 28 matching lines...) Expand all Loading... |
39 ASSERT(thread_ == Thread::Current()); | 39 ASSERT(thread_ == Thread::Current()); |
40 Zone* zone = Thread::Current()->zone(); | 40 Zone* zone = Thread::Current()->zone(); |
41 if (IsDartFrame()) { | 41 if (IsDartFrame()) { |
42 const Code& code = Code::Handle(LookupDartCode()); | 42 const Code& code = Code::Handle(LookupDartCode()); |
43 ASSERT(!code.IsNull()); | 43 ASSERT(!code.IsNull()); |
44 const Object& owner = Object::Handle(code.owner()); | 44 const Object& owner = Object::Handle(code.owner()); |
45 ASSERT(!owner.IsNull()); | 45 ASSERT(!owner.IsNull()); |
46 if (owner.IsFunction()) { | 46 if (owner.IsFunction()) { |
47 const Function& function = Function::Cast(owner); | 47 const Function& function = Function::Cast(owner); |
48 return zone->PrintToString( | 48 return zone->PrintToString( |
49 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", | 49 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", GetName(), |
50 GetName(), sp(), fp(), pc(), | 50 sp(), fp(), pc(), function.ToFullyQualifiedCString()); |
51 function.ToFullyQualifiedCString()); | |
52 } else { | 51 } else { |
53 return zone->PrintToString( | 52 return zone->PrintToString( |
54 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", | 53 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", GetName(), |
55 GetName(), sp(), fp(), pc(), | 54 sp(), fp(), pc(), owner.ToCString()); |
56 owner.ToCString()); | |
57 } | 55 } |
58 } else { | 56 } else { |
59 return zone->PrintToString( | 57 return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px |
60 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ")]", | 58 ")]", |
61 GetName(), sp(), fp(), pc()); | 59 GetName(), sp(), fp(), pc()); |
62 } | 60 } |
63 } | 61 } |
64 | 62 |
65 | 63 |
66 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 64 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
67 // There are no objects to visit in this frame. | 65 // There are no objects to visit in this frame. |
68 } | 66 } |
69 | 67 |
70 | 68 |
71 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 69 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 RawFunction* StackFrame::LookupDartFunction() const { | 213 RawFunction* StackFrame::LookupDartFunction() const { |
216 const Code& code = Code::Handle(LookupDartCode()); | 214 const Code& code = Code::Handle(LookupDartCode()); |
217 if (!code.IsNull()) { | 215 if (!code.IsNull()) { |
218 return code.function(); | 216 return code.function(); |
219 } | 217 } |
220 return Function::null(); | 218 return Function::null(); |
221 } | 219 } |
222 | 220 |
223 | 221 |
224 RawCode* StackFrame::LookupDartCode() const { | 222 RawCode* StackFrame::LookupDartCode() const { |
225 // We add a no gc scope to ensure that the code below does not trigger | 223 // We add a no gc scope to ensure that the code below does not trigger |
226 // a GC as we are handling raw object references here. It is possible | 224 // a GC as we are handling raw object references here. It is possible |
227 // that the code is called while a GC is in progress, that is ok. | 225 // that the code is called while a GC is in progress, that is ok. |
228 #if !defined(TARGET_OS_WINDOWS) | 226 #if !defined(TARGET_OS_WINDOWS) |
229 // On Windows, the profiler calls this from a separate thread where | 227 // On Windows, the profiler calls this from a separate thread where |
230 // Thread::Current() is NULL, so we cannot create a NoSafepointScope. | 228 // Thread::Current() is NULL, so we cannot create a NoSafepointScope. |
231 NoSafepointScope no_safepoint; | 229 NoSafepointScope no_safepoint; |
232 #endif | 230 #endif |
233 RawCode* code = GetCodeObject(); | 231 RawCode* code = GetCodeObject(); |
234 if ((code != Code::null()) && | 232 if ((code != Code::null()) && |
235 (code->ptr()->owner_->GetClassId() == kFunctionCid)) { | 233 (code->ptr()->owner_->GetClassId() == kFunctionCid)) { |
236 return code; | 234 return code; |
237 } | 235 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 exit_(thread), | 344 exit_(thread), |
347 frames_(thread), | 345 frames_(thread), |
348 current_frame_(NULL), | 346 current_frame_(NULL), |
349 thread_(thread) { | 347 thread_(thread) { |
350 ASSERT((thread_ == Thread::Current()) || | 348 ASSERT((thread_ == Thread::Current()) || |
351 OS::AllowStackFrameIteratorFromAnotherThread()); | 349 OS::AllowStackFrameIteratorFromAnotherThread()); |
352 SetupLastExitFrameData(); // Setup data for last exit frame. | 350 SetupLastExitFrameData(); // Setup data for last exit frame. |
353 } | 351 } |
354 | 352 |
355 | 353 |
356 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate, | 354 StackFrameIterator::StackFrameIterator(uword last_fp, |
| 355 bool validate, |
357 Thread* thread) | 356 Thread* thread) |
358 : validate_(validate), | 357 : validate_(validate), |
359 entry_(thread), | 358 entry_(thread), |
360 exit_(thread), | 359 exit_(thread), |
361 frames_(thread), | 360 frames_(thread), |
362 current_frame_(NULL), | 361 current_frame_(NULL), |
363 thread_(thread) { | 362 thread_(thread) { |
364 ASSERT((thread_ == Thread::Current()) || | 363 ASSERT((thread_ == Thread::Current()) || |
365 OS::AllowStackFrameIteratorFromAnotherThread()); | 364 OS::AllowStackFrameIteratorFromAnotherThread()); |
366 frames_.fp_ = last_fp; | 365 frames_.fp_ = last_fp; |
367 frames_.sp_ = 0; | 366 frames_.sp_ = 0; |
368 frames_.pc_ = 0; | 367 frames_.pc_ = 0; |
369 } | 368 } |
370 | 369 |
371 | 370 |
372 #if !defined(TARGET_ARCH_DBC) | 371 #if !defined(TARGET_ARCH_DBC) |
373 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, | 372 StackFrameIterator::StackFrameIterator(uword fp, |
374 bool validate, Thread* thread) | 373 uword sp, |
| 374 uword pc, |
| 375 bool validate, |
| 376 Thread* thread) |
375 : validate_(validate), | 377 : validate_(validate), |
376 entry_(thread), | 378 entry_(thread), |
377 exit_(thread), | 379 exit_(thread), |
378 frames_(thread), | 380 frames_(thread), |
379 current_frame_(NULL), | 381 current_frame_(NULL), |
380 thread_(thread) { | 382 thread_(thread) { |
381 ASSERT((thread_ == Thread::Current()) || | 383 ASSERT((thread_ == Thread::Current()) || |
382 OS::AllowStackFrameIteratorFromAnotherThread()); | 384 OS::AllowStackFrameIteratorFromAnotherThread()); |
383 frames_.fp_ = fp; | 385 frames_.fp_ = fp; |
384 frames_.sp_ = sp; | 386 frames_.sp_ = sp; |
(...skipping 18 matching lines...) Expand all Loading... |
403 if (current_frame_ == NULL) { | 405 if (current_frame_ == NULL) { |
404 if (!HasNextFrame()) { | 406 if (!HasNextFrame()) { |
405 return NULL; | 407 return NULL; |
406 } | 408 } |
407 UnpoisonStack(frames_.fp_); | 409 UnpoisonStack(frames_.fp_); |
408 #if !defined(TARGET_ARCH_DBC) | 410 #if !defined(TARGET_ARCH_DBC) |
409 if (frames_.pc_ == 0) { | 411 if (frames_.pc_ == 0) { |
410 // Iteration starts from an exit frame given by its fp. | 412 // Iteration starts from an exit frame given by its fp. |
411 current_frame_ = NextExitFrame(); | 413 current_frame_ = NextExitFrame(); |
412 } else if (*(reinterpret_cast<uword*>( | 414 } else if (*(reinterpret_cast<uword*>( |
413 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) { | 415 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == |
| 416 0) { |
414 // Iteration starts from an entry frame given by its fp, sp, and pc. | 417 // Iteration starts from an entry frame given by its fp, sp, and pc. |
415 current_frame_ = NextEntryFrame(); | 418 current_frame_ = NextEntryFrame(); |
416 } else { | 419 } else { |
417 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. | 420 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. |
418 current_frame_ = frames_.NextFrame(validate_); | 421 current_frame_ = frames_.NextFrame(validate_); |
419 } | 422 } |
420 #else | 423 #else |
421 // Iteration starts from an exit frame given by its fp. This is the only | 424 // Iteration starts from an exit frame given by its fp. This is the only |
422 // mode supported on DBC. | 425 // mode supported on DBC. |
423 ASSERT(frames_.pc_ == 0); | 426 ASSERT(frames_.pc_ == 0); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 entry_.sp_ = frames_.sp_; | 482 entry_.sp_ = frames_.sp_; |
480 entry_.fp_ = frames_.fp_; | 483 entry_.fp_ = frames_.fp_; |
481 entry_.pc_ = frames_.pc_; | 484 entry_.pc_ = frames_.pc_; |
482 SetupNextExitFrameData(); // Setup data for next exit frame in chain. | 485 SetupNextExitFrameData(); // Setup data for next exit frame in chain. |
483 ASSERT(entry_.IsValid()); | 486 ASSERT(entry_.IsValid()); |
484 return &entry_; | 487 return &entry_; |
485 } | 488 } |
486 | 489 |
487 | 490 |
488 InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc) | 491 InlinedFunctionsIterator::InlinedFunctionsIterator(const Code& code, uword pc) |
489 : index_(0), | 492 : index_(0), |
490 num_materializations_(0), | 493 num_materializations_(0), |
491 dest_frame_size_(0), | 494 dest_frame_size_(0), |
492 code_(Code::Handle(code.raw())), | 495 code_(Code::Handle(code.raw())), |
493 deopt_info_(TypedData::Handle()), | 496 deopt_info_(TypedData::Handle()), |
494 function_(Function::Handle()), | 497 function_(Function::Handle()), |
495 pc_(pc), | 498 pc_(pc), |
496 deopt_instructions_(), | 499 deopt_instructions_(), |
497 object_table_(ObjectPool::Handle()) { | 500 object_table_(ObjectPool::Handle()) { |
498 ASSERT(code_.is_optimized()); | 501 ASSERT(code_.is_optimized()); |
499 ASSERT(pc_ != 0); | 502 ASSERT(pc_ != 0); |
500 ASSERT(code.ContainsInstructionAt(pc)); | 503 ASSERT(code.ContainsInstructionAt(pc)); |
501 ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown; | 504 ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown; |
502 uint32_t deopt_flags = 0; | 505 uint32_t deopt_flags = 0; |
503 deopt_info_ = code_.GetDeoptInfoAtPc(pc, &deopt_reason, &deopt_flags); | 506 deopt_info_ = code_.GetDeoptInfoAtPc(pc, &deopt_reason, &deopt_flags); |
504 if (deopt_info_.IsNull()) { | 507 if (deopt_info_.IsNull()) { |
505 // This is the case when a call without deopt info in optimized code | 508 // This is the case when a call without deopt info in optimized code |
506 // throws an exception. (e.g. in the parameter copying prologue). | 509 // throws an exception. (e.g. in the parameter copying prologue). |
507 // In that case there won't be any inlined frames. | 510 // In that case there won't be any inlined frames. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 } | 542 } |
540 } | 543 } |
541 SetDone(); | 544 SetDone(); |
542 } | 545 } |
543 | 546 |
544 | 547 |
545 // Finds the potential offset for the current function's FP if the | 548 // Finds the potential offset for the current function's FP if the |
546 // current frame were to be deoptimized. | 549 // current frame were to be deoptimized. |
547 intptr_t InlinedFunctionsIterator::GetDeoptFpOffset() const { | 550 intptr_t InlinedFunctionsIterator::GetDeoptFpOffset() const { |
548 ASSERT(deopt_instructions_.length() != 0); | 551 ASSERT(deopt_instructions_.length() != 0); |
549 for (intptr_t index = index_; | 552 for (intptr_t index = index_; index < deopt_instructions_.length(); index++) { |
550 index < deopt_instructions_.length(); | |
551 index++) { | |
552 DeoptInstr* deopt_instr = deopt_instructions_[index]; | 553 DeoptInstr* deopt_instr = deopt_instructions_[index]; |
553 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { | 554 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { |
554 #if defined(TARGET_ARCH_DBC) | 555 #if defined(TARGET_ARCH_DBC) |
555 // Stack on DBC is growing upwards but we record deopt commands | 556 // Stack on DBC is growing upwards but we record deopt commands |
556 // in the same order we record them on other architectures as if | 557 // in the same order we record them on other architectures as if |
557 // the stack was growing downwards. | 558 // the stack was growing downwards. |
558 return dest_frame_size_ - index; | 559 return dest_frame_size_ - index; |
559 #else | 560 #else |
560 return (index - num_materializations_); | 561 return (index - num_materializations_); |
561 #endif | 562 #endif |
562 } | 563 } |
563 } | 564 } |
564 UNREACHABLE(); | 565 UNREACHABLE(); |
565 return 0; | 566 return 0; |
566 } | 567 } |
567 | 568 |
568 | 569 |
569 #if defined(DEBUG) | 570 #if defined(DEBUG) |
570 void ValidateFrames() { | 571 void ValidateFrames() { |
571 StackFrameIterator frames(StackFrameIterator::kValidateFrames); | 572 StackFrameIterator frames(StackFrameIterator::kValidateFrames); |
572 StackFrame* frame = frames.NextFrame(); | 573 StackFrame* frame = frames.NextFrame(); |
573 while (frame != NULL) { | 574 while (frame != NULL) { |
574 frame = frames.NextFrame(); | 575 frame = frames.NextFrame(); |
575 } | 576 } |
576 } | 577 } |
577 #endif | 578 #endif |
578 | 579 |
579 | 580 |
580 } // namespace dart | 581 } // namespace dart |
OLD | NEW |