diff options
Diffstat (limited to 'deps/v8/src/libplatform/tracing/trace-buffer.cc')
-rw-r--r-- | deps/v8/src/libplatform/tracing/trace-buffer.cc | 109 |
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 |