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

Side by Side Diff: src/d8.cc

Issue 1215233004: Fix bug when transferring SharedArrayBuffer to multiple Workers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: internalize transferred ArrayBuffer 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 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 if (thread_ == NULL) return; 1526 if (thread_ == NULL) return;
1527 if (Shell::options.last_run) { 1527 if (Shell::options.last_run) {
1528 thread_->Join(); 1528 thread_->Join();
1529 } else { 1529 } else {
1530 done_semaphore_.Wait(); 1530 done_semaphore_.Wait();
1531 } 1531 }
1532 } 1532 }
1533 1533
1534 1534
1535 SerializationData::~SerializationData() { 1535 SerializationData::~SerializationData() {
1536 // Any ArrayBuffer::Contents are owned by this SerializationData object. 1536 // Any ArrayBuffer::Contents are owned by this SerializationData object if
1537 // SharedArrayBuffer::Contents may be used by other threads, so must be 1537 // ownership hasn't been transferred out via ReadArrayBufferContents.
1538 // SharedArrayBuffer::Contents may be used by multiple threads, so must be
1538 // cleaned up by the main thread in Shell::CleanupWorkers(). 1539 // cleaned up by the main thread in Shell::CleanupWorkers().
1539 for (int i = 0; i < array_buffer_contents.length(); ++i) { 1540 for (int i = 0; i < array_buffer_contents_.length(); ++i) {
1540 ArrayBuffer::Contents& contents = array_buffer_contents[i]; 1541 ArrayBuffer::Contents& contents = array_buffer_contents_[i];
1541 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); 1542 if (contents.Data()) {
jochen (gone - plz use gerrit) 2015/07/03 14:29:37 how can data ever be null?
Jarin 2015/07/06 05:04:19 As the comment above says, ReadArrayBufferContents
binji 2015/07/06 06:23:27 Yes, that's correct.
1543 Shell::array_buffer_allocator->Free(contents.Data(),
1544 contents.ByteLength());
1545 }
1542 } 1546 }
1543 } 1547 }
1544 1548
1545 1549
1546 void SerializationData::WriteTag(SerializationTag tag) { data.Add(tag); } 1550 void SerializationData::WriteTag(SerializationTag tag) { data_.Add(tag); }
1547 1551
1548 1552
1549 void SerializationData::WriteMemory(const void* p, int length) { 1553 void SerializationData::WriteMemory(const void* p, int length) {
1550 if (length > 0) { 1554 if (length > 0) {
1551 i::Vector<uint8_t> block = data.AddBlock(0, length); 1555 i::Vector<uint8_t> block = data_.AddBlock(0, length);
1552 memcpy(&block[0], p, length); 1556 memcpy(&block[0], p, length);
1553 } 1557 }
1554 } 1558 }
1555 1559
1556 1560
1557 void SerializationData::WriteArrayBufferContents( 1561 void SerializationData::WriteArrayBufferContents(
1558 const ArrayBuffer::Contents& contents) { 1562 const ArrayBuffer::Contents& contents) {
1559 array_buffer_contents.Add(contents); 1563 array_buffer_contents_.Add(contents);
1560 WriteTag(kSerializationTagTransferredArrayBuffer); 1564 WriteTag(kSerializationTagTransferredArrayBuffer);
1561 int index = array_buffer_contents.length() - 1; 1565 int index = array_buffer_contents_.length() - 1;
1562 Write(index); 1566 Write(index);
1563 } 1567 }
1564 1568
1565 1569
1566 void SerializationData::WriteSharedArrayBufferContents( 1570 void SerializationData::WriteSharedArrayBufferContents(
1567 const SharedArrayBuffer::Contents& contents) { 1571 const SharedArrayBuffer::Contents& contents) {
1568 shared_array_buffer_contents.Add(contents); 1572 shared_array_buffer_contents_.Add(contents);
1569 WriteTag(kSerializationTagTransferredSharedArrayBuffer); 1573 WriteTag(kSerializationTagTransferredSharedArrayBuffer);
1570 int index = shared_array_buffer_contents.length() - 1; 1574 int index = shared_array_buffer_contents_.length() - 1;
1571 Write(index); 1575 Write(index);
1572 } 1576 }
1573 1577
1574 1578
1575 SerializationTag SerializationData::ReadTag(int* offset) const { 1579 SerializationTag SerializationData::ReadTag(int* offset) const {
1576 return static_cast<SerializationTag>(Read<uint8_t>(offset)); 1580 return static_cast<SerializationTag>(Read<uint8_t>(offset));
1577 } 1581 }
1578 1582
1579 1583
1580 void SerializationData::ReadMemory(void* p, int length, int* offset) const { 1584 void SerializationData::ReadMemory(void* p, int length, int* offset) const {
1581 if (length > 0) { 1585 if (length > 0) {
1582 memcpy(p, &data[*offset], length); 1586 memcpy(p, &data_[*offset], length);
1583 (*offset) += length; 1587 (*offset) += length;
1584 } 1588 }
1585 } 1589 }
1586 1590
1587 1591
1588 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents, 1592 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
1589 int* offset) const { 1593 int* offset) const {
1590 int index = Read<int>(offset); 1594 int index = Read<int>(offset);
1591 DCHECK(index < array_buffer_contents.length()); 1595 DCHECK(index < array_buffer_contents_.length());
1592 *contents = array_buffer_contents[index]; 1596 *contents = array_buffer_contents_[index];
1597 // Ownership of this ArrayBuffer::Contents is passed to the caller. Neuter
1598 // our copy so it won't be double-free'd when this SerializationData is
1599 // destroyed.
1600 array_buffer_contents_[index] = ArrayBuffer::Contents();
1593 } 1601 }
1594 1602
1595 1603
1596 void SerializationData::ReadSharedArrayBufferContents( 1604 void SerializationData::ReadSharedArrayBufferContents(
1597 SharedArrayBuffer::Contents* contents, int* offset) const { 1605 SharedArrayBuffer::Contents* contents, int* offset) const {
1598 int index = Read<int>(offset); 1606 int index = Read<int>(offset);
1599 DCHECK(index < shared_array_buffer_contents.length()); 1607 DCHECK(index < shared_array_buffer_contents_.length());
1600 *contents = shared_array_buffer_contents[index]; 1608 *contents = shared_array_buffer_contents_[index];
1601 } 1609 }
1602 1610
1603 1611
1604 void SerializationDataQueue::Enqueue(SerializationData* data) { 1612 void SerializationDataQueue::Enqueue(SerializationData* data) {
1605 base::LockGuard<base::Mutex> lock_guard(&mutex_); 1613 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1606 data_.Add(data); 1614 data_.Add(data);
1607 } 1615 }
1608 1616
1609 1617
1610 bool SerializationDataQueue::Dequeue(SerializationData** data) { 1618 bool SerializationDataQueue::Dequeue(SerializationData** data) {
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
2033 return false; 2041 return false;
2034 } 2042 }
2035 seen_objects->Add(array_buffer); 2043 seen_objects->Add(array_buffer);
2036 if (FindInObjectList(array_buffer, to_transfer)) { 2044 if (FindInObjectList(array_buffer, to_transfer)) {
2037 // Transfer ArrayBuffer 2045 // Transfer ArrayBuffer
2038 if (!array_buffer->IsNeuterable()) { 2046 if (!array_buffer->IsNeuterable()) {
2039 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer"); 2047 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
2040 return false; 2048 return false;
2041 } 2049 }
2042 2050
2043 ArrayBuffer::Contents contents = array_buffer->Externalize(); 2051 ArrayBuffer::Contents contents = array_buffer->IsExternal()
2052 ? array_buffer->GetContents()
2053 : array_buffer->Externalize();
2044 array_buffer->Neuter(); 2054 array_buffer->Neuter();
2045 out_data->WriteArrayBufferContents(contents); 2055 out_data->WriteArrayBufferContents(contents);
2046 } else { 2056 } else {
2047 ArrayBuffer::Contents contents = array_buffer->GetContents(); 2057 ArrayBuffer::Contents contents = array_buffer->GetContents();
2048 // Clone ArrayBuffer 2058 // Clone ArrayBuffer
2049 if (contents.ByteLength() > i::kMaxUInt32) { 2059 if (contents.ByteLength() > i::kMaxUInt32) {
2050 Throw(isolate, "ArrayBuffer is too big to clone"); 2060 Throw(isolate, "ArrayBuffer is too big to clone");
2051 return false; 2061 return false;
2052 } 2062 }
2053 2063
2054 int byte_length = static_cast<int>(contents.ByteLength()); 2064 int byte_length = static_cast<int>(contents.ByteLength());
2055 out_data->WriteTag(kSerializationTagArrayBuffer); 2065 out_data->WriteTag(kSerializationTagArrayBuffer);
2056 out_data->Write(byte_length); 2066 out_data->Write(byte_length);
2057 out_data->WriteMemory(contents.Data(), 2067 out_data->WriteMemory(contents.Data(),
2058 static_cast<int>(contents.ByteLength())); 2068 static_cast<int>(contents.ByteLength()));
2059 } 2069 }
2060 } else if (value->IsSharedArrayBuffer()) { 2070 } else if (value->IsSharedArrayBuffer()) {
2061 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value); 2071 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value);
2062 if (FindInObjectList(sab, *seen_objects)) { 2072 if (FindInObjectList(sab, *seen_objects)) {
2063 Throw(isolate, "Duplicated shared array buffers not supported"); 2073 Throw(isolate, "Duplicated shared array buffers not supported");
2064 return false; 2074 return false;
2065 } 2075 }
2066 seen_objects->Add(sab); 2076 seen_objects->Add(sab);
2067 if (!FindInObjectList(sab, to_transfer)) { 2077 if (!FindInObjectList(sab, to_transfer)) {
2068 Throw(isolate, "SharedArrayBuffer must be transferred"); 2078 Throw(isolate, "SharedArrayBuffer must be transferred");
2069 return false; 2079 return false;
2070 } 2080 }
2071 2081
2072 SharedArrayBuffer::Contents contents = sab->Externalize(); 2082 SharedArrayBuffer::Contents contents;
2083 if (sab->IsExternal()) {
2084 contents = sab->GetContents();
2085 } else {
2086 contents = sab->Externalize();
2087 externalized_shared_contents_.Add(contents);
2088 }
2073 out_data->WriteSharedArrayBufferContents(contents); 2089 out_data->WriteSharedArrayBufferContents(contents);
2074 externalized_shared_contents_.Add(contents);
2075 } else if (value->IsObject()) { 2090 } else if (value->IsObject()) {
2076 Handle<Object> object = Handle<Object>::Cast(value); 2091 Handle<Object> object = Handle<Object>::Cast(value);
2077 if (FindInObjectList(object, *seen_objects)) { 2092 if (FindInObjectList(object, *seen_objects)) {
2078 Throw(isolate, "Duplicated objects not supported"); 2093 Throw(isolate, "Duplicated objects not supported");
2079 return false; 2094 return false;
2080 } 2095 }
2081 seen_objects->Add(object); 2096 seen_objects->Add(object);
2082 Local<Array> property_names; 2097 Local<Array> property_names;
2083 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) { 2098 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
2084 Throw(isolate, "Unable to get property names"); 2099 Throw(isolate, "Unable to get property names");
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length); 2195 Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
2181 ArrayBuffer::Contents contents = array_buffer->GetContents(); 2196 ArrayBuffer::Contents contents = array_buffer->GetContents();
2182 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength()); 2197 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
2183 data.ReadMemory(contents.Data(), byte_length, offset); 2198 data.ReadMemory(contents.Data(), byte_length, offset);
2184 result = array_buffer; 2199 result = array_buffer;
2185 break; 2200 break;
2186 } 2201 }
2187 case kSerializationTagTransferredArrayBuffer: { 2202 case kSerializationTagTransferredArrayBuffer: {
2188 ArrayBuffer::Contents contents; 2203 ArrayBuffer::Contents contents;
2189 data.ReadArrayBufferContents(&contents, offset); 2204 data.ReadArrayBufferContents(&contents, offset);
2190 result = 2205 result = ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength(),
2191 ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength()); 2206 ArrayBufferCreationMode::kInternalized);
2192 break; 2207 break;
2193 } 2208 }
2194 case kSerializationTagTransferredSharedArrayBuffer: { 2209 case kSerializationTagTransferredSharedArrayBuffer: {
2195 SharedArrayBuffer::Contents contents; 2210 SharedArrayBuffer::Contents contents;
2196 data.ReadSharedArrayBufferContents(&contents, offset); 2211 data.ReadSharedArrayBufferContents(&contents, offset);
2197 result = SharedArrayBuffer::New(isolate, contents.Data(), 2212 result = SharedArrayBuffer::New(isolate, contents.Data(),
2198 contents.ByteLength()); 2213 contents.ByteLength());
2199 break; 2214 break;
2200 } 2215 }
2201 default: 2216 default:
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2430 } 2445 }
2431 2446
2432 } // namespace v8 2447 } // namespace v8
2433 2448
2434 2449
2435 #ifndef GOOGLE3 2450 #ifndef GOOGLE3
2436 int main(int argc, char* argv[]) { 2451 int main(int argc, char* argv[]) {
2437 return v8::Shell::Main(argc, argv); 2452 return v8::Shell::Main(argc, argv);
2438 } 2453 }
2439 #endif 2454 #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