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 |
11 #include <errno.h> | 11 #include <errno.h> |
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 #include <string.h> | 13 #include <string.h> |
14 #include <sys/stat.h> | 14 #include <sys/stat.h> |
15 | 15 |
16 #ifdef V8_SHARED | 16 #ifdef V8_SHARED |
17 #include <assert.h> | 17 #include <assert.h> |
18 #endif // V8_SHARED | 18 #endif // V8_SHARED |
19 | 19 |
20 #ifndef V8_SHARED | 20 #ifndef V8_SHARED |
21 #include <algorithm> | 21 #include <algorithm> |
| 22 #include <vector> |
22 #endif // !V8_SHARED | 23 #endif // !V8_SHARED |
23 | 24 |
24 #ifdef V8_SHARED | 25 #ifdef V8_SHARED |
25 #include "include/v8-testing.h" | 26 #include "include/v8-testing.h" |
26 #endif // V8_SHARED | 27 #endif // V8_SHARED |
27 | 28 |
28 #if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE) | 29 #if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE) |
29 #include "src/gdb-jit.h" | 30 #include "src/gdb-jit.h" |
30 #endif | 31 #endif |
31 | 32 |
(...skipping 1573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 | 1606 |
1606 | 1607 |
1607 void SerializationDataQueue::Enqueue(SerializationData* data) { | 1608 void SerializationDataQueue::Enqueue(SerializationData* data) { |
1608 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1609 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
1609 data_.Add(data); | 1610 data_.Add(data); |
1610 } | 1611 } |
1611 | 1612 |
1612 | 1613 |
1613 bool SerializationDataQueue::Dequeue(SerializationData** data) { | 1614 bool SerializationDataQueue::Dequeue(SerializationData** data) { |
1614 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1615 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 1616 *data = NULL; |
1615 if (data_.is_empty()) return false; | 1617 if (data_.is_empty()) return false; |
1616 *data = data_.Remove(0); | 1618 *data = data_.Remove(0); |
1617 return true; | 1619 return true; |
1618 } | 1620 } |
1619 | 1621 |
1620 | 1622 |
1621 bool SerializationDataQueue::IsEmpty() { | 1623 bool SerializationDataQueue::IsEmpty() { |
1622 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1624 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
1623 return data_.is_empty(); | 1625 return data_.is_empty(); |
1624 } | 1626 } |
1625 | 1627 |
1626 | 1628 |
1627 void SerializationDataQueue::Clear() { | 1629 void SerializationDataQueue::Clear() { |
1628 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 1630 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
1629 for (int i = 0; i < data_.length(); ++i) { | 1631 for (int i = 0; i < data_.length(); ++i) { |
1630 delete data_[i]; | 1632 delete data_[i]; |
1631 } | 1633 } |
1632 data_.Clear(); | 1634 data_.Clear(); |
1633 } | 1635 } |
1634 | 1636 |
1635 | 1637 |
1636 Worker::Worker() | 1638 Worker::Worker() |
1637 : in_semaphore_(0), | 1639 : in_semaphore_(0), |
1638 out_semaphore_(0), | 1640 out_semaphore_(0), |
1639 thread_(NULL), | 1641 thread_(NULL), |
1640 script_(NULL), | 1642 script_(NULL), |
1641 state_(IDLE) {} | 1643 state_(IDLE), |
| 1644 join_called_(false) {} |
1642 | 1645 |
1643 | 1646 |
1644 Worker::~Worker() { Cleanup(); } | 1647 Worker::~Worker() { Cleanup(); } |
1645 | 1648 |
1646 | 1649 |
1647 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) { | 1650 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) { |
1648 if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) { | 1651 if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) { |
1649 script_ = i::StrDup(script); | 1652 script_ = i::StrDup(script); |
1650 thread_ = new WorkerThread(this); | 1653 thread_ = new WorkerThread(this); |
1651 thread_->Start(); | 1654 thread_->Start(); |
1652 } else { | 1655 } else { |
1653 // Somehow the Worker was started twice. | 1656 // Somehow the Worker was started twice. |
1654 UNREACHABLE(); | 1657 UNREACHABLE(); |
1655 } | 1658 } |
1656 } | 1659 } |
1657 | 1660 |
1658 | 1661 |
1659 void Worker::PostMessage(SerializationData* data) { | 1662 void Worker::PostMessage(SerializationData* data) { |
1660 in_queue_.Enqueue(data); | 1663 in_queue_.Enqueue(data); |
1661 in_semaphore_.Signal(); | 1664 in_semaphore_.Signal(); |
1662 } | 1665 } |
1663 | 1666 |
1664 | 1667 |
1665 SerializationData* Worker::GetMessage() { | 1668 SerializationData* Worker::GetMessage() { |
1666 SerializationData* data = NULL; | 1669 SerializationData* data = NULL; |
1667 while (!out_queue_.Dequeue(&data)) { | 1670 while (!out_queue_.Dequeue(&data)) { |
| 1671 // If the worker is no longer running, and there are no messages in the |
| 1672 // queue, don't expect any more messages from it. |
1668 if (base::NoBarrier_Load(&state_) != RUNNING) break; | 1673 if (base::NoBarrier_Load(&state_) != RUNNING) break; |
1669 out_semaphore_.Wait(); | 1674 out_semaphore_.Wait(); |
1670 } | 1675 } |
1671 | 1676 |
1672 return data; | 1677 return data; |
1673 } | 1678 } |
1674 | 1679 |
1675 | 1680 |
1676 void Worker::Terminate() { | 1681 void Worker::Terminate() { |
1677 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { | 1682 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { |
1678 // Post NULL to wake the Worker thread message loop. | 1683 // Post NULL to wake the Worker thread message loop, and tell it to stop |
| 1684 // running. |
1679 PostMessage(NULL); | 1685 PostMessage(NULL); |
1680 thread_->Join(); | |
1681 } | 1686 } |
1682 } | 1687 } |
1683 | 1688 |
| 1689 |
| 1690 void Worker::WaitForThread() { |
| 1691 Terminate(); |
| 1692 |
| 1693 if (base::NoBarrier_CompareAndSwap(&join_called_, false, true) == false) { |
| 1694 thread_->Join(); |
| 1695 } else { |
| 1696 // Tried to call join twice. |
| 1697 UNREACHABLE(); |
| 1698 } |
| 1699 } |
| 1700 |
1684 | 1701 |
1685 void Worker::ExecuteInThread() { | 1702 void Worker::ExecuteInThread() { |
1686 Isolate::CreateParams create_params; | 1703 Isolate::CreateParams create_params; |
1687 create_params.array_buffer_allocator = Shell::array_buffer_allocator; | 1704 create_params.array_buffer_allocator = Shell::array_buffer_allocator; |
1688 Isolate* isolate = Isolate::New(create_params); | 1705 Isolate* isolate = Isolate::New(create_params); |
1689 { | 1706 { |
1690 Isolate::Scope iscope(isolate); | 1707 Isolate::Scope iscope(isolate); |
1691 { | 1708 { |
1692 HandleScope scope(isolate); | 1709 HandleScope scope(isolate); |
1693 PerIsolateData data(isolate); | 1710 PerIsolateData data(isolate); |
(...skipping 17 matching lines...) Expand all Loading... |
1711 // First run the script | 1728 // First run the script |
1712 Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed"); | 1729 Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed"); |
1713 Handle<String> source = String::NewFromUtf8(isolate, script_); | 1730 Handle<String> source = String::NewFromUtf8(isolate, script_); |
1714 if (Shell::ExecuteString(isolate, source, file_name, false, true)) { | 1731 if (Shell::ExecuteString(isolate, source, file_name, false, true)) { |
1715 // Get the message handler | 1732 // Get the message handler |
1716 Handle<Value> onmessage = | 1733 Handle<Value> onmessage = |
1717 global->Get(String::NewFromUtf8(isolate, "onmessage")); | 1734 global->Get(String::NewFromUtf8(isolate, "onmessage")); |
1718 if (onmessage->IsFunction()) { | 1735 if (onmessage->IsFunction()) { |
1719 Handle<Function> onmessage_fun = Handle<Function>::Cast(onmessage); | 1736 Handle<Function> onmessage_fun = Handle<Function>::Cast(onmessage); |
1720 // Now wait for messages | 1737 // Now wait for messages |
1721 bool done = false; | 1738 while (true) { |
1722 while (!done) { | |
1723 in_semaphore_.Wait(); | 1739 in_semaphore_.Wait(); |
1724 SerializationData* data; | 1740 SerializationData* data; |
1725 if (!in_queue_.Dequeue(&data)) continue; | 1741 if (!in_queue_.Dequeue(&data)) continue; |
1726 if (data == NULL) { | 1742 if (data == NULL) { |
1727 done = true; | |
1728 break; | 1743 break; |
1729 } | 1744 } |
1730 int offset = 0; | 1745 int offset = 0; |
1731 Local<Value> data_value; | 1746 Local<Value> data_value; |
1732 if (Shell::DeserializeValue(isolate, *data, &offset) | 1747 if (Shell::DeserializeValue(isolate, *data, &offset) |
1733 .ToLocal(&data_value)) { | 1748 .ToLocal(&data_value)) { |
1734 Handle<Value> argv[] = {data_value}; | 1749 Handle<Value> argv[] = {data_value}; |
1735 (void)onmessage_fun->Call(context, global, 1, argv); | 1750 (void)onmessage_fun->Call(context, global, 1, argv); |
1736 } | 1751 } |
1737 delete data; | 1752 delete data; |
1738 } | 1753 } |
1739 } | 1754 } |
1740 } | 1755 } |
1741 } | 1756 } |
1742 } | 1757 } |
1743 Shell::CollectGarbage(isolate); | 1758 Shell::CollectGarbage(isolate); |
1744 } | 1759 } |
1745 isolate->Dispose(); | 1760 isolate->Dispose(); |
1746 | 1761 |
1747 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { | 1762 // Post NULL to wake the thread waiting on GetMessage() if there is one. |
1748 // Post NULL to wake the thread waiting on GetMessage() if there is one. | 1763 out_queue_.Enqueue(NULL); |
1749 out_queue_.Enqueue(NULL); | 1764 out_semaphore_.Signal(); |
1750 out_semaphore_.Signal(); | |
1751 } | |
1752 } | 1765 } |
1753 | 1766 |
1754 | 1767 |
1755 void Worker::Cleanup() { | 1768 void Worker::Cleanup() { |
1756 delete thread_; | 1769 delete thread_; |
1757 thread_ = NULL; | 1770 thread_ = NULL; |
1758 delete[] script_; | 1771 delete[] script_; |
1759 script_ = NULL; | 1772 script_ = NULL; |
1760 in_queue_.Clear(); | 1773 in_queue_.Clear(); |
1761 out_queue_.Clear(); | 1774 out_queue_.Clear(); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2139 result = True(isolate); | 2152 result = True(isolate); |
2140 break; | 2153 break; |
2141 case kSerializationTagFalse: | 2154 case kSerializationTagFalse: |
2142 result = False(isolate); | 2155 result = False(isolate); |
2143 break; | 2156 break; |
2144 case kSerializationTagNumber: | 2157 case kSerializationTagNumber: |
2145 result = Number::New(isolate, data.Read<double>(offset)); | 2158 result = Number::New(isolate, data.Read<double>(offset)); |
2146 break; | 2159 break; |
2147 case kSerializationTagString: { | 2160 case kSerializationTagString: { |
2148 int length = data.Read<int>(offset); | 2161 int length = data.Read<int>(offset); |
2149 static char s_buffer[128]; | 2162 CHECK(length >= 0); |
2150 char* p = s_buffer; | 2163 std::vector<char> buffer(length + 1); // + 1 so it is never empty. |
2151 bool allocated = false; | 2164 data.ReadMemory(&buffer[0], length, offset); |
2152 if (length > static_cast<int>(sizeof(s_buffer))) { | 2165 MaybeLocal<String> str = String::NewFromUtf8( |
2153 p = new char[length]; | 2166 isolate, &buffer[0], String::kNormalString, length); |
2154 allocated = true; | |
2155 } | |
2156 data.ReadMemory(p, length, offset); | |
2157 MaybeLocal<String> str = | |
2158 String::NewFromUtf8(isolate, p, String::kNormalString, length); | |
2159 if (!str.IsEmpty()) result = str.ToLocalChecked(); | 2167 if (!str.IsEmpty()) result = str.ToLocalChecked(); |
2160 if (allocated) delete[] p; | |
2161 break; | 2168 break; |
2162 } | 2169 } |
2163 case kSerializationTagArray: { | 2170 case kSerializationTagArray: { |
2164 uint32_t length = data.Read<uint32_t>(offset); | 2171 uint32_t length = data.Read<uint32_t>(offset); |
2165 Handle<Array> array = Array::New(isolate, length); | 2172 Handle<Array> array = Array::New(isolate, length); |
2166 for (uint32_t i = 0; i < length; ++i) { | 2173 for (uint32_t i = 0; i < length; ++i) { |
2167 Local<Value> element_value; | 2174 Local<Value> element_value; |
2168 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value)); | 2175 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value)); |
2169 array->Set(i, element_value); | 2176 array->Set(i, element_value); |
2170 } | 2177 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2222 i::List<Worker*> workers_copy; | 2229 i::List<Worker*> workers_copy; |
2223 { | 2230 { |
2224 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); | 2231 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); |
2225 allow_new_workers_ = false; | 2232 allow_new_workers_ = false; |
2226 workers_copy.AddAll(workers_); | 2233 workers_copy.AddAll(workers_); |
2227 workers_.Clear(); | 2234 workers_.Clear(); |
2228 } | 2235 } |
2229 | 2236 |
2230 for (int i = 0; i < workers_copy.length(); ++i) { | 2237 for (int i = 0; i < workers_copy.length(); ++i) { |
2231 Worker* worker = workers_copy[i]; | 2238 Worker* worker = workers_copy[i]; |
2232 worker->Terminate(); | 2239 worker->WaitForThread(); |
2233 delete worker; | 2240 delete worker; |
2234 } | 2241 } |
2235 | 2242 |
2236 // Now that all workers are terminated, we can re-enable Worker creation. | 2243 // Now that all workers are terminated, we can re-enable Worker creation. |
2237 { | 2244 { |
2238 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); | 2245 base::LockGuard<base::Mutex> lock_guard(&workers_mutex_); |
2239 allow_new_workers_ = true; | 2246 allow_new_workers_ = true; |
2240 } | 2247 } |
2241 | 2248 |
2242 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { | 2249 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2439 } | 2446 } |
2440 | 2447 |
2441 } // namespace v8 | 2448 } // namespace v8 |
2442 | 2449 |
2443 | 2450 |
2444 #ifndef GOOGLE3 | 2451 #ifndef GOOGLE3 |
2445 int main(int argc, char* argv[]) { | 2452 int main(int argc, char* argv[]) { |
2446 return v8::Shell::Main(argc, argv); | 2453 return v8::Shell::Main(argc, argv); |
2447 } | 2454 } |
2448 #endif | 2455 #endif |
OLD | NEW |