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 |