Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: src/d8.cc

Issue 1223813008: Fix bug when transferring SharedArrayBuffer to multiple Workers. (try 2) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: more tsan fixes Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker-sharedarraybuffer.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 // Defined when linking against shared lib on Windows. 6 // Defined when linking against shared lib on Windows.
7 #if defined(USING_V8_SHARED) && !defined(V8_SHARED) 7 #if defined(USING_V8_SHARED) && !defined(V8_SHARED)
8 #define V8_SHARED 8 #define V8_SHARED
9 #endif 9 #endif
10 10
(...skipping 1519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 if (thread_ == NULL) return; 1530 if (thread_ == NULL) return;
1531 if (Shell::options.last_run) { 1531 if (Shell::options.last_run) {
1532 thread_->Join(); 1532 thread_->Join();
1533 } else { 1533 } else {
1534 done_semaphore_.Wait(); 1534 done_semaphore_.Wait();
1535 } 1535 }
1536 } 1536 }
1537 1537
1538 1538
1539 SerializationData::~SerializationData() { 1539 SerializationData::~SerializationData() {
1540 // Any ArrayBuffer::Contents are owned by this SerializationData object. 1540 // Any ArrayBuffer::Contents are owned by this SerializationData object if
1541 // SharedArrayBuffer::Contents may be used by other threads, so must be 1541 // ownership hasn't been transferred out via ReadArrayBufferContents.
1542 // SharedArrayBuffer::Contents may be used by multiple threads, so must be
1542 // cleaned up by the main thread in Shell::CleanupWorkers(). 1543 // cleaned up by the main thread in Shell::CleanupWorkers().
1543 for (int i = 0; i < array_buffer_contents.length(); ++i) { 1544 for (int i = 0; i < array_buffer_contents_.length(); ++i) {
1544 ArrayBuffer::Contents& contents = array_buffer_contents[i]; 1545 ArrayBuffer::Contents& contents = array_buffer_contents_[i];
1545 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); 1546 if (contents.Data()) {
1547 Shell::array_buffer_allocator->Free(contents.Data(),
1548 contents.ByteLength());
1549 }
1546 } 1550 }
1547 } 1551 }
1548 1552
1549 1553
1550 void SerializationData::WriteTag(SerializationTag tag) { data.Add(tag); } 1554 void SerializationData::WriteTag(SerializationTag tag) { data_.Add(tag); }
1551 1555
1552 1556
1553 void SerializationData::WriteMemory(const void* p, int length) { 1557 void SerializationData::WriteMemory(const void* p, int length) {
1554 if (length > 0) { 1558 if (length > 0) {
1555 i::Vector<uint8_t> block = data.AddBlock(0, length); 1559 i::Vector<uint8_t> block = data_.AddBlock(0, length);
1556 memcpy(&block[0], p, length); 1560 memcpy(&block[0], p, length);
1557 } 1561 }
1558 } 1562 }
1559 1563
1560 1564
1561 void SerializationData::WriteArrayBufferContents( 1565 void SerializationData::WriteArrayBufferContents(
1562 const ArrayBuffer::Contents& contents) { 1566 const ArrayBuffer::Contents& contents) {
1563 array_buffer_contents.Add(contents); 1567 array_buffer_contents_.Add(contents);
1564 WriteTag(kSerializationTagTransferredArrayBuffer); 1568 WriteTag(kSerializationTagTransferredArrayBuffer);
1565 int index = array_buffer_contents.length() - 1; 1569 int index = array_buffer_contents_.length() - 1;
1566 Write(index); 1570 Write(index);
1567 } 1571 }
1568 1572
1569 1573
1570 void SerializationData::WriteSharedArrayBufferContents( 1574 void SerializationData::WriteSharedArrayBufferContents(
1571 const SharedArrayBuffer::Contents& contents) { 1575 const SharedArrayBuffer::Contents& contents) {
1572 shared_array_buffer_contents.Add(contents); 1576 shared_array_buffer_contents_.Add(contents);
1573 WriteTag(kSerializationTagTransferredSharedArrayBuffer); 1577 WriteTag(kSerializationTagTransferredSharedArrayBuffer);
1574 int index = shared_array_buffer_contents.length() - 1; 1578 int index = shared_array_buffer_contents_.length() - 1;
1575 Write(index); 1579 Write(index);
1576 } 1580 }
1577 1581
1578 1582
1579 SerializationTag SerializationData::ReadTag(int* offset) const { 1583 SerializationTag SerializationData::ReadTag(int* offset) const {
1580 return static_cast<SerializationTag>(Read<uint8_t>(offset)); 1584 return static_cast<SerializationTag>(Read<uint8_t>(offset));
1581 } 1585 }
1582 1586
1583 1587
1584 void SerializationData::ReadMemory(void* p, int length, int* offset) const { 1588 void SerializationData::ReadMemory(void* p, int length, int* offset) const {
1585 if (length > 0) { 1589 if (length > 0) {
1586 memcpy(p, &data[*offset], length); 1590 memcpy(p, &data_[*offset], length);
1587 (*offset) += length; 1591 (*offset) += length;
1588 } 1592 }
1589 } 1593 }
1590 1594
1591 1595
1592 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents, 1596 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
1593 int* offset) const { 1597 int* offset) const {
1594 int index = Read<int>(offset); 1598 int index = Read<int>(offset);
1595 DCHECK(index < array_buffer_contents.length()); 1599 DCHECK(index < array_buffer_contents_.length());
1596 *contents = array_buffer_contents[index]; 1600 *contents = array_buffer_contents_[index];
1601 // Ownership of this ArrayBuffer::Contents is passed to the caller. Neuter
1602 // our copy so it won't be double-free'd when this SerializationData is
1603 // destroyed.
1604 array_buffer_contents_[index] = ArrayBuffer::Contents();
1597 } 1605 }
1598 1606
1599 1607
1600 void SerializationData::ReadSharedArrayBufferContents( 1608 void SerializationData::ReadSharedArrayBufferContents(
1601 SharedArrayBuffer::Contents* contents, int* offset) const { 1609 SharedArrayBuffer::Contents* contents, int* offset) const {
1602 int index = Read<int>(offset); 1610 int index = Read<int>(offset);
1603 DCHECK(index < shared_array_buffer_contents.length()); 1611 DCHECK(index < shared_array_buffer_contents_.length());
1604 *contents = shared_array_buffer_contents[index]; 1612 *contents = shared_array_buffer_contents_[index];
1605 } 1613 }
1606 1614
1607 1615
1608 void SerializationDataQueue::Enqueue(SerializationData* data) { 1616 void SerializationDataQueue::Enqueue(SerializationData* data) {
1609 base::LockGuard<base::Mutex> lock_guard(&mutex_); 1617 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1610 data_.Add(data); 1618 data_.Add(data);
1611 } 1619 }
1612 1620
1613 1621
1614 bool SerializationDataQueue::Dequeue(SerializationData** data) { 1622 bool SerializationDataQueue::Dequeue(SerializationData** data) {
(...skipping 22 matching lines...) Expand all
1637 1645
1638 Worker::Worker() 1646 Worker::Worker()
1639 : in_semaphore_(0), 1647 : in_semaphore_(0),
1640 out_semaphore_(0), 1648 out_semaphore_(0),
1641 thread_(NULL), 1649 thread_(NULL),
1642 script_(NULL), 1650 script_(NULL),
1643 state_(IDLE), 1651 state_(IDLE),
1644 join_called_(false) {} 1652 join_called_(false) {}
1645 1653
1646 1654
1647 Worker::~Worker() { Cleanup(); } 1655 Worker::~Worker() {
1656 delete thread_;
1657 thread_ = NULL;
1658 delete[] script_;
1659 script_ = NULL;
1660 in_queue_.Clear();
1661 out_queue_.Clear();
1662 }
1648 1663
1649 1664
1650 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) { 1665 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) {
1651 if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) { 1666 if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) {
1652 script_ = i::StrDup(script); 1667 script_ = i::StrDup(script);
1653 thread_ = new WorkerThread(this); 1668 thread_ = new WorkerThread(this);
1654 thread_->Start(); 1669 thread_->Start();
1655 } else { 1670 } else {
1656 // Somehow the Worker was started twice. 1671 // Somehow the Worker was started twice.
1657 UNREACHABLE(); 1672 UNREACHABLE();
1658 } 1673 }
1659 } 1674 }
1660 1675
1661 1676
1662 void Worker::PostMessage(SerializationData* data) { 1677 void Worker::PostMessage(SerializationData* data) {
1663 in_queue_.Enqueue(data); 1678 in_queue_.Enqueue(data);
1664 in_semaphore_.Signal(); 1679 in_semaphore_.Signal();
1665 } 1680 }
1666 1681
1667 1682
1668 SerializationData* Worker::GetMessage() { 1683 SerializationData* Worker::GetMessage() {
1669 SerializationData* data = NULL; 1684 SerializationData* data = NULL;
1670 while (!out_queue_.Dequeue(&data)) { 1685 while (!out_queue_.Dequeue(&data)) {
1671 // If the worker is no longer running, and there are no messages in the 1686 // If the worker is no longer running, and there are no messages in the
1672 // queue, don't expect any more messages from it. 1687 // queue, don't expect any more messages from it.
1673 if (base::NoBarrier_Load(&state_) != RUNNING) break; 1688 if (base::NoBarrier_Load(&state_) != RUNNING) break;
1674 out_semaphore_.Wait(); 1689 out_semaphore_.Wait();
1675 } 1690 }
1676
1677 return data; 1691 return data;
1678 } 1692 }
1679 1693
1680 1694
1681 void Worker::Terminate() { 1695 void Worker::Terminate() {
1682 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { 1696 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) {
1683 // Post NULL to wake the Worker thread message loop, and tell it to stop 1697 // Post NULL to wake the Worker thread message loop, and tell it to stop
1684 // running. 1698 // running.
1685 PostMessage(NULL); 1699 PostMessage(NULL);
1686 } 1700 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 Shell::CollectGarbage(isolate); 1772 Shell::CollectGarbage(isolate);
1759 } 1773 }
1760 isolate->Dispose(); 1774 isolate->Dispose();
1761 1775
1762 // Post NULL to wake the thread waiting on GetMessage() if there is one. 1776 // Post NULL to wake the thread waiting on GetMessage() if there is one.
1763 out_queue_.Enqueue(NULL); 1777 out_queue_.Enqueue(NULL);
1764 out_semaphore_.Signal(); 1778 out_semaphore_.Signal();
1765 } 1779 }
1766 1780
1767 1781
1768 void Worker::Cleanup() {
1769 delete thread_;
1770 thread_ = NULL;
1771 delete[] script_;
1772 script_ = NULL;
1773 in_queue_.Clear();
1774 out_queue_.Clear();
1775 }
1776
1777
1778 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) { 1782 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
1779 Isolate* isolate = args.GetIsolate(); 1783 Isolate* isolate = args.GetIsolate();
1780 HandleScope handle_scope(isolate); 1784 HandleScope handle_scope(isolate);
1781 1785
1782 if (args.Length() < 1) { 1786 if (args.Length() < 1) {
1783 Throw(isolate, "Invalid argument"); 1787 Throw(isolate, "Invalid argument");
1784 return; 1788 return;
1785 } 1789 }
1786 1790
1787 Handle<Value> message = args[0]; 1791 Handle<Value> message = args[0];
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 return false; 2056 return false;
2053 } 2057 }
2054 seen_objects->Add(array_buffer); 2058 seen_objects->Add(array_buffer);
2055 if (FindInObjectList(array_buffer, to_transfer)) { 2059 if (FindInObjectList(array_buffer, to_transfer)) {
2056 // Transfer ArrayBuffer 2060 // Transfer ArrayBuffer
2057 if (!array_buffer->IsNeuterable()) { 2061 if (!array_buffer->IsNeuterable()) {
2058 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer"); 2062 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
2059 return false; 2063 return false;
2060 } 2064 }
2061 2065
2062 ArrayBuffer::Contents contents = array_buffer->Externalize(); 2066 ArrayBuffer::Contents contents = array_buffer->IsExternal()
2067 ? array_buffer->GetContents()
2068 : array_buffer->Externalize();
2063 array_buffer->Neuter(); 2069 array_buffer->Neuter();
2064 out_data->WriteArrayBufferContents(contents); 2070 out_data->WriteArrayBufferContents(contents);
2065 } else { 2071 } else {
2066 ArrayBuffer::Contents contents = array_buffer->GetContents(); 2072 ArrayBuffer::Contents contents = array_buffer->GetContents();
2067 // Clone ArrayBuffer 2073 // Clone ArrayBuffer
2068 if (contents.ByteLength() > i::kMaxUInt32) { 2074 if (contents.ByteLength() > i::kMaxUInt32) {
2069 Throw(isolate, "ArrayBuffer is too big to clone"); 2075 Throw(isolate, "ArrayBuffer is too big to clone");
2070 return false; 2076 return false;
2071 } 2077 }
2072 2078
2073 int byte_length = static_cast<int>(contents.ByteLength()); 2079 int byte_length = static_cast<int>(contents.ByteLength());
2074 out_data->WriteTag(kSerializationTagArrayBuffer); 2080 out_data->WriteTag(kSerializationTagArrayBuffer);
2075 out_data->Write(byte_length); 2081 out_data->Write(byte_length);
2076 out_data->WriteMemory(contents.Data(), 2082 out_data->WriteMemory(contents.Data(),
2077 static_cast<int>(contents.ByteLength())); 2083 static_cast<int>(contents.ByteLength()));
2078 } 2084 }
2079 } else if (value->IsSharedArrayBuffer()) { 2085 } else if (value->IsSharedArrayBuffer()) {
2080 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value); 2086 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value);
2081 if (FindInObjectList(sab, *seen_objects)) { 2087 if (FindInObjectList(sab, *seen_objects)) {
2082 Throw(isolate, "Duplicated shared array buffers not supported"); 2088 Throw(isolate, "Duplicated shared array buffers not supported");
2083 return false; 2089 return false;
2084 } 2090 }
2085 seen_objects->Add(sab); 2091 seen_objects->Add(sab);
2086 if (!FindInObjectList(sab, to_transfer)) { 2092 if (!FindInObjectList(sab, to_transfer)) {
2087 Throw(isolate, "SharedArrayBuffer must be transferred"); 2093 Throw(isolate, "SharedArrayBuffer must be transferred");
2088 return false; 2094 return false;
2089 } 2095 }
2090 2096
2091 SharedArrayBuffer::Contents contents = sab->Externalize(); 2097 SharedArrayBuffer::Contents contents;
2098 if (sab->IsExternal()) {
2099 contents = sab->GetContents();
2100 } else {
2101 contents = sab->Externalize();
2102 externalized_shared_contents_.Add(contents);
2103 }
2092 out_data->WriteSharedArrayBufferContents(contents); 2104 out_data->WriteSharedArrayBufferContents(contents);
2093 externalized_shared_contents_.Add(contents);
2094 } else if (value->IsObject()) { 2105 } else if (value->IsObject()) {
2095 Handle<Object> object = Handle<Object>::Cast(value); 2106 Handle<Object> object = Handle<Object>::Cast(value);
2096 if (FindInObjectList(object, *seen_objects)) { 2107 if (FindInObjectList(object, *seen_objects)) {
2097 Throw(isolate, "Duplicated objects not supported"); 2108 Throw(isolate, "Duplicated objects not supported");
2098 return false; 2109 return false;
2099 } 2110 }
2100 seen_objects->Add(object); 2111 seen_objects->Add(object);
2101 Local<Array> property_names; 2112 Local<Array> property_names;
2102 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) { 2113 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
2103 Throw(isolate, "Unable to get property names"); 2114 Throw(isolate, "Unable to get property names");
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
2196 Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length); 2207 Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
2197 ArrayBuffer::Contents contents = array_buffer->GetContents(); 2208 ArrayBuffer::Contents contents = array_buffer->GetContents();
2198 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength()); 2209 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
2199 data.ReadMemory(contents.Data(), byte_length, offset); 2210 data.ReadMemory(contents.Data(), byte_length, offset);
2200 result = array_buffer; 2211 result = array_buffer;
2201 break; 2212 break;
2202 } 2213 }
2203 case kSerializationTagTransferredArrayBuffer: { 2214 case kSerializationTagTransferredArrayBuffer: {
2204 ArrayBuffer::Contents contents; 2215 ArrayBuffer::Contents contents;
2205 data.ReadArrayBufferContents(&contents, offset); 2216 data.ReadArrayBufferContents(&contents, offset);
2206 result = 2217 result = ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength(),
2207 ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength()); 2218 ArrayBufferCreationMode::kInternalized);
2208 break; 2219 break;
2209 } 2220 }
2210 case kSerializationTagTransferredSharedArrayBuffer: { 2221 case kSerializationTagTransferredSharedArrayBuffer: {
2211 SharedArrayBuffer::Contents contents; 2222 SharedArrayBuffer::Contents contents;
2212 data.ReadSharedArrayBufferContents(&contents, offset); 2223 data.ReadSharedArrayBufferContents(&contents, offset);
2213 result = SharedArrayBuffer::New(isolate, contents.Data(), 2224 result = SharedArrayBuffer::New(isolate, contents.Data(),
2214 contents.ByteLength()); 2225 contents.ByteLength());
2215 break; 2226 break;
2216 } 2227 }
2217 default: 2228 default:
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2446 } 2457 }
2447 2458
2448 } // namespace v8 2459 } // namespace v8
2449 2460
2450 2461
2451 #ifndef GOOGLE3 2462 #ifndef GOOGLE3
2452 int main(int argc, char* argv[]) { 2463 int main(int argc, char* argv[]) {
2453 return v8::Shell::Main(argc, argv); 2464 return v8::Shell::Main(argc, argv);
2454 } 2465 }
2455 #endif 2466 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker-sharedarraybuffer.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698