@@ -1035,7 +1035,7 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1035
1035
uword* exit_fp = reinterpret_cast <uword*>(thread_->top_exit_frame_info ());
1036
1036
bool has_exit_frame = exit_fp != nullptr ;
1037
1037
if (has_exit_frame) {
1038
- // Exited from compiled code.
1038
+ // Exited from compiled code or interpreter .
1039
1039
pc_ = nullptr ;
1040
1040
fp_ = exit_fp;
1041
1041
@@ -1047,17 +1047,27 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1047
1047
// Running compiled code.
1048
1048
// Use the FP and PC from the thread interrupt or simulator; already set
1049
1049
// 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
1050
1058
} else {
1051
1059
// No Dart on the stack; caller shouldn't use this walker.
1052
1060
UNREACHABLE ();
1053
1061
}
1054
1062
1063
+ const bool is_interpreted_frame = IsInterpretedFrame ();
1055
1064
const bool is_entry_frame =
1056
1065
#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 );
1059
1068
#else
1060
- StubCode::InInvocationStub (reinterpret_cast <uword>(lr_));
1069
+ StubCode::InInvocationStub (reinterpret_cast <uword>(lr_),
1070
+ is_interpreted_frame);
1061
1071
#endif
1062
1072
if (is_entry_frame) {
1063
1073
// During the prologue of a function, CallerPC will return the caller's
@@ -1075,7 +1085,8 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1075
1085
1076
1086
for (;;) {
1077
1087
// Skip entry frame.
1078
- if (StubCode::InInvocationStub (reinterpret_cast <uword>(pc_))) {
1088
+ if (StubCode::InInvocationStub (reinterpret_cast <uword>(pc_),
1089
+ IsInterpretedFrame ())) {
1079
1090
pc_ = nullptr ;
1080
1091
fp_ = ExitLink ();
1081
1092
if (fp_ == nullptr ) {
@@ -1087,8 +1098,8 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1087
1098
fp_ = CallerFP ();
1088
1099
1089
1100
// 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 ( )));
1092
1103
}
1093
1104
1094
1105
if (!Append (reinterpret_cast <uword>(pc_), reinterpret_cast <uword>(fp_))) {
@@ -1101,9 +1112,21 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1101
1112
}
1102
1113
1103
1114
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
+
1104
1125
uword* CallerPC () const {
1105
1126
ASSERT (fp_ != nullptr );
1106
- uword* caller_pc_ptr = fp_ + kSavedCallerPcSlotFromFp ;
1127
+ uword* caller_pc_ptr =
1128
+ fp_ + (IsInterpretedFrame () ? kKBCSavedCallerPcSlotFromFp
1129
+ : kSavedCallerPcSlotFromFp );
1107
1130
// MSan/ASan are unaware of frames initialized by generated code.
1108
1131
MSAN_UNPOISON (caller_pc_ptr, kWordSize );
1109
1132
ASAN_UNPOISON (caller_pc_ptr, kWordSize );
@@ -1112,7 +1135,9 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1112
1135
1113
1136
uword* CallerFP () const {
1114
1137
ASSERT (fp_ != nullptr );
1115
- uword* caller_fp_ptr = fp_ + kSavedCallerFpSlotFromFp ;
1138
+ uword* caller_fp_ptr =
1139
+ fp_ + (IsInterpretedFrame () ? kKBCSavedCallerFpSlotFromFp
1140
+ : kSavedCallerFpSlotFromFp );
1116
1141
// MSan/ASan are unaware of frames initialized by generated code.
1117
1142
MSAN_UNPOISON (caller_fp_ptr, kWordSize );
1118
1143
ASAN_UNPOISON (caller_fp_ptr, kWordSize );
@@ -1121,7 +1146,9 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
1121
1146
1122
1147
uword* ExitLink () const {
1123
1148
ASSERT (fp_ != nullptr );
1124
- uword* exit_link_ptr = fp_ + kExitLinkSlotFromEntryFp ;
1149
+ uword* exit_link_ptr =
1150
+ fp_ + (IsInterpretedFrame () ? kKBCExitLinkSlotFromEntryFp
1151
+ : kExitLinkSlotFromEntryFp );
1125
1152
// MSan/ASan are unaware of frames initialized by generated code.
1126
1153
MSAN_UNPOISON (exit_link_ptr, kWordSize );
1127
1154
ASAN_UNPOISON (exit_link_ptr, kWordSize );
@@ -1503,6 +1530,8 @@ class CodeLookupTableBuilder : public ObjectVisitor {
1503
1530
void VisitObject (ObjectPtr raw_obj) override {
1504
1531
if (raw_obj->IsCode () && !Code::IsUnknownDartCode (Code::RawCast (raw_obj))) {
1505
1532
table_->Add (Code::Handle (Code::RawCast (raw_obj)));
1533
+ } else if (raw_obj->IsBytecode ()) {
1534
+ table_->Add (Bytecode::Handle (Bytecode::RawCast (raw_obj)));
1506
1535
}
1507
1536
}
1508
1537
@@ -1555,7 +1584,7 @@ void CodeLookupTable::Build(Thread* thread) {
1555
1584
1556
1585
void CodeLookupTable::Add (const Object& code) {
1557
1586
ASSERT (!code.IsNull ());
1558
- ASSERT (code.IsCode ());
1587
+ ASSERT (code.IsCode () || code. IsBytecode () );
1559
1588
CodeDescriptor* cd = new CodeDescriptor (AbstractCode (code.ptr ()));
1560
1589
code_objects_.Add (cd);
1561
1590
}
@@ -1736,6 +1765,11 @@ void ProcessedSample::CheckForMissingDartFrame(const CodeLookupTable& clt,
1736
1765
uword pc_marker,
1737
1766
uword* stack_buffer) {
1738
1767
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
+ }
1739
1773
const Code& code = Code::Handle (Code::RawCast (cd->code ().ptr ()));
1740
1774
ASSERT (!code.IsNull ());
1741
1775
// Some stubs (and intrinsics) do not push a frame onto the stack leaving
0 commit comments