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

Side by Side Diff: src/d8.cc

Issue 2643723010: [d8] Use ValueSerializer for postMessage (instead of ad-hoc serializer) (Closed)
Patch Set: forgot hash_combine 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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
2599 2497
2600 2498
2601 void Shell::EmptyMessageQueues(Isolate* isolate) { 2499 void Shell::EmptyMessageQueues(Isolate* isolate) {
2602 if (!i::FLAG_verify_predictable) { 2500 if (!i::FLAG_verify_predictable) {
2603 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; 2501 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue;
2604 v8::platform::RunIdleTasks(g_platform, isolate, 2502 v8::platform::RunIdleTasks(g_platform, isolate,
2605 50.0 / base::Time::kMillisecondsPerSecond); 2503 50.0 / base::Time::kMillisecondsPerSecond);
2606 } 2504 }
2607 } 2505 }
2608 2506
2609 2507 class Serializer : public ValueSerializer::Delegate {
2610 bool Shell::SerializeValue(Isolate* isolate, Local<Value> value, 2508 public:
2611 const ObjectList& to_transfer, 2509 explicit Serializer(Isolate* isolate)
2612 ObjectList* seen_objects, 2510 : isolate_(isolate), serializer_(isolate, this) {}
2613 SerializationData* out_data) { 2511
2614 DCHECK(out_data); 2512 Maybe<bool> WriteValue(Local<Context> context, Local<Value> value,
2513 Local<Value> transfer) {
2514 bool ok;
2515 DCHECK(!data_);
2516 data_.reset(new SerializationData);
2517 if (!PrepareTransfer(context, transfer).To(&ok)) {
2518 return Nothing<bool>();
2519 }
2520 serializer_.WriteHeader();
2521
2522 if (!serializer_.WriteValue(context, value).To(&ok)) {
2523 data_.reset();
2524 return Nothing<bool>();
2525 }
2526
2527 if (!FinalizeTransfer().To(&ok)) {
2528 return Nothing<bool>();
2529 }
2530
2531 std::pair<uint8_t*, size_t> pair = serializer_.Release();
2532 data_->data_.reset(pair.first);
2533 data_->size_ = pair.second;
2534 return Just(true);
2535 }
2536
2537 std::unique_ptr<SerializationData> Release() { return std::move(data_); }
2538
2539 protected:
2540 // Implements ValueSerializer::Delegate.
2541 void ThrowDataCloneError(Local<String> message) override {
2542 isolate_->ThrowException(Exception::Error(message));
2543 }
2544
2545 Maybe<uint32_t> GetSharedArrayBufferId(
2546 Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) override {
2547 DCHECK(data_ != nullptr);
2548 for (size_t index = 0; index < shared_array_buffers_.size(); ++index) {
2549 if (shared_array_buffers_[index] == shared_array_buffer) {
2550 return Just<uint32_t>(static_cast<uint32_t>(index));
2551 }
2552 }
2553
2554 size_t index = shared_array_buffers_.size();
2555 shared_array_buffers_.emplace_back(isolate_, shared_array_buffer);
2556 return Just<uint32_t>(static_cast<uint32_t>(index));
2557 }
2558
2559 void* ReallocateBufferMemory(void* old_buffer, size_t size,
2560 size_t* actual_size) override {
2561 void* result = realloc(old_buffer, size);
2562 *actual_size = result ? size : 0;
2563 return result;
2564 }
2565
2566 void FreeBufferMemory(void* buffer) override { free(buffer); }
2567
2568 private:
2569 Maybe<bool> PrepareTransfer(Local<Context> context, Local<Value> transfer) {
2570 if (transfer->IsArray()) {
2571 Local<Array> transfer_array = Local<Array>::Cast(transfer);
2572 uint32_t length = transfer_array->Length();
2573 for (uint32_t i = 0; i < length; ++i) {
2574 Local<Value> element;
2575 if (transfer_array->Get(context, i).ToLocal(&element)) {
2576 if (!element->IsArrayBuffer()) {
2577 Throw(isolate_, "Transfer array elements must be an ArrayBuffer");
2578 break;
2579 }
2580
2581 Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(element);
2582 serializer_.TransferArrayBuffer(
2583 static_cast<uint32_t>(array_buffers_.size()), array_buffer);
2584 array_buffers_.emplace_back(isolate_, array_buffer);
2585 } else {
2586 return Nothing<bool>();
2587 }
2588 }
2589 return Just(true);
2590 } else if (transfer->IsUndefined()) {
2591 return Just(true);
2592 } else {
2593 Throw(isolate_, "Transfer list must be an Array or undefined");
2594 return Nothing<bool>();
2595 }
2596 }
2597
2598 Maybe<bool> FinalizeTransfer() {
2599 for (const auto& global_array_buffer : array_buffers_) {
2600 Local<ArrayBuffer> array_buffer =
2601 Local<ArrayBuffer>::New(isolate_, global_array_buffer);
2602 if (!array_buffer->IsNeuterable()) {
2603 Throw(isolate_, "ArrayBuffer could not be transferred");
2604 return Nothing<bool>();
2605 }
2606
2607 if (!array_buffer->IsExternal()) {
2608 array_buffer->Externalize();
2609 }
2610 ArrayBuffer::Contents contents = array_buffer->GetContents();
2611 array_buffer->Neuter();
2612 data_->array_buffer_contents_.push_back(contents);
2613 }
2614
2615 for (const auto& global_shared_array_buffer : shared_array_buffers_) {
2616 Local<SharedArrayBuffer> shared_array_buffer =
2617 Local<SharedArrayBuffer>::New(isolate_, global_shared_array_buffer);
2618 if (!shared_array_buffer->IsExternal()) {
2619 shared_array_buffer->Externalize();
2620 }
2621 data_->shared_array_buffer_contents_.push_back(
2622 shared_array_buffer->GetContents());
2623 }
2624
2625 return Just(true);
2626 }
2627
2628 Isolate* isolate_;
2629 ValueSerializer serializer_;
2630 std::unique_ptr<SerializationData> data_;
2631 std::vector<Global<ArrayBuffer>> array_buffers_;
2632 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_;
2633
2634 DISALLOW_COPY_AND_ASSIGN(Serializer);
2635 };
2636
2637 class Deserializer : public ValueDeserializer::Delegate {
2638 public:
2639 Deserializer(Isolate* isolate, std::unique_ptr<SerializationData> data)
2640 : isolate_(isolate),
2641 deserializer_(isolate, data->data(), data->size(), this),
2642 data_(std::move(data)) {
2643 deserializer_.SetSupportsLegacyWireFormat(true);
2644 }
2645
2646 MaybeLocal<Value> ReadValue(Local<Context> context) {
2647 bool read_header;
2648 if (!deserializer_.ReadHeader(context).To(&read_header)) {
2649 return MaybeLocal<Value>();
2650 }
2651
2652 uint32_t index = 0;
2653 for (const auto& contents : data_->array_buffer_contents()) {
2654 Local<ArrayBuffer> array_buffer =
2655 ArrayBuffer::New(isolate_, contents.Data(), contents.ByteLength());
2656 deserializer_.TransferArrayBuffer(index++, array_buffer);
2657 }
2658
2659 index = 0;
2660 for (const auto& contents : data_->shared_array_buffer_contents()) {
2661 Local<SharedArrayBuffer> shared_array_buffer = SharedArrayBuffer::New(
2662 isolate_, contents.Data(), contents.ByteLength());
2663 deserializer_.TransferSharedArrayBuffer(index++, shared_array_buffer);
2664 }
2665
2666 MaybeLocal<Value> result = deserializer_.ReadValue(context);
2667 if (!result.IsEmpty()) {
2668 data_->ClearTransferredArrayBuffers();
2669 }
2670 return result;
2671 }
2672
2673 private:
2674 Isolate* isolate_;
2675 ValueDeserializer deserializer_;
2676 std::unique_ptr<SerializationData> data_;
2677
2678 DISALLOW_COPY_AND_ASSIGN(Deserializer);
2679 };
2680
2681 std::unique_ptr<SerializationData> Shell::SerializeValue(
2682 Isolate* isolate, Local<Value> value, Local<Value> transfer) {
2683 bool ok;
2615 Local<Context> context = isolate->GetCurrentContext(); 2684 Local<Context> context = isolate->GetCurrentContext();
2616 2685 Serializer serializer(isolate);
2617 if (value->IsUndefined()) { 2686 if (serializer.WriteValue(context, value, transfer).To(&ok)) {
2618 out_data->WriteTag(kSerializationTagUndefined); 2687 std::unique_ptr<SerializationData> data = serializer.Release();
2619 } else if (value->IsNull()) { 2688 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2620 out_data->WriteTag(kSerializationTagNull); 2689 for (const auto& contents : data->shared_array_buffer_contents()) {
2621 } else if (value->IsTrue()) { 2690 externalized_shared_contents_.insert(contents);
2622 out_data->WriteTag(kSerializationTagTrue); 2691 }
2623 } else if (value->IsFalse()) { 2692 return data;
2624 out_data->WriteTag(kSerializationTagFalse); 2693 }
2625 } else if (value->IsNumber()) { 2694 return nullptr;
2626 Local<Number> num = Local<Number>::Cast(value);
2627 double value = num->Value();
2628 out_data->WriteTag(kSerializationTagNumber);
2629 out_data->Write(value);
2630 } else if (value->IsString()) {
2631 v8::String::Utf8Value str(value);
2632 out_data->WriteTag(kSerializationTagString);
2633 out_data->Write(str.length());
2634 out_data->WriteMemory(*str, str.length());
2635 } else if (value->IsArray()) {
2636 Local<Array> array = Local<Array>::Cast(value);
2637 if (FindInObjectList(array, *seen_objects)) {
2638 Throw(isolate, "Duplicated arrays not supported");
2639 return false;
2640 }
2641 seen_objects->Add(array);
2642 out_data->WriteTag(kSerializationTagArray);
2643 uint32_t length = array->Length();
2644 out_data->Write(length);
2645 for (uint32_t i = 0; i < length; ++i) {
2646 Local<Value> element_value;
2647 if (array->Get(context, i).ToLocal(&element_value)) {
2648 if (!SerializeValue(isolate, element_value, to_transfer, seen_objects,
2649 out_data))
2650 return false;
2651 } else {
2652 Throw(isolate, "Failed to serialize array element.");
2653 return false;
2654 }
2655 }
2656 } else if (value->IsArrayBuffer()) {
2657 Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(value);
2658 if (FindInObjectList(array_buffer, *seen_objects)) {
2659 Throw(isolate, "Duplicated array buffers not supported");
2660 return false;
2661 }
2662 seen_objects->Add(array_buffer);
2663 if (FindInObjectList(array_buffer, to_transfer)) {
2664 // Transfer ArrayBuffer
2665 if (!array_buffer->IsNeuterable()) {
2666 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
2667 return false;
2668 }
2669
2670 ArrayBuffer::Contents contents = array_buffer->IsExternal()
2671 ? array_buffer->GetContents()
2672 : array_buffer->Externalize();
2673 array_buffer->Neuter();
2674 out_data->WriteArrayBufferContents(contents);
2675 } else {
2676 ArrayBuffer::Contents contents = array_buffer->GetContents();
2677 // Clone ArrayBuffer
2678 if (contents.ByteLength() > i::kMaxInt) {
2679 Throw(isolate, "ArrayBuffer is too big to clone");
2680 return false;
2681 }
2682
2683 int32_t byte_length = static_cast<int32_t>(contents.ByteLength());
2684 out_data->WriteTag(kSerializationTagArrayBuffer);
2685 out_data->Write(byte_length);
2686 out_data->WriteMemory(contents.Data(), byte_length);
2687 }
2688 } else if (value->IsSharedArrayBuffer()) {
2689 Local<SharedArrayBuffer> sab = Local<SharedArrayBuffer>::Cast(value);
2690 if (FindInObjectList(sab, *seen_objects)) {
2691 Throw(isolate, "Duplicated shared array buffers not supported");
2692 return false;
2693 }
2694 seen_objects->Add(sab);
2695 if (!FindInObjectList(sab, to_transfer)) {
2696 Throw(isolate, "SharedArrayBuffer must be transferred");
2697 return false;
2698 }
2699
2700 SharedArrayBuffer::Contents contents;
2701 if (sab->IsExternal()) {
2702 contents = sab->GetContents();
2703 } else {
2704 contents = sab->Externalize();
2705 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2706 externalized_shared_contents_.Add(contents);
2707 }
2708 out_data->WriteSharedArrayBufferContents(contents);
2709 } else if (value->IsObject()) {
2710 Local<Object> object = Local<Object>::Cast(value);
2711 if (FindInObjectList(object, *seen_objects)) {
2712 Throw(isolate, "Duplicated objects not supported");
2713 return false;
2714 }
2715 seen_objects->Add(object);
2716 Local<Array> property_names;
2717 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
2718 Throw(isolate, "Unable to get property names");
2719 return false;
2720 }
2721
2722 uint32_t length = property_names->Length();
2723 out_data->WriteTag(kSerializationTagObject);
2724 out_data->Write(length);
2725 for (uint32_t i = 0; i < length; ++i) {
2726 Local<Value> name;
2727 Local<Value> property_value;
2728 if (property_names->Get(context, i).ToLocal(&name) &&
2729 object->Get(context, name).ToLocal(&property_value)) {
2730 if (!SerializeValue(isolate, name, to_transfer, seen_objects, out_data))
2731 return false;
2732 if (!SerializeValue(isolate, property_value, to_transfer, seen_objects,
2733 out_data))
2734 return false;
2735 } else {
2736 Throw(isolate, "Failed to serialize property.");
2737 return false;
2738 }
2739 }
2740 } else {
2741 Throw(isolate, "Don't know how to serialize object");
2742 return false;
2743 }
2744
2745 return true;
2746 } 2695 }
2747 2696
2748 2697 MaybeLocal<Value> Shell::DeserializeValue(
2749 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, 2698 Isolate* isolate, std::unique_ptr<SerializationData> data) {
2750 const SerializationData& data, 2699 Local<Value> value;
2751 int* offset) { 2700 Local<Context> context = isolate->GetCurrentContext();
2752 DCHECK(offset); 2701 Deserializer deserializer(isolate, std::move(data));
2753 EscapableHandleScope scope(isolate); 2702 return deserializer.ReadValue(context);
2754 Local<Value> result;
2755 SerializationTag tag = data.ReadTag(offset);
2756
2757 switch (tag) {
2758 case kSerializationTagUndefined:
2759 result = Undefined(isolate);
2760 break;
2761 case kSerializationTagNull:
2762 result = Null(isolate);
2763 break;
2764 case kSerializationTagTrue:
2765 result = True(isolate);
2766 break;
2767 case kSerializationTagFalse:
2768 result = False(isolate);
2769 break;
2770 case kSerializationTagNumber:
2771 result = Number::New(isolate, data.Read<double>(offset));
2772 break;
2773 case kSerializationTagString: {
2774 int length = data.Read<int>(offset);
2775 CHECK(length >= 0);
2776 std::vector<char> buffer(length + 1); // + 1 so it is never empty.
2777 data.ReadMemory(&buffer[0], length, offset);
2778 MaybeLocal<String> str =
2779 String::NewFromUtf8(isolate, &buffer[0], NewStringType::kNormal,
2780 length).ToLocalChecked();
2781 if (!str.IsEmpty()) result = str.ToLocalChecked();
2782 break;
2783 }
2784 case kSerializationTagArray: {
2785 uint32_t length = data.Read<uint32_t>(offset);
2786 Local<Array> array = Array::New(isolate, length);
2787 for (uint32_t i = 0; i < length; ++i) {
2788 Local<Value> element_value;
2789 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value));
2790 array->Set(isolate->GetCurrentContext(), i, element_value).FromJust();
2791 }
2792 result = array;
2793 break;
2794 }
2795 case kSerializationTagObject: {
2796 int length = data.Read<int>(offset);
2797 Local<Object> object = Object::New(isolate);
2798 for (int i = 0; i < length; ++i) {
2799 Local<Value> property_name;
2800 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_name));
2801 Local<Value> property_value;
2802 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_value));
2803 object->Set(isolate->GetCurrentContext(), property_name, property_value)
2804 .FromJust();
2805 }
2806 result = object;
2807 break;
2808 }
2809 case kSerializationTagArrayBuffer: {
2810 int32_t byte_length = data.Read<int32_t>(offset);
2811 Local<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
2812 ArrayBuffer::Contents contents = array_buffer->GetContents();
2813 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
2814 data.ReadMemory(contents.Data(), byte_length, offset);
2815 result = array_buffer;
2816 break;
2817 }
2818 case kSerializationTagTransferredArrayBuffer: {
2819 ArrayBuffer::Contents contents;
2820 data.ReadArrayBufferContents(&contents, offset);
2821 result = ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength(),
2822 ArrayBufferCreationMode::kInternalized);
2823 break;
2824 }
2825 case kSerializationTagTransferredSharedArrayBuffer: {
2826 SharedArrayBuffer::Contents contents;
2827 data.ReadSharedArrayBufferContents(&contents, offset);
2828 result = SharedArrayBuffer::New(isolate, contents.Data(),
2829 contents.ByteLength());
2830 break;
2831 }
2832 default:
2833 UNREACHABLE();
2834 }
2835
2836 return scope.Escape(result);
2837 } 2703 }
2838 2704
2839 2705
2840 void Shell::CleanupWorkers() { 2706 void Shell::CleanupWorkers() {
2841 // Make a copy of workers_, because we don't want to call Worker::Terminate 2707 // Make a copy of workers_, because we don't want to call Worker::Terminate
2842 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to 2708 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to
2843 // create a new Worker, it would deadlock. 2709 // create a new Worker, it would deadlock.
2844 i::List<Worker*> workers_copy; 2710 i::List<Worker*> workers_copy;
2845 { 2711 {
2846 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 2712 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2847 allow_new_workers_ = false; 2713 allow_new_workers_ = false;
2848 workers_copy.AddAll(workers_); 2714 workers_copy.AddAll(workers_);
2849 workers_.Clear(); 2715 workers_.Clear();
2850 } 2716 }
2851 2717
2852 for (int i = 0; i < workers_copy.length(); ++i) { 2718 for (int i = 0; i < workers_copy.length(); ++i) {
2853 Worker* worker = workers_copy[i]; 2719 Worker* worker = workers_copy[i];
2854 worker->WaitForThread(); 2720 worker->WaitForThread();
2855 delete worker; 2721 delete worker;
2856 } 2722 }
2857 2723
2858 // Now that all workers are terminated, we can re-enable Worker creation. 2724 // Now that all workers are terminated, we can re-enable Worker creation.
2859 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 2725 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
2860 allow_new_workers_ = true; 2726 allow_new_workers_ = true;
2861 2727
2862 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { 2728 for (const auto& contents : externalized_shared_contents_) {
2863 const SharedArrayBuffer::Contents& contents =
2864 externalized_shared_contents_[i];
2865 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); 2729 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
2866 } 2730 }
2867 externalized_shared_contents_.Clear(); 2731 externalized_shared_contents_.clear();
2868 } 2732 }
2869 2733
2870 2734
2871 static void DumpHeapConstants(i::Isolate* isolate) { 2735 static void DumpHeapConstants(i::Isolate* isolate) {
2872 i::Heap* heap = isolate->heap(); 2736 i::Heap* heap = isolate->heap();
2873 2737
2874 // Dump the INSTANCE_TYPES table to the console. 2738 // Dump the INSTANCE_TYPES table to the console.
2875 printf("# List of known V8 instance types.\n"); 2739 printf("# List of known V8 instance types.\n");
2876 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); 2740 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
2877 printf("INSTANCE_TYPES = {\n"); 2741 printf("INSTANCE_TYPES = {\n");
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 } 2949 }
3086 2950
3087 } // namespace v8 2951 } // namespace v8
3088 2952
3089 2953
3090 #ifndef GOOGLE3 2954 #ifndef GOOGLE3
3091 int main(int argc, char* argv[]) { 2955 int main(int argc, char* argv[]) {
3092 return v8::Shell::Main(argc, argv); 2956 return v8::Shell::Main(argc, argv);
3093 } 2957 }
3094 #endif 2958 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | src/messages.h » ('j') | test/mjsunit/regress/regress-crbug-514081.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698