Chromium Code Reviews| 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 |