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 #ifndef VM_TIMELINE_H_ | 5 #ifndef VM_TIMELINE_H_ |
6 #define VM_TIMELINE_H_ | 6 #define VM_TIMELINE_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/bitfield.h" | 9 #include "vm/bitfield.h" |
10 | 10 |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 private: | 264 private: |
265 TimelineEvent* event_; | 265 TimelineEvent* event_; |
266 }; | 266 }; |
267 | 267 |
268 | 268 |
269 // A block of |TimelineEvent|s. Not thread safe. | 269 // A block of |TimelineEvent|s. Not thread safe. |
270 class TimelineEventBlock { | 270 class TimelineEventBlock { |
271 public: | 271 public: |
272 static const intptr_t kBlockSize = 64; | 272 static const intptr_t kBlockSize = 64; |
273 | 273 |
274 TimelineEventBlock(); | 274 explicit TimelineEventBlock(intptr_t index); |
| 275 ~TimelineEventBlock(); |
275 | 276 |
276 TimelineEventBlock* next() const { | 277 TimelineEventBlock* next() const { |
277 return next_; | 278 return next_; |
278 } | 279 } |
279 void set_next(TimelineEventBlock* next) { | 280 void set_next(TimelineEventBlock* next) { |
280 next_ = next; | 281 next_ = next; |
281 } | 282 } |
282 | 283 |
283 intptr_t length() const { | 284 intptr_t length() const { |
284 return length_; | 285 return length_; |
285 } | 286 } |
286 | 287 |
| 288 intptr_t block_index() const { |
| 289 return block_index_; |
| 290 } |
| 291 |
287 bool IsEmpty() const { | 292 bool IsEmpty() const { |
288 return length_ == 0; | 293 return length_ == 0; |
289 } | 294 } |
290 | 295 |
291 bool IsFull() const { | 296 bool IsFull() const { |
292 return length_ == kBlockSize; | 297 return length_ == kBlockSize; |
293 } | 298 } |
294 | 299 |
295 TimelineEvent* At(intptr_t index) { | 300 TimelineEvent* At(intptr_t index) { |
296 ASSERT(index >= 0); | 301 ASSERT(index >= 0); |
297 ASSERT(index < kBlockSize); | 302 ASSERT(index < kBlockSize); |
298 return &events_[index]; | 303 return &events_[index]; |
299 } | 304 } |
300 | 305 |
| 306 const TimelineEvent* At(intptr_t index) const { |
| 307 ASSERT(index >= 0); |
| 308 ASSERT(index < kBlockSize); |
| 309 return &events_[index]; |
| 310 } |
| 311 |
301 // Attempt to sniff a thread id from the first event. | 312 // Attempt to sniff a thread id from the first event. |
302 ThreadId thread() const; | 313 ThreadId thread() const; |
303 // Attempt to sniff the timestamp from the first event. | 314 // Attempt to sniff the timestamp from the first event. |
304 int64_t LowerTimeBound() const; | 315 int64_t LowerTimeBound() const; |
305 | 316 |
306 // Returns false if |this| violates any of the following invariants: | 317 // Returns false if |this| violates any of the following invariants: |
307 // - events in the block come from one thread. | 318 // - events in the block come from one thread. |
308 // - events have monotonically increasing timestamps. | 319 // - events have monotonically increasing timestamps. |
309 bool CheckBlock(); | 320 bool CheckBlock(); |
310 | 321 |
| 322 // Call Reset on all events and set length to 0. |
| 323 void Reset(); |
| 324 |
311 protected: | 325 protected: |
312 TimelineEvent* StartEvent(); | 326 TimelineEvent* StartEvent(); |
313 | 327 |
314 TimelineEvent events_[kBlockSize]; | 328 TimelineEvent events_[kBlockSize]; |
315 TimelineEventBlock* next_; | 329 TimelineEventBlock* next_; |
316 intptr_t length_; | 330 intptr_t length_; |
| 331 intptr_t block_index_; |
317 | 332 |
318 friend class TimelineEventEndlessRecorder; | 333 friend class TimelineEventEndlessRecorder; |
| 334 friend class TimelineEventRecorder; |
319 friend class TimelineTestHelper; | 335 friend class TimelineTestHelper; |
320 | 336 |
321 private: | 337 private: |
322 DISALLOW_COPY_AND_ASSIGN(TimelineEventBlock); | 338 DISALLOW_COPY_AND_ASSIGN(TimelineEventBlock); |
323 }; | 339 }; |
324 | 340 |
325 | 341 |
326 // Recorder of |TimelineEvent|s. | 342 // Recorder of |TimelineEvent|s. |
327 class TimelineEventRecorder { | 343 class TimelineEventRecorder { |
328 public: | 344 public: |
329 TimelineEventRecorder(); | 345 TimelineEventRecorder(); |
330 virtual ~TimelineEventRecorder() {} | 346 virtual ~TimelineEventRecorder() {} |
331 | 347 |
332 // Interface method(s) which must be implemented. | 348 // Interface method(s) which must be implemented. |
333 virtual void PrintJSON(JSONStream* js) = 0; | 349 virtual void PrintJSON(JSONStream* js) = 0; |
334 | 350 virtual TimelineEventBlock* GetNewBlock() = 0; |
335 // Override if recorder uses blocks. | |
336 virtual TimelineEventBlock* GetNewBlock() { | |
337 return NULL; | |
338 } | |
339 | 351 |
340 void WriteTo(const char* directory); | 352 void WriteTo(const char* directory); |
341 | 353 |
342 protected: | 354 protected: |
343 // Interface method(s) which must be implemented. | 355 // Interface method(s) which must be implemented. |
344 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor) = 0; | 356 virtual void VisitObjectPointers(ObjectPointerVisitor* visitor) = 0; |
345 virtual TimelineEvent* StartEvent(const Object& object) = 0; | 357 virtual TimelineEvent* StartEvent(const Object& object) = 0; |
346 virtual TimelineEvent* StartEvent() = 0; | 358 virtual TimelineEvent* StartEvent() = 0; |
347 virtual void CompleteEvent(TimelineEvent* event) = 0; | 359 virtual void CompleteEvent(TimelineEvent* event) = 0; |
348 | 360 |
349 // Utility method(s). | 361 // Utility method(s). |
350 void PrintJSONMeta(JSONArray* array) const; | 362 void PrintJSONMeta(JSONArray* array) const; |
| 363 TimelineEvent* ThreadBlockStartEvent(); |
351 | 364 |
352 friend class TimelineStream; | 365 friend class TimelineStream; |
353 friend class Isolate; | 366 friend class Isolate; |
354 | 367 |
355 private: | 368 private: |
356 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); | 369 DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); |
357 }; | 370 }; |
358 | 371 |
359 | 372 |
360 // A recorder that stores events in a ring buffer of fixed capacity. | 373 // A recorder that stores events in a ring buffer of fixed capacity. |
361 // This recorder does track Dart objects. | 374 // This recorder does track Dart objects. |
362 // TODO(johnmccutchan): Make this recorder use event blocks too. | |
363 class TimelineEventRingRecorder : public TimelineEventRecorder { | 375 class TimelineEventRingRecorder : public TimelineEventRecorder { |
364 public: | 376 public: |
365 static const intptr_t kDefaultCapacity = 8192; | 377 static const intptr_t kDefaultCapacity = 8192; |
366 | 378 |
367 static intptr_t SizeForCapacity(intptr_t capacity); | |
368 | |
369 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); | 379 explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); |
370 ~TimelineEventRingRecorder(); | 380 ~TimelineEventRingRecorder(); |
371 | 381 |
372 void PrintJSON(JSONStream* js); | 382 void PrintJSON(JSONStream* js); |
| 383 TimelineEventBlock* GetNewBlock(); |
373 | 384 |
374 protected: | 385 protected: |
375 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 386 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
376 TimelineEvent* StartEvent(const Object& object); | 387 TimelineEvent* StartEvent(const Object& object); |
377 TimelineEvent* StartEvent(); | 388 TimelineEvent* StartEvent(); |
378 void CompleteEvent(TimelineEvent* event); | 389 void CompleteEvent(TimelineEvent* event); |
379 | 390 |
| 391 TimelineEventBlock* GetNewBlockLocked(); |
| 392 |
380 void PrintJSONEvents(JSONArray* array) const; | 393 void PrintJSONEvents(JSONArray* array) const; |
381 | 394 |
382 intptr_t GetNextIndex(); | 395 TimelineEventBlock** blocks_; |
383 | |
384 // events_[i] and event_objects_[i] are indexed together. | |
385 TimelineEvent* events_; | |
386 RawArray* event_objects_; | 396 RawArray* event_objects_; |
387 uintptr_t cursor_; | |
388 intptr_t capacity_; | 397 intptr_t capacity_; |
| 398 intptr_t num_blocks_; |
| 399 intptr_t block_cursor_; |
| 400 Mutex lock_; |
389 }; | 401 }; |
390 | 402 |
391 | 403 |
392 // An abstract recorder that calls |StreamEvent| whenever an event is complete. | 404 // An abstract recorder that calls |StreamEvent| whenever an event is complete. |
393 // This recorder does not track Dart objects. | 405 // This recorder does not track Dart objects. |
394 class TimelineEventStreamingRecorder : public TimelineEventRecorder { | 406 class TimelineEventStreamingRecorder : public TimelineEventRecorder { |
395 public: | 407 public: |
396 TimelineEventStreamingRecorder(); | 408 TimelineEventStreamingRecorder(); |
397 ~TimelineEventStreamingRecorder(); | 409 ~TimelineEventStreamingRecorder(); |
398 | 410 |
399 void PrintJSON(JSONStream* js); | 411 void PrintJSON(JSONStream* js); |
| 412 virtual TimelineEventBlock* GetNewBlock() { |
| 413 return NULL; |
| 414 } |
400 | 415 |
401 // Called when |event| is ready to be streamed. It is unsafe to keep a | 416 // Called when |event| is ready to be streamed. It is unsafe to keep a |
402 // reference to |event| as it may be freed as soon as this function returns. | 417 // reference to |event| as it may be freed as soon as this function returns. |
403 virtual void StreamEvent(TimelineEvent* event) = 0; | 418 virtual void StreamEvent(TimelineEvent* event) = 0; |
404 | 419 |
405 protected: | 420 protected: |
406 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 421 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
407 TimelineEvent* StartEvent(const Object& object); | 422 TimelineEvent* StartEvent(const Object& object); |
408 TimelineEvent* StartEvent(); | 423 TimelineEvent* StartEvent(); |
409 void CompleteEvent(TimelineEvent* event); | 424 void CompleteEvent(TimelineEvent* event); |
(...skipping 24 matching lines...) Expand all Loading... |
434 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 449 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
435 TimelineEvent* StartEvent(const Object& object); | 450 TimelineEvent* StartEvent(const Object& object); |
436 TimelineEvent* StartEvent(); | 451 TimelineEvent* StartEvent(); |
437 void CompleteEvent(TimelineEvent* event); | 452 void CompleteEvent(TimelineEvent* event); |
438 | 453 |
439 TimelineEventBlock* GetNewBlockLocked(); | 454 TimelineEventBlock* GetNewBlockLocked(); |
440 void PrintJSONEvents(JSONArray* array) const; | 455 void PrintJSONEvents(JSONArray* array) const; |
441 | 456 |
442 Mutex lock_; | 457 Mutex lock_; |
443 TimelineEventBlock* head_; | 458 TimelineEventBlock* head_; |
| 459 intptr_t block_index_; |
444 | 460 |
445 friend class TimelineEventBlockIterator; | 461 friend class TimelineEventBlockIterator; |
446 }; | 462 }; |
447 | 463 |
448 | 464 |
449 // An iterator for blocks. | 465 // An iterator for blocks. |
450 class TimelineEventBlockIterator { | 466 class TimelineEventBlockIterator { |
451 public: | 467 public: |
452 explicit TimelineEventBlockIterator(TimelineEventEndlessRecorder* recorder); | 468 explicit TimelineEventBlockIterator(TimelineEventEndlessRecorder* recorder); |
453 ~TimelineEventBlockIterator(); | 469 ~TimelineEventBlockIterator(); |
454 | 470 |
455 void Reset(); | 471 void Reset(); |
456 bool Next(); | 472 bool Next(); |
457 | 473 |
458 TimelineEventBlock* current() const { | 474 TimelineEventBlock* current() const { |
459 return current_; | 475 return current_; |
460 } | 476 } |
461 | 477 |
462 private: | 478 private: |
463 TimelineEventBlock* current_; | 479 TimelineEventBlock* current_; |
464 TimelineEventEndlessRecorder* recorder_; | 480 TimelineEventEndlessRecorder* recorder_; |
465 }; | 481 }; |
466 | 482 |
467 } // namespace dart | 483 } // namespace dart |
468 | 484 |
469 #endif // VM_TIMELINE_H_ | 485 #endif // VM_TIMELINE_H_ |
OLD | NEW |