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" | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 *actual_size = size; | |
2560 void* result = realloc(old_buffer, size); | |
2561 if (!result) { | |
2562 printf("Unable to allocate %" PRIuS " bytes.\n", size); | |
2563 Shell::Exit(1); | |
binji
2017/01/25 00:31:36
Not sure what to do here, actually. If I pass back
jbroman
2017/01/25 16:34:54
Chromium usually deals with out-of-memory conditio
binji
2017/01/26 00:48:39
Not sure how it performs, but I added a write_ok_
jbroman
2017/01/26 21:03:18
We should check to see if it regresses performance
| |
2564 } | |
2565 return result; | |
2566 } | |
2567 | |
2568 void FreeBufferMemory(void* buffer) override { free(buffer); } | |
2569 | |
2570 private: | |
2571 Maybe<bool> PrepareTransfer(Local<Context> context, Local<Value> transfer) { | |
2572 if (transfer->IsArray()) { | |
2573 Local<Array> transfer_array = Local<Array>::Cast(transfer); | |
2574 uint32_t length = transfer_array->Length(); | |
2575 for (uint32_t i = 0; i < length; ++i) { | |
2576 Local<Value> element; | |
2577 TryCatch try_catch(isolate_); | |
2578 if (transfer_array->Get(context, i).ToLocal(&element)) { | |
Camillo Bruni
2017/01/25 19:06:12
I think you can avoid the TryCatch here by simply
binji
2017/01/26 00:48:39
Done.
| |
2579 if (!element->IsArrayBuffer()) { | |
2580 Throw(isolate_, "Transfer array elements must be an ArrayBuffer"); | |
2581 break; | |
2582 } | |
2583 | |
2584 Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(element); | |
2585 serializer_.TransferArrayBuffer( | |
2586 static_cast<uint32_t>(array_buffers_.size()), array_buffer); | |
2587 array_buffers_.emplace_back(isolate_, array_buffer); | |
2588 } | |
2589 if (try_catch.HasCaught()) { | |
2590 try_catch.ReThrow(); | |
2591 return Nothing<bool>(); | |
2592 } | |
2593 } | |
2594 return Just(true); | |
2595 } else if (transfer->IsUndefined()) { | |
2596 return Just(true); | |
2597 } else { | |
2598 Throw(isolate_, "Transfer list must be an Array or undefined"); | |
2599 return Nothing<bool>(); | |
2600 } | |
2601 } | |
2602 | |
2603 Maybe<bool> FinalizeTransfer() { | |
2604 for (const auto& global_array_buffer : array_buffers_) { | |
2605 Local<ArrayBuffer> array_buffer = | |
2606 Local<ArrayBuffer>::New(isolate_, global_array_buffer); | |
2607 if (!array_buffer->IsNeuterable()) { | |
2608 Throw(isolate_, "ArrayBuffer could not be transferred"); | |
2609 return Nothing<bool>(); | |
2610 } | |
2611 | |
2612 if (!array_buffer->IsExternal()) { | |
2613 array_buffer->Externalize(); | |
2614 } | |
2615 ArrayBuffer::Contents contents = array_buffer->GetContents(); | |
2616 array_buffer->Neuter(); | |
2617 data_->array_buffer_contents_.push_back(contents); | |
2618 } | |
2619 | |
2620 for (const auto& global_shared_array_buffer : shared_array_buffers_) { | |
2621 Local<SharedArrayBuffer> shared_array_buffer = | |
2622 Local<SharedArrayBuffer>::New(isolate_, global_shared_array_buffer); | |
2623 if (!shared_array_buffer->IsExternal()) { | |
2624 shared_array_buffer->Externalize(); | |
2625 } | |
2626 data_->shared_array_buffer_contents_.push_back( | |
2627 shared_array_buffer->GetContents()); | |
2628 } | |
2629 | |
2630 return Just(true); | |
2631 } | |
2632 | |
2633 Isolate* isolate_; | |
2634 ValueSerializer serializer_; | |
2635 std::unique_ptr<SerializationData> data_; | |
2636 std::vector<Global<ArrayBuffer>> array_buffers_; | |
2637 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_; | |
2638 | |
2639 DISALLOW_COPY_AND_ASSIGN(Serializer); | |
2640 }; | |
2641 | |
2642 class Deserializer : public ValueDeserializer::Delegate { | |
2643 public: | |
2644 Deserializer(Isolate* isolate, std::unique_ptr<SerializationData> data) | |
2645 : isolate_(isolate), | |
2646 deserializer_(isolate, data->data(), data->size(), this), | |
2647 data_(std::move(data)) { | |
2648 deserializer_.SetSupportsLegacyWireFormat(true); | |
2649 } | |
2650 | |
2651 MaybeLocal<Value> ReadValue(Local<Context> context) { | |
2652 bool read_header; | |
2653 if (!deserializer_.ReadHeader(context).To(&read_header)) { | |
2654 return MaybeLocal<Value>(); | |
2655 } | |
2656 | |
2657 uint32_t index = 0; | |
2658 for (const auto& contents : data_->array_buffer_contents()) { | |
2659 Local<ArrayBuffer> array_buffer = | |
2660 ArrayBuffer::New(isolate_, contents.Data(), contents.ByteLength()); | |
2661 deserializer_.TransferArrayBuffer(index++, array_buffer); | |
2662 } | |
2663 | |
2664 index = 0; | |
2665 for (const auto& contents : data_->shared_array_buffer_contents()) { | |
2666 Local<SharedArrayBuffer> shared_array_buffer = SharedArrayBuffer::New( | |
2667 isolate_, contents.Data(), contents.ByteLength()); | |
2668 deserializer_.TransferSharedArrayBuffer(index++, shared_array_buffer); | |
2669 } | |
2670 | |
2671 MaybeLocal<Value> result = deserializer_.ReadValue(context); | |
2672 if (!result.IsEmpty()) { | |
2673 data_->ClearTransferredArrayBuffers(); | |
2674 } | |
2675 return result; | |
2676 } | |
2677 | |
2678 private: | |
2679 Isolate* isolate_; | |
2680 ValueDeserializer deserializer_; | |
2681 std::unique_ptr<SerializationData> data_; | |
2682 | |
2683 DISALLOW_COPY_AND_ASSIGN(Deserializer); | |
2684 }; | |
2685 | |
2686 std::unique_ptr<SerializationData> Shell::SerializeValue( | |
2687 Isolate* isolate, Local<Value> value, Local<Value> transfer) { | |
2688 bool ok; | |
2613 Local<Context> context = isolate->GetCurrentContext(); | 2689 Local<Context> context = isolate->GetCurrentContext(); |
2614 | 2690 Serializer serializer(isolate); |
2615 if (value->IsUndefined()) { | 2691 if (serializer.WriteValue(context, value, transfer).To(&ok)) { |
2616 out_data->WriteTag(kSerializationTagUndefined); | 2692 std::unique_ptr<SerializationData> data = serializer.Release(); |
2617 } else if (value->IsNull()) { | 2693 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
2618 out_data->WriteTag(kSerializationTagNull); | 2694 for (const auto& contents : data->shared_array_buffer_contents()) { |
2619 } else if (value->IsTrue()) { | 2695 externalized_shared_contents_.insert(contents); |
2620 out_data->WriteTag(kSerializationTagTrue); | 2696 } |
2621 } else if (value->IsFalse()) { | 2697 return data; |
2622 out_data->WriteTag(kSerializationTagFalse); | 2698 } |
2623 } else if (value->IsNumber()) { | 2699 return std::unique_ptr<SerializationData>(); |
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 } | 2700 } |
2745 | 2701 |
2746 | 2702 MaybeLocal<Value> Shell::DeserializeValue( |
2747 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, | 2703 Isolate* isolate, std::unique_ptr<SerializationData> data) { |
2748 const SerializationData& data, | 2704 Local<Value> value; |
2749 int* offset) { | 2705 Local<Context> context = isolate->GetCurrentContext(); |
2750 DCHECK(offset); | 2706 Deserializer deserializer(isolate, std::move(data)); |
2751 EscapableHandleScope scope(isolate); | 2707 if (deserializer.ReadValue(context).ToLocal(&value)) { |
2752 Local<Value> result; | 2708 return MaybeLocal<Value>(value); |
2753 SerializationTag tag = data.ReadTag(offset); | 2709 } |
2754 | 2710 return MaybeLocal<Value>(); |
Camillo Bruni
2017/01/25 19:06:12
Simplify: return deserializer.ReadValue(context);
binji
2017/01/26 00:48:39
Done.
| |
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 } | 2711 } |
2836 | 2712 |
2837 | 2713 |
2838 void Shell::CleanupWorkers() { | 2714 void Shell::CleanupWorkers() { |
2839 // Make a copy of workers_, because we don't want to call Worker::Terminate | 2715 // 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 | 2716 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to |
2841 // create a new Worker, it would deadlock. | 2717 // create a new Worker, it would deadlock. |
2842 i::List<Worker*> workers_copy; | 2718 i::List<Worker*> workers_copy; |
2843 { | 2719 { |
2844 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | 2720 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
2845 allow_new_workers_ = false; | 2721 allow_new_workers_ = false; |
2846 workers_copy.AddAll(workers_); | 2722 workers_copy.AddAll(workers_); |
2847 workers_.Clear(); | 2723 workers_.Clear(); |
2848 } | 2724 } |
2849 | 2725 |
2850 for (int i = 0; i < workers_copy.length(); ++i) { | 2726 for (int i = 0; i < workers_copy.length(); ++i) { |
2851 Worker* worker = workers_copy[i]; | 2727 Worker* worker = workers_copy[i]; |
2852 worker->WaitForThread(); | 2728 worker->WaitForThread(); |
2853 delete worker; | 2729 delete worker; |
2854 } | 2730 } |
2855 | 2731 |
2856 // Now that all workers are terminated, we can re-enable Worker creation. | 2732 // Now that all workers are terminated, we can re-enable Worker creation. |
2857 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | 2733 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
2858 allow_new_workers_ = true; | 2734 allow_new_workers_ = true; |
2859 | 2735 |
2860 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { | 2736 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()); | 2737 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); |
2864 } | 2738 } |
2865 externalized_shared_contents_.Clear(); | 2739 externalized_shared_contents_.clear(); |
2866 } | 2740 } |
2867 | 2741 |
2868 | 2742 |
2869 static void DumpHeapConstants(i::Isolate* isolate) { | 2743 static void DumpHeapConstants(i::Isolate* isolate) { |
2870 i::Heap* heap = isolate->heap(); | 2744 i::Heap* heap = isolate->heap(); |
2871 | 2745 |
2872 // Dump the INSTANCE_TYPES table to the console. | 2746 // Dump the INSTANCE_TYPES table to the console. |
2873 printf("# List of known V8 instance types.\n"); | 2747 printf("# List of known V8 instance types.\n"); |
2874 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); | 2748 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); |
2875 printf("INSTANCE_TYPES = {\n"); | 2749 printf("INSTANCE_TYPES = {\n"); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3083 } | 2957 } |
3084 | 2958 |
3085 } // namespace v8 | 2959 } // namespace v8 |
3086 | 2960 |
3087 | 2961 |
3088 #ifndef GOOGLE3 | 2962 #ifndef GOOGLE3 |
3089 int main(int argc, char* argv[]) { | 2963 int main(int argc, char* argv[]) { |
3090 return v8::Shell::Main(argc, argv); | 2964 return v8::Shell::Main(argc, argv); |
3091 } | 2965 } |
3092 #endif | 2966 #endif |
OLD | NEW |