diff --git a/src/SConscript b/src/SConscript
index ce41cb0fa6..4e474f4fad 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -43,6 +43,7 @@ SOURCES = {
     bootstrapper.cc
     builtins.cc
     checks.cc
+    circular-queue.cc
     code-stubs.cc
     codegen.cc
     compilation-cache.cc
diff --git a/src/circular-queue-inl.h b/src/circular-queue-inl.h
new file mode 100644
index 0000000000..ffe8fb003e
--- /dev/null
+++ b/src/circular-queue-inl.h
@@ -0,0 +1,101 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CIRCULAR_BUFFER_INL_H_
+#define V8_CIRCULAR_BUFFER_INL_H_
+
+#include "circular-queue.h"
+
+namespace v8 {
+namespace internal {
+
+
+template<typename Record>
+CircularQueue<Record>::CircularQueue(int desired_buffer_size_in_bytes)
+    : buffer_(NewArray<Record>(desired_buffer_size_in_bytes / sizeof(Record))),
+      buffer_end_(buffer_ + desired_buffer_size_in_bytes / sizeof(Record)),
+      enqueue_semaphore_(OS::CreateSemaphore((buffer_end_ - buffer_) - 1)),
+      enqueue_pos_(buffer_),
+      dequeue_pos_(buffer_) {
+  // To be able to distinguish between a full and an empty queue
+  // state, the queue must be capable of containing at least 2
+  // records.
+  ASSERT((buffer_end_ - buffer_) >= 2);
+}
+
+
+template<typename Record>
+CircularQueue<Record>::~CircularQueue() {
+  DeleteArray(buffer_);
+  delete enqueue_semaphore_;
+}
+
+
+template<typename Record>
+void CircularQueue<Record>::Dequeue(Record* rec) {
+  ASSERT(!IsEmpty());
+  *rec = *dequeue_pos_;
+  dequeue_pos_ = Next(dequeue_pos_);
+  // Tell we have a spare record.
+  enqueue_semaphore_->Signal();
+}
+
+
+template<typename Record>
+void CircularQueue<Record>::Enqueue(const Record& rec) {
+  // Wait until we have at least one spare record.
+  enqueue_semaphore_->Wait();
+  ASSERT(Next(enqueue_pos_) != dequeue_pos_);
+  *enqueue_pos_ = rec;
+  enqueue_pos_ = Next(enqueue_pos_);
+}
+
+
+template<typename Record>
+Record* CircularQueue<Record>::Next(Record* curr) {
+  return ++curr != buffer_end_ ? curr : buffer_;
+}
+
+
+void* SamplingCircularQueue::Enqueue() {
+  Cell* enqueue_pos = reinterpret_cast<Cell*>(
+      Thread::GetThreadLocal(producer_key_));
+  WrapPositionIfNeeded(&enqueue_pos);
+  Thread::SetThreadLocal(producer_key_, enqueue_pos + record_size_);
+  return enqueue_pos;
+}
+
+
+void SamplingCircularQueue::WrapPositionIfNeeded(
+    SamplingCircularQueue::Cell** pos) {
+  if (**pos == kEnd) *pos = buffer_;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CIRCULAR_BUFFER_INL_H_
diff --git a/src/circular-queue.cc b/src/circular-queue.cc
new file mode 100644
index 0000000000..5f7a33eb3a
--- /dev/null
+++ b/src/circular-queue.cc
@@ -0,0 +1,131 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "circular-queue-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+SamplingCircularQueue::SamplingCircularQueue(int record_size_in_bytes,
+                                             int desired_chunk_size_in_bytes,
+                                             int buffer_size_in_chunks)
+    : record_size_(record_size_in_bytes / sizeof(Cell)),
+      chunk_size_in_bytes_(desired_chunk_size_in_bytes / record_size_in_bytes *
+                        record_size_in_bytes),
+      chunk_size_(chunk_size_in_bytes_ / sizeof(Cell)),
+      buffer_size_(chunk_size_ * buffer_size_in_chunks),
+      // The distance ensures that producer and consumer never step on
+      // each other's chunks and helps eviction of produced data from
+      // the CPU cache (having that chunk size is bigger than the cache.)
+      producer_consumer_distance_(2 * chunk_size_),
+      buffer_(NewArray<Cell>(buffer_size_ + 1)) {
+  ASSERT(buffer_size_in_chunks > 2);
+  // Only need to keep the first cell of a chunk clean.
+  for (int i = 0; i < buffer_size_; i += chunk_size_) {
+    buffer_[i] = kClear;
+  }
+  buffer_[buffer_size_] = kEnd;
+}
+
+
+SamplingCircularQueue::~SamplingCircularQueue() {
+  DeleteArray(buffer_);
+}
+
+
+void SamplingCircularQueue::SetUpProducer() {
+  producer_key_ = Thread::CreateThreadLocalKey();
+  Thread::SetThreadLocal(producer_key_, buffer_);
+}
+
+
+void SamplingCircularQueue::TearDownProducer() {
+  Thread::DeleteThreadLocalKey(producer_key_);
+}
+
+
+void SamplingCircularQueue::SetUpConsumer() {
+  consumer_key_ = Thread::CreateThreadLocalKey();
+  ConsumerPosition* cp = new ConsumerPosition;
+  cp->dequeue_chunk_pos = buffer_;
+  cp->dequeue_chunk_poll_pos = buffer_ + producer_consumer_distance_;
+  cp->dequeue_pos = NULL;
+  Thread::SetThreadLocal(consumer_key_, cp);
+}
+
+
+void SamplingCircularQueue::TearDownConsumer() {
+  delete reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  Thread::DeleteThreadLocalKey(consumer_key_);
+}
+
+
+void* SamplingCircularQueue::StartDequeue() {
+  ConsumerPosition* cp = reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  if (cp->dequeue_pos != NULL) {
+    return cp->dequeue_pos;
+  } else {
+    if (*cp->dequeue_chunk_poll_pos != kClear) {
+      cp->dequeue_pos = cp->dequeue_chunk_pos;
+      cp->dequeue_end_pos = cp->dequeue_pos + chunk_size_;
+      return cp->dequeue_pos;
+    } else {
+      return NULL;
+    }
+  }
+}
+
+
+void SamplingCircularQueue::FinishDequeue() {
+  ConsumerPosition* cp = reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  cp->dequeue_pos += record_size_;
+  if (cp->dequeue_pos < cp->dequeue_end_pos) return;
+  // Move to next chunk.
+  cp->dequeue_pos = NULL;
+  *cp->dequeue_chunk_pos = kClear;
+  cp->dequeue_chunk_pos += chunk_size_;
+  WrapPositionIfNeeded(&cp->dequeue_chunk_pos);
+  cp->dequeue_chunk_poll_pos += chunk_size_;
+  WrapPositionIfNeeded(&cp->dequeue_chunk_poll_pos);
+}
+
+
+void SamplingCircularQueue::FlushResidualRecords() {
+  ConsumerPosition* cp = reinterpret_cast<ConsumerPosition*>(
+      Thread::GetThreadLocal(consumer_key_));
+  // Eliminate producer / consumer distance.
+  cp->dequeue_chunk_poll_pos = cp->dequeue_chunk_pos;
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/circular-queue.h b/src/circular-queue.h
new file mode 100644
index 0000000000..11159e0388
--- /dev/null
+++ b/src/circular-queue.h
@@ -0,0 +1,130 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_CIRCULAR_QUEUE_H_
+#define V8_CIRCULAR_QUEUE_H_
+
+namespace v8 {
+namespace internal {
+
+
+// Lock-based blocking circular queue for small records.  Intended for
+// transfer of small records between a single producer and a single
+// consumer. Blocks on enqueue operation if the queue is full.
+template<typename Record>
+class CircularQueue {
+ public:
+  inline explicit CircularQueue(int desired_buffer_size_in_bytes);
+  inline ~CircularQueue();
+
+  INLINE(void Dequeue(Record* rec));
+  INLINE(void Enqueue(const Record& rec));
+  INLINE(bool IsEmpty()) { return enqueue_pos_ == dequeue_pos_; }
+
+ private:
+  INLINE(Record* Next(Record* curr));
+
+  Record* buffer_;
+  Record* const buffer_end_;
+  Semaphore* enqueue_semaphore_;
+  Record* enqueue_pos_;
+  Record* dequeue_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(CircularQueue);
+};
+
+
+// Lock-free cache-friendly sampling circular queue for large
+// records. Intended for fast transfer of large records between a
+// single producer and a single consumer. If the queue is full,
+// previous unread records are overwritten. The queue is designed with
+// a goal in mind to evade cache lines thrashing by preventing
+// simultaneous reads and writes to adjanced memory locations.
+//
+// IMPORTANT: as a producer never checks for chunks cleanness, it is
+// possible that it can catch up and overwrite a chunk that a consumer
+// is currently reading, resulting in a corrupt record being read.
+class SamplingCircularQueue {
+ public:
+  // Executed on the application thread.
+  SamplingCircularQueue(int record_size_in_bytes,
+                        int desired_chunk_size_in_bytes,
+                        int buffer_size_in_chunks);
+  ~SamplingCircularQueue();
+
+  // Executed on the producer (sampler) or application thread.
+  void SetUpProducer();
+  // Enqueue returns a pointer to a memory location for storing the next
+  // record.
+  INLINE(void* Enqueue());
+  void TearDownProducer();
+
+  // Executed on the consumer (analyzer) thread.
+  void SetUpConsumer();
+  // StartDequeue returns a pointer to a memory location for retrieving
+  // the next record. After the record had been read by a consumer,
+  // FinishDequeue must be called. Until that moment, subsequent calls
+  // to StartDequeue will return the same pointer.
+  void* StartDequeue();
+  void FinishDequeue();
+  // Due to a presence of slipping between the producer and the consumer,
+  // the queue must be notified whether producing has been finished in order
+  // to process remaining records from the buffer.
+  void FlushResidualRecords();
+  void TearDownConsumer();
+
+  typedef AtomicWord Cell;
+  // Reserved values for the first cell of a record.
+  static const Cell kClear = 0;  // Marks clean (processed) chunks.
+  static const Cell kEnd = -1;   // Marks the end of the buffer.
+
+ private:
+  struct ConsumerPosition {
+    Cell* dequeue_chunk_pos;
+    Cell* dequeue_chunk_poll_pos;
+    Cell* dequeue_pos;
+    Cell* dequeue_end_pos;
+  };
+
+  INLINE(void WrapPositionIfNeeded(Cell** pos));
+
+  const int record_size_;
+  const int chunk_size_in_bytes_;
+  const int chunk_size_;
+  const int buffer_size_;
+  const int producer_consumer_distance_;
+  Cell* buffer_;
+  // Store producer and consumer data in TLS to avoid modifying the
+  // same CPU cache line from two threads simultaneously.
+  Thread::LocalStorageKey consumer_key_;
+  Thread::LocalStorageKey producer_key_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_CIRCULAR_QUEUE_H_
diff --git a/src/platform.h b/src/platform.h
index bc2e9d64f3..8f68766336 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -114,6 +114,10 @@ int random();
 namespace v8 {
 namespace internal {
 
+// Use AtomicWord for a machine-sized pointer. It is assumed that
+// reads and writes of naturally aligned values of this type are atomic.
+typedef intptr_t AtomicWord;
+
 class Semaphore;
 
 double ceiling(double x);
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index f4964ae6a7..28ead19f8b 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -39,6 +39,7 @@ SOURCES = {
     'test-alloc.cc',
     'test-api.cc',
     'test-ast.cc',
+    'test-circular-queue.cc',
     'test-compiler.cc',
     'test-conversions.cc',
     'test-dataflow.cc',
diff --git a/test/cctest/test-circular-queue.cc b/test/cctest/test-circular-queue.cc
new file mode 100644
index 0000000000..aa981b8137
--- /dev/null
+++ b/test/cctest/test-circular-queue.cc
@@ -0,0 +1,127 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+//
+// Tests of circular queues.
+
+#include "v8.h"
+#include "circular-queue-inl.h"
+#include "cctest.h"
+
+namespace i = v8::internal;
+
+using i::CircularQueue;
+using i::SamplingCircularQueue;
+
+
+TEST(SingleRecordCircularQueue) {
+  typedef int Record;
+  CircularQueue<Record> cq(sizeof(Record) * 2);
+  CHECK(cq.IsEmpty());
+  cq.Enqueue(1);
+  CHECK(!cq.IsEmpty());
+  Record rec = 0;
+  cq.Dequeue(&rec);
+  CHECK_EQ(1, rec);
+  CHECK(cq.IsEmpty());
+}
+
+
+TEST(MultipleRecordsCircularQueue) {
+  typedef int Record;
+  const int kQueueSize = 10;
+  CircularQueue<Record> cq(sizeof(Record) * (kQueueSize + 1));
+  CHECK(cq.IsEmpty());
+  cq.Enqueue(1);
+  CHECK(!cq.IsEmpty());
+  for (int i = 2; i <= 5; ++i) {
+    cq.Enqueue(i);
+    CHECK(!cq.IsEmpty());
+  }
+  Record rec = 0;
+  for (int i = 1; i <= 4; ++i) {
+    CHECK(!cq.IsEmpty());
+    cq.Dequeue(&rec);
+    CHECK_EQ(i, rec);
+  }
+  for (int i = 6; i <= 12; ++i) {
+    cq.Enqueue(i);
+    CHECK(!cq.IsEmpty());
+  }
+  for (int i = 5; i <= 12; ++i) {
+    CHECK(!cq.IsEmpty());
+    cq.Dequeue(&rec);
+    CHECK_EQ(i, rec);
+  }
+  CHECK(cq.IsEmpty());
+}
+
+
+TEST(SamplingCircularQueue) {
+  typedef int Record;
+  const int kRecordsPerChunk = 4;
+  SamplingCircularQueue scq(sizeof(Record),
+                            kRecordsPerChunk * sizeof(Record),
+                            3);
+  scq.SetUpProducer();
+  scq.SetUpConsumer();
+
+  // Check that we are using non-reserved values.
+  CHECK_NE(SamplingCircularQueue::kClear, 1);
+  CHECK_NE(SamplingCircularQueue::kEnd, 1);
+  // Fill up the first chunk.
+  CHECK_EQ(NULL, scq.StartDequeue());
+  for (int i = 1; i < 1 + kRecordsPerChunk; ++i) {
+    Record* rec = reinterpret_cast<Record*>(scq.Enqueue());
+    CHECK_NE(NULL, rec);
+    *rec = i;
+    CHECK_EQ(NULL, scq.StartDequeue());
+  }
+
+  // Fill up the second chunk. Consumption must still be unavailable.
+  CHECK_EQ(NULL, scq.StartDequeue());
+  for (int i = 10; i < 10 + kRecordsPerChunk; ++i) {
+    Record* rec = reinterpret_cast<Record*>(scq.Enqueue());
+    CHECK_NE(NULL, rec);
+    *rec = i;
+    CHECK_EQ(NULL, scq.StartDequeue());
+  }
+
+  Record* rec = reinterpret_cast<Record*>(scq.Enqueue());
+  CHECK_NE(NULL, rec);
+  *rec = 20;
+  // Now as we started filling up the third chunk, consumption
+  // must become possible.
+  CHECK_NE(NULL, scq.StartDequeue());
+
+  // Consume the first chunk.
+  for (int i = 1; i < 1 + kRecordsPerChunk; ++i) {
+    Record* rec = reinterpret_cast<Record*>(scq.StartDequeue());
+    CHECK_NE(NULL, rec);
+    CHECK_EQ(i, *rec);
+    CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue()));
+    scq.FinishDequeue();
+    CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue()));
+  }
+  // Now consumption must not be possible, as consumer now polls
+  // the first chunk for emptinness.
+  CHECK_EQ(NULL, scq.StartDequeue());
+
+  scq.FlushResidualRecords();
+  // From now, consumer no more polls ahead of the current chunk,
+  // so it's possible to consume the second chunk.
+  CHECK_NE(NULL, scq.StartDequeue());
+  // Consume the second chunk
+  for (int i = 10; i < 10 + kRecordsPerChunk; ++i) {
+    Record* rec = reinterpret_cast<Record*>(scq.StartDequeue());
+    CHECK_NE(NULL, rec);
+    CHECK_EQ(i, *rec);
+    CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue()));
+    scq.FinishDequeue();
+    CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue()));
+  }
+  // Consumption must still be possible as the first cell of the
+  // last chunk is not clean.
+  CHECK_NE(NULL, scq.StartDequeue());
+
+  scq.TearDownConsumer();
+  scq.TearDownProducer();
+}
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index d859fb0d70..a0cc3e3422 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -234,6 +234,7 @@
         '../../src/char-predicates.h',
         '../../src/checks.cc',
         '../../src/checks.h',
+        '../../src/circular-queue.cc',
         '../../src/code-stubs.cc',
         '../../src/code-stubs.h',
         '../../src/code.h',
diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index ccb197a24f..9ef2665b11 100644
--- a/tools/v8.xcodeproj/project.pbxproj
+++ b/tools/v8.xcodeproj/project.pbxproj
@@ -210,6 +210,8 @@
 		89FB0E3A0F8E533F00B04B3C /* d8-posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89FB0E360F8E531900B04B3C /* d8-posix.cc */; };
 		9F11D9A0105AF0A300EBE5B2 /* heap-profiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F11D99E105AF0A300EBE5B2 /* heap-profiler.cc */; };
 		9F11D9A1105AF0A300EBE5B2 /* heap-profiler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F11D99E105AF0A300EBE5B2 /* heap-profiler.cc */; };
