Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | Protected Member Functions | Friends | List of all members
dart::StackFrame Class Reference

#include <stack_frame.h>

Inheritance diagram for dart::StackFrame:
dart::ValueObject dart::EntryFrame dart::ExitFrame

Public Member Functions

virtual ~StackFrame ()
 
uword sp () const
 
uword fp () const
 
uword pc () const
 
bool IsMarkedForLazyDeopt () const
 
void MarkForLazyDeopt ()
 
void UnmarkForLazyDeopt ()
 
void set_pc (uword value)
 
void set_pc_marker (CodePtr code)
 
virtual void VisitObjectPointers (ObjectPointerVisitor *visitor)
 
const char * ToCString () const
 
virtual bool IsValid () const
 
bool IsBareInstructionsDartFrame () const
 
bool IsBareInstructionsStubFrame () const
 
virtual bool IsDartFrame (bool validate=true) const
 
virtual bool IsStubFrame () const
 
virtual bool IsEntryFrame () const
 
virtual bool IsExitFrame () const
 
FunctionPtr LookupDartFunction () const
 
CodePtr LookupDartCode () const
 
bool FindExceptionHandler (Thread *thread, uword *handler_pc, bool *needs_stacktrace, bool *is_catch_all, bool *is_optimized) const
 
TokenPosition GetTokenPos () const
 
uword GetCallerSp () const
 
- Public Member Functions inherited from dart::ValueObject
 ValueObject ()
 
 ~ValueObject ()
 

Static Public Member Functions

static int SavedCallerPpSlotFromFp ()
 
static void DumpCurrentTrace ()
 

Protected Member Functions

 StackFrame (Thread *thread)
 
virtual const char * GetName () const
 
Isolateisolate () const
 
IsolateGroupisolate_group () const
 
Threadthread () const
 

Friends

class FrameSetIterator
 
class StackFrameIterator
 
class UntaggedSuspendState
 
class ProfilerDartStackWalker
 

Detailed Description

Definition at line 36 of file stack_frame.h.

Constructor & Destructor Documentation

◆ ~StackFrame()

virtual dart::StackFrame::~StackFrame ( )
inlinevirtual

Definition at line 38 of file stack_frame.h.

38{}

◆ StackFrame()

dart::StackFrame::StackFrame ( Thread thread)
inlineexplicitprotected

Definition at line 120 of file stack_frame.h.

121 : fp_(0), sp_(0), pc_(0), thread_(thread) {}
Thread * thread() const
Definition: stack_frame.h:133

Member Function Documentation

◆ DumpCurrentTrace()

void dart::StackFrame::DumpCurrentTrace ( )
static

Definition at line 454 of file stack_frame.cc.

454 {
458 StackFrame* frame = frames.NextFrame();
459 while (frame != nullptr) {
460 OS::PrintErr("%s\n", frame->ToCString());
461 frame = frames.NextFrame();
462 }
463}
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
friend class StackFrameIterator
Definition: stack_frame.h:161
StackFrame(Thread *thread)
Definition: stack_frame.h:120
static Thread * Current()
Definition: thread.h:362
double frame
Definition: examples.cpp:31

◆ FindExceptionHandler()

bool dart::StackFrame::FindExceptionHandler ( Thread thread,
uword handler_pc,
bool *  needs_stacktrace,
bool *  is_catch_all,
bool *  is_optimized 
) const

Definition at line 370 of file stack_frame.cc.

