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

Side by Side Diff: src/d8.cc

Issue 1255563002: [d8 Workers] Fix bug creating Worker during main thread termination (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: doc comments, make running_ atomic 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') | test/mjsunit/regress/regress-crbug-511880.js » ('j') | 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
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) { 679 void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
680 Isolate* isolate = args.GetIsolate(); 680 Isolate* isolate = args.GetIsolate();
681 HandleScope handle_scope(isolate); 681 HandleScope handle_scope(isolate);
682 if (args.Length() < 1 || !args[0]->IsString()) { 682 if (args.Length() < 1 || !args[0]->IsString()) {
683 Throw(args.GetIsolate(), "1st argument must be string"); 683 Throw(args.GetIsolate(), "1st argument must be string");
684 return; 684 return;
685 } 685 }
686 686
687 { 687 {
688 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 688 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
689 // Intialize the internal field to NULL; if we return early without
690 // creating a new Worker (because the main thread is terminating) we can
691 // early-out from the instance calls.
692 args.Holder()->SetAlignedPointerInInternalField(0, NULL);
693
689 if (!allow_new_workers_) return; 694 if (!allow_new_workers_) return;
690 695
691 Worker* worker = new Worker; 696 Worker* worker = new Worker;
692 args.This()->SetInternalField(0, External::New(isolate, worker)); 697 args.Holder()->SetAlignedPointerInInternalField(0, worker);
693 workers_.Add(worker); 698 workers_.Add(worker);
694 699
695 String::Utf8Value script(args[0]); 700 String::Utf8Value script(args[0]);
696 if (!*script) { 701 if (!*script) {
697 Throw(args.GetIsolate(), "Can't get worker script"); 702 Throw(args.GetIsolate(), "Can't get worker script");
698 return; 703 return;
699 } 704 }
700 worker->StartExecuteInThread(isolate, *script); 705 worker->StartExecuteInThread(*script);
701 } 706 }
702 } 707 }
703 708
704 709
705 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 710 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
706 Isolate* isolate = args.GetIsolate(); 711 Isolate* isolate = args.GetIsolate();
707 HandleScope handle_scope(isolate); 712 HandleScope handle_scope(isolate);
708 Local<Context> context = isolate->GetCurrentContext(); 713 Local<Context> context = isolate->GetCurrentContext();
709 Local<Value> this_value;
710 714
711 if (args.Length() < 1) { 715 if (args.Length() < 1) {
712 Throw(isolate, "Invalid argument"); 716 Throw(isolate, "Invalid argument");
713 return; 717 return;
714 } 718 }
715 719
716 if (args.This()->InternalFieldCount() > 0) { 720 if (args.Holder()->InternalFieldCount() <= 0) {
717 this_value = args.This()->GetInternalField(0);
718 }
719 if (this_value.IsEmpty()) {
720 Throw(isolate, "this is not a Worker"); 721 Throw(isolate, "this is not a Worker");
721 return; 722 return;
722 } 723 }
723 724
724 Worker* worker = 725 Worker* worker = static_cast<Worker*>(
725 static_cast<Worker*>(Local<External>::Cast(this_value)->Value()); 726 args.Holder()->GetAlignedPointerFromInternalField(0));
727 if (worker == NULL) {
728 Throw(isolate, "Worker is defunct because main thread is terminating");
729 return;
730 }
726 731
727 Local<Value> message = args[0]; 732 Local<Value> message = args[0];
728 ObjectList to_transfer; 733 ObjectList to_transfer;
729 if (args.Length() >= 2) { 734 if (args.Length() >= 2) {
730 if (!args[1]->IsArray()) { 735 if (!args[1]->IsArray()) {
731 Throw(isolate, "Transfer list must be an Array"); 736 Throw(isolate, "Transfer list must be an Array");
732 return; 737 return;
733 } 738 }
734 739
735 Local<Array> transfer = Local<Array>::Cast(args[1]); 740 Local<Array> transfer = Local<Array>::Cast(args[1]);
(...skipping 19 matching lines...) Expand all
755 worker->PostMessage(data); 760 worker->PostMessage(data);
756 } else { 761 } else {
757 delete data; 762 delete data;
758 } 763 }
759 } 764 }
760 765
761 766
762 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 767 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
763 Isolate* isolate = args.GetIsolate(); 768 Isolate* isolate = args.GetIsolate();
764 HandleScope handle_scope(isolate); 769 HandleScope handle_scope(isolate);
765 Local<Value> this_value; 770 if (args.Holder()->InternalFieldCount() <= 0) {
766 if (args.This()->InternalFieldCount() > 0) {
767 this_value = args.This()->GetInternalField(0);
768 }
769 if (this_value.IsEmpty()) {
770 Throw(isolate, "this is not a Worker"); 771 Throw(isolate, "this is not a Worker");
771 return; 772 return;
772 } 773 }
773 774
774 Worker* worker = 775 Worker* worker = static_cast<Worker*>(
775 static_cast<Worker*>(Local<External>::Cast(this_value)->Value()); 776 args.Holder()->GetAlignedPointerFromInternalField(0));
777 if (worker == NULL) {
778 Throw(isolate, "Worker is defunct because main thread is terminating");
779 return;
780 }
Jarin 2015/07/27 05:09:28 How about factoring out the extraction of the work
binji 2015/07/29 04:37:13 Done.
776 781
777 SerializationData* data = worker->GetMessage(); 782 SerializationData* data = worker->GetMessage();
778 if (data) { 783 if (data) {
779 int offset = 0; 784 int offset = 0;
780 Local<Value> data_value; 785 Local<Value> data_value;
781 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) { 786 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) {
782 args.GetReturnValue().Set(data_value); 787 args.GetReturnValue().Set(data_value);
783 } 788 }
784 delete data; 789 delete data;
785 } 790 }
786 } 791 }
787 792
788 793
789 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { 794 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
790 Isolate* isolate = args.GetIsolate(); 795 Isolate* isolate = args.GetIsolate();
791 HandleScope handle_scope(isolate); 796 HandleScope handle_scope(isolate);
792 Local<Value> this_value; 797 if (args.Holder()->InternalFieldCount() <= 0) {
793 if (args.This()->InternalFieldCount() > 0) {
794 this_value = args.This()->GetInternalField(0);
795 }
796 if (this_value.IsEmpty()) {
797 Throw(isolate, "this is not a Worker"); 798 Throw(isolate, "this is not a Worker");
798 return; 799 return;
799 } 800 }
800 801
801 Worker* worker = 802 Worker* worker = static_cast<Worker*>(
802 static_cast<Worker*>(Local<External>::Cast(this_value)->Value()); 803 args.Holder()->GetAlignedPointerFromInternalField(0));
804 if (worker == NULL) {
805 Throw(isolate, "Worker is defunct because main thread is terminating");
806 return;
807 }
808
803 worker->Terminate(); 809 worker->Terminate();
804 } 810 }
805 #endif // !V8_SHARED 811 #endif // !V8_SHARED
806 812
807 813
808 void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args) { 814 void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args) {
809 int exit_code = (*args)[0] 815 int exit_code = (*args)[0]
810 ->Int32Value(args->GetIsolate()->GetCurrentContext()) 816 ->Int32Value(args->GetIsolate()->GetCurrentContext())
811 .FromMaybe(0); 817 .FromMaybe(0);
812 #ifndef V8_SHARED 818 #ifndef V8_SHARED
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 String::NewFromUtf8(isolate, "now", NewStringType::kNormal) 1133 String::NewFromUtf8(isolate, "now", NewStringType::kNormal)
1128 .ToLocalChecked(), 1134 .ToLocalChecked(),
1129 FunctionTemplate::New(isolate, PerformanceNow)); 1135 FunctionTemplate::New(isolate, PerformanceNow));
1130 global_template->Set( 1136 global_template->Set(
1131 String::NewFromUtf8(isolate, "performance", NewStringType::kNormal) 1137 String::NewFromUtf8(isolate, "performance", NewStringType::kNormal)
1132 .ToLocalChecked(), 1138 .ToLocalChecked(),
1133 performance_template); 1139 performance_template);
1134 1140
1135 Local<FunctionTemplate> worker_fun_template = 1141 Local<FunctionTemplate> worker_fun_template =
1136 FunctionTemplate::New(isolate, WorkerNew); 1142 FunctionTemplate::New(isolate, WorkerNew);
1143 Local<Signature> worker_signature =
1144 Signature::New(isolate, worker_fun_template);
1145 worker_fun_template->SetClassName(
1146 String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
1147 .ToLocalChecked());
1137 worker_fun_template->PrototypeTemplate()->Set( 1148 worker_fun_template->PrototypeTemplate()->Set(
1138 String::NewFromUtf8(isolate, "terminate", NewStringType::kNormal) 1149 String::NewFromUtf8(isolate, "terminate", NewStringType::kNormal)
1139 .ToLocalChecked(), 1150 .ToLocalChecked(),
1140 FunctionTemplate::New(isolate, WorkerTerminate)); 1151 FunctionTemplate::New(isolate, WorkerTerminate, Local<Value>(),
1152 worker_signature));
1141 worker_fun_template->PrototypeTemplate()->Set( 1153 worker_fun_template->PrototypeTemplate()->Set(
1142 String::NewFromUtf8(isolate, "postMessage", NewStringType::kNormal) 1154 String::NewFromUtf8(isolate, "postMessage", NewStringType::kNormal)
1143 .ToLocalChecked(), 1155 .ToLocalChecked(),
1144 FunctionTemplate::New(isolate, WorkerPostMessage)); 1156 FunctionTemplate::New(isolate, WorkerPostMessage, Local<Value>(),
1157 worker_signature));
1145 worker_fun_template->PrototypeTemplate()->Set( 1158 worker_fun_template->PrototypeTemplate()->Set(
1146 String::NewFromUtf8(isolate, "getMessage", NewStringType::kNormal) 1159 String::NewFromUtf8(isolate, "getMessage", NewStringType::kNormal)
1147 .ToLocalChecked(), 1160 .ToLocalChecked(),
1148 FunctionTemplate::New(isolate, WorkerGetMessage)); 1161 FunctionTemplate::New(isolate, WorkerGetMessage, Local<Value>(),
1162 worker_signature));
1149 worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1); 1163 worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1);
1150 global_template->Set( 1164 global_template->Set(
1151 String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal) 1165 String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
1152 .ToLocalChecked(), 1166 .ToLocalChecked(),
1153 worker_fun_template); 1167 worker_fun_template);
1154 #endif // !V8_SHARED 1168 #endif // !V8_SHARED
1155 1169
1156 Local<ObjectTemplate> os_templ = ObjectTemplate::New(isolate); 1170 Local<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
1157 AddOSMethods(isolate, os_templ); 1171 AddOSMethods(isolate, os_templ);
1158 global_template->Set( 1172 global_template->Set(
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
1637 } 1651 }
1638 data_.Clear(); 1652 data_.Clear();
1639 } 1653 }
1640 1654
1641 1655
1642 Worker::Worker() 1656 Worker::Worker()
1643 : in_semaphore_(0), 1657 : in_semaphore_(0),
1644 out_semaphore_(0), 1658 out_semaphore_(0),
1645 thread_(NULL), 1659 thread_(NULL),
1646 script_(NULL), 1660 script_(NULL),
1647 state_(IDLE), 1661 running_(false) {}
1648 join_called_(false) {}
1649 1662
1650 1663
1651 Worker::~Worker() { 1664 Worker::~Worker() {
1652 delete thread_; 1665 delete thread_;
1653 thread_ = NULL; 1666 thread_ = NULL;
1654 delete[] script_; 1667 delete[] script_;
1655 script_ = NULL; 1668 script_ = NULL;
1656 in_queue_.Clear(); 1669 in_queue_.Clear();
1657 out_queue_.Clear(); 1670 out_queue_.Clear();
1658 } 1671 }
1659 1672
1660 1673
1661 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) { 1674 void Worker::StartExecuteInThread(const char* script) {
1662 if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) { 1675 running_ = true;
1663 script_ = i::StrDup(script); 1676 script_ = i::StrDup(script);
1664 thread_ = new WorkerThread(this); 1677 thread_ = new WorkerThread(this);
1665 thread_->Start(); 1678 thread_->Start();
1666 } else {
1667 // Somehow the Worker was started twice.
1668 UNREACHABLE();
1669 }
1670 } 1679 }
1671 1680
1672 1681
1673 void Worker::PostMessage(SerializationData* data) { 1682 void Worker::PostMessage(SerializationData* data) {
1674 in_queue_.Enqueue(data); 1683 in_queue_.Enqueue(data);
1675 in_semaphore_.Signal(); 1684 in_semaphore_.Signal();
1676 } 1685 }
1677 1686
1678 1687
1679 SerializationData* Worker::GetMessage() { 1688 SerializationData* Worker::GetMessage() {
1680 SerializationData* data = NULL; 1689 SerializationData* data = NULL;
1681 while (!out_queue_.Dequeue(&data)) { 1690 while (!out_queue_.Dequeue(&data)) {
1682 // If the worker is no longer running, and there are no messages in the 1691 // If the worker is no longer running, and there are no messages in the
1683 // queue, don't expect any more messages from it. 1692 // queue, don't expect any more messages from it.
1684 if (base::NoBarrier_Load(&state_) != RUNNING) break; 1693 if (!base::NoBarrier_Load(&running_)) break;
1685 out_semaphore_.Wait(); 1694 out_semaphore_.Wait();
1686 } 1695 }
1687 return data; 1696 return data;
1688 } 1697 }
1689 1698
1690 1699
1691 void Worker::Terminate() { 1700 void Worker::Terminate() {
1692 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { 1701 base::NoBarrier_Store(&running_, false);
1693 // Post NULL to wake the Worker thread message loop, and tell it to stop 1702 // Post NULL to wake the Worker thread message loop, and tell it to stop
1694 // running. 1703 // running.
1695 PostMessage(NULL); 1704 PostMessage(NULL);
1696 }
1697 } 1705 }
1698 1706
1699 1707
1700 void Worker::WaitForThread() { 1708 void Worker::WaitForThread() {
1701 Terminate(); 1709 Terminate();
1702 1710 thread_->Join();
1703 if (base::NoBarrier_CompareAndSwap(&join_called_, false, true) == false) {
1704 thread_->Join();
1705 } else {
1706 // Tried to call join twice.
1707 UNREACHABLE();
1708 }
1709 } 1711 }
1710 1712
1711 1713
1712 void Worker::ExecuteInThread() { 1714 void Worker::ExecuteInThread() {
1713 Isolate::CreateParams create_params; 1715 Isolate::CreateParams create_params;
1714 create_params.array_buffer_allocator = Shell::array_buffer_allocator; 1716 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
1715 Isolate* isolate = Isolate::New(create_params); 1717 Isolate* isolate = Isolate::New(create_params);
1716 { 1718 {
1717 Isolate::Scope iscope(isolate); 1719 Isolate::Scope iscope(isolate);
1718 { 1720 {
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
2454 } 2456 }
2455 2457
2456 } // namespace v8 2458 } // namespace v8
2457 2459
2458 2460
2459 #ifndef GOOGLE3 2461 #ifndef GOOGLE3
2460 int main(int argc, char* argv[]) { 2462 int main(int argc, char* argv[]) {
2461 return v8::Shell::Main(argc, argv); 2463 return v8::Shell::Main(argc, argv);
2462 } 2464 }
2463 #endif 2465 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/regress/regress-crbug-511880.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698