OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/libplatform/tracing/trace-buffer.h" |
| 6 |
| 7 namespace v8 { |
| 8 namespace platform { |
| 9 namespace tracing { |
| 10 |
| 11 TraceBufferRingBuffer::TraceBufferRingBuffer(size_t max_chunks, |
| 12 TraceWriter* trace_writer) |
| 13 : max_chunks_(max_chunks), is_empty_(true), current_chunk_seq_(1) { |
| 14 trace_writer_.reset(trace_writer); |
| 15 chunks_.resize(max_chunks); |
| 16 } |
| 17 |
| 18 TraceBufferRingBuffer::~TraceBufferRingBuffer() { Flush(); } |
| 19 |
| 20 TraceObject* TraceBufferRingBuffer::AddTraceEvent(uint64_t* handle) { |
| 21 if (is_empty_ || chunks_[chunk_index_]->IsFull()) { |
| 22 chunk_index_ = is_empty_ ? 0 : NextChunkIndex(chunk_index_); |
| 23 is_empty_ = false; |
| 24 auto& chunk = chunks_[chunk_index_]; |
| 25 if (chunk) { |
| 26 chunk->Reset(current_chunk_seq_++); |
| 27 } else { |
| 28 chunk.reset(new TraceBufferChunk(current_chunk_seq_++)); |
| 29 } |
| 30 } |
| 31 auto& chunk = chunks_[chunk_index_]; |
| 32 size_t event_index; |
| 33 TraceObject* trace_object = chunk->AddTraceEvent(&event_index); |
| 34 *handle = MakeHandle(chunk_index_, chunk->seq(), event_index); |
| 35 return trace_object; |
| 36 } |
| 37 |
| 38 TraceObject* TraceBufferRingBuffer::GetEventByHandle(uint64_t handle) { |
| 39 size_t chunk_index, event_index; |
| 40 uint32_t chunk_seq; |
| 41 ExtractHandle(handle, &chunk_index, &chunk_seq, &event_index); |
| 42 if (chunk_index >= chunks_.size()) return NULL; |
| 43 auto& chunk = chunks_[chunk_index]; |
| 44 if (!chunk || chunk->seq() != chunk_seq) return NULL; |
| 45 return chunk->GetEventAt(event_index); |
| 46 } |
| 47 |
| 48 bool TraceBufferRingBuffer::Flush() { |
| 49 // This flushes all the traces stored in the buffer. |
| 50 if (!is_empty_) { |
| 51 for (size_t i = NextChunkIndex(chunk_index_);; i = NextChunkIndex(i)) { |
| 52 if (auto& chunk = chunks_[i]) { |
| 53 for (size_t j = 0; j < chunk->size(); ++j) { |
| 54 trace_writer_->AppendTraceEvent(chunk->GetEventAt(j)); |
| 55 } |
| 56 } |
| 57 if (i == chunk_index_) break; |
| 58 } |
| 59 } |
| 60 trace_writer_->Flush(); |
| 61 // This resets the trace buffer. |
| 62 is_empty_ = true; |
| 63 return true; |
| 64 } |
| 65 |
| 66 uint64_t TraceBufferRingBuffer::MakeHandle(size_t chunk_index, |
| 67 uint32_t chunk_seq, |
| 68 size_t event_index) const { |
| 69 return static_cast<uint64_t>(chunk_seq) * Capacity() + |
| 70 chunk_index * TraceBufferChunk::kChunkSize + event_index; |
| 71 } |
| 72 |
| 73 void TraceBufferRingBuffer::ExtractHandle(uint64_t handle, size_t* chunk_index, |
| 74 uint32_t* chunk_seq, |
| 75 size_t* event_index) const { |
| 76 *chunk_seq = static_cast<uint32_t>(handle / Capacity()); |
| 77 size_t indices = handle % Capacity(); |
| 78 *chunk_index = indices / TraceBufferChunk::kChunkSize; |
| 79 *event_index = indices % TraceBufferChunk::kChunkSize; |
| 80 } |
| 81 |
| 82 size_t TraceBufferRingBuffer::NextChunkIndex(size_t index) const { |
| 83 if (++index >= max_chunks_) index = 0; |
| 84 return index; |
| 85 } |
| 86 |
| 87 TraceBufferChunk::TraceBufferChunk(uint32_t seq) : next_free_(0), seq_(seq) {} |
| 88 |
| 89 void TraceBufferChunk::Reset(uint32_t new_seq) { |
| 90 next_free_ = 0; |
| 91 seq_ = new_seq; |
| 92 } |
| 93 |
| 94 TraceObject* TraceBufferChunk::AddTraceEvent(size_t* event_index) { |
| 95 *event_index = next_free_++; |
| 96 return &chunk_[*event_index]; |
| 97 } |
| 98 |
| 99 TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer( |
| 100 size_t max_chunks, TraceWriter* trace_writer) { |
| 101 return new TraceBufferRingBuffer(max_chunks, trace_writer); |
| 102 } |
| 103 |
| 104 } // namespace tracing |
| 105 } // namespace platform |
| 106 } // namespace v8 |
OLD | NEW |