OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |