| Index: src/d8.cc
|
| diff --git a/src/d8.cc b/src/d8.cc
|
| index 9aeac11bb0a439b59a8933a6b15cdc8f0ac1116f..6dee19623b897427b80282152646e06881dde027 100644
|
| --- a/src/d8.cc
|
| +++ b/src/d8.cc
|
| @@ -105,6 +105,13 @@ class MockArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
|
| v8::Platform* g_platform = NULL;
|
|
|
|
|
| +static Local<Value> Throw(Isolate* isolate, const char* message) {
|
| + return isolate->ThrowException(
|
| + String::NewFromUtf8(isolate, message, NewStringType::kNormal)
|
| + .ToLocalChecked());
|
| +}
|
| +
|
| +
|
| #ifndef V8_SHARED
|
| bool FindInObjectList(Local<Object> object, const Shell::ObjectList& list) {
|
| for (int i = 0; i < list.length(); ++i) {
|
| @@ -114,19 +121,28 @@ bool FindInObjectList(Local<Object> object, const Shell::ObjectList& list) {
|
| }
|
| return false;
|
| }
|
| -#endif // !V8_SHARED
|
|
|
|
|
| -} // namespace
|
| +Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) {
|
| + if (object->InternalFieldCount() != 1) {
|
| + Throw(isolate, "this is not a Worker");
|
| + return NULL;
|
| + }
|
|
|
| + Worker* worker =
|
| + static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0));
|
| + if (worker == NULL) {
|
| + Throw(isolate, "Worker is defunct because main thread is terminating");
|
| + return NULL;
|
| + }
|
|
|
| -static Local<Value> Throw(Isolate* isolate, const char* message) {
|
| - return isolate->ThrowException(
|
| - String::NewFromUtf8(isolate, message, NewStringType::kNormal)
|
| - .ToLocalChecked());
|
| + return worker;
|
| }
|
| +#endif // !V8_SHARED
|
|
|
|
|
| +} // namespace
|
| +
|
|
|
| class PerIsolateData {
|
| public:
|
| @@ -686,10 +702,15 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|
|
| {
|
| base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
|
| + // Initialize the internal field to NULL; if we return early without
|
| + // creating a new Worker (because the main thread is terminating) we can
|
| + // early-out from the instance calls.
|
| + args.Holder()->SetAlignedPointerInInternalField(0, NULL);
|
| +
|
| if (!allow_new_workers_) return;
|
|
|
| Worker* worker = new Worker;
|
| - args.This()->SetInternalField(0, External::New(isolate, worker));
|
| + args.Holder()->SetAlignedPointerInInternalField(0, worker);
|
| workers_.Add(worker);
|
|
|
| String::Utf8Value script(args[0]);
|
| @@ -697,7 +718,7 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| Throw(args.GetIsolate(), "Can't get worker script");
|
| return;
|
| }
|
| - worker->StartExecuteInThread(isolate, *script);
|
| + worker->StartExecuteInThread(*script);
|
| }
|
| }
|
|
|
| @@ -706,24 +727,17 @@ void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| Isolate* isolate = args.GetIsolate();
|
| HandleScope handle_scope(isolate);
|
| Local<Context> context = isolate->GetCurrentContext();
|
| - Local<Value> this_value;
|
|
|
| if (args.Length() < 1) {
|
| Throw(isolate, "Invalid argument");
|
| return;
|
| }
|
|
|
| - if (args.This()->InternalFieldCount() > 0) {
|
| - this_value = args.This()->GetInternalField(0);
|
| - }
|
| - if (this_value.IsEmpty()) {
|
| - Throw(isolate, "this is not a Worker");
|
| + Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
|
| + if (!worker) {
|
| return;
|
| }
|
|
|
| - Worker* worker =
|
| - static_cast<Worker*>(Local<External>::Cast(this_value)->Value());
|
| -
|
| Local<Value> message = args[0];
|
| ObjectList to_transfer;
|
| if (args.Length() >= 2) {
|
| @@ -762,18 +776,11 @@ void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| Isolate* isolate = args.GetIsolate();
|
| HandleScope handle_scope(isolate);
|
| - Local<Value> this_value;
|
| - if (args.This()->InternalFieldCount() > 0) {
|
| - this_value = args.This()->GetInternalField(0);
|
| - }
|
| - if (this_value.IsEmpty()) {
|
| - Throw(isolate, "this is not a Worker");
|
| + Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
|
| + if (!worker) {
|
| return;
|
| }
|
|
|
| - Worker* worker =
|
| - static_cast<Worker*>(Local<External>::Cast(this_value)->Value());
|
| -
|
| SerializationData* data = worker->GetMessage();
|
| if (data) {
|
| int offset = 0;
|
| @@ -789,17 +796,11 @@ void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| Isolate* isolate = args.GetIsolate();
|
| HandleScope handle_scope(isolate);
|
| - Local<Value> this_value;
|
| - if (args.This()->InternalFieldCount() > 0) {
|
| - this_value = args.This()->GetInternalField(0);
|
| - }
|
| - if (this_value.IsEmpty()) {
|
| - Throw(isolate, "this is not a Worker");
|
| + Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
|
| + if (!worker) {
|
| return;
|
| }
|
|
|
| - Worker* worker =
|
| - static_cast<Worker*>(Local<External>::Cast(this_value)->Value());
|
| worker->Terminate();
|
| }
|
| #endif // !V8_SHARED
|
| @@ -1134,18 +1135,26 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
|
|
|
| Local<FunctionTemplate> worker_fun_template =
|
| FunctionTemplate::New(isolate, WorkerNew);
|
| + Local<Signature> worker_signature =
|
| + Signature::New(isolate, worker_fun_template);
|
| + worker_fun_template->SetClassName(
|
| + String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
|
| + .ToLocalChecked());
|
| worker_fun_template->PrototypeTemplate()->Set(
|
| String::NewFromUtf8(isolate, "terminate", NewStringType::kNormal)
|
| .ToLocalChecked(),
|
| - FunctionTemplate::New(isolate, WorkerTerminate));
|
| + FunctionTemplate::New(isolate, WorkerTerminate, Local<Value>(),
|
| + worker_signature));
|
| worker_fun_template->PrototypeTemplate()->Set(
|
| String::NewFromUtf8(isolate, "postMessage", NewStringType::kNormal)
|
| .ToLocalChecked(),
|
| - FunctionTemplate::New(isolate, WorkerPostMessage));
|
| + FunctionTemplate::New(isolate, WorkerPostMessage, Local<Value>(),
|
| + worker_signature));
|
| worker_fun_template->PrototypeTemplate()->Set(
|
| String::NewFromUtf8(isolate, "getMessage", NewStringType::kNormal)
|
| .ToLocalChecked(),
|
| - FunctionTemplate::New(isolate, WorkerGetMessage));
|
| + FunctionTemplate::New(isolate, WorkerGetMessage, Local<Value>(),
|
| + worker_signature));
|
| worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1);
|
| global_template->Set(
|
| String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
|
| @@ -1644,8 +1653,7 @@ Worker::Worker()
|
| out_semaphore_(0),
|
| thread_(NULL),
|
| script_(NULL),
|
| - state_(IDLE),
|
| - join_called_(false) {}
|
| + running_(false) {}
|
|
|
|
|
| Worker::~Worker() {
|
| @@ -1658,15 +1666,11 @@ Worker::~Worker() {
|
| }
|
|
|
|
|
| -void Worker::StartExecuteInThread(Isolate* isolate, const char* script) {
|
| - if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) {
|
| - script_ = i::StrDup(script);
|
| - thread_ = new WorkerThread(this);
|
| - thread_->Start();
|
| - } else {
|
| - // Somehow the Worker was started twice.
|
| - UNREACHABLE();
|
| - }
|
| +void Worker::StartExecuteInThread(const char* script) {
|
| + running_ = true;
|
| + script_ = i::StrDup(script);
|
| + thread_ = new WorkerThread(this);
|
| + thread_->Start();
|
| }
|
|
|
|
|
| @@ -1681,7 +1685,7 @@ SerializationData* Worker::GetMessage() {
|
| while (!out_queue_.Dequeue(&data)) {
|
| // If the worker is no longer running, and there are no messages in the
|
| // queue, don't expect any more messages from it.
|
| - if (base::NoBarrier_Load(&state_) != RUNNING) break;
|
| + if (!base::NoBarrier_Load(&running_)) break;
|
| out_semaphore_.Wait();
|
| }
|
| return data;
|
| @@ -1689,23 +1693,16 @@ SerializationData* Worker::GetMessage() {
|
|
|
|
|
| void Worker::Terminate() {
|
| - if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) {
|
| - // Post NULL to wake the Worker thread message loop, and tell it to stop
|
| - // running.
|
| - PostMessage(NULL);
|
| - }
|
| + base::NoBarrier_Store(&running_, false);
|
| + // Post NULL to wake the Worker thread message loop, and tell it to stop
|
| + // running.
|
| + PostMessage(NULL);
|
| }
|
|
|
|
|
| void Worker::WaitForThread() {
|
| Terminate();
|
| -
|
| - if (base::NoBarrier_CompareAndSwap(&join_called_, false, true) == false) {
|
| - thread_->Join();
|
| - } else {
|
| - // Tried to call join twice.
|
| - UNREACHABLE();
|
| - }
|
| + thread_->Join();
|
| }
|
|
|
|
|
|
|