374 {
376 Code& code = reused_code_handle.Handle();
378 ExceptionHandlers& handlers = reused_exception_handlers_handle.Handle();
380 PcDescriptors& descriptors = reused_pc_descriptors_handle.Handle();
381 uword start;
383 if (code.IsNull()) {
384 return false; // Stub frames do not have exception handlers.
385 }
386 start = code.PayloadStart();
387 handlers = code.exception_handlers();
388 descriptors = code.pc_descriptors();
389 *is_optimized = code.is_optimized();
391 ExceptionHandlerInfo* info = cache->Lookup(pc());
392 if (info != nullptr) {
393 *handler_pc = start + info->handler_pc_offset;
394 *needs_stacktrace = (info->needs_stacktrace != 0);
395 *has_catch_all = (info->has_catch_all != 0);
396 return true;
397 }
398
399 intptr_t try_index = -1;
400 if (handlers.num_entries() != 0) {
401 uword pc_offset = pc() - code.PayloadStart();
402 PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
403 while (iter.MoveNext()) {
404 const intptr_t current_try_index = iter.TryIndex();
405 if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
406 try_index = current_try_index;
407 break;
408 }
409 }
410 }
411 if (try_index == -1) {
412 if (handlers.has_async_handler()) {
413 *handler_pc = StubCode::AsyncExceptionHandler().EntryPoint();
414 *needs_stacktrace = true;
415 *has_catch_all = true;
416 return true;
417 }
418 return false;
419 }
420 ExceptionHandlerInfo handler_info;
421 handlers.GetHandlerInfo(try_index, &handler_info);
422 *handler_pc = start + handler_info.handler_pc_offset;
423 *needs_stacktrace = (handler_info.needs_stacktrace != 0);
424 *has_catch_all = (handler_info.has_catch_all != 0);
425 cache->Insert(pc(), handler_info);
426 return true;
427}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
HandlerInfoCache * handler_info_cache()
Definition: isolate.h:1450
uword pc() const
Definition: stack_frame.h:43
CodePtr LookupDartCode() const
Definition: stack_frame.cc:336
Isolate * isolate() const
Definition: thread.h:534
FixedCache< intptr_t, ExceptionHandlerInfo, 16 > HandlerInfoCache
Definition: isolate.h:128
uintptr_t uword
Definition: globals.h:501
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
Definition: switches.h:191
#define REUSABLE_PC_DESCRIPTORS_HANDLESCOPE(thread)
#define REUSABLE_EXCEPTION_HANDLERS_HANDLESCOPE(thread)
#define REUSABLE_CODE_HANDLESCOPE(thread)

◆ fp()

uword dart::StackFrame::fp ( ) const
inline

Definition at line 42 of file stack_frame.h.

42{ return fp_; }

◆ GetCallerSp()

uword dart::StackFrame::GetCallerSp ( ) const
inline

Definition at line 117 of file stack_frame.h.

117{ return fp() + (kCallerSpSlotFromFp * kWordSize); }
uword fp() const
Definition: stack_frame.h:42
static constexpr int kCallerSpSlotFromFp
constexpr intptr_t kWordSize
Definition: globals.h:509

◆ GetName()

virtual const char * dart::StackFrame::GetName ( ) const
inlineprotectedvirtual

Reimplemented in dart::ExitFrame, and dart::EntryFrame.

Definition at line 124 of file stack_frame.h.

124 {
125 if (IsBareInstructionsStubFrame()) return "bare-stub";
126 if (IsStubFrame()) return "stub";
127 return IsBareInstructionsDartFrame() ? "bare-dart" : "dart";
128 }
virtual bool IsStubFrame() const
Definition: stack_frame.cc:150
bool IsBareInstructionsStubFrame() const
Definition: stack_frame.cc:132
bool IsBareInstructionsDartFrame() const
Definition: stack_frame.cc:114

◆ GetTokenPos()

TokenPosition dart::StackFrame::GetTokenPos ( ) const

Definition at line 429 of file stack_frame.cc.

429 {
430 const Code& code = Code::Handle(LookupDartCode());
431 if (code.IsNull()) {
432 return TokenPosition::kNoSource; // Stub frames do not have token_pos.
433 }
434 uword pc_offset = pc() - code.PayloadStart();
435 const PcDescriptors& descriptors =
436 PcDescriptors::Handle(code.pc_descriptors());
437 ASSERT(!descriptors.IsNull());
438 PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
439 while (iter.MoveNext()) {
440 if (iter.PcOffset() == pc_offset) {
441 return TokenPosition(iter.TokenPos());
442 }
443 }
444 return TokenPosition::kNoSource;
445}
static Object & Handle()
Definition: object.h:407
#define ASSERT(E)

◆ IsBareInstructionsDartFrame()

bool dart::StackFrame::IsBareInstructionsDartFrame ( ) const

Definition at line 114 of file stack_frame.cc.

114 {
115 if (!FLAG_precompiled_mode) {
116 return false;
117 }
118 NoSafepointScope no_safepoint;
119
120 Code code;
122 /*is_return_address=*/true);
123 if (!code.IsNull()) {
124 auto const cid = code.OwnerClassId();
125 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
126 return cid == kFunctionCid;
127 }
128
129 return false;
130}
static CodePtr Lookup(IsolateGroup *group, uword pc, bool is_return_address)
IsolateGroup * isolate_group() const
Definition: stack_frame.h:131
@ kNullCid
Definition: class_id.h:252
const intptr_t cid

◆ IsBareInstructionsStubFrame()

bool dart::StackFrame::IsBareInstructionsStubFrame ( ) const

Definition at line 132 of file stack_frame.cc.

