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

Side by Side Diff: src/d8.cc

Issue 2643723010: [d8] Use ValueSerializer for postMessage (instead of ad-hoc serializer) (Closed)
Patch Set: fix Created 3 years, 10 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
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 #include <errno.h> 5 #include <errno.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 13 matching lines...) Expand all
24 #include "include/libplatform/v8-tracing.h" 24 #include "include/libplatform/v8-tracing.h"
25 #include "src/api.h" 25 #include "src/api.h"
26 #include "src/base/cpu.h" 26 #include "src/base/cpu.h"
27 #include "src/base/debug/stack_trace.h" 27 #include "src/base/debug/stack_trace.h"
28 #include "src/base/logging.h" 28 #include "src/base/logging.h"
29 #include "src/base/platform/platform.h" 29 #include "src/base/platform/platform.h"
30 #include "src/base/platform/time.h" 30 #include "src/base/platform/time.h"
31 #include "src/base/sys-info.h" 31 #include "src/base/sys-info.h"
32 #include "src/basic-block-profiler.h" 32 #include "src/basic-block-profiler.h"
33 #include "src/interpreter/interpreter.h" 33 #include "src/interpreter/interpreter.h"
34 #include "src/list-inl.h"
34 #include "src/msan.h" 35 #include "src/msan.h"
35 #include "src/objects-inl.h" 36 #include "src/objects-inl.h"
36 #include "src/snapshot/natives.h" 37 #include "src/snapshot/natives.h"
37 #include "src/utils.h" 38 #include "src/utils.h"
38 #include "src/v8.h" 39 #include "src/v8.h"
39 40
40 #ifdef V8_INSPECTOR_ENABLED 41 #ifdef V8_INSPECTOR_ENABLED
41 #include "include/v8-inspector.h" 42 #include "include/v8-inspector.h"
42 #endif // V8_INSPECTOR_ENABLED 43 #endif // V8_INSPECTOR_ENABLED
43 44
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 212
212 v8::Platform* g_platform = NULL; 213 v8::Platform* g_platform = NULL;
213 214
214 static Local<Value> Throw(Isolate* isolate, const char* message) { 215 static Local<Value> Throw(Isolate* isolate, const char* message) {
215 return isolate->ThrowException( 216 return isolate->ThrowException(
216 String::NewFromUtf8(isolate, message, NewStringType::kNormal) 217 String::NewFromUtf8(isolate, message, NewStringType::kNormal)
217 .ToLocalChecked()); 218 .ToLocalChecked());
218 } 219 }
219 220
220 221
221 bool FindInObjectList(Local<Object> object, const Shell::ObjectList& list) {
222 for (int i = 0; i < list.length(); ++i) {
223 if (list[i]->StrictEquals(object)) {
224 return true;
225 }
226 }
227 return false;
228 }
229
230
231 Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) { 222 Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) {
232 if (object->InternalFieldCount() != 1) { 223 if (object->InternalFieldCount() != 1) {
233 Throw(isolate, "this is not a Worker"); 224 Throw(isolate, "this is not a Worker");
234 return NULL; 225 return NULL;
235 } 226 }
236 227
237 Worker* worker = 228 Worker* worker =
238 static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0)); 229 static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0));
239 if (worker == NULL) { 230 if (worker == NULL) {
240 Throw(isolate, "Worker is defunct because main thread is terminating"); 231 Throw(isolate, "Worker is defunct because main thread is terminating");
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; 394 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
404 CounterCollection Shell::local_counters_; 395 CounterCollection Shell::local_counters_;
405 CounterCollection* Shell::counters_ = &local_counters_; 396 CounterCollection* Shell::counters_ = &local_counters_;
406 base::LazyMutex Shell::context_mutex_; 397 base::LazyMutex Shell::context_mutex_;
407 const base::TimeTicks Shell::kInitialTicks = 398 const base::TimeTicks Shell::kInitialTicks =
408 base::TimeTicks::HighResolutionNow(); 399 base::TimeTicks::HighResolutionNow();
409 Global<Function> Shell::stringify_function_; 400 Global<Function> Shell::stringify_function_;
410 base::LazyMutex Shell::workers_mutex_; 401 base::LazyMutex Shell::workers_mutex_;
411 bool Shell::allow_new_workers_ = true; 402 bool Shell::allow_new_workers_ = true;
412 i::List<Worker*> Shell::workers_; 403 i::List<Worker*> Shell::workers_;
413 i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_; 404 std::unordered_set<SharedArrayBuffer::Contents,
405 Shell::SharedArrayBufferContentsHash,
406 Shell::SharedArrayBufferContentsIsEqual>
407 Shell::externalized_shared_contents_;
414 408
415 Global<Context> Shell::evaluation_context_; 409 Global<Context> Shell::evaluation_context_;
416 ArrayBuffer::Allocator* Shell::array_buffer_allocator; 410 ArrayBuffer::Allocator* Shell::array_buffer_allocator;
417 ShellOptions Shell::options; 411 ShellOptions Shell::options;
418 base::OnceType Shell::quit_once_ = V8_ONCE_INIT; 412 base::OnceType Shell::quit_once_ = V8_ONCE_INIT;
419 413
420 bool CounterMap::Match(void* key1, void* key2) { 414 bool CounterMap::Match(void* key1, void* key2) {
421 const char* name1 = reinterpret_cast<const char*>(key1); 415 const char* name1 = reinterpret_cast<const char*>(key1);
422 const char* name2 = reinterpret_cast<const char*>(key2); 416 const char* name2 = reinterpret_cast<const char*>(key2);
423 return strcmp(name1, name2) == 0; 417 return strcmp(name1, name2) == 0;
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 return; 1137 return;
1144 } 1138 }
1145 worker->StartExecuteInThread(*script); 1139 worker->StartExecuteInThread(*script);
1146 } 1140 }
1147 } 1141 }
1148 1142
1149 1143
1150 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 1144 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
1151 Isolate* isolate = args.GetIsolate(); 1145 Isolate* isolate = args.GetIsolate();
1152 HandleScope handle_scope(isolate); 1146 HandleScope handle_scope(isolate);
1153 Local<Context> context = isolate->GetCurrentContext();
1154 1147
1155 if (args.Length() < 1) { 1148 if (args.Length() < 1) {
1156 Throw(isolate, "Invalid argument"); 1149 Throw(isolate, "Invalid argument");
1157 return; 1150 return;
1158 } 1151 }
1159 1152
1160 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); 1153 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
1161 if (!worker) { 1154 if (!worker) {
1162 return; 1155 return;
1163 } 1156 }
1164 1157
1165 Local<Value> message = args[0]; 1158 Local<Value> message = args[0];
1166 ObjectList to_transfer; 1159 Local<Value> transfer =
1167 if (args.Length() >= 2) { 1160 args.Length() >= 2 ? args[1] : Local<Value>::Cast(Undefined(isolate));
1168 if (!args[1]->IsArray()) { 1161 std::unique_ptr<SerializationData> data =
1169 Throw(isolate, "Transfer list must be an Array"); 1162 Shell::SerializeValue(isolate, message, transfer);
1170 return; 1163 if (data) {
1171 } 1164 worker->PostMessage(std::move(data));
1172
1173 Local<Array> transfer = Local<Array>::Cast(args[1]);
1174 uint32_t length = transfer->Length();
1175 for (uint32_t i = 0; i < length; ++i) {
1176 Local<Value> element;
1177 if (transfer->Get(context, i).ToLocal(&element)) {
1178 if (!element->IsArrayBuffer() && !element->IsSharedArrayBuffer()) {
1179 Throw(isolate,
1180 "Transfer array elements must be an ArrayBuffer or "
1181 "SharedArrayBuffer.");
1182 break;
1183 }
1184
1185 to_transfer.Add(Local<Object>::Cast(element));
1186 }
1187 }
1188 }
1189
1190 ObjectList seen_objects;
1191 SerializationData* data = new SerializationData;
1192 if (SerializeValue(isolate, message, to_transfer, &seen_objects, data)) {
1193 worker->PostMessage(data);
1194 } else {
1195 delete data;
1196 } 1165 }
1197 } 1166 }
1198 1167
1199 1168
1200 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 1169 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
1201 Isolate* isolate = args.GetIsolate(); 1170 Isolate* isolate = args.GetIsolate();
1202 HandleScope handle_scope(isolate); 1171 HandleScope handle_scope(isolate);
1203 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); 1172 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
1204 if (!worker) { 1173 if (!worker) {
1205 return; 1174 return;
1206 } 1175 }
1207 1176
1208 SerializationData* data = worker->GetMessage(); 1177 std::unique_ptr<SerializationData> data = worker->GetMessage();
1209 if (data) { 1178 if (data) {
1210 int offset = 0; 1179 Local<Value> value;
1211 Local<Value> data_value; 1180 if (Shell::DeserializeValue(isolate, std::move(data)).ToLocal(&value)) {
1212 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) { 1181 args.GetReturnValue().Set(value);
1213 args.GetReturnValue().Set(data_value);
1214 } 1182 }
1215 delete data;
1216 } 1183 }
1217 } 1184 }
1218 1185
1219 1186
1220 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { 1187 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
1221 Isolate* isolate = args.GetIsolate(); 1188 Isolate* isolate = args.GetIsolate();
1222 HandleScope handle_scope(isolate); 1189 HandleScope handle_scope(isolate);
1223 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); 1190 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder());
1224 if (!worker) { 1191 if (!worker) {
1225 return; 1192 return;
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after
2141 if (thread_ == NULL) return; 2108 if (thread_ == NULL) return;
2142 done_semaphore_.Wait(); 2109 done_semaphore_.Wait();
2143 } 2110 }
2144 2111
2145 2112
2146 void SourceGroup::JoinThread() { 2113 void SourceGroup::JoinThread() {
2147 if (thread_ == NULL) return; 2114 if (thread_ == NULL) return;
2148 thread_->Join(); 2115 thread_->Join();
2149 } 2116 }
2150 2117
2151
2152 SerializationData::~SerializationData() { 2118 SerializationData::~SerializationData() {
2153 // Any ArrayBuffer::Contents are owned by this SerializationData object if 2119 // Any ArrayBuffer::Contents are owned by this SerializationData object if
2154 // ownership hasn't been transferred out via ReadArrayBufferContents. 2120 // ownership hasn't been transferred out.
2155 // SharedArrayBuffer::Contents may be used by multiple threads, so must be 2121 // SharedArrayBuffer::Contents may be used by multiple threads, so must be
2156 // cleaned up by the main thread in Shell::CleanupWorkers(). 2122 // cleaned up by the main thread in Shell::CleanupWorkers().
2157 for (int i = 0; i < array_buffer_contents_.length(); ++i) { 2123 for (const auto& contents : array_buffer_contents_) {
2158 ArrayBuffer::Contents& contents = array_buffer_contents_[i];
2159 if (contents.Data()) { 2124 if (contents.Data()) {
2160 Shell::array_buffer_allocator->Free(contents.Data(), 2125 Shell::array_buffer_allocator->Free(contents.Data(),
2161 contents.ByteLength()); 2126 contents.ByteLength());
2162 } 2127 }
2163 } 2128 }
2164 } 2129 }
2165 2130
2166 2131 void SerializationData::ClearTransferredArrayBuffers() {
2167 void SerializationData::WriteTag(SerializationTag tag) { data_.Add(tag); } 2132 array_buffer_contents_.clear();
2168
2169
2170 void SerializationData::WriteMemory(const void* p, int length) {
2171 if (length > 0) {
2172 i::Vector<uint8_t> block = data_.AddBlock(0, length);
2173 memcpy(&block[0], p, length);
2174 }
2175 } 2133 }
2176 2134
2177 2135 void SerializationDataQueue::Enqueue(std::unique_ptr<SerializationData> data) {
2178 void SerializationData::WriteArrayBufferContents( 2136 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2179 const ArrayBuffer::Contents& contents) { 2137 data_.push_back(std::move(data));
2180 array_buffer_contents_.Add(contents);
2181 WriteTag(kSerializationTagTransferredArrayBuffer);
2182 int index = array_buffer_contents_.length() - 1;
2183 Write(index);
2184 } 2138 }
2185 2139
2186 2140 bool SerializationDataQueue::Dequeue(
2187 void SerializationData::WriteSharedArrayBufferContents( 2141 std::unique_ptr<SerializationData>* out_data) {
2188 const SharedArrayBuffer::Contents& contents) { 2142 out_data->reset();
2189 shared_array_buffer_contents_.Add(contents);
2190 WriteTag(kSerializationTagTransferredSharedArrayBuffer);
2191 int index = shared_array_buffer_contents_.length() - 1;
2192 Write(index);
2193 }
2194
2195
2196 SerializationTag SerializationData::ReadTag(int* offset) const {
2197 return static_cast<SerializationTag>(Read<uint8_t>(offset));
2198 }
2199
2200
2201 void SerializationData::ReadMemory(void* p, int length, int* offset) const {
2202 if (length > 0) {
2203 memcpy(p, &data_[*offset], length);
2204 (*offset) += length;
2205 }
2206 }
2207
2208
2209 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
2210 int* offset) const {
2211 int index = Read<int>(offset);
2212 DCHECK(index < array_buffer_contents_.length());
2213 *contents = array_buffer_contents_[index];
2214 // Ownership of this ArrayBuffer::Contents is passed to the caller. Neuter
2215 // our copy so it won't be double-free'd when this SerializationData is
2216 // destroyed.
2217 array_buffer_contents_[index] = ArrayBuffer::Contents();
2218 }
2219
2220
2221 void SerializationData::ReadSharedArrayBufferContents(
2222 SharedArrayBuffer::Contents* contents, int* offset) const {
2223 int index = Read<int>(offset);
2224 DCHECK(index < shared_array_buffer_contents_.length());
2225 *contents = shared_array_buffer_contents_[index];
2226 }
2227
2228
2229 void SerializationDataQueue::Enqueue(SerializationData* data) {
2230 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2143 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2231 data_.Add(data); 2144 if (data_.empty()) return false;
2232 } 2145 *out_data = std::move(data_[0]);
2233 2146 data_.erase(data_.begin());
2234
2235 bool SerializationDataQueue::Dequeue(SerializationData** data) {
2236 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2237 *data = NULL;
2238 if (data_.is_empty()) return false;
2239 *data = data_.Remove(0);
2240 return true; 2147 return true;
2241 } 2148 }
2242 2149
2243 2150
2244 bool SerializationDataQueue::IsEmpty() { 2151 bool SerializationDataQueue::IsEmpty() {
2245 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2152 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2246 return data_.is_empty(); 2153 return data_.empty();
2247 } 2154 }
2248 2155
2249 2156
2250 void SerializationDataQueue::Clear() { 2157 void SerializationDataQueue::Clear() {
2251 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2158 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2252 for (int i = 0; i < data_.length(); ++i) { 2159 data_.clear();
2253 delete data_[i];
2254 }
2255 data_.Clear();
2256 } 2160 }
2257 2161
2258 2162
2259 Worker::Worker() 2163 Worker::Worker()
2260 : in_semaphore_(0), 2164 : in_semaphore_(0),
2261 out_semaphore_(0), 2165 out_semaphore_(0),
2262 thread_(NULL), 2166 thread_(NULL),
2263 script_(NULL), 2167 script_(NULL),
2264 running_(false) {} 2168 running_(false) {}
2265 2169
2266 2170
2267 Worker::~Worker() { 2171 Worker::~Worker() {
2268 delete thread_; 2172 delete thread_;
2269 thread_ = NULL; 2173 thread_ = NULL;
2270 delete[] script_; 2174 delete[] script_;
2271 script_ = NULL; 2175 script_ = NULL;
2272 in_queue_.Clear(); 2176 in_queue_.Clear();
2273 out_queue_.Clear(); 2177 out_queue_.Clear();
2274 } 2178 }
2275 2179
2276 2180
2277 void Worker::StartExecuteInThread(const char* script) { 2181 void Worker::StartExecuteInThread(const char* script) {
2278 running_ = true; 2182 running_ = true;
2279 script_ = i::StrDup(script); 2183 script_ = i::StrDup(script);
2280 thread_ = new WorkerThread(this); 2184 thread_ = new WorkerThread(this);
2281 thread_->Start(); 2185 thread_->Start();
2282 } 2186 }
2283 2187
2284 2188 void Worker::PostMessage(std::unique_ptr<SerializationData> data) {
2285 void Worker::PostMessage(SerializationData* data) { 2189 in_queue_.Enqueue(std::move(data));
2286 in_queue_.Enqueue(data);
2287 in_semaphore_.Signal(); 2190 in_semaphore_.Signal();
2288 } 2191 }
2289 2192
2290 2193 std::unique_ptr<SerializationData> Worker::GetMessage() {
2291 SerializationData* Worker::GetMessage() { 2194 std::unique_ptr<SerializationData> result;
2292 SerializationData* data = NULL; 2195 while (!out_queue_.Dequeue(&result)) {
2293 while (!out_queue_.Dequeue(&data)) {
2294 // If the worker is no longer running, and there are no messages in the 2196 // If the worker is no longer running, and there are no messages in the
2295 // queue, don't expect any more messages from it. 2197 // queue, don't expect any more messages from it.
2296 if (!base::NoBarrier_Load(&running_)) break; 2198 if (!base::NoBarrier_Load(&running_)) break;
2297 out_semaphore_.Wait(); 2199 out_semaphore_.Wait();
2298 } 2200 }
2299 return data; 2201 return result;
2300 } 2202 }
2301 2203
2302 2204
2303 void Worker::Terminate() { 2205 void Worker::Terminate() {
2304 base::NoBarrier_Store(&running_, false); 2206 base::NoBarrier_Store(&running_, false);
2305 // Post NULL to wake the Worker thread message loop, and tell it to stop 2207 // Post NULL to wake the Worker thread message loop, and tell it to stop
2306 // running. 2208 // running.
2307 PostMessage(NULL); 2209 PostMessage(NULL);
2308 } 2210 }
2309 2211
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2353 // Get the message handler 2255 // Get the message handler
2354 Local<Value> onmessage = 2256 Local<Value> onmessage =
2355 global->Get(context, String::NewFromUtf8(isolate, "onmessage", 2257 global->Get(context, String::NewFromUtf8(isolate, "onmessage",
2356 NewStringType::kNormal) 2258 NewStringType::kNormal)
2357 .ToLocalChecked()).ToLocalChecked(); 2259 .ToLocalChecked()).ToLocalChecked();
2358 if (onmessage->IsFunction()) { 2260 if (onmessage->IsFunction()) {
2359 Local<Function> onmessage_fun = Local<Function>::Cast(onmessage); 2261 Local<Function> onmessage_fun = Local<Function>::Cast(onmessage);
2360 // Now wait for messages 2262 // Now wait for messages
2361 while (true) { 2263 while (true) {
2362 in_semaphore_.Wait(); 2264 in_semaphore_.Wait();
2363 SerializationData* data; 2265 std::unique_ptr<SerializationData> data;
2364 if (!in_queue_.Dequeue(&data)) continue; 2266 if (!in_queue_.Dequeue(&data)) continue;
2365 if (data == NULL) { 2267 if (!data) {
2366 break; 2268 break;
2367 } 2269 }
2368 int offset = 0; 2270 v8::TryCatch try_catch(isolate);
2369 Local<Value> data_value; 2271 Local<Value> value;
2370 if (Shell::DeserializeValue(isolate, *data, &offset) 2272 if (Shell::DeserializeValue(isolate, std::move(data))
2371 .ToLocal(&data_value)) { 2273 .ToLocal(&value)) {
2372 Local<Value> argv[] = {data_value}; 2274 Local<Value> argv[] = {value};
2373 (void)onmessage_fun->Call(context, global, 1, argv); 2275 (void)onmessage_fun->Call(context, global, 1, argv);
2374 } 2276 }
2375 delete data; 2277 if (try_catch.HasCaught()) {
2278 Shell::ReportException(isolate, &try_catch);
2279 }
2376 } 2280 }
2377 } 2281 }
2378 } 2282 }
2379 } 2283 }
2380 DisposeModuleEmbedderData(context); 2284 DisposeModuleEmbedderData(context);
2381 } 2285 }
2382 Shell::CollectGarbage(isolate); 2286 Shell::CollectGarbage(isolate);
2383 } 2287 }
2384 isolate->Dispose(); 2288 isolate->Dispose();
2385 2289
2386 // Post NULL to wake the thread waiting on GetMessage() if there is one. 2290 // Post NULL to wake the thread waiting on GetMessage() if there is one.
2387 out_queue_.Enqueue(NULL); 2291 out_queue_.Enqueue(NULL);
2388 out_semaphore_.Signal(); 2292 out_semaphore_.Signal();
2389 } 2293 }
2390 2294
2391 2295
2392 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) { 2296 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
2393 Isolate* isolate = args.GetIsolate(); 2297 Isolate* isolate = args.GetIsolate();
2394 HandleScope handle_scope(isolate); 2298 HandleScope handle_scope(isolate);
2395 2299
2396 if (args.Length() < 1) { 2300 if (args.Length() < 1) {
2397 Throw(isolate, "Invalid argument"); 2301 Throw(isolate, "Invalid argument");
2398 return; 2302 return;
2399 } 2303 }
2400 2304
2401 Local<Value> message = args[0]; 2305 Local<Value> message = args[0];
2402 2306 Local<Value> transfer = Undefined(isolate);
2403 // TODO(binji): Allow transferring from worker to main thread? 2307 std::unique_ptr<SerializationData> data =
2404 Shell::ObjectList to_transfer; 2308 Shell::SerializeValue(isolate, message, transfer);
2405 2309 if (data) {
2406 Shell::ObjectList seen_objects;
2407 SerializationData* data = new SerializationData;
2408 if (Shell::SerializeValue(isolate, message, to_transfer, &seen_objects,
2409 data)) {
2410 DCHECK(args.Data()->IsExternal()); 2310 DCHECK(args.Data()->IsExternal());
2411 Local<External> this_value = Local<External>::Cast(args.Data()); 2311 Local<External> this_value = Local<External>::Cast(args.Data());
2412 Worker* worker = static_cast<Worker*>(this_value->Value()); 2312 Worker* worker = static_cast<Worker*>(this_value->Value());
2413 worker->out_queue_.Enqueue(data); 2313 worker->out_queue_.Enqueue(std::move(data));
2414 worker->out_semaphore_.Signal(); 2314 worker->out_semaphore_.Signal();
2415 } else {
2416 delete data;
2417 } 2315 }
2418 } 2316 }
2419 2317
2420 2318
2421 void SetFlagsFromString(const char* flags) { 2319 void SetFlagsFromString(const char* flags) {
2422 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); 2320 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
2423 } 2321 }
2424 2322
2425 2323
2426 bool Shell::SetOptions(int argc, char* argv[]) { 2324 bool Shell::SetOptions(int argc, char* argv[]) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
2597 2495
2598 2496
2599 void Shell::EmptyMessageQueues(Isolate* isolate) { 2497 void Shell::EmptyMessageQueues(Isolate* isolate) {
2600 if (!i::FLAG_verify_predictable) { 2498 if (!i::FLAG_verify_predictable) {
2601 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; 2499 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue;
2602 v8::platform::RunIdleTasks(g_platform, isolate, 2500 v8::platform::RunIdleTasks(g_platform, isolate,
2603 50.0 / base::Time::kMillisecondsPerSecond); 2501 50.0 / base::Time::kMillisecondsPerSecond);
2604 } 2502 }
2605 } 2503 }
2606 2504
2607 2505 class Serializer : public ValueSerializer::Delegate {
2608 bool Shell::SerializeValue(Isolate* isolate, Local<Value> value, 2506 public:
2609 const ObjectList& to_transfer, 2507 explicit Serializer(Isolate* isolate)
2610 ObjectList* seen_objects, 2508 : isolate_(isolate), serializer_(isolate, this) {}
2611 SerializationData* out_data) { 2509
2612 DCHECK(out_data); 2510 Maybe<bool> WriteValue(Local<Context> context, Local<Value> value,
2511 Local<Value> transfer) {
2512 bool ok;
2513 DCHECK(!data_);
2514 data_.reset(new SerializationData);
2515 if (!PrepareTransfer(context, transfer).To(&ok)) {
2516 return Nothing<bool>();
2517 }
2518 serializer_.WriteHeader();
2519
2520 if (!serializer_.WriteValue(context, value).To(&ok)) {
2521 data_.reset();
2522 return Nothing<bool>();
2523 }
2524
2525 if (!FinalizeTransfer().To(&ok)) {
2526 return Nothing<bool>();
2527 }
2528
2529 std::pair<uint8_t*, size_t> pair = serializer_.Release();
2530 data_->data_.reset(pair.first);
2531 data_->size_ = pair.second;
2532 return Just(true);
2533 }
2534
2535 std::unique_ptr<SerializationData> Release() { return std::move(data_); }
2536
2537 protected:
2538 // Implements ValueSerializer::Delegate.
2539 void ThrowDataCloneError(Local<String> message) override {
2540 isolate_->ThrowException(Exception::Error(message));
2541 }
2542
2543 Maybe<uint32_t> GetSharedArrayBufferId(
2544 Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) override {
2545 DCHECK(data_ != nullptr);
2546 for (size_t index = 0; index < shared_array_buffers_.size(); ++index) {
2547 if (shared_array_buffers_[index] == shared_array_buffer) {
2548 return Just<uint32_t>(static_cast<uint32_t>(index));
2549 }
2550 }
2551
2552 size_t index = shared_array_buffers_.size();
2553 shared_array_buffers_.emplace_back(isolate_, shared_array_buffer);
2554 return Just<uint32_t>(static_cast<uint32_t>(index));
2555 }
2556
2557 void* ReallocateBufferMemory(void* old_buffer, size_t size,
2558 size_t* actual_size) override {
2559 void* result = realloc(old_buffer, size);
2560 *actual_size = result ? size : 0;
2561 return result;
2562 }
2563
2564 void FreeBufferMemory(void* buffer) override { free(buffer); }
2565
2566 private:
2567 Maybe<bool> PrepareTransfer(Local<Context> context, Local<Value> transfer) {
2568 if (transfer->IsArray()) {
2569 Local<Array> transfer_array = Local<Array>::Cast(transfer);
2570 uint32_t length = transfer_array->Length();
2571 for (uint32_t i = 0; i < length; ++i) {
2572 Local<Value> element;
2573 if (transfer_array->Get(context, i).ToLocal(&element)) {
2574 if (!element->IsArrayBuffer()) {
2575 Throw(isolate_, "Transfer array elements must be an ArrayBuffer");
2576 break;
2577 }
2578
2579 Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(element);
2580 serializer_.TransferArrayBuffer(
2581 static_cast<uint32_t>(array_buffers_.size()), array_buffer);
2582 array_buffers_.emplace_back(isolate_, array_buffer);
2583 } else {
2584 return Nothing<bool>();
2585 }
2586 }
2587 return Just(true);
2588 } else if (transfer->IsUndefined()) {
2589 return Just(true);
2590 } else {
2591 Throw(isolate_, "Transfer list must be an Array or undefined");
2592 return Nothing<bool>();
2593 }
2594 }
2595
2596 Maybe<bool> FinalizeTransfer() {
2597 for (const auto& global_array_buffer : array_buffers_) {
2598 Local<ArrayBuffer> array_buffer =
2599 Local<ArrayBuffer>::New(isolate_, global_array_buffer);
2600 if (!array_buffer->IsNeuterable()) {
2601 Throw(isolate_, "ArrayBuffer could not be transferred");
2602 return Nothing<bool>();
2603 }
2604
2605 if (!array_buffer->IsExternal()) {
2606 array_buffer->Externalize();
2607 }
2608 ArrayBuffer::Contents contents = array_buffer->GetContents();
2609 array_buffer->Neuter();
2610 data_->array_buffer_contents_.push_back(contents);
2611 }
2612
2613 for (const auto& global_shared_array_buffer : shared_array_buffers_) {
2614 Local<SharedArrayBuffer> shared_array_buffer =
2615 Local<SharedArrayBuffer>::New(isolate_, global_shared_array_buffer);
2616 if (!shared_array_buffer->IsExternal()) {
2617 shared_array_buffer->Externalize();
2618 }
2619 data_->shared_array_buffer_contents_.push_back(
2620 shared_array_buffer->GetContents());
2621 }
2622
2623 return Just(true);
2624 }
2625
2626 Isolate* isolate_;
2627 ValueSerializer serializer_;
2628 std::unique_ptr<SerializationData> data_;
2629 std::vector<Global<ArrayBuffer>> array_buffers_;
2630 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_;
2631
2632 DISALLOW_COPY_AND_ASSIGN(Serializer);
2633 };
2634
2635 class Deserializer : public ValueDeserializer::Delegate {
2636 public:
2637 Deserializer(Isolate* isolate, std::unique_ptr<SerializationData> data)
2638 : isolate_(isolate),
2639 deserializer_(isolate, data->data(), data->size(), this),
2640 data_(std::move(data)) {
2641 deserializer_.SetSupportsLegacyWireFormat(true);
2642 }
2643
2644 MaybeLocal<Value> ReadValue(Local<Context> context) {
2645 bool read_header;
2646 if (!deserializer_.ReadHeader(context).To(&read_header)) {
2647 return MaybeLocal<Value>();
2648 }
2649
2650 uint32_t index = 0;
2651 for (const auto& contents : data_->array_buffer_contents()) {
2652 Local<ArrayBuffer> array_buffer =
2653 ArrayBuffer::New(isolate_, contents.Data(), contents.ByteLength());
2654 deserializer_.TransferArrayBuffer(index++, array_buffer);
2655 }
2656
2657 index = 0;
2658 for (const auto& contents : data_->shared_array_buffer_contents()) {
2659 Local<SharedArrayBuffer> shared_array_buffer = SharedArrayBuffer::New(
2660 isolate_, contents.Data(), contents.ByteLength());
2661 deserializer_.TransferSharedArrayBuffer(index++, shared_array_buffer);
2662 }
2663
2664 MaybeLocal<Value> result = deserializer_.ReadValue(context);
2665 if (!result.IsEmpty()) {
2666 data_->ClearTransferredArrayBuffers();
2667 }
2668 return result;
2669 }
2670
2671 private:
2672 Isolate* isolate_;
2673 ValueDeserializer deserializer_;
2674 std::unique_ptr<SerializationData> data_;
2675
2676 DISALLOW_COPY_AND_ASSIGN(Deserializer);
2677 };
2678
2679 std::unique_ptr<SerializationData> Shell::SerializeValue(
2680 Isolate* isolate, Local<Value> value, Local<Value> transfer) {
2681 bool ok;
2613 Local<Context> context = isolate->GetCurrentContext(); 2682 Local<Context> context = isolate->GetCurrentContext();
2614 2683 Serializer serializer(isolate);
2615 if (value->IsUndefined()) { 2684 if (serializer.WriteValue(context, value, transfer).To(&ok)) {
2616 out_data->WriteTag(kSerializationTagUndefined); 2685 std::unique_ptr<SerializationData> data = serializer.Release();
2617 } else if (value->IsNull()) { 2686 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2618 out_data->WriteTag(kSerializationTagNull); 2687 for (const auto& contents : data->shared_array_buffer_contents()) {
2619 } else if (value->IsTrue()) { 2688 externalized_shared_contents_.insert(contents);
2620 out_data->WriteTag(kSerializationTagTrue); 2689 }
2621 } else if (value->IsFalse()) { 2690 return data;
2622 out_data->WriteTag(kSerializationTagFalse); 2691 }
2623 } else if (value->IsNumber()) { 2692 return std::unique_ptr<SerializationData>();
jbroman 2017/01/26 21:53:03 nit: Dunno about v8, but in Chromium/Blink I'd pre
binji 2017/01/27 19:33:21 Done.
2624 Local<Number> num = Local<Number>::Cast(value);
2625 double value = num->Value();
2626 out_data->WriteTag(kSerializationTagNumber);
2627 out_data->Write(value);
2628 } else if (value->IsString()) {
2629 v8::String::Utf8Value str(value);
2630 out_data->WriteTag(kSerializationTagString);
2631 out_data->Write(str.length());
2632 out_data->WriteMemory(*str, str.length());
2633 } else if (value->IsArray()) {
2634 Local<Array> array = Local<Array>::Cast(value);
2635 if (FindInObjectList(array, *seen_objects)) {
2636 Throw(isolate, "Duplicated arrays not supported");
2637 return false;
2638 }
2639 seen_objects->Add(array);
2640 out_data->WriteTag(kSerializationTagArray);
2641 uint32_t length = array->Length();
2642 out_data->Write(length);
2643 for (uint32_t i = 0; i < length; ++i) {
2644 Local<Value> element_value;
2645 if (array->Get(context, i).ToLocal(&element_value)) {
2646 if (!SerializeValue(isolate, element_value, to_transfer, seen_objects,
2647 out_data))
2648 return false;
2649 } else {
2650 Throw(isolate, "Failed to serialize array element.");
2651 return false;
2652 }
2653 }
2654 } else if (value->IsArrayBuffer()) {
2655 Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(value);
2656 if (FindInObjectList(array_buffer, *seen_objects)) {
2657 Throw(isolate, "Duplicated array buffers not supported");
2658 return false;
2659 }
2660 seen_objects->Add(array_buffer);
2661 if (FindInObjectList(array_buffer, to_transfer)) {
2662 // Transfer ArrayBuffer
2663 if (!array_buffer->IsNeuterable()) {
2664 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
2665 return false;
2666 }
2667
2668 ArrayBuffer::Contents contents = array_buffer->IsExternal()
2669 ? array_buffer->GetContents()
2670 : array_buffer->Externalize();
2671 array_buffer->Neuter();
2672 out_data->WriteArrayBufferContents(contents);
2673 } else {
2674 ArrayBuffer::Contents contents = array_buffer->GetContents();
2675 // Clone ArrayBuffer
2676 if (contents.ByteLength() > i::kMaxInt) {
2677 Throw(isolate, "ArrayBuffer is too big to clone");
2678 return false;
2679 }
2680
2681 int32_t byte_length = static_cast<int32_t>(contents.ByteLength());
2682 out_data->WriteTag(kSerializationTagArrayBuffer);
2683 out_data->Write(byte_length);
2684 out_data->WriteMemory(contents.Data(), byte_length);
2685 }
2686 } else if (value->IsSharedArrayBuffer()) {
2687 Local<SharedArrayBuffer> sab = Local<SharedArrayBuffer>::Cast(value);
2688 if (FindInObjectList(sab, *seen_objects)) {
2689 Throw(isolate, "Duplicated shared array buffers not supported");
2690 return false;
2691 }
2692 seen_objects->Add(sab);
2693 if (!FindInObjectList(sab, to_transfer)) {
2694 Throw(isolate, "SharedArrayBuffer must be transferred");
2695 return false;
2696 }
2697
2698 SharedArrayBuffer::Contents contents;
2699 if (sab->IsExternal()) {
2700 contents = sab->GetContents();
2701 } else {
2702 contents = sab->Externalize();
2703 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2704 externalized_shared_contents_.Add(contents);
2705 }
2706 out_data->WriteSharedArrayBufferContents(contents);
2707 } else if (value->IsObject()) {
2708 Local<Object> object = Local<Object>::Cast(value);
2709 if (FindInObjectList(object, *seen_objects)) {
2710 Throw(isolate, "Duplicated objects not supported");
2711 return false;
2712 }
2713 seen_objects->Add(object);
2714 Local<Array> property_names;
2715 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
2716 Throw(isolate, "Unable to get property names");
2717 return false;
2718 }
2719
2720 uint32_t length = property_names->Length();
2721 out_data->WriteTag(kSerializationTagObject);
2722 out_data->Write(length);
2723 for (uint32_t i = 0; i < length; ++i) {
2724 Local<Value> name;
2725 Local<Value> property_value;
2726 if (property_names->Get(context, i).ToLocal(&name) &&
2727 object->Get(context, name).ToLocal(&property_value)) {
2728 if (!SerializeValue(isolate, name, to_transfer, seen_objects, out_data))
2729 return false;
2730 if (!SerializeValue(isolate, property_value, to_transfer, seen_objects,
2731 out_data))
2732 return false;
2733 } else {
2734 Throw(isolate, "Failed to serialize property.");
2735 return false;
2736 }
2737 }
2738 } else {
2739 Throw(isolate, "Don't know how to serialize object");
2740 return false;
2741 }
2742
2743 return true;
2744 } 2693 }
2745 2694
2746 2695 MaybeLocal<Value> Shell::DeserializeValue(
2747 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, 2696 Isolate* isolate, std::unique_ptr<SerializationData> data) {
2748 const SerializationData& data, 2697 Local<Value> value;
2749 int* offset) { 2698 Local<Context> context = isolate->GetCurrentContext();
2750 DCHECK(offset); 2699 Deserializer deserializer(isolate, std::move(data));
2751 EscapableHandleScope scope(isolate); 2700 return deserializer.ReadValue(context);
2752 Local<Value> result;
2753 SerializationTag tag = data.ReadTag(offset);
2754
2755 switch (tag) {
2756 case kSerializationTagUndefined:
2757 result = Undefined(isolate);
2758 break;
2759 case kSerializationTagNull:
2760 result = Null(isolate);
2761 break;
2762 case kSerializationTagTrue:
2763 result = True(isolate);
2764 break;
2765 case kSerializationTagFalse:
2766 result = False(isolate);
2767 break;
2768 case kSerializationTagNumber:
2769 result = Number::New(isolate, data.Read<double>(offset));
2770 break;
2771 case kSerializationTagString: {
2772 int length = data.Read<int>(offset);
2773 CHECK(length >= 0);
2774 std::vector<char> buffer(length + 1); // + 1 so it is never empty.
2775 data.ReadMemory(&buffer[0], length, offset);
2776 MaybeLocal<String> str =
2777 String::NewFromUtf8(isolate, &buffer[0], NewStringType::kNormal,
2778 length).ToLocalChecked();
2779 if (!str.IsEmpty()) result = str.ToLocalChecked();
2780 break;
2781 }
2782 case kSerializationTagArray: {
2783 uint32_t length = data.Read<uint32_t>(offset);
2784 Local<Array> array = Array::New(isolate, length);
2785 for (uint32_t i = 0; i < length; ++i) {
2786 Local<Value> element_value;
2787 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value));
2788 array->Set(isolate->GetCurrentContext(), i, element_value).FromJust();
2789 }
2790 result = array;
2791 break;
2792 }
2793 case kSerializationTagObject: {
2794 int length = data.Read<int>(offset);
2795 Local<Object> object = Object::New(isolate);
2796 for (int i = 0; i < length; ++i) {
2797 Local<Value> property_name;
2798 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_name));
2799 Local<Value> property_value;
2800 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_value));
2801 object->Set(isolate->GetCurrentContext(), property_name, property_value)
2802 .FromJust();
2803 }
2804 result = object;
2805 break;
2806 }
2807 case kSerializationTagArrayBuffer: {
2808 int32_t byte_length = data.Read<int32_t>(offset);
2809 Local<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
2810 ArrayBuffer::Contents contents = array_buffer->GetContents();
2811 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
2812 data.ReadMemory(contents.Data(), byte_length, offset);
2813 result = array_buffer;
2814 break;
2815 }
2816 case kSerializationTagTransferredArrayBuffer: {
2817 ArrayBuffer::Contents contents;
2818 data.ReadArrayBufferContents(&contents, offset);
2819 result = ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength(),
2820 ArrayBufferCreationMode::kInternalized);
2821 break;
2822 }
2823 case kSerializationTagTransferredSharedArrayBuffer: {
2824 SharedArrayBuffer::Contents contents;
2825 data.ReadSharedArrayBufferContents(&contents, offset);
2826 result = SharedArrayBuffer::New(isolate, contents.Data(),
2827 contents.ByteLength());
2828 break;
2829 }
2830 default:
2831 UNREACHABLE();
2832 }
2833
2834 return scope.Escape(result);
2835 } 2701 }
2836 2702
2837 2703
2838 void Shell::CleanupWorkers() { 2704 void Shell::CleanupWorkers() {
2839 // Make a copy of workers_, because we don't want to call Worker::Terminate 2705 // Make a copy of workers_, because we don't want to call Worker::Terminate
2840 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to 2706 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to
2841 // create a new Worker, it would deadlock. 2707 // create a new Worker, it would deadlock.
2842 i::List<Worker*> workers_copy; 2708 i::List<Worker*> workers_copy;
2843 { 2709 {
2844 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 2710 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2845 allow_new_workers_ = false; 2711 allow_new_workers_ = false;
2846 workers_copy.AddAll(workers_); 2712 workers_copy.AddAll(workers_);
2847 workers_.Clear(); 2713 workers_.Clear();
2848 } 2714 }
2849 2715
2850 for (int i = 0; i < workers_copy.length(); ++i) { 2716 for (int i = 0; i < workers_copy.length(); ++i) {
2851 Worker* worker = workers_copy[i]; 2717 Worker* worker = workers_copy[i];
2852 worker->WaitForThread(); 2718 worker->WaitForThread();
2853 delete worker; 2719 delete worker;
2854 } 2720 }
2855 2721
2856 // Now that all workers are terminated, we can re-enable Worker creation. 2722 // Now that all workers are terminated, we can re-enable Worker creation.
2857 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 2723 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2858 allow_new_workers_ = true; 2724 allow_new_workers_ = true;
2859 2725
2860 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { 2726 for (const auto& contents : externalized_shared_contents_) {
2861 const SharedArrayBuffer::Contents& contents =
2862 externalized_shared_contents_[i];
2863 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); 2727 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
2864 } 2728 }
2865 externalized_shared_contents_.Clear(); 2729 externalized_shared_contents_.clear();
2866 } 2730 }
2867 2731
2868 2732
2869 static void DumpHeapConstants(i::Isolate* isolate) { 2733 static void DumpHeapConstants(i::Isolate* isolate) {
2870 i::Heap* heap = isolate->heap(); 2734 i::Heap* heap = isolate->heap();
2871 2735
2872 // Dump the INSTANCE_TYPES table to the console. 2736 // Dump the INSTANCE_TYPES table to the console.
2873 printf("# List of known V8 instance types.\n"); 2737 printf("# List of known V8 instance types.\n");
2874 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); 2738 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
2875 printf("INSTANCE_TYPES = {\n"); 2739 printf("INSTANCE_TYPES = {\n");
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
3083 } 2947 }
3084 2948
3085 } // namespace v8 2949 } // namespace v8
3086 2950
3087 2951
3088 #ifndef GOOGLE3 2952 #ifndef GOOGLE3
3089 int main(int argc, char* argv[]) { 2953 int main(int argc, char* argv[]) {
3090 return v8::Shell::Main(argc, argv); 2954 return v8::Shell::Main(argc, argv);
3091 } 2955 }
3092 #endif 2956 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698