Chromium Code Reviews| 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 17 matching lines...) Expand all Loading... | |
| 28 NoSafepointScope no_safepoint; | 28 NoSafepointScope no_safepoint; |
| 29 #endif | 29 #endif |
| 30 RawCode* code = GetCodeObject(); | 30 RawCode* code = GetCodeObject(); |
| 31 intptr_t cid = code->ptr()->owner_->GetClassId(); | 31 intptr_t cid = code->ptr()->owner_->GetClassId(); |
| 32 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); | 32 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); |
| 33 return cid == kNullCid || cid == kClassCid; | 33 return cid == kNullCid || cid == kClassCid; |
| 34 } | 34 } |
| 35 | 35 |
| 36 | 36 |
| 37 const char* StackFrame::ToCString() const { | 37 const char* StackFrame::ToCString() const { |
| 38 ASSERT(isolate_ == Isolate::Current()); | 38 ASSERT(thread_ == Thread::Current()); |
| 39 Zone* zone = Thread::Current()->zone(); | 39 Zone* zone = Thread::Current()->zone(); |
| 40 if (IsDartFrame()) { | 40 if (IsDartFrame()) { |
| 41 const Code& code = Code::Handle(LookupDartCode()); | 41 const Code& code = Code::Handle(LookupDartCode()); |
| 42 ASSERT(!code.IsNull()); | 42 ASSERT(!code.IsNull()); |
| 43 const Object& owner = Object::Handle(code.owner()); | 43 const Object& owner = Object::Handle(code.owner()); |
| 44 ASSERT(!owner.IsNull()); | 44 ASSERT(!owner.IsNull()); |
| 45 if (owner.IsFunction()) { | 45 if (owner.IsFunction()) { |
| 46 const Function& function = Function::Cast(owner); | 46 const Function& function = Function::Cast(owner); |
| 47 return zone->PrintToString( | 47 return zone->PrintToString( |
| 48 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", | 48 "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") %s ]", |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| 65 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 65 void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 66 // There are no objects to visit in this frame. | 66 // There are no objects to visit in this frame. |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 70 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 71 ASSERT(isolate() == Isolate::Current()); | 71 ASSERT(thread() == Thread::Current()); |
| 72 // Visit objects between SP and (FP - callee_save_area). | 72 // Visit objects between SP and (FP - callee_save_area). |
| 73 ASSERT(visitor != NULL); | 73 ASSERT(visitor != NULL); |
| 74 RawObject** first = reinterpret_cast<RawObject**>(sp()); | 74 RawObject** first = reinterpret_cast<RawObject**>(sp()); |
| 75 RawObject** last = reinterpret_cast<RawObject**>( | 75 RawObject** last = reinterpret_cast<RawObject**>( |
| 76 fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize); | 76 fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize); |
| 77 visitor->VisitPointers(first, last); | 77 visitor->VisitPointers(first, last); |
| 78 } | 78 } |
| 79 | 79 |
| 80 | 80 |
| 81 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 81 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 82 // NOTE: This code runs while GC is in progress and runs within | 82 // NOTE: This code runs while GC is in progress and runs within |
| 83 // a NoHandleScope block. Hence it is not ok to use regular Zone or | 83 // a NoHandleScope block. Hence it is not ok to use regular Zone or |
| 84 // Scope handles. We use direct stack handles, the raw pointers in | 84 // Scope handles. We use direct stack handles, the raw pointers in |
| 85 // these handles are not traversed. The use of handles is mainly to | 85 // these handles are not traversed. The use of handles is mainly to |
| 86 // be able to reuse the handle based code and avoid having to add | 86 // be able to reuse the handle based code and avoid having to add |
| 87 // helper functions to the raw object interface. | 87 // helper functions to the raw object interface. |
| 88 ASSERT(isolate_ == Isolate::Current()); | 88 ASSERT(thread() == Thread::Current()); |
| 89 ASSERT(visitor != NULL); | 89 ASSERT(visitor != NULL); |
| 90 NoSafepointScope no_safepoint; | 90 NoSafepointScope no_safepoint; |
| 91 Code code; | 91 Code code; |
| 92 code = LookupDartCode(); | 92 code = LookupDartCode(); |
| 93 if (!code.IsNull()) { | 93 if (!code.IsNull()) { |
| 94 // Visit the code object. | 94 // Visit the code object. |
| 95 RawObject* raw_code = code.raw(); | 95 RawObject* raw_code = code.raw(); |
| 96 visitor->VisitPointer(&raw_code); | 96 visitor->VisitPointer(&raw_code); |
| 97 | 97 |
| 98 // Optimized frames have a stack map. We need to visit the frame based | 98 // Optimized frames have a stack map. We need to visit the frame based |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 // For normal unoptimized Dart frames and Stub frames each slot | 158 // For normal unoptimized Dart frames and Stub frames each slot |
| 159 // between the first and last included are tagged objects. | 159 // between the first and last included are tagged objects. |
| 160 RawObject** first = reinterpret_cast<RawObject**>(sp()); | 160 RawObject** first = reinterpret_cast<RawObject**>(sp()); |
| 161 RawObject** last = reinterpret_cast<RawObject**>( | 161 RawObject** last = reinterpret_cast<RawObject**>( |
| 162 fp() + (kFirstObjectSlotFromFp * kWordSize)); | 162 fp() + (kFirstObjectSlotFromFp * kWordSize)); |
| 163 visitor->VisitPointers(first, last); | 163 visitor->VisitPointers(first, last); |
| 164 } | 164 } |
| 165 | 165 |
| 166 | 166 |
| 167 RawFunction* StackFrame::LookupDartFunction() const { | 167 RawFunction* StackFrame::LookupDartFunction() const { |
| 168 ASSERT(isolate_ == Isolate::Current()); | |
| 169 const Code& code = Code::Handle(LookupDartCode()); | 168 const Code& code = Code::Handle(LookupDartCode()); |
| 170 if (!code.IsNull()) { | 169 if (!code.IsNull()) { |
| 171 return code.function(); | 170 return code.function(); |
| 172 } | 171 } |
| 173 return Function::null(); | 172 return Function::null(); |
| 174 } | 173 } |
| 175 | 174 |
| 176 | 175 |
| 177 RawCode* StackFrame::LookupDartCode() const { | 176 RawCode* StackFrame::LookupDartCode() const { |
| 178 ASSERT(isolate_ == Isolate::Current()); | |
| 179 // We add a no gc scope to ensure that the code below does not trigger | 177 // We add a no gc scope to ensure that the code below does not trigger |
| 180 // a GC as we are handling raw object references here. It is possible | 178 // a GC as we are handling raw object references here. It is possible |
| 181 // that the code is called while a GC is in progress, that is ok. | 179 // that the code is called while a GC is in progress, that is ok. |
| 182 #if !defined(TARGET_OS_WINDOWS) | 180 #if !defined(TARGET_OS_WINDOWS) |
| 183 // On Windows, the profiler calls this from a separate thread where | 181 // On Windows, the profiler calls this from a separate thread where |
| 184 // Thread::Current() is NULL, so we cannot create a NoSafepointScope. | 182 // Thread::Current() is NULL, so we cannot create a NoSafepointScope. |
| 185 NoSafepointScope no_safepoint; | 183 NoSafepointScope no_safepoint; |
| 186 #endif | 184 #endif |
| 187 RawCode* code = GetCodeObject(); | 185 RawCode* code = GetCodeObject(); |
| 188 if ((code != Code::null()) && | 186 if ((code != Code::null()) && |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 | 262 |
| 265 bool StackFrame::IsValid() const { | 263 bool StackFrame::IsValid() const { |
| 266 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { | 264 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { |
| 267 return true; | 265 return true; |
| 268 } | 266 } |
| 269 return (LookupDartCode() != Code::null()); | 267 return (LookupDartCode() != Code::null()); |
| 270 } | 268 } |
| 271 | 269 |
| 272 | 270 |
| 273 void StackFrameIterator::SetupLastExitFrameData() { | 271 void StackFrameIterator::SetupLastExitFrameData() { |
| 274 uword exit_marker = Thread::Current()->top_exit_frame_info(); | 272 ASSERT(thread_ != NULL); |
| 273 uword exit_marker = thread_->top_exit_frame_info(); | |
|
srdjan
2015/10/20 21:33:47
Please sync with my temporary fix and remove Isola
Cutch
2015/10/20 21:39:01
Done.
| |
| 275 frames_.fp_ = exit_marker; | 274 frames_.fp_ = exit_marker; |
| 276 } | 275 } |
| 277 | 276 |
| 278 | 277 |
| 279 void StackFrameIterator::SetupNextExitFrameData() { | 278 void StackFrameIterator::SetupNextExitFrameData() { |
| 280 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); | 279 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); |
| 281 uword exit_marker = *reinterpret_cast<uword*>(exit_address); | 280 uword exit_marker = *reinterpret_cast<uword*>(exit_address); |
| 282 frames_.fp_ = exit_marker; | 281 frames_.fp_ = exit_marker; |
| 283 frames_.sp_ = 0; | 282 frames_.sp_ = 0; |
| 284 frames_.pc_ = 0; | 283 frames_.pc_ = 0; |
| 285 } | 284 } |
| 286 | 285 |
| 287 | 286 |
| 288 // Tell MemorySanitizer that generated code initializes part of the stack. | 287 // Tell MemorySanitizer that generated code initializes part of the stack. |
| 289 // TODO(koda): Limit to frames that are actually written by generated code. | 288 // TODO(koda): Limit to frames that are actually written by generated code. |
| 290 static void UnpoisonStack(Isolate* isolate, uword fp) { | 289 static void UnpoisonStack(Isolate* isolate, uword fp) { |
| 291 ASSERT(fp != 0); | 290 ASSERT(fp != 0); |
| 292 uword size = isolate->GetSpecifiedStackSize(); | 291 uword size = isolate->GetSpecifiedStackSize(); |
| 293 MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size); | 292 MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size); |
| 294 } | 293 } |
| 295 | 294 |
| 296 | 295 |
| 297 StackFrameIterator::StackFrameIterator(bool validate, Isolate* isolate) | 296 StackFrameIterator::StackFrameIterator(bool validate, |
| 297 Thread* thread) | |
|
srdjan
2015/10/20 21:33:47
One line.
Cutch
2015/10/20 21:39:01
Done.
| |
| 298 : validate_(validate), | 298 : validate_(validate), |
| 299 entry_(isolate), | 299 entry_(thread), |
| 300 exit_(isolate), | 300 exit_(thread), |
| 301 frames_(isolate), | 301 frames_(thread), |
| 302 current_frame_(NULL), | 302 current_frame_(NULL), |
| 303 isolate_(isolate) { | 303 thread_(thread) { |
| 304 ASSERT((isolate_ == Isolate::Current()) || | 304 ASSERT((thread_ == Thread::Current()) || |
| 305 OS::AllowStackFrameIteratorFromAnotherThread()); | 305 OS::AllowStackFrameIteratorFromAnotherThread()); |
| 306 SetupLastExitFrameData(); // Setup data for last exit frame. | 306 SetupLastExitFrameData(); // Setup data for last exit frame. |
| 307 } | 307 } |
| 308 | 308 |
| 309 | 309 |
| 310 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate, | 310 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate, |
| 311 Isolate* isolate) | 311 Thread* thread) |
| 312 : validate_(validate), | 312 : validate_(validate), |
| 313 entry_(isolate), | 313 entry_(thread), |
| 314 exit_(isolate), | 314 exit_(thread), |
| 315 frames_(isolate), | 315 frames_(thread), |
| 316 current_frame_(NULL), | 316 current_frame_(NULL), |
| 317 isolate_(isolate) { | 317 thread_(thread) { |
| 318 ASSERT((isolate_ == Isolate::Current()) || | 318 ASSERT((thread_ == Thread::Current()) || |
| 319 OS::AllowStackFrameIteratorFromAnotherThread()); | 319 OS::AllowStackFrameIteratorFromAnotherThread()); |
| 320 frames_.fp_ = last_fp; | 320 frames_.fp_ = last_fp; |
| 321 frames_.sp_ = 0; | 321 frames_.sp_ = 0; |
| 322 frames_.pc_ = 0; | 322 frames_.pc_ = 0; |
| 323 } | 323 } |
| 324 | 324 |
| 325 | 325 |
| 326 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, | 326 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, |
| 327 bool validate, Isolate* isolate) | 327 bool validate, Thread* thread) |
| 328 : validate_(validate), | 328 : validate_(validate), |
| 329 entry_(isolate), | 329 entry_(thread), |
| 330 exit_(isolate), | 330 exit_(thread), |
| 331 frames_(isolate), | 331 frames_(thread), |
| 332 current_frame_(NULL), | 332 current_frame_(NULL), |
| 333 isolate_(isolate) { | 333 thread_(thread) { |
| 334 ASSERT((isolate_ == Isolate::Current()) || | 334 ASSERT((thread_ == Thread::Current()) || |
| 335 OS::AllowStackFrameIteratorFromAnotherThread()); | 335 OS::AllowStackFrameIteratorFromAnotherThread()); |
| 336 frames_.fp_ = fp; | 336 frames_.fp_ = fp; |
| 337 frames_.sp_ = sp; | 337 frames_.sp_ = sp; |
| 338 frames_.pc_ = pc; | 338 frames_.pc_ = pc; |
| 339 } | 339 } |
| 340 | 340 |
| 341 | 341 |
| 342 StackFrame* StackFrameIterator::NextFrame() { | 342 StackFrame* StackFrameIterator::NextFrame() { |
| 343 // When we are at the start of iteration after having created an | 343 // When we are at the start of iteration after having created an |
| 344 // iterator object, current_frame_ will be NULL as we haven't seen | 344 // iterator object, current_frame_ will be NULL as we haven't seen |
| 345 // any frames yet (unless we start iterating in the simulator from a given | 345 // any frames yet (unless we start iterating in the simulator from a given |
| 346 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries | 346 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries |
| 347 // to set up the next exit frame by reading the top_exit_frame_info | 347 // to set up the next exit frame by reading the top_exit_frame_info |
| 348 // from the isolate. If we do not have any dart invocations yet, | 348 // from the isolate. If we do not have any dart invocations yet, |
| 349 // top_exit_frame_info will be 0 and so we would return NULL. | 349 // top_exit_frame_info will be 0 and so we would return NULL. |
| 350 | 350 |
| 351 // current_frame_ will also be NULL, when we are at the end of having | 351 // current_frame_ will also be NULL, when we are at the end of having |
| 352 // iterated through all the frames. If NextFrame is called at this | 352 // iterated through all the frames. If NextFrame is called at this |
| 353 // point, we will try and set up the next exit frame, but since we are | 353 // point, we will try and set up the next exit frame, but since we are |
| 354 // at the end of the iteration, fp_ will be 0 and we would return NULL. | 354 // at the end of the iteration, fp_ will be 0 and we would return NULL. |
| 355 if (current_frame_ == NULL) { | 355 if (current_frame_ == NULL) { |
| 356 if (!HasNextFrame()) { | 356 if (!HasNextFrame()) { |
| 357 return NULL; | 357 return NULL; |
| 358 } | 358 } |
| 359 UnpoisonStack(isolate_, frames_.fp_); | 359 UnpoisonStack(thread_->isolate(), frames_.fp_); |
| 360 if (frames_.pc_ == 0) { | 360 if (frames_.pc_ == 0) { |
| 361 // Iteration starts from an exit frame given by its fp. | 361 // Iteration starts from an exit frame given by its fp. |
| 362 current_frame_ = NextExitFrame(); | 362 current_frame_ = NextExitFrame(); |
| 363 } else if (*(reinterpret_cast<uword*>( | 363 } else if (*(reinterpret_cast<uword*>( |
| 364 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) { | 364 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) { |
| 365 // Iteration starts from an entry frame given by its fp, sp, and pc. | 365 // Iteration starts from an entry frame given by its fp, sp, and pc. |
| 366 current_frame_ = NextEntryFrame(); | 366 current_frame_ = NextEntryFrame(); |
| 367 } else { | 367 } else { |
| 368 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. | 368 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. |
| 369 current_frame_ = frames_.NextFrame(validate_); | 369 current_frame_ = frames_.NextFrame(validate_); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { | 496 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { |
| 497 return (index - num_materializations_); | 497 return (index - num_materializations_); |
| 498 } | 498 } |
| 499 } | 499 } |
| 500 UNREACHABLE(); | 500 UNREACHABLE(); |
| 501 return 0; | 501 return 0; |
| 502 } | 502 } |
| 503 | 503 |
| 504 | 504 |
| 505 } // namespace dart | 505 } // namespace dart |
| OLD | NEW |