132 {
133 if (!FLAG_precompiled_mode) {
134 return false;
135 }
136 NoSafepointScope no_safepoint;
137
138 Code code;
140 /*is_return_address=*/true);
141 if (!code.IsNull()) {
142 auto const cid = code.OwnerClassId();
143 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
144 return cid == kNullCid || cid == kClassCid;
145 }
146
147 return false;
148}

◆ IsDartFrame()

virtual bool dart::StackFrame::IsDartFrame ( bool  validate = true) const
inlinevirtual

Reimplemented in dart::ExitFrame, and dart::EntryFrame.

Definition at line 97 of file stack_frame.h.

97 {
98 ASSERT(!validate || IsValid());
99 return !(IsEntryFrame() || IsExitFrame() || IsStubFrame());
100 }
virtual bool IsEntryFrame() const
Definition: stack_frame.h:102
virtual bool IsExitFrame() const
Definition: stack_frame.h:103
virtual bool IsValid() const
Definition: stack_frame.cc:447

◆ IsEntryFrame()

virtual bool dart::StackFrame::IsEntryFrame ( ) const
inlinevirtual

Reimplemented in dart::EntryFrame.

Definition at line 102 of file stack_frame.h.

102{ return false; }

◆ IsExitFrame()

virtual bool dart::StackFrame::IsExitFrame ( ) const
inlinevirtual

Reimplemented in dart::ExitFrame.

Definition at line 103 of file stack_frame.h.

103{ return false; }

◆ IsMarkedForLazyDeopt()

bool dart::StackFrame::IsMarkedForLazyDeopt ( ) const
inline

Definition at line 55 of file stack_frame.h.

55 {
56 uword raw_pc =
57 *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize));
58 return raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint();
59 }
uword sp() const
Definition: stack_frame.h:41
static constexpr int kSavedPcSlotFromSp

◆ isolate()

Isolate * dart::StackFrame::isolate ( ) const
inlineprotected

Definition at line 130 of file stack_frame.h.

130{ return thread_->isolate(); }

◆ isolate_group()

IsolateGroup * dart::StackFrame::isolate_group ( ) const
inlineprotected

Definition at line 131 of file stack_frame.h.

131{ return thread_->isolate_group(); }
IsolateGroup * isolate_group() const
Definition: thread.h:541

◆ IsStubFrame()

bool dart::StackFrame::IsStubFrame ( ) const
virtual

Reimplemented in dart::ExitFrame, and dart::EntryFrame.

Definition at line 150 of file stack_frame.cc.

150 {
151 if (FLAG_precompiled_mode) {
153 }
154
156#if !defined(DART_HOST_OS_WINDOWS) && !defined(DART_HOST_OS_FUCHSIA)
157 // On Windows and Fuchsia, the profiler calls this from a separate thread
158 // where Thread::Current() is nullptr, so we cannot create a NoSafepointScope.
159 NoSafepointScope no_safepoint;
160#endif
161
162 CodePtr code = GetCodeObject();
164 auto const cid = Code::OwnerClassIdOf(code);
165 ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
166 return cid == kNullCid || cid == kClassCid;
167}
static classid_t OwnerClassIdOf(CodePtr raw)
Definition: object.h:7141
static ObjectPtr null()
Definition: object.h:433

◆ IsValid()

bool dart::StackFrame::IsValid ( ) const
virtual

Reimplemented in dart::ExitFrame, and dart::EntryFrame.

Definition at line 447 of file stack_frame.cc.

447 {
448 if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) {
449 return true;
450 }
451 return (LookupDartCode() != Code::null());
452}

◆ LookupDartCode()

CodePtr dart::StackFrame::LookupDartCode ( ) const

Definition at line 336 of file stack_frame.cc.

336 {
337// We add a no gc scope to ensure that the code below does not trigger
338// a GC as we are handling raw object references here. It is possible
339// that the code is called while a GC is in progress, that is ok.
340#if !defined(DART_HOST_OS_WINDOWS) && !defined(DART_HOST_OS_FUCHSIA)
341 // On Windows and Fuchsia, the profiler calls this from a separate thread
342 // where Thread::Current() is nullptr, so we cannot create a NoSafepointScope.
343 NoSafepointScope no_safepoint;
344#endif
345 CodePtr code = GetCodeObject();
346 if ((code != Code::null()) && Code::OwnerClassIdOf(code) == kFunctionCid) {
347 return code;
348 }
349 return Code::null();
350}

◆ LookupDartFunction()

FunctionPtr dart::StackFrame::LookupDartFunction ( ) const

Definition at line 325 of file stack_frame.cc.

325 {
326 const Code& code = Code::Handle(LookupDartCode());
327 if (!code.IsNull()) {
328 const Object& owner = Object::Handle(code.owner());
329 if (owner.IsFunction()) {
330 return Function::Cast(owner).ptr();
331 }
332 }
333 return Function::null();
334}

