summaryrefslogtreecommitdiff
path: root/deps/v8/src/libplatform/tracing/trace-buffer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/libplatform/tracing/trace-buffer.cc')
-rw-r--r--deps/v8/src/libplatform/tracing/trace-buffer.cc109
1 files changed, 109 insertions, 0 deletions
diff --git a/deps/v8/src/libplatform/tracing/trace-buffer.cc b/deps/v8/src/libplatform/tracing/trace-buffer.cc
new file mode 100644
index 0000000000..354f0459f6
--- /dev/null
+++ b/deps/v8/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