| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 #ifndef RUNTIME_VM_STACK_FRAME_H_ | 5 #ifndef RUNTIME_VM_STACK_FRAME_H_ |
| 6 #define RUNTIME_VM_STACK_FRAME_H_ | 6 #define RUNTIME_VM_STACK_FRAME_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/stub_code.h" | 10 #include "vm/stub_code.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 namespace dart { | 28 namespace dart { |
| 29 | 29 |
| 30 // Forward declarations. | 30 // Forward declarations. |
| 31 class ObjectPointerVisitor; | 31 class ObjectPointerVisitor; |
| 32 class RawContext; | 32 class RawContext; |
| 33 | 33 |
| 34 | 34 |
| 35 // Generic stack frame. | 35 // Generic stack frame. |
| 36 class StackFrame : public ValueObject { | 36 class StackFrame : public ValueObject { |
| 37 public: | 37 public: |
| 38 virtual ~StackFrame() { } | 38 virtual ~StackFrame() {} |
| 39 | 39 |
| 40 // Accessors to get the pc, sp and fp of a frame. | 40 // Accessors to get the pc, sp and fp of a frame. |
| 41 uword sp() const { return sp_; } | 41 uword sp() const { return sp_; } |
| 42 uword fp() const { return fp_; } | 42 uword fp() const { return fp_; } |
| 43 uword pc() const { return pc_; } | 43 uword pc() const { return pc_; } |
| 44 | 44 |
| 45 // The pool pointer is not implemented on all architectures. | 45 // The pool pointer is not implemented on all architectures. |
| 46 static int SavedCallerPpSlotFromFp() { | 46 static int SavedCallerPpSlotFromFp() { |
| 47 if (kSavedCallerPpSlotFromFp != kSavedCallerFpSlotFromFp) { | 47 if (kSavedCallerPpSlotFromFp != kSavedCallerFpSlotFromFp) { |
| 48 return kSavedCallerPpSlotFromFp; | 48 return kSavedCallerPpSlotFromFp; |
| 49 } | 49 } |
| 50 UNREACHABLE(); | 50 UNREACHABLE(); |
| 51 return 0; | 51 return 0; |
| 52 } | 52 } |
| 53 | 53 |
| 54 uword IsMarkedForLazyDeopt() const { | 54 uword IsMarkedForLazyDeopt() const { |
| 55 uword raw_pc = *reinterpret_cast<uword*>( | 55 uword raw_pc = |
| 56 sp() + (kSavedPcSlotFromSp * kWordSize)); | 56 *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize)); |
| 57 return raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint(); | 57 return raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint(); |
| 58 } | 58 } |
| 59 void MarkForLazyDeopt() { | 59 void MarkForLazyDeopt() { |
| 60 set_pc(StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()); | 60 set_pc(StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()); |
| 61 } | 61 } |
| 62 void UnmarkForLazyDeopt() { | 62 void UnmarkForLazyDeopt() { |
| 63 // If this frame was marked for lazy deopt, pc_ was computed to be the | 63 // If this frame was marked for lazy deopt, pc_ was computed to be the |
| 64 // original return address using the pending deopts table in GetCallerPc. | 64 // original return address using the pending deopts table in GetCallerPc. |
| 65 // Write this value back into the frame. | 65 // Write this value back into the frame. |
| 66 uword original_pc = pc(); | 66 uword original_pc = pc(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 RawCode* LookupDartCode() const; | 100 RawCode* LookupDartCode() const; |
| 101 bool FindExceptionHandler(Thread* thread, | 101 bool FindExceptionHandler(Thread* thread, |
| 102 uword* handler_pc, | 102 uword* handler_pc, |
| 103 bool* needs_stacktrace, | 103 bool* needs_stacktrace, |
| 104 bool* is_catch_all) const; | 104 bool* is_catch_all) const; |
| 105 // Returns token_pos of the pc(), or -1 if none exists. | 105 // Returns token_pos of the pc(), or -1 if none exists. |
| 106 TokenPosition GetTokenPos() const; | 106 TokenPosition GetTokenPos() const; |
| 107 | 107 |
| 108 protected: | 108 protected: |
| 109 explicit StackFrame(Thread* thread) | 109 explicit StackFrame(Thread* thread) |
| 110 : fp_(0), sp_(0), pc_(0), thread_(thread) { } | 110 : fp_(0), sp_(0), pc_(0), thread_(thread) {} |
| 111 | 111 |
| 112 // Name of the frame, used for generic frame printing functionality. | 112 // Name of the frame, used for generic frame printing functionality. |
| 113 virtual const char* GetName() const { return IsStubFrame()? "stub" : "dart"; } | 113 virtual const char* GetName() const { |
| 114 return IsStubFrame() ? "stub" : "dart"; |
| 115 } |
| 114 | 116 |
| 115 Isolate* isolate() const { return thread_->isolate(); } | 117 Isolate* isolate() const { return thread_->isolate(); } |
| 116 | 118 |
| 117 Thread* thread() const { return thread_; } | 119 Thread* thread() const { return thread_; } |
| 118 | 120 |
| 119 private: | 121 private: |
| 120 RawCode* GetCodeObject() const; | 122 RawCode* GetCodeObject() const; |
| 121 | 123 |
| 122 uword GetCallerSp() const { | 124 uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); } |
| 123 return fp() + (kCallerSpSlotFromFp * kWordSize); | |
| 124 } | |
| 125 | 125 |
| 126 uword GetCallerFp() const { | 126 uword GetCallerFp() const { |
| 127 return *(reinterpret_cast<uword*>( | 127 return *(reinterpret_cast<uword*>(fp() + |
| 128 fp() + (kSavedCallerFpSlotFromFp * kWordSize))); | 128 (kSavedCallerFpSlotFromFp * kWordSize))); |
| 129 } | 129 } |
| 130 | 130 |
| 131 uword GetCallerPc() const { | 131 uword GetCallerPc() const { |
| 132 uword raw_pc = *(reinterpret_cast<uword*>( | 132 uword raw_pc = *(reinterpret_cast<uword*>( |
| 133 fp() + (kSavedCallerPcSlotFromFp * kWordSize))); | 133 fp() + (kSavedCallerPcSlotFromFp * kWordSize))); |
| 134 ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint()); | 134 ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint()); |
| 135 if (raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()) { | 135 if (raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()) { |
| 136 return isolate()->FindPendingDeopt(GetCallerFp()); | 136 return isolate()->FindPendingDeopt(GetCallerFp()); |
| 137 } | 137 } |
| 138 return raw_pc; | 138 return raw_pc; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 160 bool IsStubFrame() const { return false; } | 160 bool IsStubFrame() const { return false; } |
| 161 bool IsExitFrame() const { return true; } | 161 bool IsExitFrame() const { return true; } |
| 162 | 162 |
| 163 // Visit objects in the frame. | 163 // Visit objects in the frame. |
| 164 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor); | 164 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 165 | 165 |
| 166 protected: | 166 protected: |
| 167 virtual const char* GetName() const { return "exit"; } | 167 virtual const char* GetName() const { return "exit"; } |
| 168 | 168 |
| 169 private: | 169 private: |
| 170 explicit ExitFrame(Thread* thread) : StackFrame(thread) { } | 170 explicit ExitFrame(Thread* thread) : StackFrame(thread) {} |
| 171 | 171 |
| 172 friend class StackFrameIterator; | 172 friend class StackFrameIterator; |
| 173 DISALLOW_COPY_AND_ASSIGN(ExitFrame); | 173 DISALLOW_COPY_AND_ASSIGN(ExitFrame); |
| 174 }; | 174 }; |
| 175 | 175 |
| 176 | 176 |
| 177 // Entry Frame is used to mark the transition from dart VM runtime code into | 177 // Entry Frame is used to mark the transition from dart VM runtime code into |
| 178 // dart code. | 178 // dart code. |
| 179 class EntryFrame : public StackFrame { | 179 class EntryFrame : public StackFrame { |
| 180 public: | 180 public: |
| 181 bool IsValid() const { | 181 bool IsValid() const { return StubCode::InInvocationStub(pc()); } |
| 182 return StubCode::InInvocationStub(pc()); | |
| 183 } | |
| 184 bool IsDartFrame(bool validate = true) const { return false; } | 182 bool IsDartFrame(bool validate = true) const { return false; } |
| 185 bool IsStubFrame() const { return false; } | 183 bool IsStubFrame() const { return false; } |
| 186 bool IsEntryFrame() const { return true; } | 184 bool IsEntryFrame() const { return true; } |
| 187 | 185 |
| 188 // Visit objects in the frame. | 186 // Visit objects in the frame. |
| 189 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor); | 187 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor); |
| 190 | 188 |
| 191 protected: | 189 protected: |
| 192 virtual const char* GetName() const { return "entry"; } | 190 virtual const char* GetName() const { return "entry"; } |
| 193 | 191 |
| 194 private: | 192 private: |
| 195 explicit EntryFrame(Thread* thread) : StackFrame(thread) { } | 193 explicit EntryFrame(Thread* thread) : StackFrame(thread) {} |
| 196 | 194 |
| 197 friend class StackFrameIterator; | 195 friend class StackFrameIterator; |
| 198 DISALLOW_COPY_AND_ASSIGN(EntryFrame); | 196 DISALLOW_COPY_AND_ASSIGN(EntryFrame); |
| 199 }; | 197 }; |
| 200 | 198 |
| 201 | 199 |
| 202 // A StackFrameIterator can be initialized with a thread other than the | 200 // A StackFrameIterator can be initialized with a thread other than the |
| 203 // current thread. Because this is generally a bad idea, it is only allowed on | 201 // current thread. Because this is generally a bad idea, it is only allowed on |
| 204 // Windows- where it is needed for the profiler. It is the responsibility of | 202 // Windows- where it is needed for the profiler. It is the responsibility of |
| 205 // users of StackFrameIterator to ensure that the thread given is not running | 203 // users of StackFrameIterator to ensure that the thread given is not running |
| 206 // concurrently. | 204 // concurrently. |
| 207 class StackFrameIterator : public ValueObject { | 205 class StackFrameIterator : public ValueObject { |
| 208 public: | 206 public: |
| 209 static const bool kValidateFrames = true; | 207 static const bool kValidateFrames = true; |
| 210 static const bool kDontValidateFrames = false; | 208 static const bool kDontValidateFrames = false; |
| 211 | 209 |
| 212 // Iterators for iterating over all frames from the last ExitFrame to the | 210 // Iterators for iterating over all frames from the last ExitFrame to the |
| 213 // first EntryFrame. | 211 // first EntryFrame. |
| 214 StackFrameIterator(bool validate, | 212 explicit StackFrameIterator(bool validate, |
| 215 Thread* thread = Thread::Current()); | 213 Thread* thread = Thread::Current()); |
| 216 StackFrameIterator(uword last_fp, bool validate, | 214 StackFrameIterator(uword last_fp, |
| 215 bool validate, |
| 217 Thread* thread = Thread::Current()); | 216 Thread* thread = Thread::Current()); |
| 218 | 217 |
| 219 #if !defined(TARGET_ARCH_DBC) | 218 #if !defined(TARGET_ARCH_DBC) |
| 220 // Iterator for iterating over all frames from the current frame (given by its | 219 // Iterator for iterating over all frames from the current frame (given by its |
| 221 // fp, sp, and pc) to the first EntryFrame. | 220 // fp, sp, and pc) to the first EntryFrame. |
| 222 StackFrameIterator(uword fp, uword sp, uword pc, bool validate, | 221 StackFrameIterator(uword fp, |
| 222 uword sp, |
| 223 uword pc, |
| 224 bool validate, |
| 223 Thread* thread = Thread::Current()); | 225 Thread* thread = Thread::Current()); |
| 224 #endif | 226 #endif |
| 225 | 227 |
| 226 // Checks if a next frame exists. | 228 // Checks if a next frame exists. |
| 227 bool HasNextFrame() const { return frames_.fp_ != 0; } | 229 bool HasNextFrame() const { return frames_.fp_ != 0; } |
| 228 | 230 |
| 229 // Get next frame. | 231 // Get next frame. |
| 230 StackFrame* NextFrame(); | 232 StackFrame* NextFrame(); |
| 231 | 233 |
| 232 bool validate() const { return validate_; } | 234 bool validate() const { return validate_; } |
| 233 | 235 |
| 234 private: | 236 private: |
| 235 // Iterator for iterating over the set of frames (dart or stub) which exist | 237 // Iterator for iterating over the set of frames (dart or stub) which exist |
| 236 // in one EntryFrame and ExitFrame block. | 238 // in one EntryFrame and ExitFrame block. |
| 237 class FrameSetIterator : public ValueObject { | 239 class FrameSetIterator : public ValueObject { |
| 238 public: | 240 public: |
| 239 // Checks if a next non entry/exit frame exists in the set. | 241 // Checks if a next non entry/exit frame exists in the set. |
| 240 bool HasNext() const { | 242 bool HasNext() const { |
| 241 if (fp_ == 0) { | 243 if (fp_ == 0) { |
| 242 return false; | 244 return false; |
| 243 } | 245 } |
| 244 const uword pc = *(reinterpret_cast<uword*>( | 246 const uword pc = |
| 245 sp_ + (kSavedPcSlotFromSp * kWordSize))); | 247 *(reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize))); |
| 246 return !StubCode::InInvocationStub(pc); | 248 return !StubCode::InInvocationStub(pc); |
| 247 } | 249 } |
| 248 | 250 |
| 249 // Get next non entry/exit frame in the set (assumes a next frame exists). | 251 // Get next non entry/exit frame in the set (assumes a next frame exists). |
| 250 StackFrame* NextFrame(bool validate); | 252 StackFrame* NextFrame(bool validate); |
| 251 | 253 |
| 252 private: | 254 private: |
| 253 explicit FrameSetIterator(Thread* thread) | 255 explicit FrameSetIterator(Thread* thread) |
| 254 : fp_(0), sp_(0), pc_(0), stack_frame_(thread), thread_(thread) { } | 256 : fp_(0), sp_(0), pc_(0), stack_frame_(thread), thread_(thread) {} |
| 255 uword fp_; | 257 uword fp_; |
| 256 uword sp_; | 258 uword sp_; |
| 257 uword pc_; | 259 uword pc_; |
| 258 StackFrame stack_frame_; // Singleton frame returned by NextFrame(). | 260 StackFrame stack_frame_; // Singleton frame returned by NextFrame(). |
| 259 Thread* thread_; | 261 Thread* thread_; |
| 260 | 262 |
| 261 friend class StackFrameIterator; | 263 friend class StackFrameIterator; |
| 262 DISALLOW_COPY_AND_ASSIGN(FrameSetIterator); | 264 DISALLOW_COPY_AND_ASSIGN(FrameSetIterator); |
| 263 }; | 265 }; |
| 264 | 266 |
| 265 // Get next exit frame. | 267 // Get next exit frame. |
| 266 ExitFrame* NextExitFrame(); | 268 ExitFrame* NextExitFrame(); |
| 267 | 269 |
| 268 // Get next entry frame. | 270 // Get next entry frame. |
| 269 EntryFrame* NextEntryFrame(); | 271 EntryFrame* NextEntryFrame(); |
| 270 | 272 |
| 271 // Get an iterator to the next set of frames between an entry and exit | 273 // Get an iterator to the next set of frames between an entry and exit |
| 272 // frame. | 274 // frame. |
| 273 FrameSetIterator* NextFrameSet() { return &frames_; } | 275 FrameSetIterator* NextFrameSet() { return &frames_; } |
| 274 | 276 |
| 275 // Setup last or next exit frames so that we are ready to iterate over | 277 // Setup last or next exit frames so that we are ready to iterate over |
| 276 // stack frames. | 278 // stack frames. |
| 277 void SetupLastExitFrameData(); | 279 void SetupLastExitFrameData(); |
| 278 void SetupNextExitFrameData(); | 280 void SetupNextExitFrameData(); |
| 279 | 281 |
| 280 bool validate_; // Validate each frame as we traverse the frames. | 282 bool validate_; // Validate each frame as we traverse the frames. |
| 281 EntryFrame entry_; // Singleton entry frame returned by NextEntryFrame(). | 283 EntryFrame entry_; // Singleton entry frame returned by NextEntryFrame(). |
| 282 ExitFrame exit_; // Singleton exit frame returned by NextExitFrame(). | 284 ExitFrame exit_; // Singleton exit frame returned by NextExitFrame(). |
| 283 FrameSetIterator frames_; | 285 FrameSetIterator frames_; |
| 284 StackFrame* current_frame_; // Points to the current frame in the iterator. | 286 StackFrame* current_frame_; // Points to the current frame in the iterator. |
| 285 Thread* thread_; | 287 Thread* thread_; |
| 286 | 288 |
| 287 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); | 289 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); |
| 288 }; | 290 }; |
| 289 | 291 |
| 290 | 292 |
| 291 // Iterator for iterating over all dart frames (skips over exit frames, | 293 // Iterator for iterating over all dart frames (skips over exit frames, |
| 292 // entry frames and stub frames). | 294 // entry frames and stub frames). |
| 293 // A DartFrameIterator can be initialized with an isolate other than the | 295 // A DartFrameIterator can be initialized with an isolate other than the |
| 294 // current thread's isolate. Because this is generally a bad idea, | 296 // current thread's isolate. Because this is generally a bad idea, |
| 295 // it is only allowed on Windows- where it is needed for the profiler. | 297 // it is only allowed on Windows- where it is needed for the profiler. |
| 296 // It is the responsibility of users of DartFrameIterator to ensure that the | 298 // It is the responsibility of users of DartFrameIterator to ensure that the |
| 297 // isolate given is not running concurrently on another thread. | 299 // isolate given is not running concurrently on another thread. |
| 298 class DartFrameIterator : public ValueObject { | 300 class DartFrameIterator : public ValueObject { |
| 299 public: | 301 public: |
| 300 explicit DartFrameIterator(Thread* thread = Thread::Current()) | 302 explicit DartFrameIterator(Thread* thread = Thread::Current()) |
| 301 : frames_(StackFrameIterator::kDontValidateFrames, thread) { } | 303 : frames_(StackFrameIterator::kDontValidateFrames, thread) {} |
| 302 DartFrameIterator(uword last_fp, | 304 explicit DartFrameIterator(uword last_fp, Thread* thread = Thread::Current()) |
| 303 Thread* thread = Thread::Current()) | 305 : frames_(last_fp, StackFrameIterator::kDontValidateFrames, thread) {} |
| 304 : frames_(last_fp, StackFrameIterator::kDontValidateFrames, thread) { } | |
| 305 | 306 |
| 306 #if !defined(TARGET_ARCH_DBC) | 307 #if !defined(TARGET_ARCH_DBC) |
| 307 DartFrameIterator(uword fp, | 308 DartFrameIterator(uword fp, |
| 308 uword sp, | 309 uword sp, |
| 309 uword pc, | 310 uword pc, |
| 310 Thread* thread = Thread::Current()) | 311 Thread* thread = Thread::Current()) |
| 311 : frames_(fp, sp, pc, | 312 : frames_(fp, sp, pc, StackFrameIterator::kDontValidateFrames, thread) {} |
| 312 StackFrameIterator::kDontValidateFrames, thread) { | |
| 313 } | |
| 314 #endif | 313 #endif |
| 315 | 314 |
| 316 // Get next dart frame. | 315 // Get next dart frame. |
| 317 StackFrame* NextFrame() { | 316 StackFrame* NextFrame() { |
| 318 StackFrame* frame = frames_.NextFrame(); | 317 StackFrame* frame = frames_.NextFrame(); |
| 319 while (frame != NULL && !frame->IsDartFrame(frames_.validate())) { | 318 while (frame != NULL && !frame->IsDartFrame(frames_.validate())) { |
| 320 frame = frames_.NextFrame(); | 319 frame = frames_.NextFrame(); |
| 321 } | 320 } |
| 322 return frame; | 321 return frame; |
| 323 } | 322 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 | 400 |
| 402 | 401 |
| 403 DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) { | 402 DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) { |
| 404 return fp + LocalVarIndex(0, index) * kWordSize; | 403 return fp + LocalVarIndex(0, index) * kWordSize; |
| 405 } | 404 } |
| 406 | 405 |
| 407 | 406 |
| 408 } // namespace dart | 407 } // namespace dart |
| 409 | 408 |
| 410 #endif // RUNTIME_VM_STACK_FRAME_H_ | 409 #endif // RUNTIME_VM_STACK_FRAME_H_ |
| OLD | NEW |