Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(537)

Side by Side Diff: runtime/vm/profiler.cc

Issue 1435533003: Make profiler work without Instructions -> Code pointer (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_service.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 "platform/address_sanitizer.h" 5 #include "platform/address_sanitizer.h"
6 #include "platform/memory_sanitizer.h" 6 #include "platform/memory_sanitizer.h"
7 #include "platform/utils.h" 7 #include "platform/utils.h"
8 8
9 #include "vm/allocation.h" 9 #include "vm/allocation.h"
10 #include "vm/atomic.h" 10 #include "vm/atomic.h"
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 sample, 1042 sample,
1043 &native_stack_walker, 1043 &native_stack_walker,
1044 &dart_exit_stack_walker, 1044 &dart_exit_stack_walker,
1045 &dart_stack_walker, 1045 &dart_stack_walker,
1046 pc, 1046 pc,
1047 fp, 1047 fp,
1048 sp); 1048 sp);
1049 } 1049 }
1050 1050
1051 1051
1052
1053 CodeDescriptor::CodeDescriptor(const Code& code)
1054 : code_(code) {
srdjan 2015/11/10 19:08:51 One line
Cutch 2015/11/10 19:12:21 Done.
1055 ASSERT(!code_.IsNull());
1056 }
1057
1058
1059 uword CodeDescriptor::Entry() const {
1060 return code_.EntryPoint();
1061 }
1062
1063
1064 uword CodeDescriptor::Size() const {
1065 return code_.Size();
1066 }
1067
1068
1069 int64_t CodeDescriptor::CompileTimestamp() const {
1070 return code_.compile_timestamp();
1071 }
1072
1073
1074 CodeLookupTable::CodeLookupTable(Thread* thread) {
1075 Build(thread);
1076 }
1077
1078
1079 class CodeLookupTableBuilder : public ObjectVisitor {
1080 public:
1081 CodeLookupTableBuilder(Isolate* isolate, CodeLookupTable* table)
1082 : ObjectVisitor(isolate),
1083 table_(table) {
1084 ASSERT(table_ != NULL);
1085 }
1086
1087 ~CodeLookupTableBuilder() {
1088 }
1089
1090 void VisitObject(RawObject* raw_obj) {
1091 uword tags = raw_obj->ptr()->tags_;
1092 if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
1093 RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
1094 const Code& code = Code::Handle(raw_code);
1095 ASSERT(!code.IsNull());
1096 const Instructions& instructions =
1097 Instructions::Handle(code.instructions());
1098 ASSERT(!instructions.IsNull());
1099 table_->Add(code);
1100 }
1101 }
1102
1103 private:
1104 CodeLookupTable* table_;
1105 };
1106
1107
1108 void CodeLookupTable::Build(Thread* thread) {
1109 ASSERT(thread != NULL);
1110 Isolate* isolate = thread->isolate();
1111 ASSERT(isolate != NULL);
1112 Isolate* vm_isolate = Dart::vm_isolate();
1113 ASSERT(vm_isolate != NULL);
1114
1115 // Clear.
1116 code_objects_.Clear();
1117
1118 // Add all found Code objects.
1119 CodeLookupTableBuilder cltb(isolate, this);
1120 vm_isolate->heap()->IterateOldObjects(&cltb);
1121 isolate->heap()->IterateOldObjects(&cltb);
1122
1123 // Sort by entry.
1124 code_objects_.Sort(CodeDescriptor::Compare);
1125
1126 #if defined(DEBUG)
1127 if (length() <= 1) {
1128 return;
1129 }
1130 // Sanity check that we don't have duplicate entries.
1131 for (intptr_t i = 0; i < length() - 1; i++) {
1132 const CodeDescriptor* a = At(i);
1133 const CodeDescriptor* b = At(i + 1);
1134 ASSERT(a->Entry() < b->Entry());
1135 ASSERT(FindCode(0) == NULL);
rmacnak 2015/11/10 18:53:13 This can go out of the loop
Cutch 2015/11/10 19:12:21 Done.
1136 ASSERT(FindCode(~0) == NULL);
1137 ASSERT(FindCode(a->Entry()) == a);
1138 ASSERT(FindCode(b->Entry()) == b);
1139 ASSERT(FindCode(a->Entry() + a->Size() - 1) == a);
1140 ASSERT(FindCode(b->Entry() + b->Size() - 1) == b);
1141 }
1142 #endif
1143 }
1144
1145
1146 void CodeLookupTable::Add(const Code& code) {
1147 ASSERT(!code.IsNull());
1148 CodeDescriptor* cd = new CodeDescriptor(code);
1149 code_objects_.Add(cd);
1150 }
1151
1152
1153 const CodeDescriptor* CodeLookupTable::FindCode(uword pc) const {
1154 // std::upper_bound.
srdjan 2015/11/10 19:08:51 Why this comment?
Cutch 2015/11/10 19:12:21 It's the name of the algorithm from C++ <algorithm
1155 intptr_t first = 0;
1156 intptr_t count = length();
1157 while (count > 0) {
1158 intptr_t current = first;
1159 intptr_t step = count / 2;
1160 current += step;
1161 const CodeDescriptor* cd = At(current);
1162 if (!(pc < cd->Entry())) {
srdjan 2015/11/10 19:08:51 Either pc >= cd->Entry() or if (pc<cd->Entry()) {
Cutch 2015/11/10 19:12:21 Done.
1163 first = ++current;
1164 count -= step + 1;
1165 } else {
1166 count = step;
1167 }
1168 }
1169 // First points to the first code object whose entry is greater than PC.
1170 // That means the code object we need to check is first - 1.
1171 if (first == 0) {
1172 return NULL;
1173 }
1174 first--;
1175 ASSERT(first >= 0);
1176 ASSERT(first < length());
1177 const CodeDescriptor* cd = At(first);
1178 if (cd->Contains(pc)) {
1179 return cd;
1180 }
1181 return NULL;
1182 }
1183
1184
1052 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( 1185 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
1053 SampleFilter* filter) { 1186 SampleFilter* filter) {
1054 ASSERT(filter != NULL); 1187 ASSERT(filter != NULL);
1055 Thread* thread = Thread::Current(); 1188 Thread* thread = Thread::Current();
1056 Zone* zone = thread->zone(); 1189 Zone* zone = thread->zone();
1057 1190
1058 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); 1191 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer();
1059 1192
1060 const intptr_t length = capacity(); 1193 const intptr_t length = capacity();
1061 for (intptr_t i = 0; i < length; i++) { 1194 for (intptr_t i = 0; i < length; i++) {
(...skipping 15 matching lines...) Expand all
1077 continue; 1210 continue;
1078 } 1211 }
1079 if (sample->At(0) == 0) { 1212 if (sample->At(0) == 0) {
1080 // No frames. 1213 // No frames.
1081 continue; 1214 continue;
1082 } 1215 }
1083 if (!filter->FilterSample(sample)) { 1216 if (!filter->FilterSample(sample)) {
1084 // Did not pass filter. 1217 // Did not pass filter.
1085 continue; 1218 continue;
1086 } 1219 }
1087 buffer->Add(BuildProcessedSample(sample)); 1220 buffer->Add(BuildProcessedSample(sample, buffer->code_lookup_table()));
1088 } 1221 }
1089 return buffer; 1222 return buffer;
1090 } 1223 }
1091 1224
1092 1225
1093 ProcessedSample* SampleBuffer::BuildProcessedSample(Sample* sample) { 1226 ProcessedSample* SampleBuffer::BuildProcessedSample(
1227 Sample* sample,
1228 const CodeLookupTable& clt) {
1094 Thread* thread = Thread::Current(); 1229 Thread* thread = Thread::Current();
1095 Zone* zone = thread->zone(); 1230 Zone* zone = thread->zone();
1096 1231
1097 ProcessedSample* processed_sample = new(zone) ProcessedSample(); 1232 ProcessedSample* processed_sample = new(zone) ProcessedSample();
1098 1233
1099 // Copy state bits from sample. 1234 // Copy state bits from sample.
1100 processed_sample->set_timestamp(sample->timestamp()); 1235 processed_sample->set_timestamp(sample->timestamp());
1101 processed_sample->set_vm_tag(sample->vm_tag()); 1236 processed_sample->set_vm_tag(sample->vm_tag());
1102 processed_sample->set_user_tag(sample->user_tag()); 1237 processed_sample->set_user_tag(sample->user_tag());
1103 if (sample->is_allocation_sample()) { 1238 if (sample->is_allocation_sample()) {
(...skipping 10 matching lines...) Expand all
1114 break; 1249 break;
1115 } 1250 }
1116 processed_sample->Add(current->At(i)); 1251 processed_sample->Add(current->At(i));
1117 } 1252 }
1118 1253
1119 truncated = truncated || current->truncated_trace(); 1254 truncated = truncated || current->truncated_trace();
1120 current = Next(current); 1255 current = Next(current);
1121 } 1256 }
1122 1257
1123 if (!sample->exit_frame_sample()) { 1258 if (!sample->exit_frame_sample()) {
1124 Isolate* vm_isolate = Dart::vm_isolate(); 1259 processed_sample->FixupCaller(clt,
1125 processed_sample->FixupCaller(thread,
1126 vm_isolate,
1127 sample->pc_marker(), 1260 sample->pc_marker(),
1128 sample->GetStackBuffer()); 1261 sample->GetStackBuffer());
1129 } 1262 }
1130 1263
1131 processed_sample->set_truncated(truncated); 1264 processed_sample->set_truncated(truncated);
1132 return processed_sample; 1265 return processed_sample;
1133 } 1266 }
1134 1267
1135 1268
1136 Sample* SampleBuffer::Next(Sample* sample) { 1269 Sample* SampleBuffer::Next(Sample* sample) {
(...skipping 19 matching lines...) Expand all
1156 ProcessedSample::ProcessedSample() 1289 ProcessedSample::ProcessedSample()
1157 : pcs_(kSampleSize), 1290 : pcs_(kSampleSize),
1158 timestamp_(0), 1291 timestamp_(0),
1159 vm_tag_(0), 1292 vm_tag_(0),
1160 user_tag_(0), 1293 user_tag_(0),
1161 allocation_cid_(-1), 1294 allocation_cid_(-1),
1162 truncated_(false) { 1295 truncated_(false) {
1163 } 1296 }
1164 1297
1165 1298
1166 void ProcessedSample::FixupCaller(Thread* thread, 1299 void ProcessedSample::FixupCaller(const CodeLookupTable& clt,
1167 Isolate* vm_isolate,
1168 uword pc_marker, 1300 uword pc_marker,
1169 uword* stack_buffer) { 1301 uword* stack_buffer) {
1170 REUSABLE_CODE_HANDLESCOPE(thread); 1302 const CodeDescriptor* cd = clt.FindCode(At(0));
1171 // Lookup code object for leaf frame. 1303 if (cd == NULL) {
1172 Code& code = reused_code_handle.Handle(); 1304 // No Dart code.
1173 code = FindCodeForPC(thread->isolate(), vm_isolate, At(0));
1174 if (code.IsNull()) {
1175 return; 1305 return;
1176 } 1306 }
1177 if (code.compile_timestamp() > timestamp()) { 1307 if (cd->CompileTimestamp() > timestamp()) {
1178 // Code compiled after sample. Ignore. 1308 // Code compiled after sample. Ignore.
1179 return; 1309 return;
1180 } 1310 }
1181 CheckForMissingDartFrame( 1311 CheckForMissingDartFrame(clt, cd, pc_marker, stack_buffer);
1182 thread->isolate(), vm_isolate, code, pc_marker, stack_buffer);
1183 } 1312 }
1184 1313
1185 1314
1186 void ProcessedSample::CheckForMissingDartFrame(Isolate* isolate, 1315 void ProcessedSample::CheckForMissingDartFrame(const CodeLookupTable& clt,
1187 Isolate* vm_isolate, 1316 const CodeDescriptor* cd,
1188 const Code& code,
1189 uword pc_marker, 1317 uword pc_marker,
1190 uword* stack_buffer) { 1318 uword* stack_buffer) {
1319 ASSERT(cd != NULL);
1320 const Code& code = Code::Handle(cd->code());
1321 ASSERT(!code.IsNull());
1191 // Some stubs (and intrinsics) do not push a frame onto the stack leaving 1322 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
1192 // the frame pointer in the caller. 1323 // the frame pointer in the caller.
1193 // 1324 //
1194 // PC -> STUB 1325 // PC -> STUB
1195 // FP -> DART3 <-+ 1326 // FP -> DART3 <-+
1196 // DART2 <-| <- TOP FRAME RETURN ADDRESS. 1327 // DART2 <-| <- TOP FRAME RETURN ADDRESS.
1197 // DART1 <-| 1328 // DART1 <-|
1198 // ..... 1329 // .....
1199 // 1330 //
1200 // In this case, traversing the linked stack frames will not collect a PC 1331 // In this case, traversing the linked stack frames will not collect a PC
1201 // inside DART3. The stack will incorrectly be: STUB, DART2, DART1. 1332 // inside DART3. The stack will incorrectly be: STUB, DART2, DART1.
1202 // In Dart code, after pushing the FP onto the stack, an IP in the current 1333 // In Dart code, after pushing the FP onto the stack, an IP in the current
1203 // function is pushed onto the stack as well. This stack slot is called 1334 // function is pushed onto the stack as well. This stack slot is called
1204 // the PC marker. We can use the PC marker to insert DART3 into the stack 1335 // the PC marker. We can use the PC marker to insert DART3 into the stack
1205 // so that it will correctly be: STUB, DART3, DART2, DART1. Note the 1336 // so that it will correctly be: STUB, DART3, DART2, DART1. Note the
1206 // inserted PC may not accurately reflect the true return address into DART3. 1337 // inserted PC may not accurately reflect the true return address into DART3.
1207 ASSERT(!code.IsNull());
1208 1338
1209 // The pc marker is our current best guess of a return address. 1339 // The pc marker is our current best guess of a return address.
1210 uword return_address = pc_marker; 1340 uword return_address = pc_marker;
1211 1341
1212 // Attempt to find a better return address. 1342 // Attempt to find a better return address.
1213 ReturnAddressLocator ral(At(0), stack_buffer, code); 1343 ReturnAddressLocator ral(At(0), stack_buffer, code);
1214 1344
1215 if (!ral.LocateReturnAddress(&return_address)) { 1345 if (!ral.LocateReturnAddress(&return_address)) {
1216 ASSERT(return_address == pc_marker); 1346 ASSERT(return_address == pc_marker);
1217 if (code.GetPrologueOffset() == 0) { 1347 if (code.GetPrologueOffset() == 0) {
1218 // Code has the prologue at offset 0. The frame is already setup and 1348 // Code has the prologue at offset 0. The frame is already setup and
1219 // can be trusted. 1349 // can be trusted.
1220 return; 1350 return;
1221 } 1351 }
1222 // Could not find a better return address than the pc_marker. 1352 // Could not find a better return address than the pc_marker.
1223 if (code.ContainsInstructionAt(return_address)) { 1353 if (code.ContainsInstructionAt(return_address)) {
1224 // PC marker is in the same code as pc, no missing frame. 1354 // PC marker is in the same code as pc, no missing frame.
1225 return; 1355 return;
1226 } 1356 }
1227 } 1357 }
1228 1358
1229 if (!ContainedInDartCodeHeaps(isolate, vm_isolate, return_address)) { 1359 if (clt.FindCode(return_address) == NULL) {
1230 // return address is not from the Dart heap. Do not insert. 1360 // Return address is not from a Dart code object. Do not insert.
1231 return; 1361 return;
1232 } 1362 }
1233 1363
1234 if (return_address != 0) { 1364 if (return_address != 0) {
1235 InsertAt(1, return_address); 1365 InsertAt(1, return_address);
1236 } 1366 }
1237 } 1367 }
1238 1368
1239 1369
1240 RawCode* ProcessedSample::FindCodeForPC(Isolate* isolate, 1370 ProcessedSampleBuffer::ProcessedSampleBuffer()
1241 Isolate* vm_isolate, 1371 : code_lookup_table_(new CodeLookupTable(Thread::Current())) {
1242 uword pc) { 1372 ASSERT(code_lookup_table_ != NULL);
1243 // Check current isolate for pc.
1244 if (isolate->heap()->CodeContains(pc)) {
1245 return Code::LookupCode(pc);
1246 }
1247
1248 // Check VM isolate for pc.
1249 if (vm_isolate->heap()->CodeContains(pc)) {
1250 return Code::LookupCodeInVmIsolate(pc);
1251 }
1252
1253 return Code::null();
1254 }
1255
1256
1257 bool ProcessedSample::ContainedInDartCodeHeaps(Isolate* isolate,
1258 Isolate* vm_isolate,
1259 uword pc) {
1260 return vm_isolate->heap()->CodeContains(pc)
1261 || isolate->heap()->CodeContains(pc);
1262 }
1263
1264
1265 ProcessedSampleBuffer::ProcessedSampleBuffer() {
1266 } 1373 }
1267 1374
1268 } // namespace dart 1375 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698