| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "test/inspector/task-runner.h" | 5 #include "test/inspector/task-runner.h" |
| 6 | 6 |
| 7 #include "test/inspector/inspector-impl.h" | 7 #include "test/inspector/inspector-impl.h" |
| 8 | 8 |
| 9 #if !defined(_WIN32) && !defined(_WIN64) | 9 #if !defined(_WIN32) && !defined(_WIN64) |
| 10 #include <unistd.h> // NOLINT | 10 #include <unistd.h> // NOLINT |
| 11 #endif // !defined(_WIN32) && !defined(_WIN64) | 11 #endif // !defined(_WIN32) && !defined(_WIN64) |
| 12 | 12 |
| 13 namespace { | 13 namespace { |
| 14 | 14 |
| 15 const int kTaskRunnerIndex = 2; | 15 const int kIsolateDataIndex = 2; |
| 16 const int kContextGroupIdIndex = 3; | |
| 17 | 16 |
| 18 void ReportUncaughtException(v8::Isolate* isolate, | 17 void ReportUncaughtException(v8::Isolate* isolate, |
| 19 const v8::TryCatch& try_catch) { | 18 const v8::TryCatch& try_catch) { |
| 20 CHECK(try_catch.HasCaught()); | 19 CHECK(try_catch.HasCaught()); |
| 21 v8::HandleScope handle_scope(isolate); | 20 v8::HandleScope handle_scope(isolate); |
| 22 std::string message = *v8::String::Utf8Value(try_catch.Message()->Get()); | 21 std::string message = *v8::String::Utf8Value(try_catch.Message()->Get()); |
| 23 fprintf(stderr, "Unhandle exception: %s\n", message.data()); | 22 fprintf(stderr, "Unhandle exception: %s\n", message.data()); |
| 24 } | 23 } |
| 25 | 24 |
| 26 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { | 25 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { |
| 27 v8::internal::Vector<uint16_t> buffer = | 26 v8::internal::Vector<uint16_t> buffer = |
| 28 v8::internal::Vector<uint16_t>::New(str->Length()); | 27 v8::internal::Vector<uint16_t>::New(str->Length()); |
| 29 str->Write(buffer.start(), 0, str->Length()); | 28 str->Write(buffer.start(), 0, str->Length()); |
| 30 return buffer; | 29 return buffer; |
| 31 } | 30 } |
| 32 | 31 |
| 33 } // namespace | 32 } // namespace |
| 34 | 33 |
| 35 TaskRunner::TaskRunner(TaskRunner::SetupGlobalTasks setup_global_tasks, | 34 IsolateData::IsolateData(TaskRunner* task_runner, |
| 35 IsolateData::SetupGlobalTasks setup_global_tasks, |
| 36 v8::StartupData* startup_data) |
| 37 : task_runner_(task_runner), |
| 38 setup_global_tasks_(std::move(setup_global_tasks)) { |
| 39 v8::Isolate::CreateParams params; |
| 40 params.array_buffer_allocator = |
| 41 v8::ArrayBuffer::Allocator::NewDefaultAllocator(); |
| 42 params.snapshot_blob = startup_data; |
| 43 isolate_ = v8::Isolate::New(params); |
| 44 isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped); |
| 45 } |
| 46 |
| 47 IsolateData* IsolateData::FromContext(v8::Local<v8::Context> context) { |
| 48 return static_cast<IsolateData*>( |
| 49 context->GetAlignedPointerFromEmbedderData(kIsolateDataIndex)); |
| 50 } |
| 51 |
| 52 int IsolateData::CreateContextGroup() { |
| 53 v8::Local<v8::ObjectTemplate> global_template = |
| 54 v8::ObjectTemplate::New(isolate_); |
| 55 for (auto it = setup_global_tasks_.begin(); it != setup_global_tasks_.end(); |
| 56 ++it) { |
| 57 (*it)->Run(isolate_, global_template); |
| 58 } |
| 59 v8::Local<v8::Context> context = |
| 60 v8::Context::New(isolate_, nullptr, global_template); |
| 61 context->SetAlignedPointerInEmbedderData(kIsolateDataIndex, this); |
| 62 int context_group_id = ++last_context_group_id_; |
| 63 contexts_[context_group_id].Reset(isolate_, context); |
| 64 return context_group_id; |
| 65 } |
| 66 |
| 67 v8::Local<v8::Context> IsolateData::GetContext(int context_group_id) { |
| 68 return contexts_[context_group_id].Get(isolate_); |
| 69 } |
| 70 |
| 71 void IsolateData::RegisterModule(v8::Local<v8::Context> context, |
| 72 v8::internal::Vector<uint16_t> name, |
| 73 v8::ScriptCompiler::Source* source) { |
| 74 v8::Local<v8::Module> module; |
| 75 if (!v8::ScriptCompiler::CompileModule(isolate(), source).ToLocal(&module)) |
| 76 return; |
| 77 if (!module->Instantiate(context, &IsolateData::ModuleResolveCallback)) |
| 78 return; |
| 79 v8::Local<v8::Value> result; |
| 80 if (!module->Evaluate(context).ToLocal(&result)) return; |
| 81 modules_[name] = v8::Global<v8::Module>(isolate_, module); |
| 82 } |
| 83 |
| 84 v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback( |
| 85 v8::Local<v8::Context> context, v8::Local<v8::String> specifier, |
| 86 v8::Local<v8::Module> referrer) { |
| 87 std::string str = *v8::String::Utf8Value(specifier); |
| 88 IsolateData* data = IsolateData::FromContext(context); |
| 89 return data->modules_[ToVector(specifier)].Get(data->isolate_); |
| 90 } |
| 91 |
| 92 TaskRunner::TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks, |
| 36 bool catch_exceptions, | 93 bool catch_exceptions, |
| 37 v8::base::Semaphore* ready_semaphore, | 94 v8::base::Semaphore* ready_semaphore, |
| 38 v8::StartupData* startup_data) | 95 v8::StartupData* startup_data) |
| 39 : Thread(Options("Task Runner")), | 96 : Thread(Options("Task Runner")), |
| 40 setup_global_tasks_(std::move(setup_global_tasks)), | 97 setup_global_tasks_(std::move(setup_global_tasks)), |
| 41 startup_data_(startup_data), | 98 startup_data_(startup_data), |
| 42 catch_exceptions_(catch_exceptions), | 99 catch_exceptions_(catch_exceptions), |
| 43 ready_semaphore_(ready_semaphore), | 100 ready_semaphore_(ready_semaphore), |
| 44 isolate_(nullptr), | 101 data_(nullptr), |
| 45 process_queue_semaphore_(0), | 102 process_queue_semaphore_(0), |
| 46 nested_loop_count_(0) { | 103 nested_loop_count_(0) { |
| 47 Start(); | 104 Start(); |
| 48 } | 105 } |
| 49 | 106 |
| 50 TaskRunner::~TaskRunner() { Join(); } | 107 TaskRunner::~TaskRunner() { Join(); } |
| 51 | 108 |
| 52 void TaskRunner::InitializeIsolate() { | 109 void TaskRunner::Run() { |
| 53 v8::Isolate::CreateParams params; | 110 data_.reset( |
| 54 params.array_buffer_allocator = | 111 new IsolateData(this, std::move(setup_global_tasks_), startup_data_)); |
| 55 v8::ArrayBuffer::Allocator::NewDefaultAllocator(); | 112 |
| 56 params.snapshot_blob = startup_data_; | 113 v8::Isolate::Scope isolate_scope(isolate()); |
| 57 isolate_ = v8::Isolate::New(params); | 114 v8::HandleScope handle_scope(isolate()); |
| 58 isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped); | 115 default_context_group_id_ = data_->CreateContextGroup(); |
| 59 v8::Isolate::Scope isolate_scope(isolate_); | 116 |
| 60 v8::HandleScope handle_scope(isolate_); | |
| 61 NewContextGroup(setup_global_tasks_); | |
| 62 if (ready_semaphore_) ready_semaphore_->Signal(); | 117 if (ready_semaphore_) ready_semaphore_->Signal(); |
| 63 } | |
| 64 | |
| 65 v8::Local<v8::Context> TaskRunner::NewContextGroup( | |
| 66 const TaskRunner::SetupGlobalTasks& setup_global_tasks) { | |
| 67 v8::Local<v8::ObjectTemplate> global_template = | |
| 68 v8::ObjectTemplate::New(isolate_); | |
| 69 for (auto it = setup_global_tasks.begin(); it != setup_global_tasks.end(); | |
| 70 ++it) { | |
| 71 (*it)->Run(isolate_, global_template); | |
| 72 } | |
| 73 v8::Local<v8::Context> context = | |
| 74 v8::Context::New(isolate_, nullptr, global_template); | |
| 75 context->SetAlignedPointerInEmbedderData(kTaskRunnerIndex, this); | |
| 76 intptr_t context_group_id = ++last_context_group_id_; | |
| 77 // Should be 2-byte aligned. | |
| 78 context->SetAlignedPointerInEmbedderData( | |
| 79 kContextGroupIdIndex, reinterpret_cast<void*>(context_group_id * 2)); | |
| 80 contexts_[context_group_id].Reset(isolate_, context); | |
| 81 return context; | |
| 82 } | |
| 83 | |
| 84 v8::Local<v8::Context> TaskRunner::GetContext(int context_group_id) { | |
| 85 return contexts_[context_group_id].Get(isolate_); | |
| 86 } | |
| 87 | |
| 88 int TaskRunner::GetContextGroupId(v8::Local<v8::Context> context) { | |
| 89 return static_cast<int>( | |
| 90 reinterpret_cast<intptr_t>( | |
| 91 context->GetAlignedPointerFromEmbedderData(kContextGroupIdIndex)) / | |
| 92 2); | |
| 93 } | |
| 94 | |
| 95 void TaskRunner::Run() { | |
| 96 InitializeIsolate(); | |
| 97 RunMessageLoop(false); | 118 RunMessageLoop(false); |
| 98 } | 119 } |
| 99 | 120 |
| 100 void TaskRunner::RunMessageLoop(bool only_protocol) { | 121 void TaskRunner::RunMessageLoop(bool only_protocol) { |
| 101 int loop_number = ++nested_loop_count_; | 122 int loop_number = ++nested_loop_count_; |
| 102 while (nested_loop_count_ == loop_number && !is_terminated_.Value()) { | 123 while (nested_loop_count_ == loop_number && !is_terminated_.Value()) { |
| 103 TaskRunner::Task* task = GetNext(only_protocol); | 124 TaskRunner::Task* task = GetNext(only_protocol); |
| 104 if (!task) return; | 125 if (!task) return; |
| 105 v8::Isolate::Scope isolate_scope(isolate_); | 126 v8::Isolate::Scope isolate_scope(isolate()); |
| 106 if (catch_exceptions_) { | 127 if (catch_exceptions_) { |
| 107 v8::TryCatch try_catch(isolate_); | 128 v8::TryCatch try_catch(isolate()); |
| 108 task->RunOnTaskRunner(this); | 129 task->RunOnTaskRunner(this); |
| 109 delete task; | 130 delete task; |
| 110 if (try_catch.HasCaught()) { | 131 if (try_catch.HasCaught()) { |
| 111 ReportUncaughtException(isolate_, try_catch); | 132 ReportUncaughtException(isolate(), try_catch); |
| 112 fflush(stdout); | 133 fflush(stdout); |
| 113 fflush(stderr); | 134 fflush(stderr); |
| 114 _exit(0); | 135 _exit(0); |
| 115 } | 136 } |
| 116 } else { | 137 } else { |
| 117 task->RunOnTaskRunner(this); | 138 task->RunOnTaskRunner(this); |
| 118 delete task; | 139 delete task; |
| 119 } | 140 } |
| 120 } | 141 } |
| 121 } | 142 } |
| 122 | 143 |
| 123 void TaskRunner::QuitMessageLoop() { | 144 void TaskRunner::QuitMessageLoop() { |
| 124 DCHECK(nested_loop_count_ > 0); | 145 DCHECK(nested_loop_count_ > 0); |
| 125 --nested_loop_count_; | 146 --nested_loop_count_; |
| 126 } | 147 } |
| 127 | 148 |
| 128 void TaskRunner::Append(Task* task) { | 149 void TaskRunner::Append(Task* task) { |
| 129 queue_.Enqueue(task); | 150 queue_.Enqueue(task); |
| 130 process_queue_semaphore_.Signal(); | 151 process_queue_semaphore_.Signal(); |
| 131 } | 152 } |
| 132 | 153 |
| 133 void TaskRunner::Terminate() { | 154 void TaskRunner::Terminate() { |
| 134 is_terminated_.Increment(1); | 155 is_terminated_.Increment(1); |
| 135 process_queue_semaphore_.Signal(); | 156 process_queue_semaphore_.Signal(); |
| 136 } | 157 } |
| 137 | 158 |
| 138 void TaskRunner::RegisterModule(v8::internal::Vector<uint16_t> name, | |
| 139 v8::Local<v8::Module> module) { | |
| 140 modules_[name] = v8::Global<v8::Module>(isolate_, module); | |
| 141 } | |
| 142 | |
| 143 v8::MaybeLocal<v8::Module> TaskRunner::ModuleResolveCallback( | |
| 144 v8::Local<v8::Context> context, v8::Local<v8::String> specifier, | |
| 145 v8::Local<v8::Module> referrer) { | |
| 146 std::string str = *v8::String::Utf8Value(specifier); | |
| 147 TaskRunner* runner = TaskRunner::FromContext(context); | |
| 148 return runner->modules_[ToVector(specifier)].Get(runner->isolate_); | |
| 149 } | |
| 150 | |
| 151 TaskRunner::Task* TaskRunner::GetNext(bool only_protocol) { | 159 TaskRunner::Task* TaskRunner::GetNext(bool only_protocol) { |
| 152 for (;;) { | 160 for (;;) { |
| 153 if (is_terminated_.Value()) return nullptr; | 161 if (is_terminated_.Value()) return nullptr; |
| 154 if (only_protocol) { | 162 if (only_protocol) { |
| 155 Task* task = nullptr; | 163 Task* task = nullptr; |
| 156 if (queue_.Dequeue(&task)) { | 164 if (queue_.Dequeue(&task)) { |
| 157 if (task->is_inspector_task()) return task; | 165 if (task->is_inspector_task()) return task; |
| 158 deffered_queue_.Enqueue(task); | 166 deffered_queue_.Enqueue(task); |
| 159 } | 167 } |
| 160 } else { | 168 } else { |
| 161 Task* task = nullptr; | 169 Task* task = nullptr; |
| 162 if (deffered_queue_.Dequeue(&task)) return task; | 170 if (deffered_queue_.Dequeue(&task)) return task; |
| 163 if (queue_.Dequeue(&task)) return task; | 171 if (queue_.Dequeue(&task)) return task; |
| 164 } | 172 } |
| 165 process_queue_semaphore_.Wait(); | 173 process_queue_semaphore_.Wait(); |
| 166 } | 174 } |
| 167 return nullptr; | 175 return nullptr; |
| 168 } | 176 } |
| 169 | 177 |
| 170 TaskRunner* TaskRunner::FromContext(v8::Local<v8::Context> context) { | |
| 171 return static_cast<TaskRunner*>( | |
| 172 context->GetAlignedPointerFromEmbedderData(kTaskRunnerIndex)); | |
| 173 } | |
| 174 | |
| 175 AsyncTask::AsyncTask(const char* task_name, | 178 AsyncTask::AsyncTask(const char* task_name, |
| 176 v8_inspector::V8Inspector* inspector) | 179 v8_inspector::V8Inspector* inspector) |
| 177 : inspector_(task_name ? inspector : nullptr) { | 180 : inspector_(task_name ? inspector : nullptr) { |
| 178 if (inspector_) { | 181 if (inspector_) { |
| 179 inspector_->asyncTaskScheduled( | 182 inspector_->asyncTaskScheduled( |
| 180 v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name), | 183 v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name), |
| 181 strlen(task_name)), | 184 strlen(task_name)), |
| 182 this, false); | 185 this, false); |
| 183 } | 186 } |
| 184 } | 187 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 } | 246 } |
| 244 | 247 |
| 245 v8::ScriptCompiler::Source scriptSource(source, origin); | 248 v8::ScriptCompiler::Source scriptSource(source, origin); |
| 246 if (!is_module_) { | 249 if (!is_module_) { |
| 247 v8::Local<v8::Script> script; | 250 v8::Local<v8::Script> script; |
| 248 if (!v8::ScriptCompiler::Compile(context, &scriptSource).ToLocal(&script)) | 251 if (!v8::ScriptCompiler::Compile(context, &scriptSource).ToLocal(&script)) |
| 249 return; | 252 return; |
| 250 v8::MaybeLocal<v8::Value> result; | 253 v8::MaybeLocal<v8::Value> result; |
| 251 result = script->Run(context); | 254 result = script->Run(context); |
| 252 } else { | 255 } else { |
| 253 v8::Local<v8::Module> module; | 256 IsolateData::FromContext(context)->RegisterModule(context, name_, |
| 254 if (!v8::ScriptCompiler::CompileModule(isolate(), &scriptSource) | 257 &scriptSource); |
| 255 .ToLocal(&module)) { | |
| 256 return; | |
| 257 } | |
| 258 if (!module->Instantiate(context, &TaskRunner::ModuleResolveCallback)) | |
| 259 return; | |
| 260 v8::Local<v8::Value> result; | |
| 261 if (!module->Evaluate(context).ToLocal(&result)) return; | |
| 262 TaskRunner* runner = TaskRunner::FromContext(context); | |
| 263 runner->RegisterModule(name_, module); | |
| 264 } | 258 } |
| 265 } | 259 } |
| OLD | NEW |