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

Unified Diff: src/d8.cc

Issue 1185643004: Add d8 API for spawning function on a new thread. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: . Created 5 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: src/d8.cc
diff --git a/src/d8.cc b/src/d8.cc
index c46df53851a5fef9e39d1b02c829d8d7073a4308..e025826042f0ccf5e9482c5f2560a01bcf873952 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -145,6 +145,7 @@ class PerIsolateData {
int realm_switch_;
Persistent<Context>* realms_;
Persistent<Value> realm_shared_;
+ ArrayBuffer::Allocator* array_buffer_allocator_;
int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
int arg_offset);
@@ -191,6 +192,8 @@ base::Mutex Shell::context_mutex_;
const base::TimeTicks Shell::kInitialTicks =
base::TimeTicks::HighResolutionNow();
Persistent<Context> Shell::utility_context_;
+Worker Shell::worker_;
+i::List<v8::SharedArrayBuffer::Contents> Shell::externalized_shared_contents_;
#endif // !V8_SHARED
Persistent<Context> Shell::evaluation_context_;
@@ -661,6 +664,39 @@ void Shell::Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
+#ifndef V8_SHARED
+void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ HandleScope handle_scope(isolate);
+ if (args.Length() < 1 || !args[0]->IsFunction()) {
+ Throw(args.GetIsolate(), "1st argument must be function");
+ return;
+ }
+ if (args.Length() >= 2 && !args[1]->IsSharedArrayBuffer()) {
+ Throw(args.GetIsolate(), "2nd argument must be SharedArrayBuffer");
+ return;
+ }
+
+ String::Utf8Value function_string(args[0]->ToString());
+ v8::SharedArrayBuffer::Contents contents;
+ if (args.Length() >= 2) {
+ Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(args[1]);
+ contents = sab->Externalize();
+ externalized_shared_contents_.Add(contents);
+ }
+ worker_.StartExecuteInThread(isolate, *function_string, contents);
+}
+
+
+void Shell::WorkerJoin(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ HandleScope handle_scope(isolate);
+ Handle<Value> result = worker_.WaitForThread(isolate);
+ args.GetReturnValue().Set(result);
+}
+#endif // !V8_SHARED
+
+
void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
int exit_code = args[0]->Int32Value();
OnExit(args.GetIsolate());
@@ -992,6 +1028,13 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
FunctionTemplate::New(isolate, PerformanceNow));
global_template->Set(String::NewFromUtf8(isolate, "performance"),
performance_template);
+
+ Handle<ObjectTemplate> worker_template = ObjectTemplate::New(isolate);
+ worker_template->Set(String::NewFromUtf8(isolate, "new"),
+ FunctionTemplate::New(isolate, WorkerNew));
+ worker_template->Set(String::NewFromUtf8(isolate, "join"),
+ FunctionTemplate::New(isolate, WorkerJoin));
+ global_template->Set(String::NewFromUtf8(isolate, "Worker"), worker_template);
#endif // !V8_SHARED
Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
@@ -1369,6 +1412,117 @@ void SourceGroup::WaitForThread() {
done_semaphore_.Wait();
}
}
+
+
+Worker::Worker() : thread_(NULL), script_(NULL), result_json_(NULL) {}
+
+
+Worker::~Worker() { Cleanup(); }
+
+
+void Worker::StartExecuteInThread(
+ Isolate* isolate, const char* function_string,
+ const v8::SharedArrayBuffer::Contents& contents) {
+ if (thread_) {
+ Throw(isolate, "Only one worker allowed");
+ return;
+ }
+
+ static const char format[] = "JSON.stringify((%s).call(this, sab));";
binji 2015/06/15 19:11:48 Better way to do this?
+ size_t len = strlen(function_string) + sizeof(format);
+
+ script_ = new char[len + 1];
+ snprintf(script_, len, format, function_string);
+ script_[len] = 0;
+
+ contents_ = contents;
+
+ thread_ = new WorkerThread(this);
+ thread_->Start();
+}
+
+
+Handle<Value> Worker::WaitForThread(Isolate* isolate) {
+ EscapableHandleScope handle_scope(isolate);
+ Handle<Value> result;
+
+ if (thread_ == NULL) return result;
+ thread_->Join();
+
+ if (result_json_) {
+ Local<String> result_json = String::NewFromUtf8(isolate, result_json_);
+ MaybeLocal<Value> maybe_result = JSON::Parse(isolate, result_json);
+ if (!maybe_result.IsEmpty()) {
+ result = maybe_result.ToLocalChecked();
+ }
+ }
+
+ Cleanup();
+ return handle_scope.Escape(Local<Value>::Cast(result));
+}
+
+
+void Worker::ExecuteInThread() {
binji 2015/06/15 19:11:48 A lot of this function is copy/paste from other pl
+ ShellArrayBufferAllocator allocator;
+ Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = &allocator;
+ Isolate* isolate = Isolate::New(create_params);
+ {
+ Isolate::Scope iscope(isolate);
+ {
+ HandleScope scope(isolate);
+ PerIsolateData data(isolate);
+ Local<Context> context = Shell::CreateEvaluationContext(isolate);
+ {
+ Context::Scope cscope(context);
+ PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
+
+ Handle<String> sab_name = String::NewFromUtf8(isolate, "sab");
+ if (contents_.Data()) {
+ Handle<v8::SharedArrayBuffer> sab = v8::SharedArrayBuffer::New(
+ isolate, contents_.Data(), contents_.ByteLength());
+ context->Global()->Set(sab_name, sab);
+ } else {
+ context->Global()->Set(sab_name, v8::Undefined(isolate));
+ }
+
+ Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed");
+ Handle<String> source = String::NewFromUtf8(isolate, script_);
+
+ TryCatch try_catch(isolate);
+ Handle<Script> script =
+ Shell::CompileString(isolate, source, file_name,
+ Shell::options.compile_options, Shell::SCRIPT);
+ result_json_ = NULL;
+ if (script.IsEmpty()) {
+ // Print errors that happened during compilation.
+ // TODO(binji): support debugger?
+ Shell::ReportException(isolate, &try_catch);
+ } else {
+ Handle<Value> result = script->Run();
+ if (result->IsString()) {
+ Handle<String> str_result = Handle<String>::Cast(result);
+ v8::String::Utf8Value str(str_result);
+ result_json_ = new char[str.length() + 1];
+ memcpy(result_json_, *str, str.length() + 1);
+ }
+ }
+ }
+ }
+ }
+ Shell::CollectGarbage(isolate);
+ isolate->Dispose();
+}
+
+
+void Worker::Cleanup() {
+ delete thread_;
+ thread_ = NULL;
+ delete[] script_;
+ script_ = NULL;
+ delete[] result_json_;
+ result_json_ = NULL;
+}
#endif // !V8_SHARED
@@ -1543,6 +1697,7 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) {
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].WaitForThread();
}
+ CleanupWorker(isolate);
#endif // !V8_SHARED
return 0;
}
@@ -1565,6 +1720,22 @@ void Shell::CollectGarbage(Isolate* isolate) {
#ifndef V8_SHARED
+void Shell::CleanupWorker(Isolate* isolate) {
+ {
+ HandleScope scope(isolate);
+ worker_.WaitForThread(isolate);
+ }
+ PerIsolateData* data = PerIsolateData::Get(isolate);
+
+ for (int i = 0; i < externalized_shared_contents_.length(); ++i) {
+ const v8::SharedArrayBuffer::Contents& contents =
+ externalized_shared_contents_[i];
+ data->array_buffer_allocator_->Free(contents.Data(), contents.ByteLength());
+ }
+ externalized_shared_contents_.Clear();
+}
+
+
static void DumpHeapConstants(i::Isolate* isolate) {
i::Heap* heap = isolate->heap();
@@ -1684,6 +1855,7 @@ int Shell::Main(int argc, char* argv[]) {
Isolate::Scope scope(isolate);
Initialize(isolate);
PerIsolateData data(isolate);
+ data.array_buffer_allocator_ = create_params.array_buffer_allocator;
InitializeDebugger(isolate);
#ifndef V8_SHARED
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker.js » ('j') | test/mjsunit/d8-worker.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698