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 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1602 | 1602 |
1603 | 1603 |
1604 void SerializationDataQueue::Enqueue(SerializationData* data) { | 1604 void SerializationDataQueue::Enqueue(SerializationData* data) { |
1605 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1605 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
1606 data_.Add(data); | 1606 data_.Add(data); |
1607 } | 1607 } |
1608 | 1608 |
1609 | 1609 |
1610 bool SerializationDataQueue::Dequeue(SerializationData** data) { | 1610 bool SerializationDataQueue::Dequeue(SerializationData** data) { |
1611 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1611 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
1612 *data = NULL; | |
1612 if (data_.is_empty()) return false; | 1613 if (data_.is_empty()) return false; |
1613 *data = data_.Remove(0); | 1614 *data = data_.Remove(0); |
1614 return true; | 1615 return true; |
1615 } | 1616 } |
1616 | 1617 |
1617 | 1618 |
1618 bool SerializationDataQueue::IsEmpty() { | 1619 bool SerializationDataQueue::IsEmpty() { |
1619 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1620 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
1620 return data_.is_empty(); | 1621 return data_.is_empty(); |
1621 } | 1622 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1655 | 1656 |
1656 void Worker::PostMessage(SerializationData* data) { | 1657 void Worker::PostMessage(SerializationData* data) { |
1657 in_queue_.Enqueue(data); | 1658 in_queue_.Enqueue(data); |
1658 in_semaphore_.Signal(); | 1659 in_semaphore_.Signal(); |
1659 } | 1660 } |
1660 | 1661 |
1661 | 1662 |
1662 SerializationData* Worker::GetMessage() { | 1663 SerializationData* Worker::GetMessage() { |
1663 SerializationData* data = NULL; | 1664 SerializationData* data = NULL; |
1664 while (!out_queue_.Dequeue(&data)) { | 1665 while (!out_queue_.Dequeue(&data)) { |
1665 if (base::NoBarrier_Load(&state_) != RUNNING) break; | 1666 // If the worker is no longer running, and there are no messages in the |
1667 // queue, don't expect any more messages from it. | |
1668 if (base::NoBarrier_Load(&state_) > RUNNING) break; | |
1666 out_semaphore_.Wait(); | 1669 out_semaphore_.Wait(); |
1667 } | 1670 } |
1668 | 1671 |
1669 return data; | 1672 return data; |
1670 } | 1673 } |
1671 | 1674 |
1672 | 1675 |
1673 void Worker::Terminate() { | 1676 void Worker::Terminate() { |
1674 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { | 1677 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATING) == |
1678 RUNNING) { | |
1675 // Post NULL to wake the Worker thread message loop. | 1679 // Post NULL to wake the Worker thread message loop. |
1676 PostMessage(NULL); | 1680 PostMessage(NULL); |
1677 thread_->Join(); | |
1678 } | 1681 } |
1679 } | 1682 } |
1680 | 1683 |
1681 | 1684 |
1685 void Worker::WaitForThread() { | |
1686 Terminate(); | |
1687 | |
1688 State expected_state = TERMINATING; | |
1689 while (true) { | |
1690 State actual_state = static_cast<State>( | |
1691 base::NoBarrier_CompareAndSwap(&state_, expected_state, JOINING)); | |
1692 | |
1693 if (actual_state == expected_state) break; | |
1694 | |
1695 switch (actual_state) { | |
1696 case IDLE: | |
1697 case RUNNING: | |
1698 // We terminated above, we should never be IDLE or RUNNING. | |
1699 UNREACHABLE(); | |
1700 return; | |
1701 | |
1702 case TERMINATING: | |
1703 case STOPPED: | |
Jarin
2015/07/10 10:43:17
Why do we want to retry when STOPPED?
Actually, I
binji
2015/07/10 17:40:46
You're right, this is too complicated. I refactore
| |
1704 // Try again. | |
1705 expected_state = actual_state; | |
1706 break; | |
1707 | |
1708 case JOINING: | |
Jarin
2015/07/10 10:43:17
Is not this only called when the shell finishes, s
binji
2015/07/10 17:40:46
True, this was just caution to prevent multiple jo
| |
1709 // Someone else is joining. Bail. | |
1710 return; | |
1711 | |
1712 case JOINED: | |
1713 // Tried to join twice. | |
1714 UNREACHABLE(); | |
1715 return; | |
1716 } | |
1717 } | |
1718 | |
1719 thread_->Join(); | |
1720 base::NoBarrier_Store(&state_, JOINED); | |
1721 } | |
1722 | |
1723 | |
1682 void Worker::ExecuteInThread() { | 1724 void Worker::ExecuteInThread() { |
1683 Isolate::CreateParams create_params; | 1725 Isolate::CreateParams create_params; |
1684 create_params.array_buffer_allocator = Shell::array_buffer_allocator; | 1726 create_params.array_buffer_allocator = Shell::array_buffer_allocator; |
1685 Isolate* isolate = Isolate::New(create_params); | 1727 Isolate* isolate = Isolate::New(create_params); |
1686 { | 1728 { |
1687 Isolate::Scope iscope(isolate); | 1729 Isolate::Scope iscope(isolate); |
1688 { | 1730 { |
1689 HandleScope scope(isolate); | 1731 HandleScope scope(isolate); |
1690 PerIsolateData data(isolate); | 1732 PerIsolateData data(isolate); |
1691 Local<Context> context = Shell::CreateEvaluationContext(isolate); | 1733 Local<Context> context = Shell::CreateEvaluationContext(isolate); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1734 delete data; | 1776 delete data; |
1735 } | 1777 } |
1736 } | 1778 } |
1737 } | 1779 } |
1738 } | 1780 } |
1739 } | 1781 } |
1740 Shell::CollectGarbage(isolate); | 1782 Shell::CollectGarbage(isolate); |
1741 } | 1783 } |
1742 isolate->Dispose(); | 1784 isolate->Dispose(); |
1743 | 1785 |
1744 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { | 1786 base::NoBarrier_Store(&state_, STOPPED); |
1745 // Post NULL to wake the thread waiting on GetMessage() if there is one. | 1787 // Post NULL to wake the thread waiting on GetMessage() if there is one. |
1746 out_queue_.Enqueue(NULL); | 1788 out_queue_.Enqueue(NULL); |
1747 out_semaphore_.Signal(); | 1789 out_semaphore_.Signal(); |
1748 } | |
1749 } | 1790 } |
1750 | 1791 |
1751 | 1792 |
1752 void Worker::Cleanup() { | 1793 void Worker::Cleanup() { |
1753 delete thread_; | 1794 delete thread_; |
1754 thread_ = NULL; | 1795 thread_ = NULL; |
1755 delete[] script_; | 1796 delete[] script_; |
1756 script_ = NULL; | 1797 script_ = NULL; |
1757 in_queue_.Clear(); | 1798 in_queue_.Clear(); |
1758 out_queue_.Clear(); | 1799 out_queue_.Clear(); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2136 result = True(isolate); | 2177 result = True(isolate); |
2137 break; | 2178 break; |
2138 case kSerializationTagFalse: | 2179 case kSerializationTagFalse: |
2139 result = False(isolate); | 2180 result = False(isolate); |
2140 break; | 2181 break; |
2141 case kSerializationTagNumber: | 2182 case kSerializationTagNumber: |
2142 result = Number::New(isolate, data.Read<double>(offset)); | 2183 result = Number::New(isolate, data.Read<double>(offset)); |
2143 break; | 2184 break; |
2144 case kSerializationTagString: { | 2185 case kSerializationTagString: { |
2145 int length = data.Read<int>(offset); | 2186 int length = data.Read<int>(offset); |
2146 static char s_buffer[128]; | 2187 char* p = new char[length]; |
binji
2015/07/09 00:13:12
I'm pretty ashamed of this one... :-|
|
Jarin
2015/07/10 10:43:17
How about using std::vector<char> here, instead of
binji
2015/07/10 17:40:46
Done (though I was not sure that std containers we
|
2147 char* p = s_buffer; | |
2148 bool allocated = false; | |
2149 if (length > static_cast<int>(sizeof(s_buffer))) { | |
2150 p = new char[length]; | |
2151 allocated = true; | |
2152 } | |
2153 data.ReadMemory(p, length, offset); | 2188 data.ReadMemory(p, length, offset); |
2154 MaybeLocal<String> str = | 2189 MaybeLocal<String> str = |
2155 String::NewFromUtf8(isolate, p, String::kNormalString, length); | 2190 String::NewFromUtf8(isolate, p, String::kNormalString, length); |
2156 if (!str.IsEmpty()) result = str.ToLocalChecked(); | 2191 if (!str.IsEmpty()) result = str.ToLocalChecked(); |
2157 if (allocated) delete[] p; | 2192 delete[] p; |
2158 break; | 2193 break; |
2159 } | 2194 } |
2160 case kSerializationTagArray: { | 2195 case kSerializationTagArray: { |
2161 uint32_t length = data.Read<uint32_t>(offset); | 2196 uint32_t length = data.Read<uint32_t>(offset); |
2162 Handle<Array> array = Array::New(isolate, length); | 2197 Handle<Array> array = Array::New(isolate, length); |
2163 for (uint32_t i = 0; i < length; ++i) { | 2198 for (uint32_t i = 0; i < length; ++i) { |
2164 Local<Value> element_value; | 2199 Local<Value> element_value; |
2165 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value)); | 2200 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value)); |
2166 array->Set(i, element_value); | 2201 array->Set(i, element_value); |
2167 } | 2202 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2219 i::List<Worker*> workers_copy; | 2254 i::List<Worker*> workers_copy; |
2220 { | 2255 { |
2221 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); | 2256 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); |
2222 allow_new_workers_ = false; | 2257 allow_new_workers_ = false; |
2223 workers_copy.AddAll(workers_); | 2258 workers_copy.AddAll(workers_); |
2224 workers_.Clear(); | 2259 workers_.Clear(); |
2225 } | 2260 } |
2226 | 2261 |
2227 for (int i = 0; i < workers_copy.length(); ++i) { | 2262 for (int i = 0; i < workers_copy.length(); ++i) { |
2228 Worker* worker = workers_copy[i]; | 2263 Worker* worker = workers_copy[i]; |
2229 worker->Terminate(); | 2264 worker->WaitForThread(); |
2230 delete worker; | 2265 delete worker; |
2231 } | 2266 } |
2232 | 2267 |
2233 // Now that all workers are terminated, we can re-enable Worker creation. | 2268 // Now that all workers are terminated, we can re-enable Worker creation. |
Jarin
2015/07/10 10:43:17
I know this has not be introduced by this CL, but
| |
2234 { | 2269 { |
2235 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); | 2270 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); |
2236 allow_new_workers_ = true; | 2271 allow_new_workers_ = true; |
2237 } | 2272 } |
2238 | 2273 |
2239 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { | 2274 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { |
2240 const SharedArrayBuffer::Contents& contents = | 2275 const SharedArrayBuffer::Contents& contents = |
2241 externalized_shared_contents_[i]; | 2276 externalized_shared_contents_[i]; |
2242 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); | 2277 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); |
2243 } | 2278 } |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2436 } | 2471 } |
2437 | 2472 |
2438 } // namespace v8 | 2473 } // namespace v8 |
2439 | 2474 |
2440 | 2475 |
2441 #ifndef GOOGLE3 | 2476 #ifndef GOOGLE3 |
2442 int main(int argc, char* argv[]) { | 2477 int main(int argc, char* argv[]) { |
2443 return v8::Shell::Main(argc, argv); | 2478 return v8::Shell::Main(argc, argv); |
2444 } | 2479 } |
2445 #endif | 2480 #endif |
OLD | NEW |