| 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 |