| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 "vm/timeline_analysis.h" | 5 #include "vm/timeline_analysis.h" |
| 6 | 6 |
| 7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
| 8 #include "vm/log.h" | 8 #include "vm/log.h" |
| 9 #include "vm/os_thread.h" | 9 #include "vm/os_thread.h" |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 ASSERT(*a != NULL); | 32 ASSERT(*a != NULL); |
| 33 ASSERT(b != NULL); | 33 ASSERT(b != NULL); |
| 34 ASSERT(*b != NULL); | 34 ASSERT(*b != NULL); |
| 35 return (*a)->LowerTimeBound() - (*b)->LowerTimeBound(); | 35 return (*a)->LowerTimeBound() - (*b)->LowerTimeBound(); |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 void TimelineAnalysisThread::Finalize() { | 39 void TimelineAnalysisThread::Finalize() { |
| 40 blocks_.Sort(CompareBlocksLowerTimeBound); | 40 blocks_.Sort(CompareBlocksLowerTimeBound); |
| 41 if (FLAG_trace_timeline_analysis) { | 41 if (FLAG_trace_timeline_analysis) { |
| 42 ISL_Print("Thread %" Px " has %" Pd " blocks\n", | 42 THR_Print("Thread %" Px " has %" Pd " blocks\n", |
| 43 OSThread::ThreadIdToIntPtr(id_), | 43 OSThread::ThreadIdToIntPtr(id_), |
| 44 blocks_.length()); | 44 blocks_.length()); |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 | 47 |
| 48 | 48 |
| 49 TimelineAnalysisThreadEventIterator::TimelineAnalysisThreadEventIterator( | 49 TimelineAnalysisThreadEventIterator::TimelineAnalysisThreadEventIterator( |
| 50 TimelineAnalysisThread* thread) { | 50 TimelineAnalysisThread* thread) { |
| 51 Reset(thread); | 51 Reset(thread); |
| 52 } | 52 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 TimelineEventBlockIterator it(recorder_); | 156 TimelineEventBlockIterator it(recorder_); |
| 157 while (it.HasNext()) { | 157 while (it.HasNext()) { |
| 158 TimelineEventBlock* block = it.Next(); | 158 TimelineEventBlock* block = it.Next(); |
| 159 ASSERT(block != NULL); | 159 ASSERT(block != NULL); |
| 160 if (block->IsEmpty()) { | 160 if (block->IsEmpty()) { |
| 161 // Skip empty blocks. | 161 // Skip empty blocks. |
| 162 continue; | 162 continue; |
| 163 } | 163 } |
| 164 if (!block->CheckBlock()) { | 164 if (!block->CheckBlock()) { |
| 165 if (FLAG_trace_timeline_analysis) { | 165 if (FLAG_trace_timeline_analysis) { |
| 166 ISL_Print("DiscoverThreads block %" Pd " " | 166 THR_Print("DiscoverThreads block %" Pd " " |
| 167 "violates invariants.\n", block->block_index()); | 167 "violates invariants.\n", block->block_index()); |
| 168 } | 168 } |
| 169 SetError("Block %" Pd " violates invariants. See " | 169 SetError("Block %" Pd " violates invariants. See " |
| 170 "TimelineEventBlock::CheckBlock", block->block_index()); | 170 "TimelineEventBlock::CheckBlock", block->block_index()); |
| 171 return; | 171 return; |
| 172 } | 172 } |
| 173 TimelineAnalysisThread* thread = GetOrAddThread(block->thread()); | 173 TimelineAnalysisThread* thread = GetOrAddThread(block->thread()); |
| 174 ASSERT(thread != NULL); | 174 ASSERT(thread != NULL); |
| 175 thread->AddBlock(block); | 175 thread->AddBlock(block); |
| 176 } | 176 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 } | 293 } |
| 294 | 294 |
| 295 | 295 |
| 296 void TimelinePauses::ProcessThread(TimelineAnalysisThread* thread) { | 296 void TimelinePauses::ProcessThread(TimelineAnalysisThread* thread) { |
| 297 ASSERT(thread != NULL); | 297 ASSERT(thread != NULL); |
| 298 stack_.Clear(); | 298 stack_.Clear(); |
| 299 labels_.Clear(); | 299 labels_.Clear(); |
| 300 | 300 |
| 301 TimelineAnalysisThreadEventIterator it(thread); | 301 TimelineAnalysisThreadEventIterator it(thread); |
| 302 if (FLAG_trace_timeline_analysis) { | 302 if (FLAG_trace_timeline_analysis) { |
| 303 ISL_Print(">>> TimelinePauses::ProcessThread %" Px "\n", | 303 THR_Print(">>> TimelinePauses::ProcessThread %" Px "\n", |
| 304 OSThread::ThreadIdToIntPtr(thread->id())); | 304 OSThread::ThreadIdToIntPtr(thread->id())); |
| 305 } | 305 } |
| 306 intptr_t event_count = 0; | 306 intptr_t event_count = 0; |
| 307 while (it.HasNext()) { | 307 while (it.HasNext()) { |
| 308 TimelineEvent* event = it.Next(); | 308 TimelineEvent* event = it.Next(); |
| 309 if (!event->IsFinishedDuration()) { | 309 if (!event->IsFinishedDuration()) { |
| 310 // We only care about finished duration events. | 310 // We only care about finished duration events. |
| 311 continue; | 311 continue; |
| 312 } | 312 } |
| 313 int64_t start = event->TimeOrigin(); | 313 int64_t start = event->TimeOrigin(); |
| 314 PopFinished(start); | 314 PopFinished(start); |
| 315 if (!CheckStack(event)) { | 315 if (!CheckStack(event)) { |
| 316 SetError("Duration check fail."); | 316 SetError("Duration check fail."); |
| 317 return; | 317 return; |
| 318 } | 318 } |
| 319 event_count++; | 319 event_count++; |
| 320 Push(event); | 320 Push(event); |
| 321 } | 321 } |
| 322 // Pop remaining stack. | 322 // Pop remaining stack. |
| 323 PopFinished(kMaxInt64); | 323 PopFinished(kMaxInt64); |
| 324 if (FLAG_trace_timeline_analysis) { | 324 if (FLAG_trace_timeline_analysis) { |
| 325 ISL_Print("<<< TimelinePauses::ProcessThread %" Px " had %" Pd " events\n", | 325 THR_Print("<<< TimelinePauses::ProcessThread %" Px " had %" Pd " events\n", |
| 326 OSThread::ThreadIdToIntPtr(thread->id()), | 326 OSThread::ThreadIdToIntPtr(thread->id()), |
| 327 event_count); | 327 event_count); |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 | 330 |
| 331 | 331 |
| 332 // Verify that |event| is contained within all parent events on the stack. | 332 // Verify that |event| is contained within all parent events on the stack. |
| 333 bool TimelinePauses::CheckStack(TimelineEvent* event) { | 333 bool TimelinePauses::CheckStack(TimelineEvent* event) { |
| 334 ASSERT(event != NULL); | 334 ASSERT(event != NULL); |
| 335 for (intptr_t i = 0; i < stack_.length(); i++) { | 335 for (intptr_t i = 0; i < stack_.length(); i++) { |
| 336 const StackItem& slot = stack_.At(i); | 336 const StackItem& slot = stack_.At(i); |
| 337 if (!slot.event->DurationContains(event)) { | 337 if (!slot.event->DurationContains(event)) { |
| 338 return false; | 338 return false; |
| 339 } | 339 } |
| 340 } | 340 } |
| 341 return true; | 341 return true; |
| 342 } | 342 } |
| 343 | 343 |
| 344 | 344 |
| 345 void TimelinePauses::PopFinished(int64_t start) { | 345 void TimelinePauses::PopFinished(int64_t start) { |
| 346 while (stack_.length() > 0) { | 346 while (stack_.length() > 0) { |
| 347 const StackItem& top = stack_.Last(); | 347 const StackItem& top = stack_.Last(); |
| 348 if (top.event->DurationFinishedBefore(start)) { | 348 if (top.event->DurationFinishedBefore(start)) { |
| 349 top.pause_info->OnPop(top.exclusive_micros); | 349 top.pause_info->OnPop(top.exclusive_micros); |
| 350 // Top of stack completes before |start|. | 350 // Top of stack completes before |start|. |
| 351 stack_.RemoveLast(); | 351 stack_.RemoveLast(); |
| 352 if (FLAG_trace_timeline_analysis) { | 352 if (FLAG_trace_timeline_analysis) { |
| 353 ISL_Print("Popping %s (%" Pd64 " <= %" Pd64 ")\n", | 353 THR_Print("Popping %s (%" Pd64 " <= %" Pd64 ")\n", |
| 354 top.event->label(), | 354 top.event->label(), |
| 355 top.event->TimeEnd(), | 355 top.event->TimeEnd(), |
| 356 start); | 356 start); |
| 357 } | 357 } |
| 358 } else { | 358 } else { |
| 359 return; | 359 return; |
| 360 } | 360 } |
| 361 } | 361 } |
| 362 } | 362 } |
| 363 | 363 |
| 364 | 364 |
| 365 void TimelinePauses::Push(TimelineEvent* event) { | 365 void TimelinePauses::Push(TimelineEvent* event) { |
| 366 TimelineLabelPauseInfo* pause_info = GetOrAddLabelPauseInfo(event->label()); | 366 TimelineLabelPauseInfo* pause_info = GetOrAddLabelPauseInfo(event->label()); |
| 367 ASSERT(pause_info != NULL); | 367 ASSERT(pause_info != NULL); |
| 368 // |pause_info| will be running for |event->TimeDuration()|. | 368 // |pause_info| will be running for |event->TimeDuration()|. |
| 369 if (FLAG_trace_timeline_analysis) { | 369 if (FLAG_trace_timeline_analysis) { |
| 370 ISL_Print("Pushing %s %" Pd64 " us\n", | 370 THR_Print("Pushing %s %" Pd64 " us\n", |
| 371 pause_info->name(), | 371 pause_info->name(), |
| 372 event->TimeDuration()); | 372 event->TimeDuration()); |
| 373 } | 373 } |
| 374 pause_info->OnPush(event->TimeDuration(), IsLabelOnStack(event->label())); | 374 pause_info->OnPush(event->TimeDuration(), IsLabelOnStack(event->label())); |
| 375 if (StackDepth() > 0) { | 375 if (StackDepth() > 0) { |
| 376 StackItem& top = GetStackTop(); | 376 StackItem& top = GetStackTop(); |
| 377 // |top| is under |event|'s shadow, adjust the exclusive micros. | 377 // |top| is under |event|'s shadow, adjust the exclusive micros. |
| 378 top.exclusive_micros -= event->TimeDuration(); | 378 top.exclusive_micros -= event->TimeDuration(); |
| 379 } | 379 } |
| 380 // Push onto the stack. | 380 // Push onto the stack. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 if (pause_info != NULL) { | 416 if (pause_info != NULL) { |
| 417 return pause_info; | 417 return pause_info; |
| 418 } | 418 } |
| 419 // New label. | 419 // New label. |
| 420 pause_info = new TimelineLabelPauseInfo(name); | 420 pause_info = new TimelineLabelPauseInfo(name); |
| 421 labels_.Add(pause_info); | 421 labels_.Add(pause_info); |
| 422 return pause_info; | 422 return pause_info; |
| 423 } | 423 } |
| 424 | 424 |
| 425 } // namespace dart | 425 } // namespace dart |
| OLD | NEW |