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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 | 261 |
264 bool StackFrame::IsValid() const { | 262 bool StackFrame::IsValid() const { |
265 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { | 263 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) { |
266 return true; | 264 return true; |
267 } | 265 } |
268 return (LookupDartCode() != Code::null()); | 266 return (LookupDartCode() != Code::null()); |
269 } | 267 } |
270 | 268 |
271 | 269 |
272 void StackFrameIterator::SetupLastExitFrameData() { | 270 void StackFrameIterator::SetupLastExitFrameData() { |
273 // This gets called by profiler which may run in a different thread (Windows) | 271 ASSERT(thread_ != NULL); |
274 // but needs the info from mutator_thread instead. | 272 uword exit_marker = thread_->top_exit_frame_info(); |
275 uword exit_marker = isolate_->top_exit_frame_info(); | |
276 frames_.fp_ = exit_marker; | 273 frames_.fp_ = exit_marker; |
277 } | 274 } |
278 | 275 |
279 | 276 |
280 void StackFrameIterator::SetupNextExitFrameData() { | 277 void StackFrameIterator::SetupNextExitFrameData() { |
281 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); | 278 uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize); |
282 uword exit_marker = *reinterpret_cast<uword*>(exit_address); | 279 uword exit_marker = *reinterpret_cast<uword*>(exit_address); |
283 frames_.fp_ = exit_marker; | 280 frames_.fp_ = exit_marker; |
284 frames_.sp_ = 0; | 281 frames_.sp_ = 0; |
285 frames_.pc_ = 0; | 282 frames_.pc_ = 0; |
286 } | 283 } |
287 | 284 |
288 | 285 |
| 286 // TODO(johnmccutchan): Remove |isolate| argument. |
289 // Tell MemorySanitizer that generated code initializes part of the stack. | 287 // Tell MemorySanitizer that generated code initializes part of the stack. |
290 // 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. |
291 static void UnpoisonStack(Isolate* isolate, uword fp) { | 289 static void UnpoisonStack(Isolate* isolate, uword fp) { |
292 ASSERT(fp != 0); | 290 ASSERT(fp != 0); |
293 uword size = isolate->GetSpecifiedStackSize(); | 291 uword size = isolate->GetSpecifiedStackSize(); |
294 MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size); | 292 MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size); |
295 } | 293 } |
296 | 294 |
297 | 295 |
298 StackFrameIterator::StackFrameIterator(bool validate, Isolate* isolate) | 296 StackFrameIterator::StackFrameIterator(bool validate, Thread* thread) |
299 : validate_(validate), | 297 : validate_(validate), |
300 entry_(isolate), | 298 entry_(thread), |
301 exit_(isolate), | 299 exit_(thread), |
302 frames_(isolate), | 300 frames_(thread), |
303 current_frame_(NULL), | 301 current_frame_(NULL), |
304 isolate_(isolate) { | 302 thread_(thread) { |
305 ASSERT((isolate_ == Isolate::Current()) || | 303 ASSERT((thread_ == Thread::Current()) || |
306 OS::AllowStackFrameIteratorFromAnotherThread()); | 304 OS::AllowStackFrameIteratorFromAnotherThread()); |
307 SetupLastExitFrameData(); // Setup data for last exit frame. | 305 SetupLastExitFrameData(); // Setup data for last exit frame. |
308 } | 306 } |
309 | 307 |
310 | 308 |
311 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate, | 309 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate, |
312 Isolate* isolate) | 310 Thread* thread) |
313 : validate_(validate), | 311 : validate_(validate), |
314 entry_(isolate), | 312 entry_(thread), |
315 exit_(isolate), | 313 exit_(thread), |
316 frames_(isolate), | 314 frames_(thread), |
317 current_frame_(NULL), | 315 current_frame_(NULL), |
318 isolate_(isolate) { | 316 thread_(thread) { |
319 ASSERT((isolate_ == Isolate::Current()) || | 317 ASSERT((thread_ == Thread::Current()) || |
320 OS::AllowStackFrameIteratorFromAnotherThread()); | 318 OS::AllowStackFrameIteratorFromAnotherThread()); |
321 frames_.fp_ = last_fp; | 319 frames_.fp_ = last_fp; |
322 frames_.sp_ = 0; | 320 frames_.sp_ = 0; |
323 frames_.pc_ = 0; | 321 frames_.pc_ = 0; |
324 } | 322 } |
325 | 323 |
326 | 324 |
327 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, | 325 StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, |
328 bool validate, Isolate* isolate) | 326 bool validate, Thread* thread) |
329 : validate_(validate), | 327 : validate_(validate), |
330 entry_(isolate), | 328 entry_(thread), |
331 exit_(isolate), | 329 exit_(thread), |
332 frames_(isolate), | 330 frames_(thread), |
333 current_frame_(NULL), | 331 current_frame_(NULL), |
334 isolate_(isolate) { | 332 thread_(thread) { |
335 ASSERT((isolate_ == Isolate::Current()) || | 333 ASSERT((thread_ == Thread::Current()) || |
336 OS::AllowStackFrameIteratorFromAnotherThread()); | 334 OS::AllowStackFrameIteratorFromAnotherThread()); |
337 frames_.fp_ = fp; | 335 frames_.fp_ = fp; |
338 frames_.sp_ = sp; | 336 frames_.sp_ = sp; |
339 frames_.pc_ = pc; | 337 frames_.pc_ = pc; |
340 } | 338 } |
341 | 339 |
342 | 340 |
343 StackFrame* StackFrameIterator::NextFrame() { | 341 StackFrame* StackFrameIterator::NextFrame() { |
344 // When we are at the start of iteration after having created an | 342 // When we are at the start of iteration after having created an |
345 // iterator object, current_frame_ will be NULL as we haven't seen | 343 // iterator object, current_frame_ will be NULL as we haven't seen |
346 // any frames yet (unless we start iterating in the simulator from a given | 344 // any frames yet (unless we start iterating in the simulator from a given |
347 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries | 345 // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries |
348 // to set up the next exit frame by reading the top_exit_frame_info | 346 // to set up the next exit frame by reading the top_exit_frame_info |
349 // from the isolate. If we do not have any dart invocations yet, | 347 // from the isolate. If we do not have any dart invocations yet, |
350 // top_exit_frame_info will be 0 and so we would return NULL. | 348 // top_exit_frame_info will be 0 and so we would return NULL. |
351 | 349 |
352 // current_frame_ will also be NULL, when we are at the end of having | 350 // current_frame_ will also be NULL, when we are at the end of having |
353 // iterated through all the frames. If NextFrame is called at this | 351 // iterated through all the frames. If NextFrame is called at this |
354 // point, we will try and set up the next exit frame, but since we are | 352 // point, we will try and set up the next exit frame, but since we are |
355 // at the end of the iteration, fp_ will be 0 and we would return NULL. | 353 // at the end of the iteration, fp_ will be 0 and we would return NULL. |
356 if (current_frame_ == NULL) { | 354 if (current_frame_ == NULL) { |
357 if (!HasNextFrame()) { | 355 if (!HasNextFrame()) { |
358 return NULL; | 356 return NULL; |
359 } | 357 } |
360 UnpoisonStack(isolate_, frames_.fp_); | 358 UnpoisonStack(thread_->isolate(), frames_.fp_); |
361 if (frames_.pc_ == 0) { | 359 if (frames_.pc_ == 0) { |
362 // Iteration starts from an exit frame given by its fp. | 360 // Iteration starts from an exit frame given by its fp. |
363 current_frame_ = NextExitFrame(); | 361 current_frame_ = NextExitFrame(); |
364 } else if (*(reinterpret_cast<uword*>( | 362 } else if (*(reinterpret_cast<uword*>( |
365 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) { | 363 frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) { |
366 // Iteration starts from an entry frame given by its fp, sp, and pc. | 364 // Iteration starts from an entry frame given by its fp, sp, and pc. |
367 current_frame_ = NextEntryFrame(); | 365 current_frame_ = NextEntryFrame(); |
368 } else { | 366 } else { |
369 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. | 367 // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. |
370 current_frame_ = frames_.NextFrame(validate_); | 368 current_frame_ = frames_.NextFrame(validate_); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { | 495 if (deopt_instr->kind() == DeoptInstr::kCallerFp) { |
498 return (index - num_materializations_); | 496 return (index - num_materializations_); |
499 } | 497 } |
500 } | 498 } |
501 UNREACHABLE(); | 499 UNREACHABLE(); |
502 return 0; | 500 return 0; |
503 } | 501 } |
504 | 502 |
505 | 503 |
506 } // namespace dart | 504 } // namespace dart |
OLD | NEW |