@@ -1035,7 +1035,7 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
10351035 uword* exit_fp = reinterpret_cast <uword*>(thread_->top_exit_frame_info ());
10361036 bool has_exit_frame = exit_fp != nullptr ;
10371037 if (has_exit_frame) {
1038- // Exited from compiled code.
1038+ // Exited from compiled code or interpreter .
10391039 pc_ = nullptr ;
10401040 fp_ = exit_fp;
10411041
@@ -1047,17 +1047,27 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
10471047 // Running compiled code.
10481048 // Use the FP and PC from the thread interrupt or simulator; already set
10491049 // in the constructor.
1050+
1051+ #if defined(DART_DYNAMIC_MODULES)
1052+ } else if (thread_->vm_tag () == VMTag::kDartInterpretedTagId ) {
1053+ // Running interpreter.
1054+ pc_ = reinterpret_cast <uword*>(thread_->interpreter ()->get_pc ());
1055+ fp_ = reinterpret_cast <uword*>(thread_->interpreter ()->get_fp ());
1056+ RELEASE_ASSERT (IsInterpretedFrame ());
1057+ #endif
10501058 } else {
10511059 // No Dart on the stack; caller shouldn't use this walker.
10521060 UNREACHABLE ();
10531061 }
10541062
1063+ const bool is_interpreted_frame = IsInterpretedFrame ();
10551064 const bool is_entry_frame =
10561065#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
1057- StubCode::InInvocationStub (Stack (0 )) ||
1058- StubCode::InInvocationStub (Stack (1 ));
1066+ StubCode::InInvocationStub (Stack (0 ), is_interpreted_frame ) ||
1067+ StubCode::InInvocationStub (Stack (1 ), is_interpreted_frame );
10591068#else
1060- StubCode::InInvocationStub (reinterpret_cast <uword>(lr_));
1069+ StubCode::InInvocationStub (reinterpret_cast <uword>(lr_),
1070+ is_interpreted_frame);
10611071#endif
10621072 if (is_entry_frame) {
10631073 // During the prologue of a function, CallerPC will return the caller's
@@ -1075,7 +1085,8 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
10751085
10761086 for (;;) {
10771087 // Skip entry frame.
1078- if (StubCode::InInvocationStub (reinterpret_cast <uword>(pc_))) {
1088+ if (StubCode::InInvocationStub (reinterpret_cast <uword>(pc_),
1089+ IsInterpretedFrame ())) {
10791090 pc_ = nullptr ;
10801091 fp_ = ExitLink ();
10811092 if (fp_ == nullptr ) {
@@ -1087,8 +1098,8 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
10871098 fp_ = CallerFP ();
10881099
10891100 // At least one frame between exit and next entry frame.
1090- RELEASE_ASSERT (
1091- ! StubCode::InInvocationStub ( reinterpret_cast <uword>(pc_ )));
1101+ RELEASE_ASSERT (! StubCode::InInvocationStub ( reinterpret_cast <uword>(pc_),
1102+ IsInterpretedFrame ( )));
10921103 }
10931104
10941105 if (!Append (reinterpret_cast <uword>(pc_), reinterpret_cast <uword>(fp_))) {
@@ -1101,9 +1112,21 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
11011112 }
11021113
11031114 private:
1115+ bool IsInterpretedFrame () const {
1116+ #if defined(DART_DYNAMIC_MODULES)
1117+ Interpreter* interpreter = thread_->interpreter ();
1118+ return (interpreter != nullptr ) &&
1119+ interpreter->HasFrame (reinterpret_cast <uword>(fp_));
1120+ #else
1121+ return false ;
1122+ #endif
1123+ }
1124+
11041125 uword* CallerPC () const {
11051126 ASSERT (fp_ != nullptr );
1106- uword* caller_pc_ptr = fp_ + kSavedCallerPcSlotFromFp ;
1127+ uword* caller_pc_ptr =
1128+ fp_ + (IsInterpretedFrame () ? kKBCSavedCallerPcSlotFromFp
1129+ : kSavedCallerPcSlotFromFp );
11071130 // MSan/ASan are unaware of frames initialized by generated code.
11081131 MSAN_UNPOISON (caller_pc_ptr, kWordSize );
11091132 ASAN_UNPOISON (caller_pc_ptr, kWordSize );
@@ -1112,7 +1135,9 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
11121135
11131136 uword* CallerFP () const {
11141137 ASSERT (fp_ != nullptr );
1115- uword* caller_fp_ptr = fp_ + kSavedCallerFpSlotFromFp ;
1138+ uword* caller_fp_ptr =
1139+ fp_ + (IsInterpretedFrame () ? kKBCSavedCallerFpSlotFromFp
1140+ : kSavedCallerFpSlotFromFp );
11161141 // MSan/ASan are unaware of frames initialized by generated code.
11171142 MSAN_UNPOISON (caller_fp_ptr, kWordSize );
11181143 ASAN_UNPOISON (caller_fp_ptr, kWordSize );
@@ -1121,7 +1146,9 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
11211146
11221147 uword* ExitLink () const {
11231148 ASSERT (fp_ != nullptr );
1124- uword* exit_link_ptr = fp_ + kExitLinkSlotFromEntryFp ;
1149+ uword* exit_link_ptr =
1150+ fp_ + (IsInterpretedFrame () ? kKBCExitLinkSlotFromEntryFp
1151+ : kExitLinkSlotFromEntryFp );
11251152 // MSan/ASan are unaware of frames initialized by generated code.
11261153 MSAN_UNPOISON (exit_link_ptr, kWordSize );
11271154 ASAN_UNPOISON (exit_link_ptr, kWordSize );
@@ -1503,6 +1530,8 @@ class CodeLookupTableBuilder : public ObjectVisitor {
15031530 void VisitObject (ObjectPtr raw_obj) override {
15041531 if (raw_obj->IsCode () && !Code::IsUnknownDartCode (Code::RawCast (raw_obj))) {
15051532 table_->Add (Code::Handle (Code::RawCast (raw_obj)));
1533+ } else if (raw_obj->IsBytecode ()) {
1534+ table_->Add (Bytecode::Handle (Bytecode::RawCast (raw_obj)));
15061535 }
15071536 }
15081537
@@ -1555,7 +1584,7 @@ void CodeLookupTable::Build(Thread* thread) {
15551584
15561585void CodeLookupTable::Add (const Object& code) {
15571586 ASSERT (!code.IsNull ());
1558- ASSERT (code.IsCode ());
1587+ ASSERT (code.IsCode () || code. IsBytecode () );
15591588 CodeDescriptor* cd = new CodeDescriptor (AbstractCode (code.ptr ()));
15601589 code_objects_.Add (cd);
15611590}
@@ -1736,6 +1765,11 @@ void ProcessedSample::CheckForMissingDartFrame(const CodeLookupTable& clt,
17361765 uword pc_marker,
17371766 uword* stack_buffer) {
17381767 ASSERT (cd != nullptr );
1768+ if (cd->code ().IsBytecode ()) {
1769+ // Bytecode frame build is atomic from the profiler's perspective,
1770+ // there are no missing frames.
1771+ return ;
1772+ }
17391773 const Code& code = Code::Handle (Code::RawCast (cd->code ().ptr ()));
17401774 ASSERT (!code.IsNull ());
17411775 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
0 commit comments