| 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..a2b75395497c164052afbe7656264abf87a82649 | 
| --- /dev/null | 
| +++ b/src/libplatform/tracing/trace-buffer.cc | 
| @@ -0,0 +1,106 @@ | 
| +// 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), is_empty_(true), current_chunk_seq_(1) { | 
| +  trace_writer_.reset(trace_writer); | 
| +  chunks_.resize(max_chunks); | 
| +} | 
| + | 
| +TraceBufferRingBuffer::~TraceBufferRingBuffer() { Flush(); } | 
| + | 
| +TraceObject* TraceBufferRingBuffer::AddTraceEvent(uint64_t* handle) { | 
| +  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) { | 
| +  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() { | 
| +  // 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) : next_free_(0), 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 | 
|  |