OLD | NEW |
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 Loading... |
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" | |
35 #include "src/msan.h" | 34 #include "src/msan.h" |
36 #include "src/objects-inl.h" | 35 #include "src/objects-inl.h" |
37 #include "src/snapshot/natives.h" | 36 #include "src/snapshot/natives.h" |
38 #include "src/utils.h" | 37 #include "src/utils.h" |
39 #include "src/v8.h" | 38 #include "src/v8.h" |
40 | 39 |
41 #ifdef V8_INSPECTOR_ENABLED | 40 #ifdef V8_INSPECTOR_ENABLED |
42 #include "include/v8-inspector.h" | 41 #include "include/v8-inspector.h" |
43 #endif // V8_INSPECTOR_ENABLED | 42 #endif // V8_INSPECTOR_ENABLED |
44 | 43 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 211 |
213 v8::Platform* g_platform = NULL; | 212 v8::Platform* g_platform = NULL; |
214 | 213 |
215 static Local<Value> Throw(Isolate* isolate, const char* message) { | 214 static Local<Value> Throw(Isolate* isolate, const char* message) { |
216 return isolate->ThrowException( | 215 return isolate->ThrowException( |
217 String::NewFromUtf8(isolate, message, NewStringType::kNormal) | 216 String::NewFromUtf8(isolate, message, NewStringType::kNormal) |
218 .ToLocalChecked()); | 217 .ToLocalChecked()); |
219 } | 218 } |
220 | 219 |
221 | 220 |
| 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 |
222 Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) { | 231 Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) { |
223 if (object->InternalFieldCount() != 1) { | 232 if (object->InternalFieldCount() != 1) { |
224 Throw(isolate, "this is not a Worker"); | 233 Throw(isolate, "this is not a Worker"); |
225 return NULL; | 234 return NULL; |
226 } | 235 } |
227 | 236 |
228 Worker* worker = | 237 Worker* worker = |
229 static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0)); | 238 static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0)); |
230 if (worker == NULL) { | 239 if (worker == NULL) { |
231 Throw(isolate, "Worker is defunct because main thread is terminating"); | 240 Throw(isolate, "Worker is defunct because main thread is terminating"); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; | 403 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; |
395 CounterCollection Shell::local_counters_; | 404 CounterCollection Shell::local_counters_; |
396 CounterCollection* Shell::counters_ = &local_counters_; | 405 CounterCollection* Shell::counters_ = &local_counters_; |
397 base::LazyMutex Shell::context_mutex_; | 406 base::LazyMutex Shell::context_mutex_; |
398 const base::TimeTicks Shell::kInitialTicks = | 407 const base::TimeTicks Shell::kInitialTicks = |
399 base::TimeTicks::HighResolutionNow(); | 408 base::TimeTicks::HighResolutionNow(); |
400 Global<Function> Shell::stringify_function_; | 409 Global<Function> Shell::stringify_function_; |
401 base::LazyMutex Shell::workers_mutex_; | 410 base::LazyMutex Shell::workers_mutex_; |
402 bool Shell::allow_new_workers_ = true; | 411 bool Shell::allow_new_workers_ = true; |
403 i::List<Worker*> Shell::workers_; | 412 i::List<Worker*> Shell::workers_; |
404 std::unordered_set<SharedArrayBuffer::Contents, | 413 i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_; |
405 Shell::SharedArrayBufferContentsHash, | |
406 Shell::SharedArrayBufferContentsIsEqual> | |
407 Shell::externalized_shared_contents_; | |
408 | 414 |
409 Global<Context> Shell::evaluation_context_; | 415 Global<Context> Shell::evaluation_context_; |
410 ArrayBuffer::Allocator* Shell::array_buffer_allocator; | 416 ArrayBuffer::Allocator* Shell::array_buffer_allocator; |
411 ShellOptions Shell::options; | 417 ShellOptions Shell::options; |
412 base::OnceType Shell::quit_once_ = V8_ONCE_INIT; | 418 base::OnceType Shell::quit_once_ = V8_ONCE_INIT; |
413 | 419 |
414 bool CounterMap::Match(void* key1, void* key2) { | 420 bool CounterMap::Match(void* key1, void* key2) { |
415 const char* name1 = reinterpret_cast<const char*>(key1); | 421 const char* name1 = reinterpret_cast<const char*>(key1); |
416 const char* name2 = reinterpret_cast<const char*>(key2); | 422 const char* name2 = reinterpret_cast<const char*>(key2); |
417 return strcmp(name1, name2) == 0; | 423 return strcmp(name1, name2) == 0; |
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 return; | 1143 return; |
1138 } | 1144 } |
1139 worker->StartExecuteInThread(*script); | 1145 worker->StartExecuteInThread(*script); |
1140 } | 1146 } |
1141 } | 1147 } |
1142 | 1148 |
1143 | 1149 |
1144 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { | 1150 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { |
1145 Isolate* isolate = args.GetIsolate(); | 1151 Isolate* isolate = args.GetIsolate(); |
1146 HandleScope handle_scope(isolate); | 1152 HandleScope handle_scope(isolate); |
| 1153 Local<Context> context = isolate->GetCurrentContext(); |
1147 | 1154 |
1148 if (args.Length() < 1) { | 1155 if (args.Length() < 1) { |
1149 Throw(isolate, "Invalid argument"); | 1156 Throw(isolate, "Invalid argument"); |
1150 return; | 1157 return; |
1151 } | 1158 } |
1152 | 1159 |
1153 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); | 1160 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); |
1154 if (!worker) { | 1161 if (!worker) { |
1155 return; | 1162 return; |
1156 } | 1163 } |
1157 | 1164 |
1158 Local<Value> message = args[0]; | 1165 Local<Value> message = args[0]; |
1159 Local<Value> transfer = | 1166 ObjectList to_transfer; |
1160 args.Length() >= 2 ? args[1] : Local<Value>::Cast(Undefined(isolate)); | 1167 if (args.Length() >= 2) { |
1161 std::unique_ptr<SerializationData> data = | 1168 if (!args[1]->IsArray()) { |
1162 Shell::SerializeValue(isolate, message, transfer); | 1169 Throw(isolate, "Transfer list must be an Array"); |
1163 if (data) { | 1170 return; |
1164 worker->PostMessage(std::move(data)); | 1171 } |
| 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; |
1165 } | 1196 } |
1166 } | 1197 } |
1167 | 1198 |
1168 | 1199 |
1169 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { | 1200 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { |
1170 Isolate* isolate = args.GetIsolate(); | 1201 Isolate* isolate = args.GetIsolate(); |
1171 HandleScope handle_scope(isolate); | 1202 HandleScope handle_scope(isolate); |
1172 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); | 1203 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); |
1173 if (!worker) { | 1204 if (!worker) { |
1174 return; | 1205 return; |
1175 } | 1206 } |
1176 | 1207 |
1177 std::unique_ptr<SerializationData> data = worker->GetMessage(); | 1208 SerializationData* data = worker->GetMessage(); |
1178 if (data) { | 1209 if (data) { |
1179 Local<Value> value; | 1210 int offset = 0; |
1180 if (Shell::DeserializeValue(isolate, std::move(data)).ToLocal(&value)) { | 1211 Local<Value> data_value; |
1181 args.GetReturnValue().Set(value); | 1212 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) { |
| 1213 args.GetReturnValue().Set(data_value); |
1182 } | 1214 } |
| 1215 delete data; |
1183 } | 1216 } |
1184 } | 1217 } |
1185 | 1218 |
1186 | 1219 |
1187 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 1220 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
1188 Isolate* isolate = args.GetIsolate(); | 1221 Isolate* isolate = args.GetIsolate(); |
1189 HandleScope handle_scope(isolate); | 1222 HandleScope handle_scope(isolate); |
1190 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); | 1223 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); |
1191 if (!worker) { | 1224 if (!worker) { |
1192 return; | 1225 return; |
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 if (thread_ == NULL) return; | 2141 if (thread_ == NULL) return; |
2109 done_semaphore_.Wait(); | 2142 done_semaphore_.Wait(); |
2110 } | 2143 } |
2111 | 2144 |
2112 | 2145 |
2113 void SourceGroup::JoinThread() { | 2146 void SourceGroup::JoinThread() { |
2114 if (thread_ == NULL) return; | 2147 if (thread_ == NULL) return; |
2115 thread_->Join(); | 2148 thread_->Join(); |
2116 } | 2149 } |
2117 | 2150 |
| 2151 |
2118 SerializationData::~SerializationData() { | 2152 SerializationData::~SerializationData() { |
2119 // Any ArrayBuffer::Contents are owned by this SerializationData object if | 2153 // Any ArrayBuffer::Contents are owned by this SerializationData object if |
2120 // ownership hasn't been transferred out. | 2154 // ownership hasn't been transferred out via ReadArrayBufferContents. |
2121 // SharedArrayBuffer::Contents may be used by multiple threads, so must be | 2155 // SharedArrayBuffer::Contents may be used by multiple threads, so must be |
2122 // cleaned up by the main thread in Shell::CleanupWorkers(). | 2156 // cleaned up by the main thread in Shell::CleanupWorkers(). |
2123 for (const auto& contents : array_buffer_contents_) { | 2157 for (int i = 0; i < array_buffer_contents_.length(); ++i) { |
| 2158 ArrayBuffer::Contents& contents = array_buffer_contents_[i]; |
2124 if (contents.Data()) { | 2159 if (contents.Data()) { |
2125 Shell::array_buffer_allocator->Free(contents.Data(), | 2160 Shell::array_buffer_allocator->Free(contents.Data(), |
2126 contents.ByteLength()); | 2161 contents.ByteLength()); |
2127 } | 2162 } |
2128 } | 2163 } |
2129 } | 2164 } |
2130 | 2165 |
2131 void SerializationData::ClearTransferredArrayBuffers() { | 2166 |
2132 array_buffer_contents_.clear(); | 2167 void SerializationData::WriteTag(SerializationTag tag) { data_.Add(tag); } |
| 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 } |
2133 } | 2175 } |
2134 | 2176 |
2135 void SerializationDataQueue::Enqueue(std::unique_ptr<SerializationData> data) { | 2177 |
2136 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2178 void SerializationData::WriteArrayBufferContents( |
2137 data_.push_back(std::move(data)); | 2179 const ArrayBuffer::Contents& contents) { |
| 2180 array_buffer_contents_.Add(contents); |
| 2181 WriteTag(kSerializationTagTransferredArrayBuffer); |
| 2182 int index = array_buffer_contents_.length() - 1; |
| 2183 Write(index); |
2138 } | 2184 } |
2139 | 2185 |
2140 bool SerializationDataQueue::Dequeue( | 2186 |
2141 std::unique_ptr<SerializationData>* out_data) { | 2187 void SerializationData::WriteSharedArrayBufferContents( |
2142 out_data->reset(); | 2188 const SharedArrayBuffer::Contents& contents) { |
| 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) { |
2143 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2230 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2144 if (data_.empty()) return false; | 2231 data_.Add(data); |
2145 *out_data = std::move(data_[0]); | 2232 } |
2146 data_.erase(data_.begin()); | 2233 |
| 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); |
2147 return true; | 2240 return true; |
2148 } | 2241 } |
2149 | 2242 |
2150 | 2243 |
2151 bool SerializationDataQueue::IsEmpty() { | 2244 bool SerializationDataQueue::IsEmpty() { |
2152 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2245 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2153 return data_.empty(); | 2246 return data_.is_empty(); |
2154 } | 2247 } |
2155 | 2248 |
2156 | 2249 |
2157 void SerializationDataQueue::Clear() { | 2250 void SerializationDataQueue::Clear() { |
2158 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2251 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2159 data_.clear(); | 2252 for (int i = 0; i < data_.length(); ++i) { |
| 2253 delete data_[i]; |
| 2254 } |
| 2255 data_.Clear(); |
2160 } | 2256 } |
2161 | 2257 |
2162 | 2258 |
2163 Worker::Worker() | 2259 Worker::Worker() |
2164 : in_semaphore_(0), | 2260 : in_semaphore_(0), |
2165 out_semaphore_(0), | 2261 out_semaphore_(0), |
2166 thread_(NULL), | 2262 thread_(NULL), |
2167 script_(NULL), | 2263 script_(NULL), |
2168 running_(false) {} | 2264 running_(false) {} |
2169 | 2265 |
2170 | 2266 |
2171 Worker::~Worker() { | 2267 Worker::~Worker() { |
2172 delete thread_; | 2268 delete thread_; |
2173 thread_ = NULL; | 2269 thread_ = NULL; |
2174 delete[] script_; | 2270 delete[] script_; |
2175 script_ = NULL; | 2271 script_ = NULL; |
2176 in_queue_.Clear(); | 2272 in_queue_.Clear(); |
2177 out_queue_.Clear(); | 2273 out_queue_.Clear(); |
2178 } | 2274 } |
2179 | 2275 |
2180 | 2276 |
2181 void Worker::StartExecuteInThread(const char* script) { | 2277 void Worker::StartExecuteInThread(const char* script) { |
2182 running_ = true; | 2278 running_ = true; |
2183 script_ = i::StrDup(script); | 2279 script_ = i::StrDup(script); |
2184 thread_ = new WorkerThread(this); | 2280 thread_ = new WorkerThread(this); |
2185 thread_->Start(); | 2281 thread_->Start(); |
2186 } | 2282 } |
2187 | 2283 |
2188 void Worker::PostMessage(std::unique_ptr<SerializationData> data) { | 2284 |
2189 in_queue_.Enqueue(std::move(data)); | 2285 void Worker::PostMessage(SerializationData* data) { |
| 2286 in_queue_.Enqueue(data); |
2190 in_semaphore_.Signal(); | 2287 in_semaphore_.Signal(); |
2191 } | 2288 } |
2192 | 2289 |
2193 std::unique_ptr<SerializationData> Worker::GetMessage() { | 2290 |
2194 std::unique_ptr<SerializationData> result; | 2291 SerializationData* Worker::GetMessage() { |
2195 while (!out_queue_.Dequeue(&result)) { | 2292 SerializationData* data = NULL; |
| 2293 while (!out_queue_.Dequeue(&data)) { |
2196 // If the worker is no longer running, and there are no messages in the | 2294 // If the worker is no longer running, and there are no messages in the |
2197 // queue, don't expect any more messages from it. | 2295 // queue, don't expect any more messages from it. |
2198 if (!base::NoBarrier_Load(&running_)) break; | 2296 if (!base::NoBarrier_Load(&running_)) break; |
2199 out_semaphore_.Wait(); | 2297 out_semaphore_.Wait(); |
2200 } | 2298 } |
2201 return result; | 2299 return data; |
2202 } | 2300 } |
2203 | 2301 |
2204 | 2302 |
2205 void Worker::Terminate() { | 2303 void Worker::Terminate() { |
2206 base::NoBarrier_Store(&running_, false); | 2304 base::NoBarrier_Store(&running_, false); |
2207 // Post NULL to wake the Worker thread message loop, and tell it to stop | 2305 // Post NULL to wake the Worker thread message loop, and tell it to stop |
2208 // running. | 2306 // running. |
2209 PostMessage(NULL); | 2307 PostMessage(NULL); |
2210 } | 2308 } |
2211 | 2309 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2255 // Get the message handler | 2353 // Get the message handler |
2256 Local<Value> onmessage = | 2354 Local<Value> onmessage = |
2257 global->Get(context, String::NewFromUtf8(isolate, "onmessage", | 2355 global->Get(context, String::NewFromUtf8(isolate, "onmessage", |
2258 NewStringType::kNormal) | 2356 NewStringType::kNormal) |
2259 .ToLocalChecked()).ToLocalChecked(); | 2357 .ToLocalChecked()).ToLocalChecked(); |
2260 if (onmessage->IsFunction()) { | 2358 if (onmessage->IsFunction()) { |
2261 Local<Function> onmessage_fun = Local<Function>::Cast(onmessage); | 2359 Local<Function> onmessage_fun = Local<Function>::Cast(onmessage); |
2262 // Now wait for messages | 2360 // Now wait for messages |
2263 while (true) { | 2361 while (true) { |
2264 in_semaphore_.Wait(); | 2362 in_semaphore_.Wait(); |
2265 std::unique_ptr<SerializationData> data; | 2363 SerializationData* data; |
2266 if (!in_queue_.Dequeue(&data)) continue; | 2364 if (!in_queue_.Dequeue(&data)) continue; |
2267 if (!data) { | 2365 if (data == NULL) { |
2268 break; | 2366 break; |
2269 } | 2367 } |
2270 v8::TryCatch try_catch(isolate); | 2368 int offset = 0; |
2271 Local<Value> value; | 2369 Local<Value> data_value; |
2272 if (Shell::DeserializeValue(isolate, std::move(data)) | 2370 if (Shell::DeserializeValue(isolate, *data, &offset) |
2273 .ToLocal(&value)) { | 2371 .ToLocal(&data_value)) { |
2274 Local<Value> argv[] = {value}; | 2372 Local<Value> argv[] = {data_value}; |
2275 (void)onmessage_fun->Call(context, global, 1, argv); | 2373 (void)onmessage_fun->Call(context, global, 1, argv); |
2276 } | 2374 } |
2277 if (try_catch.HasCaught()) { | 2375 delete data; |
2278 Shell::ReportException(isolate, &try_catch); | |
2279 } | |
2280 } | 2376 } |
2281 } | 2377 } |
2282 } | 2378 } |
2283 } | 2379 } |
2284 DisposeModuleEmbedderData(context); | 2380 DisposeModuleEmbedderData(context); |
2285 } | 2381 } |
2286 Shell::CollectGarbage(isolate); | 2382 Shell::CollectGarbage(isolate); |
2287 } | 2383 } |
2288 isolate->Dispose(); | 2384 isolate->Dispose(); |
2289 | 2385 |
2290 // Post NULL to wake the thread waiting on GetMessage() if there is one. | 2386 // Post NULL to wake the thread waiting on GetMessage() if there is one. |
2291 out_queue_.Enqueue(NULL); | 2387 out_queue_.Enqueue(NULL); |
2292 out_semaphore_.Signal(); | 2388 out_semaphore_.Signal(); |
2293 } | 2389 } |
2294 | 2390 |
2295 | 2391 |
2296 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) { | 2392 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) { |
2297 Isolate* isolate = args.GetIsolate(); | 2393 Isolate* isolate = args.GetIsolate(); |
2298 HandleScope handle_scope(isolate); | 2394 HandleScope handle_scope(isolate); |
2299 | 2395 |
2300 if (args.Length() < 1) { | 2396 if (args.Length() < 1) { |
2301 Throw(isolate, "Invalid argument"); | 2397 Throw(isolate, "Invalid argument"); |
2302 return; | 2398 return; |
2303 } | 2399 } |
2304 | 2400 |
2305 Local<Value> message = args[0]; | 2401 Local<Value> message = args[0]; |
2306 Local<Value> transfer = Undefined(isolate); | 2402 |
2307 std::unique_ptr<SerializationData> data = | 2403 // TODO(binji): Allow transferring from worker to main thread? |
2308 Shell::SerializeValue(isolate, message, transfer); | 2404 Shell::ObjectList to_transfer; |
2309 if (data) { | 2405 |
| 2406 Shell::ObjectList seen_objects; |
| 2407 SerializationData* data = new SerializationData; |
| 2408 if (Shell::SerializeValue(isolate, message, to_transfer, &seen_objects, |
| 2409 data)) { |
2310 DCHECK(args.Data()->IsExternal()); | 2410 DCHECK(args.Data()->IsExternal()); |
2311 Local<External> this_value = Local<External>::Cast(args.Data()); | 2411 Local<External> this_value = Local<External>::Cast(args.Data()); |
2312 Worker* worker = static_cast<Worker*>(this_value->Value()); | 2412 Worker* worker = static_cast<Worker*>(this_value->Value()); |
2313 worker->out_queue_.Enqueue(std::move(data)); | 2413 worker->out_queue_.Enqueue(data); |
2314 worker->out_semaphore_.Signal(); | 2414 worker->out_semaphore_.Signal(); |
| 2415 } else { |
| 2416 delete data; |
2315 } | 2417 } |
2316 } | 2418 } |
2317 | 2419 |
2318 | 2420 |
2319 void SetFlagsFromString(const char* flags) { | 2421 void SetFlagsFromString(const char* flags) { |
2320 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); | 2422 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); |
2321 } | 2423 } |
2322 | 2424 |
2323 | 2425 |
2324 bool Shell::SetOptions(int argc, char* argv[]) { | 2426 bool Shell::SetOptions(int argc, char* argv[]) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2497 | 2599 |
2498 | 2600 |
2499 void Shell::EmptyMessageQueues(Isolate* isolate) { | 2601 void Shell::EmptyMessageQueues(Isolate* isolate) { |
2500 if (!i::FLAG_verify_predictable) { | 2602 if (!i::FLAG_verify_predictable) { |
2501 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; | 2603 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; |
2502 v8::platform::RunIdleTasks(g_platform, isolate, | 2604 v8::platform::RunIdleTasks(g_platform, isolate, |
2503 50.0 / base::Time::kMillisecondsPerSecond); | 2605 50.0 / base::Time::kMillisecondsPerSecond); |
2504 } | 2606 } |
2505 } | 2607 } |
2506 | 2608 |
2507 class Serializer : public ValueSerializer::Delegate { | 2609 |
2508 public: | 2610 bool Shell::SerializeValue(Isolate* isolate, Local<Value> value, |
2509 explicit Serializer(Isolate* isolate) | 2611 const ObjectList& to_transfer, |
2510 : isolate_(isolate), serializer_(isolate, this) {} | 2612 ObjectList* seen_objects, |
2511 | 2613 SerializationData* out_data) { |
2512 Maybe<bool> WriteValue(Local<Context> context, Local<Value> value, | 2614 DCHECK(out_data); |
2513 Local<Value> transfer) { | 2615 Local<Context> context = isolate->GetCurrentContext(); |
2514 bool ok; | 2616 |
2515 DCHECK(!data_); | 2617 if (value->IsUndefined()) { |
2516 data_.reset(new SerializationData); | 2618 out_data->WriteTag(kSerializationTagUndefined); |
2517 if (!PrepareTransfer(context, transfer).To(&ok)) { | 2619 } else if (value->IsNull()) { |
2518 return Nothing<bool>(); | 2620 out_data->WriteTag(kSerializationTagNull); |
2519 } | 2621 } else if (value->IsTrue()) { |
2520 serializer_.WriteHeader(); | 2622 out_data->WriteTag(kSerializationTagTrue); |
2521 | 2623 } else if (value->IsFalse()) { |
2522 if (!serializer_.WriteValue(context, value).To(&ok)) { | 2624 out_data->WriteTag(kSerializationTagFalse); |
2523 data_.reset(); | 2625 } else if (value->IsNumber()) { |
2524 return Nothing<bool>(); | 2626 Local<Number> num = Local<Number>::Cast(value); |
2525 } | 2627 double value = num->Value(); |
2526 | 2628 out_data->WriteTag(kSerializationTagNumber); |
2527 if (!FinalizeTransfer().To(&ok)) { | 2629 out_data->Write(value); |
2528 return Nothing<bool>(); | 2630 } else if (value->IsString()) { |
2529 } | 2631 v8::String::Utf8Value str(value); |
2530 | 2632 out_data->WriteTag(kSerializationTagString); |
2531 std::pair<uint8_t*, size_t> pair = serializer_.Release(); | 2633 out_data->Write(str.length()); |
2532 data_->data_.reset(pair.first); | 2634 out_data->WriteMemory(*str, str.length()); |
2533 data_->size_ = pair.second; | 2635 } else if (value->IsArray()) { |
2534 return Just(true); | 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; |
2535 } | 2743 } |
2536 | 2744 |
2537 std::unique_ptr<SerializationData> Release() { return std::move(data_); } | 2745 return true; |
2538 | 2746 } |
2539 protected: | 2747 |
2540 // Implements ValueSerializer::Delegate. | 2748 |
2541 void ThrowDataCloneError(Local<String> message) override { | 2749 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, |
2542 isolate_->ThrowException(Exception::Error(message)); | 2750 const SerializationData& data, |
| 2751 int* offset) { |
| 2752 DCHECK(offset); |
| 2753 EscapableHandleScope scope(isolate); |
| 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(); |
2543 } | 2834 } |
2544 | 2835 |
2545 Maybe<uint32_t> GetSharedArrayBufferId( | 2836 return scope.Escape(result); |
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; | |
2684 Local<Context> context = isolate->GetCurrentContext(); | |
2685 Serializer serializer(isolate); | |
2686 if (serializer.WriteValue(context, value, transfer).To(&ok)) { | |
2687 std::unique_ptr<SerializationData> data = serializer.Release(); | |
2688 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | |
2689 for (const auto& contents : data->shared_array_buffer_contents()) { | |
2690 externalized_shared_contents_.insert(contents); | |
2691 } | |
2692 return data; | |
2693 } | |
2694 return nullptr; | |
2695 } | 2837 } |
2696 | 2838 |
2697 MaybeLocal<Value> Shell::DeserializeValue( | 2839 |
2698 Isolate* isolate, std::unique_ptr<SerializationData> data) { | |
2699 Local<Value> value; | |
2700 Local<Context> context = isolate->GetCurrentContext(); | |
2701 Deserializer deserializer(isolate, std::move(data)); | |
2702 return deserializer.ReadValue(context); | |
2703 } | |
2704 | |
2705 | |
2706 void Shell::CleanupWorkers() { | 2840 void Shell::CleanupWorkers() { |
2707 // Make a copy of workers_, because we don't want to call Worker::Terminate | 2841 // Make a copy of workers_, because we don't want to call Worker::Terminate |
2708 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to | 2842 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to |
2709 // create a new Worker, it would deadlock. | 2843 // create a new Worker, it would deadlock. |
2710 i::List<Worker*> workers_copy; | 2844 i::List<Worker*> workers_copy; |
2711 { | 2845 { |
2712 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | 2846 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
2713 allow_new_workers_ = false; | 2847 allow_new_workers_ = false; |
2714 workers_copy.AddAll(workers_); | 2848 workers_copy.AddAll(workers_); |
2715 workers_.Clear(); | 2849 workers_.Clear(); |
2716 } | 2850 } |
2717 | 2851 |
2718 for (int i = 0; i < workers_copy.length(); ++i) { | 2852 for (int i = 0; i < workers_copy.length(); ++i) { |
2719 Worker* worker = workers_copy[i]; | 2853 Worker* worker = workers_copy[i]; |
2720 worker->WaitForThread(); | 2854 worker->WaitForThread(); |
2721 delete worker; | 2855 delete worker; |
2722 } | 2856 } |
2723 | 2857 |
2724 // Now that all workers are terminated, we can re-enable Worker creation. | 2858 // Now that all workers are terminated, we can re-enable Worker creation. |
2725 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | 2859 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
2726 allow_new_workers_ = true; | 2860 allow_new_workers_ = true; |
2727 | 2861 |
2728 for (const auto& contents : externalized_shared_contents_) { | 2862 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { |
| 2863 const SharedArrayBuffer::Contents& contents = |
| 2864 externalized_shared_contents_[i]; |
2729 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); | 2865 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); |
2730 } | 2866 } |
2731 externalized_shared_contents_.clear(); | 2867 externalized_shared_contents_.Clear(); |
2732 } | 2868 } |
2733 | 2869 |
2734 | 2870 |
2735 static void DumpHeapConstants(i::Isolate* isolate) { | 2871 static void DumpHeapConstants(i::Isolate* isolate) { |
2736 i::Heap* heap = isolate->heap(); | 2872 i::Heap* heap = isolate->heap(); |
2737 | 2873 |
2738 // Dump the INSTANCE_TYPES table to the console. | 2874 // Dump the INSTANCE_TYPES table to the console. |
2739 printf("# List of known V8 instance types.\n"); | 2875 printf("# List of known V8 instance types.\n"); |
2740 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); | 2876 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); |
2741 printf("INSTANCE_TYPES = {\n"); | 2877 printf("INSTANCE_TYPES = {\n"); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2949 } | 3085 } |
2950 | 3086 |
2951 } // namespace v8 | 3087 } // namespace v8 |
2952 | 3088 |
2953 | 3089 |
2954 #ifndef GOOGLE3 | 3090 #ifndef GOOGLE3 |
2955 int main(int argc, char* argv[]) { | 3091 int main(int argc, char* argv[]) { |
2956 return v8::Shell::Main(argc, argv); | 3092 return v8::Shell::Main(argc, argv); |
2957 } | 3093 } |
2958 #endif | 3094 #endif |
OLD | NEW |