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" >