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

Side by Side Diff: src/d8.cc

Issue 1226143003: d8: Fix some TSAN bugs (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: can't use DCHECK for join_called_, unused in NDEBUG builds 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') | no next file » | 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/d8.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698