Index: src/libplatform/tracing/trace-buffer.cc |
diff --git a/src/libplatform/tracing/trace-buffer.cc b/src/libplatform/tracing/trace-buffer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..354f0459f68531503bd6eaf6ee09d5928945015f |
--- /dev/null |
+++ b/src/libplatform/tracing/trace-buffer.cc |
@@ -0,0 +1,109 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/libplatform/tracing/trace-buffer.h" |
+ |
+namespace v8 { |
+namespace platform { |
+namespace tracing { |
+ |
+TraceBufferRingBuffer::TraceBufferRingBuffer(size_t max_chunks, |
+ TraceWriter* trace_writer) |
+ : max_chunks_(max_chunks) { |
+ trace_writer_.reset(trace_writer); |
+ chunks_.resize(max_chunks); |
+} |
+ |
+TraceBufferRingBuffer::~TraceBufferRingBuffer() {} |
+ |
+TraceObject* TraceBufferRingBuffer::AddTraceEvent(uint64_t* handle) { |
+ base::LockGuard<base::Mutex> guard(&mutex_); |
+ if (is_empty_ || chunks_[chunk_index_]->IsFull()) { |
+ chunk_index_ = is_empty_ ? 0 : NextChunkIndex(chunk_index_); |
+ is_empty_ = false; |
+ auto& chunk = chunks_[chunk_index_]; |
+ if (chunk) { |
+ chunk->Reset(current_chunk_seq_++); |
+ } else { |
+ chunk.reset(new TraceBufferChunk(current_chunk_seq_++)); |
+ } |
+ } |
+ auto& chunk = chunks_[chunk_index_]; |
+ size_t event_index; |
+ TraceObject* trace_object = chunk->AddTraceEvent(&event_index); |
+ *handle = MakeHandle(chunk_index_, chunk->seq(), event_index); |
+ return trace_object; |
+} |
+ |
+TraceObject* TraceBufferRingBuffer::GetEventByHandle(uint64_t handle) { |
+ base::LockGuard<base::Mutex> guard(&mutex_); |
+ size_t chunk_index, event_index; |
+ uint32_t chunk_seq; |
+ ExtractHandle(handle, &chunk_index, &chunk_seq, &event_index); |
+ if (chunk_index >= chunks_.size()) return NULL; |
+ auto& chunk = chunks_[chunk_index]; |
+ if (!chunk || chunk->seq() != chunk_seq) return NULL; |
+ return chunk->GetEventAt(event_index); |
+} |
+ |
+bool TraceBufferRingBuffer::Flush() { |
+ base::LockGuard<base::Mutex> guard(&mutex_); |
+ // This flushes all the traces stored in the buffer. |
+ if (!is_empty_) { |
+ for (size_t i = NextChunkIndex(chunk_index_);; i = NextChunkIndex(i)) { |
+ if (auto& chunk = chunks_[i]) { |
+ for (size_t j = 0; j < chunk->size(); ++j) { |
+ trace_writer_->AppendTraceEvent(chunk->GetEventAt(j)); |
+ } |
+ } |
+ if (i == chunk_index_) break; |
+ } |
+ } |
+ trace_writer_->Flush(); |
+ // This resets the trace buffer. |
+ is_empty_ = true; |
+ return true; |
+} |
+ |
+uint64_t TraceBufferRingBuffer::MakeHandle(size_t chunk_index, |
+ uint32_t chunk_seq, |
+ size_t event_index) const { |
+ return static_cast<uint64_t>(chunk_seq) * Capacity() + |
+ chunk_index * TraceBufferChunk::kChunkSize + event_index; |
+} |
+ |
+void TraceBufferRingBuffer::ExtractHandle(uint64_t handle, size_t* chunk_index, |
+ uint32_t* chunk_seq, |
+ size_t* event_index) const { |
+ *chunk_seq = static_cast<uint32_t>(handle / Capacity()); |
+ size_t indices = handle % Capacity(); |
+ *chunk_index = indices / TraceBufferChunk::kChunkSize; |
+ *event_index = indices % TraceBufferChunk::kChunkSize; |
+} |
+ |
+size_t TraceBufferRingBuffer::NextChunkIndex(size_t index) const { |
+ if (++index >= max_chunks_) index = 0; |
+ return index; |
+} |
+ |
+TraceBufferChunk::TraceBufferChunk(uint32_t seq) : seq_(seq) {} |
+ |
+void TraceBufferChunk::Reset(uint32_t new_seq) { |
+ next_free_ = 0; |
+ seq_ = new_seq; |
+} |
+ |
+TraceObject* TraceBufferChunk::AddTraceEvent(size_t* event_index) { |
+ *event_index = next_free_++; |
+ return &chunk_[*event_index]; |
+} |
+ |
+TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer( |
+ size_t max_chunks, TraceWriter* trace_writer) { |
+ return new TraceBufferRingBuffer(max_chunks, trace_writer); |
+} |
+ |
+} // namespace tracing |
+} // namespace platform |
+} // namespace v8 |