+		9F2B3711114FF62D007CDAF4 /* circular-queue.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B370F114FF62D007CDAF4 /* circular-queue.cc */; };
+		9F2B3712114FF62D007CDAF4 /* circular-queue.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F2B370F114FF62D007CDAF4 /* circular-queue.cc */; };
 		9F4B7B890FCC877A00DC4117 /* log-utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F4B7B870FCC877A00DC4117 /* log-utils.cc */; };
 		9F4B7B8A0FCC877A00DC4117 /* log-utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F4B7B870FCC877A00DC4117 /* log-utils.cc */; };
 		9F73E3B1114E61A100F84A5A /* profile-generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F73E3AF114E61A100F84A5A /* profile-generator.cc */; };
@@ -552,6 +554,9 @@
 		89FB0E370F8E531900B04B3C /* d8-windows.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-windows.cc"; path = "../src/d8-windows.cc"; sourceTree = "<group>"; };
 		9F11D99E105AF0A300EBE5B2 /* heap-profiler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "heap-profiler.cc"; sourceTree = "<group>"; };
 		9F11D99F105AF0A300EBE5B2 /* heap-profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "heap-profiler.h"; sourceTree = "<group>"; };
+		9F2B370E114FF62D007CDAF4 /* circular-queue-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "circular-queue-inl.h"; sourceTree = "<group>"; };
+		9F2B370F114FF62D007CDAF4 /* circular-queue.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "circular-queue.cc"; sourceTree = "<group>"; };
+		9F2B3710114FF62D007CDAF4 /* circular-queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "circular-queue.h"; sourceTree = "<group>"; };
 		9F4B7B870FCC877A00DC4117 /* log-utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "log-utils.cc"; sourceTree = "<group>"; };
 		9F4B7B880FCC877A00DC4117 /* log-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "log-utils.h"; sourceTree = "<group>"; };
 		9F73E3AE114E61A100F84A5A /* profile-generator-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "profile-generator-inl.h"; sourceTree = "<group>"; };
@@ -681,6 +686,9 @@
 				897FF10E0E719B8F00D62E90 /* char-predicates.h */,
 				897FF10F0E719B8F00D62E90 /* checks.cc */,
 				897FF1100E719B8F00D62E90 /* checks.h */,
