Re-apply r4159 now with working test on x64
TBR=sgjesse@chromium.org Review URL: http://codereview.chromium.org/979005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4164 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
0f988248b2
commit
d2188658ca
@ -43,6 +43,7 @@ SOURCES = {
|
||||
bootstrapper.cc
|
||||
builtins.cc
|
||||
checks.cc
|
||||
circular-queue.cc
|
||||
code-stubs.cc
|
||||
codegen.cc
|
||||
compilation-cache.cc
|
||||
|
101
src/circular-queue-inl.h
Normal file
101
src/circular-queue-inl.h
Normal file
@ -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_
|
131
src/circular-queue.cc
Normal file
131
src/circular-queue.cc
Normal file
@ -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
|
130
src/circular-queue.h
Normal file
130
src/circular-queue.h
Normal file
@ -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_
|
@ -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);
|
||||
|
@ -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',
|
||||
|
127
test/cctest/test-circular-queue.cc
Normal file
127
test/cctest/test-circular-queue.cc
Normal file
@ -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 SamplingCircularQueue::Cell 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 (Record 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 (Record 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 (Record i = 1; i < 1 + kRecordsPerChunk; ++i) {
|
||||
Record* rec = reinterpret_cast<Record*>(scq.StartDequeue());
|
||||
CHECK_NE(NULL, rec);
|
||||
CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*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 (Record i = 10; i < 10 + kRecordsPerChunk; ++i) {
|
||||
Record* rec = reinterpret_cast<Record*>(scq.StartDequeue());
|
||||
CHECK_NE(NULL, rec);
|
||||
CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*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();
|
||||
}
|
@ -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',
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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"
|
||||
>
|
||||
|
Loading…
Reference in New Issue
Block a user