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

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) : code_(code) {
1054 ASSERT(!code_.IsNull());
1055 }
1056
1057
1058 uword CodeDescriptor::Entry() const {
1059 return code_.EntryPoint();
1060 }
1061
1062
1063 uword CodeDescriptor::Size() const {
1064 return code_.Size();
1065 }
1066
1067
1068 int64_t CodeDescriptor::CompileTimestamp() const {
1069 return code_.compile_timestamp();
1070 }
1071
1072
1073 CodeLookupTable::CodeLookupTable(Thread* thread) {
1074 Build(thread);
1075 }
1076
1077
1078 class CodeLookupTableBuilder : public ObjectVisitor {
1079 public:
1080 CodeLookupTableBuilder(Isolate* isolate, CodeLookupTable* table)
1081 : ObjectVisitor(isolate),
1082 table_(table) {
1083 ASSERT(table_ != NULL);
1084 }
1085
1086 ~CodeLookupTableBuilder() {
1087 }
1088
1089 void VisitObject(RawObject* raw_obj) {
1090 uword tags = raw_obj->ptr()->tags_;
1091 if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
1092 RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
1093 const Code& code = Code::Handle(raw_code);
1094 ASSERT(!code.IsNull());
1095 const Instructions& instructions =
1096 Instructions::Handle(code.instructions());
1097 ASSERT(!instructions.IsNull());
1098 table_->Add(code);
1099 }
1100 }
1101
1102 private:
1103 CodeLookupTable* table_;
1104 };
1105
1106
1107 void CodeLookupTable::Build(Thread* thread) {
1108 ASSERT(thread != NULL);
1109 Isolate* isolate = thread->isolate();
1110 ASSERT(isolate != NULL);
1111 Isolate* vm_isolate = Dart::vm_isolate();
1112 ASSERT(vm_isolate != NULL);
1113
1114 // Clear.
1115 code_objects_.Clear();
1116
1117 // Add all found Code objects.
1118 CodeLookupTableBuilder cltb(isolate, this);
1119 vm_isolate->heap()->IterateOldObjects(&cltb);
1120 isolate->heap()->IterateOldObjects(&cltb);
1121
1122 // Sort by entry.
1123 code_objects_.Sort(CodeDescriptor::Compare);
1124
1125 #if defined(DEBUG)
1126 if (length() <= 1) {
1127 return;
1128 }
1129 ASSERT(FindCode(0) == NULL);
1130 ASSERT(FindCode(~0) == NULL);
1131 // Sanity check that we don't have duplicate entries and that the entries
1132 // are sorted.
1133 for (intptr_t i = 0; i < length() - 1; i++) {
1134 const CodeDescriptor* a = At(i);
1135 const CodeDescriptor* b = At(i + 1);
1136 ASSERT(a->Entry() < b->Entry());
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 intptr_t first = 0;
1155 intptr_t count = length();
1156 while (count > 0) {
1157 intptr_t current = first;
1158 intptr_t step = count / 2;
1159 current += step;
1160 const CodeDescriptor* cd = At(current);
1161 if (pc >= cd->Entry()) {
1162 first = ++current;
1163 count -= step + 1;
1164 } else {
1165 count = step;
1166 }
1167 }
1168 // First points to the first code object whose entry is greater than PC.
1169 // That means the code object we need to check is first - 1.
1170 if (first == 0) {
1171 return NULL;
1172 }
1173 first--;
1174 ASSERT(first >= 0);
1175 ASSERT(first < length());
1176 const CodeDescriptor* cd = At(first);
1177 if (cd->Contains(pc)) {
1178 return cd;
1179 }
1180 return NULL;
1181 }
1182
1183
1052 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( 1184 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
1053 SampleFilter* filter) { 1185 SampleFilter* filter) {
1054 ASSERT(filter != NULL); 1186 ASSERT(filter != NULL);
1055 Thread* thread = Thread::Current(); 1187 Thread* thread = Thread::Current();
1056 Zone* zone = thread->zone(); 1188 Zone* zone = thread->zone();
1057 1189
1058 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer(); 1190 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer();
1059 1191
1060 const intptr_t length = capacity(); 1192 const intptr_t length = capacity();
1061 for (intptr_t i = 0; i < length; i++) { 1193 for (intptr_t i = 0; i < length; i++) {
(...skipping 15 matching lines...) Expand all
1077 continue; 1209 continue;
1078 } 1210 }
1079 if (sample->At(0) == 0) { 1211 if (sample->At(0) == 0) {
1080 // No frames. 1212 // No frames.
1081 continue; 1213 continue;
1082 } 1214 }
1083 if (!filter->FilterSample(sample)) { 1215 if (!filter->FilterSample(sample)) {
1084 // Did not pass filter. 1216 // Did not pass filter.
1085 continue; 1217 continue;
1086 } 1218 }
1087 buffer->Add(BuildProcessedSample(sample)); 1219 buffer->Add(BuildProcessedSample(sample, buffer->code_lookup_table()));
1088 } 1220 }
1089 return buffer; 1221 return buffer;
1090 } 1222 }
1091 1223
1092 1224
1093 ProcessedSample* SampleBuffer::BuildProcessedSample(Sample* sample) { 1225 ProcessedSample* SampleBuffer::BuildProcessedSample(
1226 Sample* sample,
1227 const CodeLookupTable& clt) {
1094 Thread* thread = Thread::Current(); 1228 Thread* thread = Thread::Current();
1095 Zone* zone = thread->zone(); 1229 Zone* zone = thread->zone();
1096 1230
1097 ProcessedSample* processed_sample = new(zone) ProcessedSample(); 1231 ProcessedSample* processed_sample = new(zone) ProcessedSample();
1098 1232
1099 // Copy state bits from sample. 1233 // Copy state bits from sample.
1100 processed_sample->set_timestamp(sample->timestamp()); 1234 processed_sample->set_timestamp(sample->timestamp());
1101 processed_sample->set_vm_tag(sample->vm_tag()); 1235 processed_sample->set_vm_tag(sample->vm_tag());
1102 processed_sample->set_user_tag(sample->user_tag()); 1236 processed_sample->set_user_tag(sample->user_tag());
1103 if (sample->is_allocation_sample()) { 1237 if (sample->is_allocation_sample()) {
(...skipping 10 matching lines...) Expand all
1114 break; 1248 break;
1115 } 1249 }
1116 processed_sample->Add(current->At(i)); 1250 processed_sample->Add(current->At(i));
1117 } 1251 }
1118 1252
1119 truncated = truncated || current->truncated_trace(); 1253 truncated = truncated || current->truncated_trace();
1120 current = Next(current); 1254 current = Next(current);
1121 } 1255 }
1122 1256
1123 if (!sample->exit_frame_sample()) { 1257 if (!sample->exit_frame_sample()) {
1124 Isolate* vm_isolate = Dart::vm_isolate(); 1258 processed_sample->FixupCaller(clt,
1125 processed_sample->FixupCaller(thread,
1126 vm_isolate,
1127 sample->pc_marker(), 1259 sample->pc_marker(),
1128 sample->GetStackBuffer()); 1260 sample->GetStackBuffer());
1129 } 1261 }
1130 1262
1131 processed_sample->set_truncated(truncated); 1263 processed_sample->set_truncated(truncated);
1132 return processed_sample; 1264 return processed_sample;
1133 } 1265 }
1134 1266
1135 1267
1136 Sample* SampleBuffer::Next(Sample* sample) { 1268 Sample* SampleBuffer::Next(Sample* sample) {
(...skipping 19 matching lines...) Expand all
1156 ProcessedSample::ProcessedSample() 1288 ProcessedSample::ProcessedSample()
1157 : pcs_(kSampleSize), 1289 : pcs_(kSampleSize),
1158 timestamp_(0), 1290 timestamp_(0),
1159 vm_tag_(0), 1291 vm_tag_(0),
1160 user_tag_(0), 1292 user_tag_(0),
1161 allocation_cid_(-1), 1293 allocation_cid_(-1),
1162 truncated_(false) { 1294 truncated_(false) {
1163 } 1295 }
1164 1296
1165 1297
1166 void ProcessedSample::FixupCaller(Thread* thread, 1298 void ProcessedSample::FixupCaller(const CodeLookupTable& clt,
1167 Isolate* vm_isolate,
1168 uword pc_marker, 1299 uword pc_marker,
1169 uword* stack_buffer) { 1300 uword* stack_buffer) {
1170 REUSABLE_CODE_HANDLESCOPE(thread); 1301 const CodeDescriptor* cd = clt.FindCode(At(0));
1171 // Lookup code object for leaf frame. 1302 if (cd == NULL) {
1172 Code& code = reused_code_handle.Handle(); 1303 // No Dart code.
1173 code = FindCodeForPC(thread->isolate(), vm_isolate, At(0));
1174 if (code.IsNull()) {
1175 return; 1304 return;
1176 } 1305 }
1177 if (code.compile_timestamp() > timestamp()) { 1306 if (cd->CompileTimestamp() > timestamp()) {
1178 // Code compiled after sample. Ignore. 1307 // Code compiled after sample. Ignore.
1179 return; 1308 return;
1180 } 1309 }
1181 CheckForMissingDartFrame( 1310 CheckForMissingDartFrame(clt, cd, pc_marker, stack_buffer);
1182 thread->isolate(), vm_isolate, code, pc_marker, stack_buffer);
1183 } 1311 }
1184 1312
1185 1313
1186 void ProcessedSample::CheckForMissingDartFrame(Isolate* isolate, 1314 void ProcessedSample::CheckForMissingDartFrame(const CodeLookupTable& clt,
1187 Isolate* vm_isolate, 1315 const CodeDescriptor* cd,
1188 const Code& code,
1189 uword pc_marker, 1316 uword pc_marker,
1190 uword* stack_buffer) { 1317 uword* stack_buffer) {
1318 ASSERT(cd != NULL);
1319 const Code& code = Code::Handle(cd->code());
1320 ASSERT(!code.IsNull());
1191 // Some stubs (and intrinsics) do not push a frame onto the stack leaving 1321 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
1192 // the frame pointer in the caller. 1322 // the frame pointer in the caller.
1193 // 1323 //
1194 // PC -> STUB 1324 // PC -> STUB
1195 // FP -> DART3 <-+ 1325 // FP -> DART3 <-+
1196 // DART2 <-| <- TOP FRAME RETURN ADDRESS. 1326 // DART2 <-| <- TOP FRAME RETURN ADDRESS.
1197 // DART1 <-| 1327 // DART1 <-|
1198 // ..... 1328 // .....
1199 // 1329 //
1200 // In this case, traversing the linked stack frames will not collect a PC 1330 // In this case, traversing the linked stack frames will not collect a PC
1201 // inside DART3. The stack will incorrectly be: STUB, DART2, DART1. 1331 // 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 1332 // 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 1333 // 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 1334 // 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 1335 // 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. 1336 // inserted PC may not accurately reflect the true return address into DART3.
1207 ASSERT(!code.IsNull());
1208 1337
1209 // The pc marker is our current best guess of a return address. 1338 // The pc marker is our current best guess of a return address.
1210 uword return_address = pc_marker; 1339 uword return_address = pc_marker;
1211 1340
1212 // Attempt to find a better return address. 1341 // Attempt to find a better return address.
1213 ReturnAddressLocator ral(At(0), stack_buffer, code); 1342 ReturnAddressLocator ral(At(0), stack_buffer, code);
1214 1343
1215 if (!ral.LocateReturnAddress(&return_address)) { 1344 if (!ral.LocateReturnAddress(&return_address)) {
1216 ASSERT(return_address == pc_marker); 1345 ASSERT(return_address == pc_marker);
1217 if (code.GetPrologueOffset() == 0) { 1346 if (code.GetPrologueOffset() == 0) {
1218 // Code has the prologue at offset 0. The frame is already setup and 1347 // Code has the prologue at offset 0. The frame is already setup and
1219 // can be trusted. 1348 // can be trusted.
1220 return; 1349 return;
1221 } 1350 }
1222 // Could not find a better return address than the pc_marker. 1351 // Could not find a better return address than the pc_marker.
1223 if (code.ContainsInstructionAt(return_address)) { 1352 if (code.ContainsInstructionAt(return_address)) {
1224 // PC marker is in the same code as pc, no missing frame. 1353 // PC marker is in the same code as pc, no missing frame.
1225 return; 1354 return;
1226 } 1355 }
1227 } 1356 }
1228 1357
1229 if (!ContainedInDartCodeHeaps(isolate, vm_isolate, return_address)) { 1358 if (clt.FindCode(return_address) == NULL) {
1230 // return address is not from the Dart heap. Do not insert. 1359 // Return address is not from a Dart code object. Do not insert.
1231 return; 1360 return;
1232 } 1361 }
1233 1362
1234 if (return_address != 0) { 1363 if (return_address != 0) {
1235 InsertAt(1, return_address); 1364 InsertAt(1, return_address);
1236 } 1365 }
1237 } 1366 }
1238 1367
1239 1368
1240 RawCode* ProcessedSample::FindCodeForPC(Isolate* isolate, 1369 ProcessedSampleBuffer::ProcessedSampleBuffer()
1241 Isolate* vm_isolate, 1370 : code_lookup_table_(new CodeLookupTable(Thread::Current())) {
1242 uword pc) { 1371 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 } 1372 }
1267 1373
1268 } // namespace dart 1374 } // 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