+				9F2B370E114FF62D007CDAF4 /* circular-queue-inl.h */,
+				9F2B370F114FF62D007CDAF4 /* circular-queue.cc */,
+				9F2B3710114FF62D007CDAF4 /* circular-queue.h */,
 				897FF1110E719B8F00D62E90 /* code-stubs.cc */,
 				897FF1120E719B8F00D62E90 /* code-stubs.h */,
 				897FF1130E719B8F00D62E90 /* code.h */,
@@ -1248,6 +1256,7 @@
 				9FBE03DE10BD409900F8BFBA /* fast-codegen.cc in Sources */,
 				9FBE03E210BD40EA00F8BFBA /* fast-codegen-ia32.cc in Sources */,
 				9F73E3B2114E61A100F84A5A /* profile-generator.cc in Sources */,
+				9F2B3712114FF62D007CDAF4 /* circular-queue.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1358,6 +1367,7 @@
 				9FBE03DF10BD409900F8BFBA /* fast-codegen.cc in Sources */,
 				9FBE03E510BD412600F8BFBA /* fast-codegen-arm.cc in Sources */,
 				9F73E3B1114E61A100F84A5A /* profile-generator.cc in Sources */,
+				9F2B3711114FF62D007CDAF4 /* circular-queue.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index 37ea01c0e9..be32bcf984 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -252,6 +252,18 @@
 				RelativePath="..\..\src\checks.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\src\circular-queue-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\circular-queue.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\circular-queue.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\src\code-stubs.cc"
 				>
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
index de2d65a247..74a7359f45 100644
--- a/tools/visual_studio/v8_base_arm.vcproj
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -252,6 +252,18 @@
 				RelativePath="..\..\src\checks.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\src\circular-queue-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\circular-queue.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\circular-queue.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\src\code-stubs.cc"
 				>
diff --git a/tools/visual_studio/v8_base_x64.vcproj b/tools/visual_studio/v8_base_x64.vcproj
index 29f4ed77b0..f573910d90 100644
--- a/tools/visual_studio/v8_base_x64.vcproj
+++ b/tools/visual_studio/v8_base_x64.vcproj
@@ -252,6 +252,18 @@
 				RelativePath="..\..\src\checks.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\src\circular-queue-inl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\circular-queue.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\circular-queue.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\src\code-stubs.cc"
 				>
diff --git a/tools/visual_studio/v8_cctest.vcproj b/tools/visual_studio/v8_cctest.vcproj
index 9acb835c02..7d0c4fffa9 100644
--- a/tools/visual_studio/v8_cctest.vcproj
+++ b/tools/visual_studio/v8_cctest.vcproj
@@ -155,6 +155,10 @@
 			RelativePath="..\..\test\cctest\test-ast.cc"
 			>
 		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-circular-queue.cc"
+			>
+		</File>
 		<File
 			RelativePath="..\..\test\cctest\test-compiler.cc"
 			>
@@ -219,6 +223,10 @@
 			RelativePath="..\..\test\cctest\test-platform-win32.cc"
 			>
 		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-profile-generator.cc"
+			>
+		</File>
 		<File
 			RelativePath="..\..\test\cctest\test-serialize.cc"
 			>
diff --git a/tools/visual_studio/v8_cctest_arm.vcproj b/tools/visual_studio/v8_cctest_arm.vcproj
index 7ff953e241..ee08b4fbf6 100644
--- a/tools/visual_studio/v8_cctest_arm.vcproj
+++ b/tools/visual_studio/v8_cctest_arm.vcproj
@@ -155,6 +155,10 @@
 			RelativePath="..\..\test\cctest\test-ast.cc"
 			>
 		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-circular-queue.cc"
+			>
+		</File>
 		<File
 			RelativePath="..\..\test\cctest\test-compiler.cc"
 			>
@@ -211,6 +215,10 @@
 			RelativePath="..\..\test\cctest\test-platform-win32.cc"
 			>
 		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-profile-generator.cc"
+			>
+		</File>
 		<File
 			RelativePath="..\..\test\cctest\test-serialize.cc"
 			>
diff --git a/tools/visual_studio/v8_cctest_x64.vcproj b/tools/visual_studio/v8_cctest_x64.vcproj
index 1e9044b1b2..ee80c41eca 100644
--- a/tools/visual_studio/v8_cctest_x64.vcproj
+++ b/tools/visual_studio/v8_cctest_x64.vcproj
@@ -155,6 +155,10 @@
 			RelativePath="..\..\test\cctest\test-ast.cc"
 			>
 		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-circular-queue.cc"
+			>
+		</File>
 		<File
 			RelativePath="..\..\test\cctest\test-compiler.cc"
 			>
@@ -215,6 +219,10 @@
 			RelativePath="..\..\test\cctest\test-platform-win32.cc"
 			>
 		</File>
+		<File
+			RelativePath="..\..\test\cctest\test-profile-generator.cc"
+			>
+		</File>
 		<File
 			RelativePath="..\..\test\cctest\test-serialize.cc"
 			>