◆ MarkForLazyDeopt()

void dart::StackFrame::MarkForLazyDeopt ( )
inline

Definition at line 60 of file stack_frame.h.

60 {
61 set_pc(StubCode::DeoptimizeLazyFromReturn().EntryPoint());
62 }
void set_pc(uword value)
Definition: stack_frame.h:72

◆ pc()

uword dart::StackFrame::pc ( ) const
inline

Definition at line 43 of file stack_frame.h.

43{ return pc_; }

◆ SavedCallerPpSlotFromFp()

static int dart::StackFrame::SavedCallerPpSlotFromFp ( )
inlinestatic

Definition at line 46 of file stack_frame.h.

46 {
50 }
52 return 0;
53 }
#define UNREACHABLE()
Definition: assert.h:248
static constexpr int kSavedCallerFpSlotFromFp
FrameLayout runtime_frame_layout
Definition: stack_frame.cc:81
intptr_t saved_caller_pp_from_fp
Definition: frame_layout.h:43

◆ set_pc()

void dart::StackFrame::set_pc ( uword  value)
inline

Definition at line 72 of file stack_frame.h.

72 {
73 *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize)) = value;
74 pc_ = value;
75 }
uint8_t value

◆ set_pc_marker()

void dart::StackFrame::set_pc_marker ( CodePtr  code)
inline

Definition at line 77 of file stack_frame.h.

