Chromium Code Reviews| 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 |
| 44 #if !defined(_WIN32) && !defined(_WIN64) | 45 #if !defined(_WIN32) && !defined(_WIN64) |
| 45 #include <unistd.h> // NOLINT | 46 #include <unistd.h> // NOLINT |
| 46 #else | 47 #else |
| 47 #include <windows.h> // NOLINT | 48 #include <windows.h> // NOLINT |
| 48 #if defined(_MSC_VER) | 49 #if defined(_MSC_VER) |
| 49 #include <crtdbg.h> // NOLINT | 50 #include <crtdbg.h> // NOLINT |
| 50 #endif // defined(_MSC_VER) | 51 #endif // defined(_MSC_VER) |
| 51 #endif // !defined(_WIN32) && !defined(_WIN64) | 52 #endif // !defined(_WIN32) && !defined(_WIN64) |
| 52 | 53 |
| 53 #ifndef DCHECK | 54 #ifndef DCHECK |
| 54 #define DCHECK(condition) assert(condition) | 55 #define DCHECK(condition) assert(condition) |
| 55 #endif | 56 #endif |
| 56 | 57 |
| 57 #ifndef CHECK | 58 #ifndef CHECK |
| 58 #define CHECK(condition) assert(condition) | 59 #define CHECK(condition) assert(condition) |
| 59 #endif | 60 #endif |
| 60 | 61 |
| 62 namespace std { | |
| 63 | |
| 64 template <> | |
| 65 struct hash<v8::SharedArrayBuffer::Contents> { | |
|
jbroman
2017/01/24 18:53:43
(I'm not a V8 owner, but...)
1. The Chromium/Goog
binji
2017/01/25 00:31:35
Done.
| |
| 66 size_t operator()(const v8::SharedArrayBuffer::Contents& contents) const { | |
| 67 return std::hash<void*>()(contents.Data()) ^ | |
| 68 std::hash<size_t>()(contents.ByteLength()); | |
| 69 } | |
| 70 }; | |
| 71 | |
| 72 } // namespace std | |
| 73 | |
| 61 namespace v8 { | 74 namespace v8 { |
| 62 | 75 |
| 76 bool operator==(const SharedArrayBuffer::Contents& a, | |
| 77 const SharedArrayBuffer::Contents& b) { | |
| 78 return a.Data() == b.Data() && a.ByteLength() == b.ByteLength(); | |
| 79 } | |
| 80 | |
| 63 namespace { | 81 namespace { |
| 64 | 82 |
| 65 const int MB = 1024 * 1024; | 83 const int MB = 1024 * 1024; |
| 66 const int kMaxWorkers = 50; | 84 const int kMaxWorkers = 50; |
| 67 | 85 |
| 68 #define USE_VM 1 | 86 #define USE_VM 1 |
| 69 #define VM_THRESHOLD 65536 | 87 #define VM_THRESHOLD 65536 |
| 70 // TODO(titzer): allocations should fail if >= 2gb because of | 88 // TODO(titzer): allocations should fail if >= 2gb because of |
| 71 // array buffers storing the lengths as a SMI internally. | 89 // array buffers storing the lengths as a SMI internally. |
| 72 #define TWO_GB (2u * 1024u * 1024u * 1024u) | 90 #define TWO_GB (2u * 1024u * 1024u * 1024u) |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 | 229 |
| 212 v8::Platform* g_platform = NULL; | 230 v8::Platform* g_platform = NULL; |
| 213 | 231 |
| 214 static Local<Value> Throw(Isolate* isolate, const char* message) { | 232 static Local<Value> Throw(Isolate* isolate, const char* message) { |
| 215 return isolate->ThrowException( | 233 return isolate->ThrowException( |
| 216 String::NewFromUtf8(isolate, message, NewStringType::kNormal) | 234 String::NewFromUtf8(isolate, message, NewStringType::kNormal) |
| 217 .ToLocalChecked()); | 235 .ToLocalChecked()); |
| 218 } | 236 } |
| 219 | 237 |
| 220 | 238 |
| 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) { | 239 Worker* GetWorkerFromInternalField(Isolate* isolate, Local<Object> object) { |
| 232 if (object->InternalFieldCount() != 1) { | 240 if (object->InternalFieldCount() != 1) { |
| 233 Throw(isolate, "this is not a Worker"); | 241 Throw(isolate, "this is not a Worker"); |
| 234 return NULL; | 242 return NULL; |
| 235 } | 243 } |
| 236 | 244 |
| 237 Worker* worker = | 245 Worker* worker = |
| 238 static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0)); | 246 static_cast<Worker*>(object->GetAlignedPointerFromInternalField(0)); |
| 239 if (worker == NULL) { | 247 if (worker == NULL) { |
| 240 Throw(isolate, "Worker is defunct because main thread is terminating"); | 248 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; | 411 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; |
| 404 CounterCollection Shell::local_counters_; | 412 CounterCollection Shell::local_counters_; |
| 405 CounterCollection* Shell::counters_ = &local_counters_; | 413 CounterCollection* Shell::counters_ = &local_counters_; |
| 406 base::LazyMutex Shell::context_mutex_; | 414 base::LazyMutex Shell::context_mutex_; |
| 407 const base::TimeTicks Shell::kInitialTicks = | 415 const base::TimeTicks Shell::kInitialTicks = |
| 408 base::TimeTicks::HighResolutionNow(); | 416 base::TimeTicks::HighResolutionNow(); |
| 409 Global<Function> Shell::stringify_function_; | 417 Global<Function> Shell::stringify_function_; |
| 410 base::LazyMutex Shell::workers_mutex_; | 418 base::LazyMutex Shell::workers_mutex_; |
| 411 bool Shell::allow_new_workers_ = true; | 419 bool Shell::allow_new_workers_ = true; |
| 412 i::List<Worker*> Shell::workers_; | 420 i::List<Worker*> Shell::workers_; |
| 413 i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_; | 421 std::unordered_set<SharedArrayBuffer::Contents> |
| 422 Shell::externalized_shared_contents_; | |
| 414 | 423 |
| 415 Global<Context> Shell::evaluation_context_; | 424 Global<Context> Shell::evaluation_context_; |
| 416 ArrayBuffer::Allocator* Shell::array_buffer_allocator; | 425 ArrayBuffer::Allocator* Shell::array_buffer_allocator; |
| 417 ShellOptions Shell::options; | 426 ShellOptions Shell::options; |
| 418 base::OnceType Shell::quit_once_ = V8_ONCE_INIT; | 427 base::OnceType Shell::quit_once_ = V8_ONCE_INIT; |
| 419 | 428 |
| 420 bool CounterMap::Match(void* key1, void* key2) { | 429 bool CounterMap::Match(void* key1, void* key2) { |
| 421 const char* name1 = reinterpret_cast<const char*>(key1); | 430 const char* name1 = reinterpret_cast<const char*>(key1); |
| 422 const char* name2 = reinterpret_cast<const char*>(key2); | 431 const char* name2 = reinterpret_cast<const char*>(key2); |
| 423 return strcmp(name1, name2) == 0; | 432 return strcmp(name1, name2) == 0; |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 Throw(isolate, "Invalid argument"); | 1165 Throw(isolate, "Invalid argument"); |
| 1157 return; | 1166 return; |
| 1158 } | 1167 } |
| 1159 | 1168 |
| 1160 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); | 1169 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); |
| 1161 if (!worker) { | 1170 if (!worker) { |
| 1162 return; | 1171 return; |
| 1163 } | 1172 } |
| 1164 | 1173 |
| 1165 Local<Value> message = args[0]; | 1174 Local<Value> message = args[0]; |
| 1166 ObjectList to_transfer; | 1175 Local<Value> transfer = |
| 1167 if (args.Length() >= 2) { | 1176 args.Length() >= 2 ? args[1] : Local<Value>::Cast(Undefined(isolate)); |
|
jbroman
2017/01/24 18:53:43
nit: is the Local<Value> cast necessary; I think i
binji
2017/01/25 00:31:36
The two arms of the conditional have different typ
jbroman
2017/01/25 16:34:54
OK, sorry.
Ordinarily the compiler would still ad
| |
| 1168 if (!args[1]->IsArray()) { | 1177 SerializationData* data; |
| 1169 Throw(isolate, "Transfer list must be an Array"); | 1178 if (Shell::SerializeValue(isolate, message, transfer).To(&data)) { |
| 1170 return; | |
| 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); | 1179 worker->PostMessage(data); |
| 1194 } else { | |
| 1195 delete data; | |
| 1196 } | 1180 } |
| 1197 } | 1181 } |
| 1198 | 1182 |
| 1199 | 1183 |
| 1200 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { | 1184 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 1201 Isolate* isolate = args.GetIsolate(); | 1185 Isolate* isolate = args.GetIsolate(); |
| 1202 HandleScope handle_scope(isolate); | 1186 HandleScope handle_scope(isolate); |
| 1203 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); | 1187 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); |
| 1204 if (!worker) { | 1188 if (!worker) { |
| 1205 return; | 1189 return; |
| 1206 } | 1190 } |
| 1207 | 1191 |
| 1208 SerializationData* data = worker->GetMessage(); | 1192 SerializationData* data = worker->GetMessage(); |
| 1209 if (data) { | 1193 if (data) { |
| 1210 int offset = 0; | 1194 Local<Value> value; |
| 1211 Local<Value> data_value; | 1195 if (Shell::DeserializeValue(isolate, data).ToLocal(&value)) { |
|
jbroman
2017/01/24 18:53:43
nit: Just checking, if this fails (i.e. an excepti
binji
2017/01/25 00:31:35
Yeah, it definitely will break the tests (or perha
| |
| 1212 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) { | 1196 args.GetReturnValue().Set(value); |
| 1213 args.GetReturnValue().Set(data_value); | |
| 1214 } | 1197 } |
| 1215 delete data; | |
| 1216 } | 1198 } |
| 1217 } | 1199 } |
| 1218 | 1200 |
| 1219 | 1201 |
| 1220 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 1202 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 1221 Isolate* isolate = args.GetIsolate(); | 1203 Isolate* isolate = args.GetIsolate(); |
| 1222 HandleScope handle_scope(isolate); | 1204 HandleScope handle_scope(isolate); |
| 1223 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); | 1205 Worker* worker = GetWorkerFromInternalField(isolate, args.Holder()); |
| 1224 if (!worker) { | 1206 if (!worker) { |
| 1225 return; | 1207 return; |
| (...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2141 if (thread_ == NULL) return; | 2123 if (thread_ == NULL) return; |
| 2142 done_semaphore_.Wait(); | 2124 done_semaphore_.Wait(); |
| 2143 } | 2125 } |
| 2144 | 2126 |
| 2145 | 2127 |
| 2146 void SourceGroup::JoinThread() { | 2128 void SourceGroup::JoinThread() { |
| 2147 if (thread_ == NULL) return; | 2129 if (thread_ == NULL) return; |
| 2148 thread_->Join(); | 2130 thread_->Join(); |
| 2149 } | 2131 } |
| 2150 | 2132 |
| 2151 | |
| 2152 SerializationData::~SerializationData() { | 2133 SerializationData::~SerializationData() { |
| 2153 // Any ArrayBuffer::Contents are owned by this SerializationData object if | 2134 // Any ArrayBuffer::Contents are owned by this SerializationData object if |
| 2154 // ownership hasn't been transferred out via ReadArrayBufferContents. | 2135 // ownership hasn't been transferred out. |
| 2155 // SharedArrayBuffer::Contents may be used by multiple threads, so must be | 2136 // SharedArrayBuffer::Contents may be used by multiple threads, so must be |
| 2156 // cleaned up by the main thread in Shell::CleanupWorkers(). | 2137 // cleaned up by the main thread in Shell::CleanupWorkers(). |
| 2157 for (int i = 0; i < array_buffer_contents_.length(); ++i) { | 2138 for (const auto& contents : array_buffer_contents_) { |
| 2158 ArrayBuffer::Contents& contents = array_buffer_contents_[i]; | |
| 2159 if (contents.Data()) { | 2139 if (contents.Data()) { |
| 2160 Shell::array_buffer_allocator->Free(contents.Data(), | 2140 Shell::array_buffer_allocator->Free(contents.Data(), |
| 2161 contents.ByteLength()); | 2141 contents.ByteLength()); |
| 2162 } | 2142 } |
| 2163 } | 2143 } |
| 2164 } | 2144 } |
| 2165 | 2145 |
| 2166 | 2146 void SerializationData::ClearTransferredArrayBuffers() { |
| 2167 void SerializationData::WriteTag(SerializationTag tag) { data_.Add(tag); } | 2147 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 } | 2148 } |
| 2176 | 2149 |
| 2177 | 2150 |
| 2178 void SerializationData::WriteArrayBufferContents( | |
| 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); | |
| 2184 } | |
| 2185 | |
| 2186 | |
| 2187 void SerializationData::WriteSharedArrayBufferContents( | |
| 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) { | 2151 void SerializationDataQueue::Enqueue(SerializationData* data) { |
| 2230 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2152 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2231 data_.Add(data); | 2153 data_.Add(data); |
| 2232 } | 2154 } |
| 2233 | 2155 |
| 2234 | 2156 |
| 2235 bool SerializationDataQueue::Dequeue(SerializationData** data) { | 2157 bool SerializationDataQueue::Dequeue(SerializationData** data) { |
| 2236 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2158 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2237 *data = NULL; | 2159 *data = NULL; |
| 2238 if (data_.is_empty()) return false; | 2160 if (data_.is_empty()) return false; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2358 if (onmessage->IsFunction()) { | 2280 if (onmessage->IsFunction()) { |
| 2359 Local<Function> onmessage_fun = Local<Function>::Cast(onmessage); | 2281 Local<Function> onmessage_fun = Local<Function>::Cast(onmessage); |
| 2360 // Now wait for messages | 2282 // Now wait for messages |
| 2361 while (true) { | 2283 while (true) { |
| 2362 in_semaphore_.Wait(); | 2284 in_semaphore_.Wait(); |
| 2363 SerializationData* data; | 2285 SerializationData* data; |
| 2364 if (!in_queue_.Dequeue(&data)) continue; | 2286 if (!in_queue_.Dequeue(&data)) continue; |
| 2365 if (data == NULL) { | 2287 if (data == NULL) { |
| 2366 break; | 2288 break; |
| 2367 } | 2289 } |
| 2368 int offset = 0; | 2290 Local<Value> value; |
| 2369 Local<Value> data_value; | 2291 if (Shell::DeserializeValue(isolate, data).ToLocal(&value)) { |
|
jbroman
2017/01/24 18:53:43
If an exception is thrown from DeserializeValue, d
binji
2017/01/25 00:31:35
Done.
| |
| 2370 if (Shell::DeserializeValue(isolate, *data, &offset) | 2292 Local<Value> argv[] = {value}; |
| 2371 .ToLocal(&data_value)) { | 2293 v8::TryCatch try_catch(isolate); |
| 2372 Local<Value> argv[] = {data_value}; | |
| 2373 (void)onmessage_fun->Call(context, global, 1, argv); | 2294 (void)onmessage_fun->Call(context, global, 1, argv); |
| 2295 if (try_catch.HasCaught()) { | |
| 2296 Shell::ReportException(isolate, &try_catch); | |
| 2297 } | |
| 2374 } | 2298 } |
| 2375 delete data; | |
| 2376 } | 2299 } |
| 2377 } | 2300 } |
| 2378 } | 2301 } |
| 2379 } | 2302 } |
| 2380 DisposeModuleEmbedderData(context); | 2303 DisposeModuleEmbedderData(context); |
| 2381 } | 2304 } |
| 2382 Shell::CollectGarbage(isolate); | 2305 Shell::CollectGarbage(isolate); |
| 2383 } | 2306 } |
| 2384 isolate->Dispose(); | 2307 isolate->Dispose(); |
| 2385 | 2308 |
| 2386 // Post NULL to wake the thread waiting on GetMessage() if there is one. | 2309 // Post NULL to wake the thread waiting on GetMessage() if there is one. |
| 2387 out_queue_.Enqueue(NULL); | 2310 out_queue_.Enqueue(NULL); |
| 2388 out_semaphore_.Signal(); | 2311 out_semaphore_.Signal(); |
| 2389 } | 2312 } |
| 2390 | 2313 |
| 2391 | 2314 |
| 2392 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) { | 2315 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 2393 Isolate* isolate = args.GetIsolate(); | 2316 Isolate* isolate = args.GetIsolate(); |
| 2394 HandleScope handle_scope(isolate); | 2317 HandleScope handle_scope(isolate); |
| 2395 | 2318 |
| 2396 if (args.Length() < 1) { | 2319 if (args.Length() < 1) { |
| 2397 Throw(isolate, "Invalid argument"); | 2320 Throw(isolate, "Invalid argument"); |
| 2398 return; | 2321 return; |
| 2399 } | 2322 } |
| 2400 | 2323 |
| 2324 SerializationData* data; | |
|
jbroman
2017/01/24 18:53:43
Here and elsewhere: managing this memory by hand m
binji
2017/01/25 00:31:35
At the time when I originally wrote some of this,
| |
| 2401 Local<Value> message = args[0]; | 2325 Local<Value> message = args[0]; |
| 2402 | 2326 Local<Value> transfer = Undefined(isolate); |
| 2403 // TODO(binji): Allow transferring from worker to main thread? | 2327 if (Shell::SerializeValue(isolate, message, transfer).To(&data)) { |
| 2404 Shell::ObjectList to_transfer; | |
| 2405 | |
| 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()); | 2328 DCHECK(args.Data()->IsExternal()); |
| 2411 Local<External> this_value = Local<External>::Cast(args.Data()); | 2329 Local<External> this_value = Local<External>::Cast(args.Data()); |
| 2412 Worker* worker = static_cast<Worker*>(this_value->Value()); | 2330 Worker* worker = static_cast<Worker*>(this_value->Value()); |
| 2413 worker->out_queue_.Enqueue(data); | 2331 worker->out_queue_.Enqueue(data); |
| 2414 worker->out_semaphore_.Signal(); | 2332 worker->out_semaphore_.Signal(); |
| 2415 } else { | |
| 2416 delete data; | |
| 2417 } | 2333 } |
| 2418 } | 2334 } |
| 2419 | 2335 |
| 2420 | 2336 |
| 2421 void SetFlagsFromString(const char* flags) { | 2337 void SetFlagsFromString(const char* flags) { |
| 2422 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); | 2338 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); |
| 2423 } | 2339 } |
| 2424 | 2340 |
| 2425 | 2341 |
| 2426 bool Shell::SetOptions(int argc, char* argv[]) { | 2342 bool Shell::SetOptions(int argc, char* argv[]) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2597 | 2513 |
| 2598 | 2514 |
| 2599 void Shell::EmptyMessageQueues(Isolate* isolate) { | 2515 void Shell::EmptyMessageQueues(Isolate* isolate) { |
| 2600 if (!i::FLAG_verify_predictable) { | 2516 if (!i::FLAG_verify_predictable) { |
| 2601 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; | 2517 while (v8::platform::PumpMessageLoop(g_platform, isolate)) continue; |
| 2602 v8::platform::RunIdleTasks(g_platform, isolate, | 2518 v8::platform::RunIdleTasks(g_platform, isolate, |
| 2603 50.0 / base::Time::kMillisecondsPerSecond); | 2519 50.0 / base::Time::kMillisecondsPerSecond); |
| 2604 } | 2520 } |
| 2605 } | 2521 } |
| 2606 | 2522 |
| 2607 | 2523 class Serializer : public ValueSerializer::Delegate { |
| 2608 bool Shell::SerializeValue(Isolate* isolate, Local<Value> value, | 2524 public: |
| 2609 const ObjectList& to_transfer, | 2525 explicit Serializer(Isolate* isolate) |
| 2610 ObjectList* seen_objects, | 2526 : isolate_(isolate), serializer_(isolate, this), data_(nullptr) {} |
| 2611 SerializationData* out_data) { | 2527 |
| 2612 DCHECK(out_data); | 2528 ~Serializer() { delete data_; } |
| 2529 | |
| 2530 Maybe<bool> WriteValue(Local<Context> context, Local<Value> value, | |
| 2531 Local<Value> transfer) { | |
| 2532 bool ok; | |
| 2533 DCHECK(data_ == nullptr); | |
| 2534 data_ = new SerializationData; | |
| 2535 if (!PrepareTransfer(context, transfer).To(&ok)) { | |
| 2536 return Nothing<bool>(); | |
| 2537 } | |
| 2538 serializer_.WriteHeader(); | |
| 2539 | |
| 2540 if (serializer_.WriteValue(context, value).To(&ok)) { | |
| 2541 if (!FinalizeTransfer().To(&ok)) { | |
| 2542 return Nothing<bool>(); | |
| 2543 } | |
| 2544 | |
| 2545 std::pair<uint8_t*, size_t> pair = serializer_.Release(); | |
| 2546 data_->data_ = pair.first; | |
| 2547 data_->size_ = pair.second; | |
| 2548 return Just(true); | |
| 2549 } else { | |
| 2550 delete data_; | |
| 2551 data_ = nullptr; | |
| 2552 } | |
| 2553 return Nothing<bool>(); | |
| 2554 } | |
| 2555 | |
| 2556 SerializationData* Release() { | |
| 2557 SerializationData* result = data_; | |
| 2558 data_ = nullptr; | |
| 2559 return result; | |
| 2560 } | |
| 2561 | |
| 2562 protected: | |
| 2563 // Implements ValueSerializer::Delegate. | |
| 2564 void ThrowDataCloneError(Local<String> message) override { | |
| 2565 isolate_->ThrowException(Exception::Error(message)); | |
| 2566 } | |
| 2567 | |
| 2568 Maybe<uint32_t> GetSharedArrayBufferId( | |
| 2569 Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) override { | |
| 2570 DCHECK(data_ != nullptr); | |
| 2571 for (size_t index = 0; index < shared_array_buffers_.size(); ++index) { | |
| 2572 if (shared_array_buffers_[index] == shared_array_buffer) { | |
| 2573 return Just<uint32_t>(static_cast<uint32_t>(index)); | |
| 2574 } | |
| 2575 } | |
| 2576 | |
| 2577 size_t index = shared_array_buffers_.size(); | |
| 2578 shared_array_buffers_.emplace_back(isolate_, shared_array_buffer); | |
| 2579 return Just<uint32_t>(static_cast<uint32_t>(index)); | |
| 2580 } | |
| 2581 | |
| 2582 void* ReallocateBufferMemory(void* old_buffer, size_t size, | |
| 2583 size_t* actual_size) override { | |
| 2584 *actual_size = size; | |
| 2585 return realloc(old_buffer, size); | |
| 2586 } | |
| 2587 | |
| 2588 void FreeBufferMemory(void* buffer) override { free(buffer); } | |
| 2589 | |
| 2590 private: | |
| 2591 Maybe<bool> PrepareTransfer(Local<Context> context, Local<Value> transfer) { | |
| 2592 if (transfer->IsArray()) { | |
| 2593 Local<Array> transfer_array = Local<Array>::Cast(transfer); | |
| 2594 uint32_t length = transfer_array->Length(); | |
| 2595 for (uint32_t i = 0; i < length; ++i) { | |
| 2596 Local<Value> element; | |
| 2597 if (transfer_array->Get(context, i).ToLocal(&element)) { | |
|
jbroman
2017/01/24 18:53:43
Not new, but this isn't very resilient against cod
binji
2017/01/25 00:31:35
Good point, added a TryCatch.
| |
| 2598 if (!element->IsArrayBuffer()) { | |
| 2599 Throw(isolate_, "Transfer array elements must be an ArrayBuffer"); | |
| 2600 break; | |
| 2601 } | |
| 2602 | |
| 2603 Local<ArrayBuffer> array_buffer = Local<ArrayBuffer>::Cast(element); | |
| 2604 serializer_.TransferArrayBuffer( | |
| 2605 static_cast<uint32_t>(array_buffers_.size()), array_buffer); | |
| 2606 array_buffers_.emplace_back(isolate_, array_buffer); | |
| 2607 } | |
| 2608 } | |
| 2609 return Just(true); | |
| 2610 } else if (transfer->IsUndefined()) { | |
| 2611 return Just(true); | |
| 2612 } else { | |
| 2613 Throw(isolate_, "Transfer list must be an Array or undefined"); | |
| 2614 return Nothing<bool>(); | |
| 2615 } | |
| 2616 } | |
| 2617 | |
| 2618 Maybe<bool> FinalizeTransfer() { | |
| 2619 for (const auto& global_array_buffer : array_buffers_) { | |
| 2620 Local<ArrayBuffer> array_buffer = | |
| 2621 Local<ArrayBuffer>::New(isolate_, global_array_buffer); | |
| 2622 if (!array_buffer->IsNeuterable()) { | |
| 2623 Throw(isolate_, "ArrayBuffer could not be transferred"); | |
| 2624 return Nothing<bool>(); | |
| 2625 } | |
| 2626 | |
| 2627 if (!array_buffer->IsExternal()) { | |
| 2628 array_buffer->Externalize(); | |
| 2629 } | |
| 2630 ArrayBuffer::Contents contents = array_buffer->GetContents(); | |
| 2631 array_buffer->Neuter(); | |
| 2632 data_->array_buffer_contents_.push_back(contents); | |
| 2633 } | |
| 2634 | |
| 2635 for (const auto& global_shared_array_buffer : shared_array_buffers_) { | |
| 2636 Local<SharedArrayBuffer> shared_array_buffer = | |
| 2637 Local<SharedArrayBuffer>::New(isolate_, global_shared_array_buffer); | |
| 2638 if (!shared_array_buffer->IsExternal()) { | |
| 2639 shared_array_buffer->Externalize(); | |
| 2640 } | |
| 2641 data_->shared_array_buffer_contents_.push_back( | |
| 2642 shared_array_buffer->GetContents()); | |
| 2643 } | |
| 2644 | |
| 2645 return Just(true); | |
| 2646 } | |
| 2647 | |
| 2648 Isolate* isolate_; | |
| 2649 ValueSerializer serializer_; | |
| 2650 SerializationData* data_; | |
| 2651 std::vector<Global<ArrayBuffer>> array_buffers_; | |
| 2652 std::vector<Global<SharedArrayBuffer>> shared_array_buffers_; | |
| 2653 | |
| 2654 DISALLOW_COPY_AND_ASSIGN(Serializer); | |
| 2655 }; | |
| 2656 | |
| 2657 class Deserializer : public ValueDeserializer::Delegate { | |
| 2658 public: | |
| 2659 Deserializer(Isolate* isolate, SerializationData* data) | |
| 2660 : isolate_(isolate), | |
| 2661 deserializer_(isolate, data->data(), data->size(), this), | |
| 2662 data_(data) { | |
| 2663 deserializer_.SetSupportsLegacyWireFormat(true); | |
| 2664 } | |
| 2665 | |
| 2666 ~Deserializer() { delete data_; } | |
| 2667 | |
| 2668 MaybeLocal<Value> ReadValue(Local<Context> context) { | |
| 2669 bool read_header; | |
| 2670 if (!deserializer_.ReadHeader(context).To(&read_header)) { | |
| 2671 return MaybeLocal<Value>(); | |
| 2672 } | |
| 2673 | |
| 2674 uint32_t index = 0; | |
| 2675 for (const auto& contents : data_->array_buffer_contents()) { | |
| 2676 Local<ArrayBuffer> array_buffer = | |
| 2677 ArrayBuffer::New(isolate_, contents.Data(), contents.ByteLength()); | |
| 2678 deserializer_.TransferArrayBuffer(index++, array_buffer); | |
| 2679 } | |
| 2680 | |
| 2681 index = 0; | |
| 2682 for (const auto& contents : data_->shared_array_buffer_contents()) { | |
| 2683 Local<SharedArrayBuffer> shared_array_buffer = SharedArrayBuffer::New( | |
| 2684 isolate_, contents.Data(), contents.ByteLength()); | |
| 2685 deserializer_.TransferSharedArrayBuffer(index++, shared_array_buffer); | |
| 2686 } | |
| 2687 | |
| 2688 MaybeLocal<Value> result = deserializer_.ReadValue(context); | |
| 2689 if (!result.IsEmpty()) { | |
| 2690 data_->ClearTransferredArrayBuffers(); | |
| 2691 } | |
| 2692 return result; | |
| 2693 } | |
| 2694 | |
| 2695 private: | |
| 2696 Isolate* isolate_; | |
| 2697 ValueDeserializer deserializer_; | |
| 2698 SerializationData* data_; | |
| 2699 | |
| 2700 DISALLOW_COPY_AND_ASSIGN(Deserializer); | |
| 2701 }; | |
| 2702 | |
| 2703 Maybe<SerializationData*> Shell::SerializeValue(Isolate* isolate, | |
| 2704 Local<Value> value, | |
| 2705 Local<Value> transfer) { | |
| 2706 bool ok; | |
| 2613 Local<Context> context = isolate->GetCurrentContext(); | 2707 Local<Context> context = isolate->GetCurrentContext(); |
| 2614 | 2708 Serializer serializer(isolate); |
| 2615 if (value->IsUndefined()) { | 2709 if (serializer.WriteValue(context, value, transfer).To(&ok)) { |
| 2616 out_data->WriteTag(kSerializationTagUndefined); | 2710 SerializationData* data = serializer.Release(); |
| 2617 } else if (value->IsNull()) { | 2711 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
| 2618 out_data->WriteTag(kSerializationTagNull); | 2712 for (const auto& contents : data->shared_array_buffer_contents()) { |
| 2619 } else if (value->IsTrue()) { | 2713 externalized_shared_contents_.insert(contents); |
| 2620 out_data->WriteTag(kSerializationTagTrue); | 2714 } |
| 2621 } else if (value->IsFalse()) { | 2715 return Just(data); |
| 2622 out_data->WriteTag(kSerializationTagFalse); | 2716 } |
| 2623 } else if (value->IsNumber()) { | 2717 return Nothing<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 } | 2718 } |
| 2745 | 2719 |
| 2746 | |
| 2747 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, | 2720 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, |
| 2748 const SerializationData& data, | 2721 SerializationData* data) { |
| 2749 int* offset) { | 2722 Local<Value> value; |
| 2750 DCHECK(offset); | 2723 Local<Context> context = isolate->GetCurrentContext(); |
| 2751 EscapableHandleScope scope(isolate); | 2724 Deserializer deserializer(isolate, data); |
| 2752 Local<Value> result; | 2725 if (deserializer.ReadValue(context).ToLocal(&value)) { |
| 2753 SerializationTag tag = data.ReadTag(offset); | 2726 return MaybeLocal<Value>(value); |
| 2754 | 2727 } |
| 2755 switch (tag) { | 2728 return MaybeLocal<Value>(); |
| 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 } | 2729 } |
| 2836 | 2730 |
| 2837 | 2731 |
| 2838 void Shell::CleanupWorkers() { | 2732 void Shell::CleanupWorkers() { |
| 2839 // Make a copy of workers_, because we don't want to call Worker::Terminate | 2733 // 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 | 2734 // while holding the workers_mutex_ lock. Otherwise, if a worker is about to |
| 2841 // create a new Worker, it would deadlock. | 2735 // create a new Worker, it would deadlock. |
| 2842 i::List<Worker*> workers_copy; | 2736 i::List<Worker*> workers_copy; |
| 2843 { | 2737 { |
| 2844 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | 2738 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
| 2845 allow_new_workers_ = false; | 2739 allow_new_workers_ = false; |
| 2846 workers_copy.AddAll(workers_); | 2740 workers_copy.AddAll(workers_); |
| 2847 workers_.Clear(); | 2741 workers_.Clear(); |
| 2848 } | 2742 } |
| 2849 | 2743 |
| 2850 for (int i = 0; i < workers_copy.length(); ++i) { | 2744 for (int i = 0; i < workers_copy.length(); ++i) { |
| 2851 Worker* worker = workers_copy[i]; | 2745 Worker* worker = workers_copy[i]; |
| 2852 worker->WaitForThread(); | 2746 worker->WaitForThread(); |
| 2853 delete worker; | 2747 delete worker; |
| 2854 } | 2748 } |
| 2855 | 2749 |
| 2856 // Now that all workers are terminated, we can re-enable Worker creation. | 2750 // Now that all workers are terminated, we can re-enable Worker creation. |
| 2857 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); | 2751 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); |
| 2858 allow_new_workers_ = true; | 2752 allow_new_workers_ = true; |
| 2859 | 2753 |
| 2860 for (int i = 0; i < externalized_shared_contents_.length(); ++i) { | 2754 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()); | 2755 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength()); |
| 2864 } | 2756 } |
| 2865 externalized_shared_contents_.Clear(); | 2757 externalized_shared_contents_.clear(); |
| 2866 } | 2758 } |
| 2867 | 2759 |
| 2868 | 2760 |
| 2869 static void DumpHeapConstants(i::Isolate* isolate) { | 2761 static void DumpHeapConstants(i::Isolate* isolate) { |
| 2870 i::Heap* heap = isolate->heap(); | 2762 i::Heap* heap = isolate->heap(); |
| 2871 | 2763 |
| 2872 // Dump the INSTANCE_TYPES table to the console. | 2764 // Dump the INSTANCE_TYPES table to the console. |
| 2873 printf("# List of known V8 instance types.\n"); | 2765 printf("# List of known V8 instance types.\n"); |
| 2874 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); | 2766 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); |
| 2875 printf("INSTANCE_TYPES = {\n"); | 2767 printf("INSTANCE_TYPES = {\n"); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3083 } | 2975 } |
| 3084 | 2976 |
| 3085 } // namespace v8 | 2977 } // namespace v8 |
| 3086 | 2978 |
| 3087 | 2979 |
| 3088 #ifndef GOOGLE3 | 2980 #ifndef GOOGLE3 |
| 3089 int main(int argc, char* argv[]) { | 2981 int main(int argc, char* argv[]) { |
| 3090 return v8::Shell::Main(argc, argv); | 2982 return v8::Shell::Main(argc, argv); |
| 3091 } | 2983 } |
| 3092 #endif | 2984 #endif |
| OLD | NEW |