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

Unified Diff: src/d8.cc

Issue 1191373005: Revert of Add d8 API for spawning function on a new thread (Second try) (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
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/d8.cc
diff --git a/src/d8.cc b/src/d8.cc
index 28342363e940f77e9faf402c61c5b888d5eb0d29..c46df53851a5fef9e39d1b02c829d8d7073a4308 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -46,7 +46,6 @@
#include "src/d8-debug.h"
#include "src/debug.h"
#include "src/snapshot/natives.h"
-#include "src/utils.h"
#include "src/v8.h"
#endif // !V8_SHARED
@@ -104,19 +103,6 @@
v8::Platform* g_platform = NULL;
-
-
-#ifndef V8_SHARED
-bool FindInObjectList(Handle<Object> object, const Shell::ObjectList& list) {
- for (int i = 0; i < list.length(); ++i) {
- if (list[i]->StrictEquals(object)) {
- return true;
- }
- }
- return false;
-}
-#endif // !V8_SHARED
-
} // namespace
@@ -205,12 +191,9 @@
const base::TimeTicks Shell::kInitialTicks =
base::TimeTicks::HighResolutionNow();
Persistent<Context> Shell::utility_context_;
-Worker Shell::worker_;
-i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_;
#endif // !V8_SHARED
Persistent<Context> Shell::evaluation_context_;
-ArrayBuffer::Allocator* Shell::array_buffer_allocator;
ShellOptions Shell::options;
const char* Shell::kPrompt = "d8> ";
@@ -243,8 +226,9 @@
name_buffer = new uint16_t[name_length];
name_string->Write(name_buffer, 0, name_length);
}
+ ShellArrayBufferAllocator allocator;
Isolate::CreateParams create_params;
- create_params.array_buffer_allocator = Shell::array_buffer_allocator;
+ create_params.array_buffer_allocator = &allocator;
Isolate* temp_isolate = Isolate::New(create_params);
ScriptCompiler::CachedData* result = NULL;
{
@@ -677,86 +661,6 @@
}
-#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;
- }
-
- String::Utf8Value function_string(args[0]->ToString());
- worker_.StartExecuteInThread(isolate, *function_string);
-}
-
-
-void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
- Isolate* isolate = args.GetIsolate();
- HandleScope handle_scope(isolate);
- Local<Context> context = isolate->GetCurrentContext();
-
- if (args.Length() < 1) {
- Throw(isolate, "Invalid argument");
- return;
- }
-
- Handle<Value> message = args[0];
- ObjectList to_transfer;
- if (args.Length() >= 2) {
- if (!args[1]->IsArray()) {
- Throw(isolate, "Transfer list must be an Array");
- return;
- }
-
- Handle<Array> transfer = Handle<Array>::Cast(args[1]);
- uint32_t length = transfer->Length();
- for (uint32_t i = 0; i < length; ++i) {
- Handle<Value> element;
- if (transfer->Get(context, i).ToLocal(&element)) {
- if (!element->IsArrayBuffer() && !element->IsSharedArrayBuffer()) {
- Throw(isolate,
- "Transfer array elements must be an ArrayBuffer or "
- "SharedArrayBuffer.");
- break;
- }
-
- to_transfer.Add(Handle<Object>::Cast(element));
- }
- }
- }
-
- ObjectList seen_objects;
- SerializationData* data = new SerializationData;
- if (SerializeValue(isolate, message, to_transfer, &seen_objects, data)) {
- worker_.PostMessage(data);
- } else {
- delete data;
- }
-}
-
-
-void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
- Isolate* isolate = args.GetIsolate();
- HandleScope handle_scope(isolate);
- SerializationData* data = worker_.GetMessage();
- if (data) {
- int offset = 0;
- Local<Value> data_value;
- if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) {
- args.GetReturnValue().Set(data_value);
- }
- delete data;
- }
-}
-
-
-void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
- worker_.Terminate();
-}
-#endif // !V8_SHARED
-
-
void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
int exit_code = args[0]->Int32Value();
OnExit(args.GetIsolate());
@@ -1088,20 +992,6 @@
FunctionTemplate::New(isolate, PerformanceNow));
global_template->Set(String::NewFromUtf8(isolate, "performance"),
performance_template);
-
- Handle<FunctionTemplate> worker_fun_template =
- FunctionTemplate::New(isolate, WorkerNew);
- worker_fun_template->PrototypeTemplate()->Set(
- String::NewFromUtf8(isolate, "terminate"),
- FunctionTemplate::New(isolate, WorkerTerminate));
- worker_fun_template->PrototypeTemplate()->Set(
- String::NewFromUtf8(isolate, "postMessage"),
- FunctionTemplate::New(isolate, WorkerPostMessage));
- worker_fun_template->PrototypeTemplate()->Set(
- String::NewFromUtf8(isolate, "getMessage"),
- FunctionTemplate::New(isolate, WorkerGetMessage));
- global_template->Set(String::NewFromUtf8(isolate, "Worker"),
- worker_fun_template);
#endif // !V8_SHARED
Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
@@ -1435,8 +1325,9 @@
void SourceGroup::ExecuteInThread() {
+ ShellArrayBufferAllocator allocator;
Isolate::CreateParams create_params;
- create_params.array_buffer_allocator = Shell::array_buffer_allocator;
+ create_params.array_buffer_allocator = &allocator;
Isolate* isolate = Isolate::New(create_params);
do {
next_semaphore_.Wait();
@@ -1476,253 +1367,6 @@
thread_->Join();
} else {
done_semaphore_.Wait();
- }
-}
-
-
-SerializationData::~SerializationData() {
- // Any ArrayBuffer::Contents are owned by this SerializationData object.
- // SharedArrayBuffer::Contents may be used by other threads, so must be
- // cleaned up by the main thread in Shell::CleanupWorkers().
- for (int i = 0; i < array_buffer_contents.length(); ++i) {
- ArrayBuffer::Contents& contents = array_buffer_contents[i];
- Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
- }
-}
-
-
-void SerializationData::WriteTag(SerializationTag tag) { data.Add(tag); }
-
-
-void SerializationData::WriteMemory(const void* p, int length) {
- i::Vector<uint8_t> block = data.AddBlock(0, length);
- memcpy(&block[0], p, length);
-}
-
-
-void SerializationData::WriteArrayBufferContents(
- const ArrayBuffer::Contents& contents) {
- array_buffer_contents.Add(contents);
- WriteTag(kSerializationTagTransferredArrayBuffer);
- int index = array_buffer_contents.length() - 1;
- Write(index);
-}
-
-
-void SerializationData::WriteSharedArrayBufferContents(
- const SharedArrayBuffer::Contents& contents) {
- shared_array_buffer_contents.Add(contents);
- WriteTag(kSerializationTagTransferredSharedArrayBuffer);
- int index = shared_array_buffer_contents.length() - 1;
- Write(index);
-}
-
-
-SerializationTag SerializationData::ReadTag(int* offset) const {
- return static_cast<SerializationTag>(Read<uint8_t>(offset));
-}
-
-
-void SerializationData::ReadMemory(void* p, int length, int* offset) const {
- memcpy(p, &data[*offset], length);
- (*offset) += length;
-}
-
-
-void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
- int* offset) const {
- int index = Read<int>(offset);
- DCHECK(index < array_buffer_contents.length());
- *contents = array_buffer_contents[index];
-}
-
-
-void SerializationData::ReadSharedArrayBufferContents(
- SharedArrayBuffer::Contents* contents, int* offset) const {
- int index = Read<int>(offset);
- DCHECK(index < shared_array_buffer_contents.length());
- *contents = shared_array_buffer_contents[index];
-}
-
-
-void SerializationDataQueue::Enqueue(SerializationData* data) {
- base::LockGuard<base::Mutex> lock_guard(&mutex_);
- data_.Add(data);
-}
-
-
-bool SerializationDataQueue::Dequeue(SerializationData** data) {
- base::LockGuard<base::Mutex> lock_guard(&mutex_);
- if (data_.is_empty()) return false;
- *data = data_.Remove(0);
- return true;
-}
-
-
-bool SerializationDataQueue::IsEmpty() {
- base::LockGuard<base::Mutex> lock_guard(&mutex_);
- return data_.is_empty();
-}
-
-
-void SerializationDataQueue::Clear() {
- base::LockGuard<base::Mutex> lock_guard(&mutex_);
- for (int i = 0; i < data_.length(); ++i) {
- delete data_[i];
- }
- data_.Clear();
-}
-
-
-Worker::Worker()
- : in_semaphore_(0), out_semaphore_(0), thread_(NULL), script_(NULL) {}
-
-
-Worker::~Worker() { Cleanup(); }
-
-
-void Worker::StartExecuteInThread(Isolate* isolate,
- const char* function_string) {
- if (thread_) {
- Throw(isolate, "Only one worker allowed");
- return;
- }
-
- static const char format[] = "(%s).call(this);";
- size_t len = strlen(function_string) + sizeof(format);
-
- script_ = new char[len + 1];
- i::Vector<char> vec(script_, static_cast<int>(len + 1));
- i::SNPrintF(vec, format, function_string);
-
- thread_ = new WorkerThread(this);
- thread_->Start();
-}
-
-
-void Worker::PostMessage(SerializationData* data) {
- in_queue_.Enqueue(data);
- in_semaphore_.Signal();
-}
-
-
-SerializationData* Worker::GetMessage() {
- SerializationData* data;
- while (!out_queue_.Dequeue(&data)) {
- out_semaphore_.Wait();
- }
-
- return data;
-}
-
-
-void Worker::Terminate() {
- if (thread_ == NULL) return;
- PostMessage(NULL);
- thread_->Join();
- Cleanup();
-}
-
-
-void Worker::ExecuteInThread() {
- Isolate::CreateParams create_params;
- create_params.array_buffer_allocator = Shell::array_buffer_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<Object> global = context->Global();
- Handle<Value> this_value = External::New(isolate, this);
- Handle<FunctionTemplate> postmessage_fun_template =
- FunctionTemplate::New(isolate, PostMessageOut, this_value);
-
- Handle<Function> postmessage_fun;
- if (postmessage_fun_template->GetFunction(context)
- .ToLocal(&postmessage_fun)) {
- global->Set(String::NewFromUtf8(isolate, "postMessage"),
- postmessage_fun);
- }
-
- // First run the script
- Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed");
- Handle<String> source = String::NewFromUtf8(isolate, script_);
- Shell::ExecuteString(isolate, source, file_name, false, true);
-
- // Get the message handler
- Handle<Value> onmessage =
- global->Get(String::NewFromUtf8(isolate, "onmessage"));
- if (onmessage->IsFunction()) {
- Handle<Function> onmessage_fun = Handle<Function>::Cast(onmessage);
- // Now wait for messages
- bool done = false;
- while (!done) {
- in_semaphore_.Wait();
- SerializationData* data;
- if (!in_queue_.Dequeue(&data)) continue;
- if (data == NULL) {
- done = true;
- break;
- }
- int offset = 0;
- Local<Value> data_value;
- if (Shell::DeserializeValue(isolate, *data, &offset)
- .ToLocal(&data_value)) {
- Handle<Value> argv[] = {data_value};
- (void)onmessage_fun->Call(context, global, 1, argv);
- }
- delete data;
- }
- }
- }
- }
- }
- Shell::CollectGarbage(isolate);
- isolate->Dispose();
-}
-
-
-void Worker::Cleanup() {
- delete thread_;
- thread_ = NULL;
- delete[] script_;
- script_ = NULL;
- in_queue_.Clear();
- out_queue_.Clear();
-}
-
-
-void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
- Isolate* isolate = args.GetIsolate();
- HandleScope handle_scope(isolate);
-
- if (args.Length() < 1) {
- Throw(isolate, "Invalid argument");
- return;
- }
-
- Handle<Value> message = args[0];
-
- // TODO(binji): Allow transferring from worker to main thread?
- Shell::ObjectList to_transfer;
-
- Shell::ObjectList seen_objects;
- SerializationData* data = new SerializationData;
- if (Shell::SerializeValue(isolate, message, to_transfer, &seen_objects,
- data)) {
- DCHECK(args.Data()->IsExternal());
- Handle<External> this_value = Handle<External>::Cast(args.Data());
- Worker* worker = static_cast<Worker*>(this_value->Value());
- worker->out_queue_.Enqueue(data);
- worker->out_semaphore_.Signal();
- } else {
- delete data;
}
}
#endif // !V8_SHARED
@@ -1899,7 +1543,6 @@
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].WaitForThread();
}
- CleanupWorkers();
#endif // !V8_SHARED
return 0;
}
@@ -1922,242 +1565,6 @@
#ifndef V8_SHARED
-bool Shell::SerializeValue(Isolate* isolate, Handle<Value> value,
- const ObjectList& to_transfer,
- ObjectList* seen_objects,
- SerializationData* out_data) {
- DCHECK(out_data);
- HandleScope scope(isolate);
- Local<Context> context = isolate->GetCurrentContext();
-
- if (value->IsUndefined()) {
- out_data->WriteTag(kSerializationTagUndefined);
- } else if (value->IsNull()) {
- out_data->WriteTag(kSerializationTagNull);
- } else if (value->IsTrue()) {
- out_data->WriteTag(kSerializationTagTrue);
- } else if (value->IsFalse()) {
- out_data->WriteTag(kSerializationTagFalse);
- } else if (value->IsNumber()) {
- Handle<Number> num = Handle<Number>::Cast(value);
- double value = num->Value();
- out_data->WriteTag(kSerializationTagNumber);
- out_data->Write(value);
- } else if (value->IsString()) {
- v8::String::Utf8Value str(value);
- out_data->WriteTag(kSerializationTagString);
- out_data->Write(str.length());
- out_data->WriteMemory(*str, str.length());
- } else if (value->IsArray()) {
- Handle<Array> array = Handle<Array>::Cast(value);
- if (FindInObjectList(array, *seen_objects)) {
- Throw(isolate, "Duplicated arrays not supported");
- return false;
- }
- seen_objects->Add(array);
- out_data->WriteTag(kSerializationTagArray);
- uint32_t length = array->Length();
- out_data->Write(length);
- for (uint32_t i = 0; i < length; ++i) {
- Local<Value> element_value;
- if (array->Get(context, i).ToLocal(&element_value)) {
- if (!SerializeValue(isolate, element_value, to_transfer, seen_objects,
- out_data))
- return false;
- }
- }
- } else if (value->IsArrayBuffer()) {
- Handle<ArrayBuffer> array_buffer = Handle<ArrayBuffer>::Cast(value);
- if (FindInObjectList(array_buffer, *seen_objects)) {
- Throw(isolate, "Duplicated array buffers not supported");
- return false;
- }
- seen_objects->Add(array_buffer);
- if (FindInObjectList(array_buffer, to_transfer)) {
- // Transfer ArrayBuffer
- if (!array_buffer->IsNeuterable()) {
- Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
- return false;
- }
-
- ArrayBuffer::Contents contents = array_buffer->Externalize();
- array_buffer->Neuter();
- out_data->WriteArrayBufferContents(contents);
- } else {
- ArrayBuffer::Contents contents = array_buffer->GetContents();
- // Clone ArrayBuffer
- if (contents.ByteLength() > i::kMaxUInt32) {
- Throw(isolate, "ArrayBuffer is too big to clone");
- return false;
- }
-
- int byte_length = static_cast<int>(contents.ByteLength());
- out_data->WriteTag(kSerializationTagArrayBuffer);
- out_data->Write(byte_length);
- out_data->WriteMemory(contents.Data(),
- static_cast<int>(contents.ByteLength()));
- }
- } else if (value->IsSharedArrayBuffer()) {
- Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value);
- if (FindInObjectList(sab, *seen_objects)) {
- Throw(isolate, "Duplicated shared array buffers not supported");
- return false;
- }
- seen_objects->Add(sab);
- if (!FindInObjectList(sab, to_transfer)) {
- Throw(isolate, "SharedArrayBuffer must be transferred");
- return false;
- }
-
- SharedArrayBuffer::Contents contents = sab->Externalize();
- out_data->WriteSharedArrayBufferContents(contents);
- externalized_shared_contents_.Add(contents);
- } else if (value->IsObject()) {
- Handle<Object> object = Handle<Object>::Cast(value);
- if (FindInObjectList(object, *seen_objects)) {
- Throw(isolate, "Duplicated objects not supported");
- return false;
- }
- seen_objects->Add(object);
- Local<Array> property_names;
- if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
- Throw(isolate, "Unable to get property names");
- return false;
- }
-
- uint32_t length = property_names->Length();
- out_data->WriteTag(kSerializationTagObject);
- out_data->Write(length);
- for (uint32_t i = 0; i < length; ++i) {
- Handle<Value> name;
- Handle<Value> property_value;
- if (property_names->Get(context, i).ToLocal(&name) &&
- object->Get(context, name).ToLocal(&property_value)) {
- if (!SerializeValue(isolate, name, to_transfer, seen_objects, out_data))
- return false;
- if (!SerializeValue(isolate, property_value, to_transfer, seen_objects,
- out_data))
- return false;
- }
- }
- } else {
- Throw(isolate, "Don't know how to serialize object");
- return false;
- }
-
- return true;
-}
-
-
-MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate,
- const SerializationData& data,
- int* offset) {
- DCHECK(offset);
- EscapableHandleScope scope(isolate);
- // This function should not use utility_context_ because it is running on a
- // different thread.
- Local<Value> result;
- SerializationTag tag = data.ReadTag(offset);
-
- switch (tag) {
- case kSerializationTagUndefined:
- result = Undefined(isolate);
- break;
- case kSerializationTagNull:
- result = Null(isolate);
- break;
- case kSerializationTagTrue:
- result = True(isolate);
- break;
- case kSerializationTagFalse:
- result = False(isolate);
- break;
- case kSerializationTagNumber:
- result = Number::New(isolate, data.Read<double>(offset));
- break;
- case kSerializationTagString: {
- int length = data.Read<int>(offset);
- static char s_buffer[128];
- char* p = s_buffer;
- bool allocated = false;
- if (length > static_cast<int>(sizeof(s_buffer))) {
- p = new char[length];
- allocated = true;
- }
- data.ReadMemory(p, length, offset);
- MaybeLocal<String> str =
- String::NewFromUtf8(isolate, p, String::kNormalString, length);
- if (!str.IsEmpty()) result = str.ToLocalChecked();
- if (allocated) delete[] p;
- break;
- }
- case kSerializationTagArray: {
- uint32_t length = data.Read<uint32_t>(offset);
- Handle<Array> array = Array::New(isolate, length);
- for (uint32_t i = 0; i < length; ++i) {
- Local<Value> element_value;
- CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value));
- array->Set(i, element_value);
- }
- result = array;
- break;
- }
- case kSerializationTagObject: {
- int length = data.Read<int>(offset);
- Handle<Object> object = Object::New(isolate);
- for (int i = 0; i < length; ++i) {
- Local<Value> property_name;
- CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_name));
- DCHECK(property_name->IsString());
- Local<Value> property_value;
- CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_value));
- object->Set(property_name, property_value);
- }
- result = object;
- break;
- }
- case kSerializationTagArrayBuffer: {
- int byte_length = data.Read<int>(offset);
- Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
- ArrayBuffer::Contents contents = array_buffer->GetContents();
- DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
- data.ReadMemory(contents.Data(), byte_length, offset);
- result = array_buffer;
- break;
- }
- case kSerializationTagTransferredArrayBuffer: {
- ArrayBuffer::Contents contents;
- data.ReadArrayBufferContents(&contents, offset);
- result =
- ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength());
- break;
- }
- case kSerializationTagTransferredSharedArrayBuffer: {
- SharedArrayBuffer::Contents contents;
- data.ReadSharedArrayBufferContents(&contents, offset);
- result = SharedArrayBuffer::New(isolate, contents.Data(),
- contents.ByteLength());
- break;
- }
- default:
- UNREACHABLE();
- }
-
- return scope.Escape(result);
-}
-
-
-void Shell::CleanupWorkers() {
- worker_.Terminate();
- for (int i = 0; i < externalized_shared_contents_.length(); ++i) {
- const SharedArrayBuffer::Contents& contents =
- externalized_shared_contents_[i];
- Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
- }
- externalized_shared_contents_.Clear();
-}
-
-
static void DumpHeapConstants(i::Isolate* isolate) {
i::Heap* heap = isolate->heap();
@@ -2244,14 +1651,13 @@
SetFlagsFromString("--redirect-code-traces-to=code.asm");
int result = 0;
Isolate::CreateParams create_params;
- ShellArrayBufferAllocator shell_array_buffer_allocator;
+ ShellArrayBufferAllocator array_buffer_allocator;
MockArrayBufferAllocator mock_arraybuffer_allocator;
if (options.mock_arraybuffer_allocator) {
- Shell::array_buffer_allocator = &mock_arraybuffer_allocator;
+ create_params.array_buffer_allocator = &mock_arraybuffer_allocator;
} else {
- Shell::array_buffer_allocator = &shell_array_buffer_allocator;
- }
- create_params.array_buffer_allocator = Shell::array_buffer_allocator;
+ create_params.array_buffer_allocator = &array_buffer_allocator;
+ }
#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
if (i::FLAG_gdbjit) {
create_params.code_event_handler = i::GDBJITInterface::EventHandler;
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698