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

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

Issue 1202943002: Begin transition to ProcessedSample in Profiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months 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 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 cursor = cursor % capacity_; 270 cursor = cursor % capacity_;
271 return At(cursor); 271 return At(cursor);
272 } 272 }
273 273
274 // Attempts to find the true return address when a Dart frame is being setup 274 // Attempts to find the true return address when a Dart frame is being setup
275 // or torn down. 275 // or torn down.
276 // NOTE: Architecture specific implementations below. 276 // NOTE: Architecture specific implementations below.
277 class ReturnAddressLocator : public ValueObject { 277 class ReturnAddressLocator : public ValueObject {
278 public: 278 public:
279 ReturnAddressLocator(Sample* sample, const Code& code) 279 ReturnAddressLocator(Sample* sample, const Code& code)
280 : sample_(sample), 280 : stack_buffer_(sample->GetStackBuffer()),
281 pc_(sample->pc()),
281 code_(Code::ZoneHandle(code.raw())) { 282 code_(Code::ZoneHandle(code.raw())) {
282 ASSERT(!code_.IsNull()); 283 ASSERT(!code_.IsNull());
283 ASSERT(code_.ContainsInstructionAt(pc())); 284 ASSERT(code_.ContainsInstructionAt(pc()));
284 } 285 }
285 286
287 ReturnAddressLocator(uword pc, uword* stack_buffer, const Code& code)
288 : stack_buffer_(stack_buffer),
289 pc_(pc),
290 code_(Code::ZoneHandle(code.raw())) {
291 ASSERT(!code_.IsNull());
292 ASSERT(code_.ContainsInstructionAt(pc_));
293 }
294
286 uword pc() { 295 uword pc() {
287 return sample_->pc(); 296 return pc_;
288 } 297 }
289 298
290 // Returns false on failure. 299 // Returns false on failure.
291 bool LocateReturnAddress(uword* return_address); 300 bool LocateReturnAddress(uword* return_address);
292 301
293 // Returns offset into code object. 302 // Returns offset into code object.
294 intptr_t RelativePC() { 303 intptr_t RelativePC() {
295 ASSERT(pc() >= code_.EntryPoint()); 304 ASSERT(pc() >= code_.EntryPoint());
296 return static_cast<intptr_t>(pc() - code_.EntryPoint()); 305 return static_cast<intptr_t>(pc() - code_.EntryPoint());
297 } 306 }
298 307
299 uint8_t* CodePointer(intptr_t offset) { 308 uint8_t* CodePointer(intptr_t offset) {
300 const intptr_t size = code_.Size(); 309 const intptr_t size = code_.Size();
301 ASSERT(offset < size); 310 ASSERT(offset < size);
302 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code_.EntryPoint()); 311 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code_.EntryPoint());
303 code_pointer += offset; 312 code_pointer += offset;
304 return code_pointer; 313 return code_pointer;
305 } 314 }
306 315
307 uword StackAt(intptr_t i) { 316 uword StackAt(intptr_t i) {
308 ASSERT(i >= 0); 317 ASSERT(i >= 0);
309 ASSERT(i < Sample::kStackBufferSizeInWords); 318 ASSERT(i < Sample::kStackBufferSizeInWords);
310 return sample_->GetStackBuffer()[i]; 319 return stack_buffer_[i];
311 } 320 }
312 321
313 private: 322 private:
314 Sample* sample_; 323 uword* stack_buffer_;
324 uword pc_;
315 const Code& code_; 325 const Code& code_;
316 }; 326 };
317 327
318 328
319 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) 329 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
320 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { 330 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
321 ASSERT(return_address != NULL); 331 ASSERT(return_address != NULL);
322 const intptr_t offset = RelativePC(); 332 const intptr_t offset = RelativePC();
323 ASSERT(offset >= 0); 333 ASSERT(offset >= 0);
324 const intptr_t size = code_.Size(); 334 const intptr_t size = code_.Size();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 #elif defined(TARGET_ARCH_MIPS) 388 #elif defined(TARGET_ARCH_MIPS)
379 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { 389 bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
380 ASSERT(return_address != NULL); 390 ASSERT(return_address != NULL);
381 return false; 391 return false;
382 } 392 }
383 #else 393 #else
384 #error ReturnAddressLocator implementation missing for this architecture. 394 #error ReturnAddressLocator implementation missing for this architecture.
385 #endif 395 #endif
386 396
387 397
388 PreprocessVisitor::PreprocessVisitor(Isolate* isolate)
389 : SampleVisitor(isolate),
390 vm_isolate_(Dart::vm_isolate()) {
391 }
392
393
394 void PreprocessVisitor::VisitSample(Sample* sample) {
395 if (sample->processed()) {
396 // Already processed.
397 return;
398 }
399 // Mark that we've processed this sample.
400 sample->set_processed(true);
401
402 if (sample->exit_frame_sample()) {
403 // Exit frame sample, no preprocessing required.
404 return;
405 }
406 REUSABLE_CODE_HANDLESCOPE(isolate());
407 // Lookup code object for leaf frame.
408 Code& code = reused_code_handle.Handle();
409 code = FindCodeForPC(sample->At(0));
410 sample->set_leaf_frame_is_dart(!code.IsNull());
411 if (!code.IsNull() && (code.compile_timestamp() > sample->timestamp())) {
412 // Code compiled after sample. Ignore.
413 return;
414 }
415 if (sample->leaf_frame_is_dart()) {
416 CheckForMissingDartFrame(code, sample);
417 }
418 }
419
420
421 void PreprocessVisitor::CheckForMissingDartFrame(const Code& code,
422 Sample* sample) const {
423 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
424 // the frame pointer in the caller.
425 //
426 // PC -> STUB
427 // FP -> DART3 <-+
428 // DART2 <-| <- TOP FRAME RETURN ADDRESS.
429 // DART1 <-|
430 // .....
431 //
432 // In this case, traversing the linked stack frames will not collect a PC
433 // inside DART3. The stack will incorrectly be: STUB, DART2, DART1.
434 // In Dart code, after pushing the FP onto the stack, an IP in the current
435 // function is pushed onto the stack as well. This stack slot is called
436 // the PC marker. We can use the PC marker to insert DART3 into the stack
437 // so that it will correctly be: STUB, DART3, DART2, DART1. Note the
438 // inserted PC may not accurately reflect the true return address into DART3.
439 ASSERT(!code.IsNull());
440
441 // The pc marker is our current best guess of a return address.
442 uword return_address = sample->pc_marker();
443
444 // Attempt to find a better return address.
445 ReturnAddressLocator ral(sample, code);
446
447 if (!ral.LocateReturnAddress(&return_address)) {
448 ASSERT(return_address == sample->pc_marker());
449 if (code.GetPrologueOffset() == 0) {
450 // Code has the prologue at offset 0. The frame is already setup and
451 // can be trusted.
452 return;
453 }
454 // Could not find a better return address than the pc_marker.
455 if (code.ContainsInstructionAt(return_address)) {
456 // PC marker is in the same code as pc, no missing frame.
457 return;
458 }
459 }
460
461 if (!ContainedInDartCodeHeaps(return_address)) {
462 // return address is not from the Dart heap. Do not insert.
463 return;
464 }
465
466 if (return_address != 0) {
467 sample->InsertCallerForTopFrame(return_address);
468 }
469 }
470
471
472 bool PreprocessVisitor::ContainedInDartCodeHeaps(uword pc) const {
473 return isolate()->heap()->CodeContains(pc) ||
474 vm_isolate()->heap()->CodeContains(pc);
475 }
476
477
478 RawCode* PreprocessVisitor::FindCodeForPC(uword pc) const {
479 // Check current isolate for pc.
480 if (isolate()->heap()->CodeContains(pc)) {
481 return Code::LookupCode(pc);
482 }
483 // Check VM isolate for pc.
484 if (vm_isolate()->heap()->CodeContains(pc)) {
485 return Code::LookupCodeInVmIsolate(pc);
486 }
487 return Code::null();
488 }
489
490
491 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate) 398 ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
492 : SampleVisitor(isolate) { 399 : SampleVisitor(isolate) {
493 } 400 }
494 401
495 402
496 void ClearProfileVisitor::VisitSample(Sample* sample) { 403 void ClearProfileVisitor::VisitSample(Sample* sample) {
497 sample->Clear(); 404 sample->Clear();
498 } 405 }
499 406
500 407
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 in_dart_code, 980 in_dart_code,
1074 sample, 981 sample,
1075 &native_stack_walker, 982 &native_stack_walker,
1076 &dart_exit_stack_walker, 983 &dart_exit_stack_walker,
1077 &dart_stack_walker, 984 &dart_stack_walker,
1078 pc, 985 pc,
1079 fp, 986 fp,
1080 sp); 987 sp);
1081 } 988 }
1082 989
990
991 ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
992 SampleFilter* filter) {
993 ASSERT(filter != NULL);
994 Thread* thread = Thread::Current();
995 Zone* zone = thread->zone();
996
997 ProcessedSampleBuffer* buffer = new(zone) ProcessedSampleBuffer();
998
999 const intptr_t length = capacity();
1000 for (intptr_t i = 0; i < length; i++) {
1001 Sample* sample = At(i);
1002 if (sample->ignore_sample()) {
1003 // Bad sample.
1004 continue;
1005 }
1006 if (sample->isolate() != filter->isolate()) {
1007 // Another isolate.
1008 continue;
1009 }
1010 if (sample->timestamp() == 0) {
1011 // Empty.
1012 continue;
1013 }
1014 if (sample->At(0) == 0) {
1015 // No frames.
1016 continue;
1017 }
1018 if (!filter->FilterSample(sample)) {
1019 // Did not pass filter.
1020 continue;
1021 }
1022 buffer->Add(BuildProcessedSample(sample));
1023 }
1024 return buffer;
1025 }
1026
1027
1028 ProcessedSample* SampleBuffer::BuildProcessedSample(Sample* sample) {
1029 Thread* thread = Thread::Current();
1030 Zone* zone = thread->zone();
1031
1032 ProcessedSample* processed_sample = new(zone) ProcessedSample();
1033
1034 // Copy state bits from sample.
1035 processed_sample->set_timestamp(sample->timestamp());
1036 processed_sample->set_vm_tag(sample->vm_tag());
1037 processed_sample->set_user_tag(sample->user_tag());
1038 if (sample->is_allocation_sample()) {
1039 processed_sample->set_allocation_cid(sample->allocation_cid());
1040 }
1041 processed_sample->set_first_frame_executing(!sample->exit_frame_sample());
1042
1043 // Copy stack trace from sample(s).
1044 bool truncated = false;
1045 Sample* current = sample;
1046 while (current != NULL) {
1047 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
1048 if (current->At(i) == 0) {
1049 break;
1050 }
1051 processed_sample->Add(current->At(i));
1052 }
1053
1054 truncated = truncated || current->truncated_trace();
1055 current = Next(sample);
1056 }
1057
1058 if (!sample->exit_frame_sample()) {
1059 Isolate* isolate = thread->isolate();
1060 Isolate* vm_isolate = Dart::vm_isolate();
1061 processed_sample->FixupCaller(isolate,
1062 vm_isolate,
1063 sample->pc_marker(),
1064 sample->GetStackBuffer());
1065 }
1066
1067 processed_sample->set_truncated(truncated);
1068 return processed_sample;
1069 }
1070
1071
1072 Sample* SampleBuffer::Next(Sample* sample) {
1073 // TODO(johnmccutchan): Support chaining samples for complete stack traces.
1074 return NULL;
1075 }
1076
1077
1078 ProcessedSample::ProcessedSample()
1079 : pcs_(FLAG_profile_depth),
1080 timestamp_(0),
1081 vm_tag_(0),
1082 user_tag_(0),
1083 allocation_cid_(-1),
1084 truncated_(false) {
1085 }
1086
1087
1088 void ProcessedSample::FixupCaller(Isolate* isolate,
1089 Isolate* vm_isolate,
1090 uword pc_marker,
1091 uword* stack_buffer) {
1092 REUSABLE_CODE_HANDLESCOPE(isolate);
1093 // Lookup code object for leaf frame.
1094 Code& code = reused_code_handle.Handle();
1095 code = FindCodeForPC(isolate, vm_isolate, At(0));
1096 if (code.IsNull()) {
1097 return;
1098 }
1099 if (code.compile_timestamp() > timestamp()) {
1100 // Code compiled after sample. Ignore.
1101 return;
1102 }
1103 CheckForMissingDartFrame(isolate, vm_isolate, code, pc_marker, stack_buffer);
1104 }
1105
1106
1107 void ProcessedSample::CheckForMissingDartFrame(Isolate* isolate,
1108 Isolate* vm_isolate,
1109 const Code& code,
1110 uword pc_marker,
1111 uword* stack_buffer) {
1112 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
1113 // the frame pointer in the caller.
1114 //
1115 // PC -> STUB
1116 // FP -> DART3 <-+
1117 // DART2 <-| <- TOP FRAME RETURN ADDRESS.
1118 // DART1 <-|
1119 // .....
1120 //
1121 // In this case, traversing the linked stack frames will not collect a PC
1122 // inside DART3. The stack will incorrectly be: STUB, DART2, DART1.
1123 // In Dart code, after pushing the FP onto the stack, an IP in the current
1124 // function is pushed onto the stack as well. This stack slot is called
1125 // the PC marker. We can use the PC marker to insert DART3 into the stack
1126 // so that it will correctly be: STUB, DART3, DART2, DART1. Note the
1127 // inserted PC may not accurately reflect the true return address into DART3.
1128 ASSERT(!code.IsNull());
1129
1130 // The pc marker is our current best guess of a return address.
1131 uword return_address = pc_marker;
1132
1133 // Attempt to find a better return address.
1134 ReturnAddressLocator ral(At(0), stack_buffer, code);
1135
1136 if (!ral.LocateReturnAddress(&return_address)) {
1137 ASSERT(return_address == pc_marker);
1138 if (code.GetPrologueOffset() == 0) {
1139 // Code has the prologue at offset 0. The frame is already setup and
1140 // can be trusted.
1141 return;
1142 }
1143 // Could not find a better return address than the pc_marker.
1144 if (code.ContainsInstructionAt(return_address)) {
1145 // PC marker is in the same code as pc, no missing frame.
1146 return;
1147 }
1148 }
1149
1150 if (!ContainedInDartCodeHeaps(isolate, vm_isolate, return_address)) {
1151 // return address is not from the Dart heap. Do not insert.
1152 return;
1153 }
1154
1155 if (return_address != 0) {
1156 InsertAt(1, return_address);
1157 }
1158 }
1159
1160
1161 RawCode* ProcessedSample::FindCodeForPC(Isolate* isolate,
1162 Isolate* vm_isolate,
1163 uword pc) {
1164 // Check current isolate for pc.
1165 if (isolate->heap()->CodeContains(pc)) {
1166 return Code::LookupCode(pc);
1167 }
1168
1169 // Check VM isolate for pc.
1170 if (vm_isolate->heap()->CodeContains(pc)) {
1171 return Code::LookupCodeInVmIsolate(pc);
1172 }
1173
1174 return Code::null();
1175 }
1176
1177
1178 bool ProcessedSample::ContainedInDartCodeHeaps(Isolate* isolate,
1179 Isolate* vm_isolate,
1180 uword pc) {
1181 return vm_isolate->heap()->CodeContains(pc)
1182 || isolate->heap()->CodeContains(pc);
1183 }
1184
1185
1186 ProcessedSampleBuffer::ProcessedSampleBuffer() {
1187 }
1188
1083 } // namespace dart 1189 } // 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