77 {
78 *reinterpret_cast<CodePtr*>(
80 }
intptr_t code_from_fp
Definition: frame_layout.h:52

◆ sp()

uword dart::StackFrame::sp ( ) const
inline

Definition at line 41 of file stack_frame.h.

41{ return sp_; }

◆ thread()

Thread * dart::StackFrame::thread ( ) const
inlineprotected

Definition at line 133 of file stack_frame.h.

133{ return thread_; }

◆ ToCString()

const char * dart::StackFrame::ToCString ( ) const

Definition at line 169 of file stack_frame.cc.

169 {
170 ASSERT(thread_ == Thread::Current());
171 Zone* zone = Thread::Current()->zone();
172 const Code& code = Code::Handle(zone, GetCodeObject());
173 const char* name =
174 code.IsNull()
175 ? "Cannot find code object"
176 : code.QualifiedName(NameFormattingParams(Object::kInternalName));
177 return zone->PrintToString(" pc 0x%" Pp " fp 0x%" Pp " sp 0x%" Pp " %s",
178 pc(), fp(), sp(), name);
179}
@ kInternalName
Definition: object.h:622
Zone * zone() const
Definition: thread_state.h:37
const char *const name
#define Pp
Definition: globals.h:425

◆ UnmarkForLazyDeopt()

void dart::StackFrame::UnmarkForLazyDeopt ( )
inline

Definition at line 63 of file stack_frame.h.

63 {
64 // If this frame was marked for lazy deopt, pc_ was computed to be the
65 // original return address using the pending deopts table in GetCallerPc.
66 // Write this value back into the frame.
67 uword original_pc = pc();
68 ASSERT(original_pc != StubCode::DeoptimizeLazyFromReturn().EntryPoint());
69 set_pc(original_pc);
70 }

◆ VisitObjectPointers()

void dart::StackFrame::VisitObjectPointers ( ObjectPointerVisitor visitor)
virtual

Reimplemented in dart::ExitFrame, and dart::EntryFrame.

Definition at line 206 of file stack_frame.cc.

206 {
207 ASSERT(visitor != nullptr);
208 // NOTE: This code runs while GC is in progress and runs within
209 // a NoHandleScope block. Hence it is not ok to use regular Zone or
210 // Scope handles. We use direct stack handles, the raw pointers in
211 // these handles are not traversed. The use of handles is mainly to
212 // be able to reuse the handle based code and avoid having to add
213 // helper functions to the raw object interface.
214 NoSafepointScope no_safepoint;
215 Code code;
216
217 CompressedStackMaps::RawPayloadHandle maps;
218 CompressedStackMaps::RawPayloadHandle global_table;
219
220 uword code_start;
221
222 if (FLAG_precompiled_mode) {
223 const UntaggedCompressedStackMaps::Payload* global_table_payload;
225 /*is_return_address=*/true, &code_start,
226 &global_table_payload);
227 global_table = global_table_payload;
228 } else {
229 ObjectPtr pc_marker = *(reinterpret_cast<ObjectPtr*>(
231 // May forward raw code. Note we don't just visit the pc marker slot first
232 // because the visitor's forwarding might not be idempotent.
233 visitor->VisitPointer(&pc_marker);
234 if (pc_marker->IsHeapObject() && (pc_marker->GetClassId() == kCodeCid)) {
235 code ^= pc_marker;
236 code_start = code.PayloadStart();
237 ASSERT(code.compressed_stackmaps() != CompressedStackMaps::null());
238 maps = code.compressed_stackmaps();
239 if (maps.UsesGlobalTable()) {
240 global_table =
241 isolate_group()->object_store()->canonicalized_stack_map_entries();
242 }
243 } else {
244 ASSERT(pc_marker == Object::null());
245 }
246 }
247
248 if (!maps.IsNull()) {
249 // Optimized frames have a stack map. We need to visit the frame based
250 // on the stack map.
251 CompressedStackMaps::Iterator<CompressedStackMaps::RawPayloadHandle> it(
252 maps, global_table);
253 const uint32_t pc_offset = pc() - code_start;
254 if (it.Find(pc_offset)) {
255 ObjectPtr* first = reinterpret_cast<ObjectPtr*>(sp());
256 ObjectPtr* last = reinterpret_cast<ObjectPtr*>(
258
259 // A stack map is present in the code object, use the stack map to
260 // visit frame slots which are marked as having objects.
261 //
262 // The layout of the frame is (lower addresses to the right):
263 // | spill slots | outgoing arguments | saved registers | slow-path args |
264 // |XXXXXXXXXXXXX|--------------------|XXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXX|
265 //
266 // The spill slots and any saved registers are described in the stack
267 // map. The outgoing arguments are assumed to be tagged; the number
268 // of outgoing arguments is not explicitly tracked.
269
270 // Spill slots are at the 'bottom' of the frame.
271 intptr_t spill_slot_count = it.SpillSlotBitCount();
272 for (intptr_t bit = 0; bit < spill_slot_count; ++bit) {
273 if (it.IsObject(bit)) {
274 visitor->VisitPointer(last);
275 }
276 --last;
277 }
278
279 // The live registers at the 'top' of the frame comprise the rest of the
280 // stack map.
281 for (intptr_t bit = it.Length() - 1; bit >= spill_slot_count; --bit) {
282 if (it.IsObject(bit)) {
283 visitor->VisitPointer(first);
284 }
285 ++first;
286 }
287
288 // The last slot can be one slot (but not more) past the last slot
289 // in the case that all slots were covered by the stack map.
290 ASSERT((last + 1) >= first);
291 visitor->VisitPointers(first, last);
292
293 // Now visit other slots which might be part of the calling convention.
294 first = reinterpret_cast<ObjectPtr*>(
296 last = reinterpret_cast<ObjectPtr*>(
298 visitor->VisitPointers(first, last);
299 return;
300 }
301
302 // If we are missing a stack map for a given PC offset, this must either be
303 // unoptimized code, code with no stack map information at all, or the entry
304 // to an osr function. In each of these cases, all stack slots contain
305 // tagged pointers, so fall through.
306#if defined(DEBUG)
307 if (FLAG_precompiled_mode) {
309 } else {
310 ASSERT(!code.is_optimized() ||
311 (pc_offset == code.EntryPoint() - code.PayloadStart()));
312 }
313#endif // defined(DEBUG)
314 }
315
316 // For normal unoptimized Dart frames and Stub frames each slot
317 // between the first and last included are tagged objects.
318 ObjectPtr* first = reinterpret_cast<ObjectPtr*>(sp());
319 ObjectPtr* last = reinterpret_cast<ObjectPtr*>(
321
322 visitor->VisitPointers(first, last);
323}
ObjectStore * object_store() const
Definition: isolate.h:510
static const UntaggedCompressedStackMaps::Payload * FindStackMap(IsolateGroup *group, uword pc, bool is_return_address, uword *code_start, const UntaggedCompressedStackMaps::Payload **global_table)
intptr_t first_local_from_fp
Definition: frame_layout.h:37
intptr_t first_object_from_fp
Definition: frame_layout.h:24

Friends And Related Function Documentation

◆ FrameSetIterator

friend class FrameSetIterator
friend

Definition at line 160 of file stack_frame.h.

◆ ProfilerDartStackWalker

friend class ProfilerDartStackWalker
friend

Definition at line 165 of file stack_frame.h.

◆ StackFrameIterator

friend class StackFrameIterator
friend

Definition at line 161 of file stack_frame.h.

◆ UntaggedSuspendState

friend class UntaggedSuspendState
friend

Definition at line 164 of file stack_frame.h.


The documentation for this class was generated from the following files: