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

Side by Side Diff: src/d8.cc

Issue 2657403002: Revert of [d8] Use ValueSerializer for postMessage (instead of ad-hoc serializer) (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/d8.h ('k') | src/messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 13 matching lines...) Expand all
24 #include "include/libplatform/v8-tracing.h" 24 #include "include/libplatform/v8-tracing.h"
25 #include "src/api.h" 25 #include "src/api.h"
26 #include "src/base/cpu.h" 26 #include "src/base/cpu.h"
27 #include "src/base/debug/stack_trace.h" 27 #include "src/base/debug/stack_trace.h"
28 #include "src/base/logging.h" 28 #include "src/base/logging.h"
29 #include "src/base/platform/platform.h" 29 #include "src/base/platform/platform.h"
30 #include "src/base/platform/time.h" 30 #include "src/base/platform/time.h"
31 #include "src/base/sys-info.h" 31 #include "src/base/sys-info.h"
32 #include "src/basic-block-profiler.h" 32 #include "src/basic-block-profiler.h"
33 #include "src/interpreter/interpreter.h" 33 #include "src/interpreter/interpreter.h"
34 #include "src/list-inl.h"
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/d8.h ('k') | src/messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698