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

Side by Side Diff: src/d8.cc

Issue 1191373005: Revert of Add d8 API for spawning function on a new thread (Second try) (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 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') | test/mjsunit/d8-worker.js » ('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 5
6 // Defined when linking against shared lib on Windows. 6 // Defined when linking against shared lib on Windows.
7 #if defined(USING_V8_SHARED) && !defined(V8_SHARED) 7 #if defined(USING_V8_SHARED) && !defined(V8_SHARED)
8 #define V8_SHARED 8 #define V8_SHARED
9 #endif 9 #endif
10 10
(...skipping 28 matching lines...) Expand all
39 #ifndef V8_SHARED 39 #ifndef V8_SHARED
40 #include "src/api.h" 40 #include "src/api.h"
41 #include "src/base/cpu.h" 41 #include "src/base/cpu.h"
42 #include "src/base/logging.h" 42 #include "src/base/logging.h"
43 #include "src/base/platform/platform.h" 43 #include "src/base/platform/platform.h"
44 #include "src/base/sys-info.h" 44 #include "src/base/sys-info.h"
45 #include "src/basic-block-profiler.h" 45 #include "src/basic-block-profiler.h"
46 #include "src/d8-debug.h" 46 #include "src/d8-debug.h"
47 #include "src/debug.h" 47 #include "src/debug.h"
48 #include "src/snapshot/natives.h" 48 #include "src/snapshot/natives.h"
49 #include "src/utils.h"
50 #include "src/v8.h" 49 #include "src/v8.h"
51 #endif // !V8_SHARED 50 #endif // !V8_SHARED
52 51
53 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 52 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
54 #include "src/startup-data-util.h" 53 #include "src/startup-data-util.h"
55 #endif // V8_USE_EXTERNAL_STARTUP_DATA 54 #endif // V8_USE_EXTERNAL_STARTUP_DATA
56 55
57 #if !defined(_WIN32) && !defined(_WIN64) 56 #if !defined(_WIN32) && !defined(_WIN64)
58 #include <unistd.h> // NOLINT 57 #include <unistd.h> // NOLINT
59 #else 58 #else
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 } 97 }
99 void* AllocateUninitialized(size_t length) override { 98 void* AllocateUninitialized(size_t length) override {
100 return length > 10 * MB ? malloc(1) : malloc(length); 99 return length > 10 * MB ? malloc(1) : malloc(length);
101 } 100 }
102 void Free(void* p, size_t) override { free(p); } 101 void Free(void* p, size_t) override { free(p); }
103 }; 102 };
104 103
105 104
106 v8::Platform* g_platform = NULL; 105 v8::Platform* g_platform = NULL;
107 106
108
109 #ifndef V8_SHARED
110 bool FindInObjectList(Handle<Object> object, const Shell::ObjectList& list) {
111 for (int i = 0; i < list.length(); ++i) {
112 if (list[i]->StrictEquals(object)) {
113 return true;
114 }
115 }
116 return false;
117 }
118 #endif // !V8_SHARED
119
120
121 } // namespace 107 } // namespace
122 108
123 109
124 static Handle<Value> Throw(Isolate* isolate, const char* message) { 110 static Handle<Value> Throw(Isolate* isolate, const char* message) {
125 return isolate->ThrowException(String::NewFromUtf8(isolate, message)); 111 return isolate->ThrowException(String::NewFromUtf8(isolate, message));
126 } 112 }
127 113
128 114
129 115
130 class PerIsolateData { 116 class PerIsolateData {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 184
199 #ifndef V8_SHARED 185 #ifndef V8_SHARED
200 CounterMap* Shell::counter_map_; 186 CounterMap* Shell::counter_map_;
201 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; 187 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
202 CounterCollection Shell::local_counters_; 188 CounterCollection Shell::local_counters_;
203 CounterCollection* Shell::counters_ = &local_counters_; 189 CounterCollection* Shell::counters_ = &local_counters_;
204 base::Mutex Shell::context_mutex_; 190 base::Mutex Shell::context_mutex_;
205 const base::TimeTicks Shell::kInitialTicks = 191 const base::TimeTicks Shell::kInitialTicks =
206 base::TimeTicks::HighResolutionNow(); 192 base::TimeTicks::HighResolutionNow();
207 Persistent<Context> Shell::utility_context_; 193 Persistent<Context> Shell::utility_context_;
208 Worker Shell::worker_;
209 i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_;
210 #endif // !V8_SHARED 194 #endif // !V8_SHARED
211 195
212 Persistent<Context> Shell::evaluation_context_; 196 Persistent<Context> Shell::evaluation_context_;
213 ArrayBuffer::Allocator* Shell::array_buffer_allocator;
214 ShellOptions Shell::options; 197 ShellOptions Shell::options;
215 const char* Shell::kPrompt = "d8> "; 198 const char* Shell::kPrompt = "d8> ";
216 199
217 #ifndef V8_SHARED 200 #ifndef V8_SHARED
218 bool CounterMap::Match(void* key1, void* key2) { 201 bool CounterMap::Match(void* key1, void* key2) {
219 const char* name1 = reinterpret_cast<const char*>(key1); 202 const char* name1 = reinterpret_cast<const char*>(key1);
220 const char* name2 = reinterpret_cast<const char*>(key2); 203 const char* name2 = reinterpret_cast<const char*>(key2);
221 return strcmp(name1, name2) == 0; 204 return strcmp(name1, name2) == 0;
222 } 205 }
223 #endif // !V8_SHARED 206 #endif // !V8_SHARED
(...skipping 12 matching lines...) Expand all
236 uint16_t* source_buffer = new uint16_t[source_length]; 219 uint16_t* source_buffer = new uint16_t[source_length];
237 source->Write(source_buffer, 0, source_length); 220 source->Write(source_buffer, 0, source_length);
238 int name_length = 0; 221 int name_length = 0;
239 uint16_t* name_buffer = NULL; 222 uint16_t* name_buffer = NULL;
240 if (name->IsString()) { 223 if (name->IsString()) {
241 Local<String> name_string = Local<String>::Cast(name); 224 Local<String> name_string = Local<String>::Cast(name);
242 name_length = name_string->Length(); 225 name_length = name_string->Length();
243 name_buffer = new uint16_t[name_length]; 226 name_buffer = new uint16_t[name_length];
244 name_string->Write(name_buffer, 0, name_length); 227 name_string->Write(name_buffer, 0, name_length);
245 } 228 }
229 ShellArrayBufferAllocator allocator;
246 Isolate::CreateParams create_params; 230 Isolate::CreateParams create_params;
247 create_params.array_buffer_allocator = Shell::array_buffer_allocator; 231 create_params.array_buffer_allocator = &allocator;
248 Isolate* temp_isolate = Isolate::New(create_params); 232 Isolate* temp_isolate = Isolate::New(create_params);
249 ScriptCompiler::CachedData* result = NULL; 233 ScriptCompiler::CachedData* result = NULL;
250 { 234 {
251 Isolate::Scope isolate_scope(temp_isolate); 235 Isolate::Scope isolate_scope(temp_isolate);
252 HandleScope handle_scope(temp_isolate); 236 HandleScope handle_scope(temp_isolate);
253 Context::Scope context_scope(Context::New(temp_isolate)); 237 Context::Scope context_scope(Context::New(temp_isolate));
254 Local<String> source_copy = v8::String::NewFromTwoByte( 238 Local<String> source_copy = v8::String::NewFromTwoByte(
255 temp_isolate, source_buffer, v8::String::kNormalString, source_length); 239 temp_isolate, source_buffer, v8::String::kNormalString, source_length);
256 Local<Value> name_copy; 240 Local<Value> name_copy;
257 if (name_buffer) { 241 if (name_buffer) {
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 String::NewFromUtf8(args.GetIsolate(), *file), 654 String::NewFromUtf8(args.GetIsolate(), *file),
671 false, 655 false,
672 true)) { 656 true)) {
673 Throw(args.GetIsolate(), "Error executing file"); 657 Throw(args.GetIsolate(), "Error executing file");
674 return; 658 return;
675 } 659 }
676 } 660 }
677 } 661 }
678 662
679 663
680 #ifndef V8_SHARED
681 void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
682 Isolate* isolate = args.GetIsolate();
683 HandleScope handle_scope(isolate);
684 if (args.Length() < 1 || !args[0]->IsFunction()) {
685 Throw(args.GetIsolate(), "1st argument must be function");
686 return;
687 }
688
689 String::Utf8Value function_string(args[0]->ToString());
690 worker_.StartExecuteInThread(isolate, *function_string);
691 }
692
693
694 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
695 Isolate* isolate = args.GetIsolate();
696 HandleScope handle_scope(isolate);
697 Local<Context> context = isolate->GetCurrentContext();
698
699 if (args.Length() < 1) {
700 Throw(isolate, "Invalid argument");
701 return;
702 }
703
704 Handle<Value> message = args[0];
705 ObjectList to_transfer;
706 if (args.Length() >= 2) {
707 if (!args[1]->IsArray()) {
708 Throw(isolate, "Transfer list must be an Array");
709 return;
710 }
711
712 Handle<Array> transfer = Handle<Array>::Cast(args[1]);
713 uint32_t length = transfer->Length();
714 for (uint32_t i = 0; i < length; ++i) {
715 Handle<Value> element;
716 if (transfer->Get(context, i).ToLocal(&element)) {
717 if (!element->IsArrayBuffer() && !element->IsSharedArrayBuffer()) {
718 Throw(isolate,
719 "Transfer array elements must be an ArrayBuffer or "
720 "SharedArrayBuffer.");
721 break;
722 }
723
724 to_transfer.Add(Handle<Object>::Cast(element));
725 }
726 }
727 }
728
729 ObjectList seen_objects;
730 SerializationData* data = new SerializationData;
731 if (SerializeValue(isolate, message, to_transfer, &seen_objects, data)) {
732 worker_.PostMessage(data);
733 } else {
734 delete data;
735 }
736 }
737
738
739 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
740 Isolate* isolate = args.GetIsolate();
741 HandleScope handle_scope(isolate);
742 SerializationData* data = worker_.GetMessage();
743 if (data) {
744 int offset = 0;
745 Local<Value> data_value;
746 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) {
747 args.GetReturnValue().Set(data_value);
748 }
749 delete data;
750 }
751 }
752
753
754 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
755 worker_.Terminate();
756 }
757 #endif // !V8_SHARED
758
759
760 void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) { 664 void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
761 int exit_code = args[0]->Int32Value(); 665 int exit_code = args[0]->Int32Value();
762 OnExit(args.GetIsolate()); 666 OnExit(args.GetIsolate());
763 exit(exit_code); 667 exit(exit_code);
764 } 668 }
765 669
766 670
767 void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) { 671 void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
768 args.GetReturnValue().Set( 672 args.GetReturnValue().Set(
769 String::NewFromUtf8(args.GetIsolate(), V8::GetVersion())); 673 String::NewFromUtf8(args.GetIsolate(), V8::GetVersion()));
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 realm_template->SetAccessor(String::NewFromUtf8(isolate, "shared"), 985 realm_template->SetAccessor(String::NewFromUtf8(isolate, "shared"),
1082 RealmSharedGet, RealmSharedSet); 986 RealmSharedGet, RealmSharedSet);
1083 global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template); 987 global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template);
1084 988
1085 #ifndef V8_SHARED 989 #ifndef V8_SHARED
1086 Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate); 990 Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate);
1087 performance_template->Set(String::NewFromUtf8(isolate, "now"), 991 performance_template->Set(String::NewFromUtf8(isolate, "now"),
1088 FunctionTemplate::New(isolate, PerformanceNow)); 992 FunctionTemplate::New(isolate, PerformanceNow));
1089 global_template->Set(String::NewFromUtf8(isolate, "performance"), 993 global_template->Set(String::NewFromUtf8(isolate, "performance"),
1090 performance_template); 994 performance_template);
1091
1092 Handle<FunctionTemplate> worker_fun_template =
1093 FunctionTemplate::New(isolate, WorkerNew);
1094 worker_fun_template->PrototypeTemplate()->Set(
1095 String::NewFromUtf8(isolate, "terminate"),
1096 FunctionTemplate::New(isolate, WorkerTerminate));
1097 worker_fun_template->PrototypeTemplate()->Set(
1098 String::NewFromUtf8(isolate, "postMessage"),
1099 FunctionTemplate::New(isolate, WorkerPostMessage));
1100 worker_fun_template->PrototypeTemplate()->Set(
1101 String::NewFromUtf8(isolate, "getMessage"),
1102 FunctionTemplate::New(isolate, WorkerGetMessage));
1103 global_template->Set(String::NewFromUtf8(isolate, "Worker"),
1104 worker_fun_template);
1105 #endif // !V8_SHARED 995 #endif // !V8_SHARED
1106 996
1107 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate); 997 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
1108 AddOSMethods(isolate, os_templ); 998 AddOSMethods(isolate, os_templ);
1109 global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ); 999 global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ);
1110 1000
1111 return global_template; 1001 return global_template;
1112 } 1002 }
1113 1003
1114 1004
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 base::Thread::Options SourceGroup::GetThreadOptions() { 1318 base::Thread::Options SourceGroup::GetThreadOptions() {
1429 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less 1319 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
1430 // which is not enough to parse the big literal expressions used in tests. 1320 // which is not enough to parse the big literal expressions used in tests.
1431 // The stack size should be at least StackGuard::kLimitSize + some 1321 // The stack size should be at least StackGuard::kLimitSize + some
1432 // OS-specific padding for thread startup code. 2Mbytes seems to be enough. 1322 // OS-specific padding for thread startup code. 2Mbytes seems to be enough.
1433 return base::Thread::Options("IsolateThread", 2 * MB); 1323 return base::Thread::Options("IsolateThread", 2 * MB);
1434 } 1324 }
1435 1325
1436 1326
1437 void SourceGroup::ExecuteInThread() { 1327 void SourceGroup::ExecuteInThread() {
1328 ShellArrayBufferAllocator allocator;
1438 Isolate::CreateParams create_params; 1329 Isolate::CreateParams create_params;
1439 create_params.array_buffer_allocator = Shell::array_buffer_allocator; 1330 create_params.array_buffer_allocator = &allocator;
1440 Isolate* isolate = Isolate::New(create_params); 1331 Isolate* isolate = Isolate::New(create_params);
1441 do { 1332 do {
1442 next_semaphore_.Wait(); 1333 next_semaphore_.Wait();
1443 { 1334 {
1444 Isolate::Scope iscope(isolate); 1335 Isolate::Scope iscope(isolate);
1445 { 1336 {
1446 HandleScope scope(isolate); 1337 HandleScope scope(isolate);
1447 PerIsolateData data(isolate); 1338 PerIsolateData data(isolate);
1448 Local<Context> context = Shell::CreateEvaluationContext(isolate); 1339 Local<Context> context = Shell::CreateEvaluationContext(isolate);
1449 { 1340 {
(...skipping 21 matching lines...) Expand all
1471 1362
1472 1363
1473 void SourceGroup::WaitForThread() { 1364 void SourceGroup::WaitForThread() {
1474 if (thread_ == NULL) return; 1365 if (thread_ == NULL) return;
1475 if (Shell::options.last_run) { 1366 if (Shell::options.last_run) {
1476 thread_->Join(); 1367 thread_->Join();
1477 } else { 1368 } else {
1478 done_semaphore_.Wait(); 1369 done_semaphore_.Wait();
1479 } 1370 }
1480 } 1371 }
1481
1482
1483 SerializationData::~SerializationData() {
1484 // Any ArrayBuffer::Contents are owned by this SerializationData object.
1485 // SharedArrayBuffer::Contents may be used by other threads, so must be
1486 // cleaned up by the main thread in Shell::CleanupWorkers().
1487 for (int i = 0; i < array_buffer_contents.length(); ++i) {
1488 ArrayBuffer::Contents& contents = array_buffer_contents[i];
1489 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
1490 }
1491 }
1492
1493
1494 void SerializationData::WriteTag(SerializationTag tag) { data.Add(tag); }
1495
1496
1497 void SerializationData::WriteMemory(const void* p, int length) {
1498 i::Vector<uint8_t> block = data.AddBlock(0, length);
1499 memcpy(&block[0], p, length);
1500 }
1501
1502
1503 void SerializationData::WriteArrayBufferContents(
1504 const ArrayBuffer::Contents& contents) {
1505 array_buffer_contents.Add(contents);
1506 WriteTag(kSerializationTagTransferredArrayBuffer);
1507 int index = array_buffer_contents.length() - 1;
1508 Write(index);
1509 }
1510
1511
1512 void SerializationData::WriteSharedArrayBufferContents(
1513 const SharedArrayBuffer::Contents& contents) {
1514 shared_array_buffer_contents.Add(contents);
1515 WriteTag(kSerializationTagTransferredSharedArrayBuffer);
1516 int index = shared_array_buffer_contents.length() - 1;
1517 Write(index);
1518 }
1519
1520
1521 SerializationTag SerializationData::ReadTag(int* offset) const {
1522 return static_cast<SerializationTag>(Read<uint8_t>(offset));
1523 }
1524
1525
1526 void SerializationData::ReadMemory(void* p, int length, int* offset) const {
1527 memcpy(p, &data[*offset], length);
1528 (*offset) += length;
1529 }
1530
1531
1532 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
1533 int* offset) const {
1534 int index = Read<int>(offset);
1535 DCHECK(index < array_buffer_contents.length());
1536 *contents = array_buffer_contents[index];
1537 }
1538
1539
1540 void SerializationData::ReadSharedArrayBufferContents(
1541 SharedArrayBuffer::Contents* contents, int* offset) const {
1542 int index = Read<int>(offset);
1543 DCHECK(index < shared_array_buffer_contents.length());
1544 *contents = shared_array_buffer_contents[index];
1545 }
1546
1547
1548 void SerializationDataQueue::Enqueue(SerializationData* data) {
1549 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1550 data_.Add(data);
1551 }
1552
1553
1554 bool SerializationDataQueue::Dequeue(SerializationData** data) {
1555 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1556 if (data_.is_empty()) return false;
1557 *data = data_.Remove(0);
1558 return true;
1559 }
1560
1561
1562 bool SerializationDataQueue::IsEmpty() {
1563 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1564 return data_.is_empty();
1565 }
1566
1567
1568 void SerializationDataQueue::Clear() {
1569 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1570 for (int i = 0; i < data_.length(); ++i) {
1571 delete data_[i];
1572 }
1573 data_.Clear();
1574 }
1575
1576
1577 Worker::Worker()
1578 : in_semaphore_(0), out_semaphore_(0), thread_(NULL), script_(NULL) {}
1579
1580
1581 Worker::~Worker() { Cleanup(); }
1582
1583
1584 void Worker::StartExecuteInThread(Isolate* isolate,
1585 const char* function_string) {
1586 if (thread_) {
1587 Throw(isolate, "Only one worker allowed");
1588 return;
1589 }
1590
1591 static const char format[] = "(%s).call(this);";
1592 size_t len = strlen(function_string) + sizeof(format);
1593
1594 script_ = new char[len + 1];
1595 i::Vector<char> vec(script_, static_cast<int>(len + 1));
1596 i::SNPrintF(vec, format, function_string);
1597
1598 thread_ = new WorkerThread(this);
1599 thread_->Start();
1600 }
1601
1602
1603 void Worker::PostMessage(SerializationData* data) {
1604 in_queue_.Enqueue(data);
1605 in_semaphore_.Signal();
1606 }
1607
1608
1609 SerializationData* Worker::GetMessage() {
1610 SerializationData* data;
1611 while (!out_queue_.Dequeue(&data)) {
1612 out_semaphore_.Wait();
1613 }
1614
1615 return data;
1616 }
1617
1618
1619 void Worker::Terminate() {
1620 if (thread_ == NULL) return;
1621 PostMessage(NULL);
1622 thread_->Join();
1623 Cleanup();
1624 }
1625
1626
1627 void Worker::ExecuteInThread() {
1628 Isolate::CreateParams create_params;
1629 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
1630 Isolate* isolate = Isolate::New(create_params);
1631 {
1632 Isolate::Scope iscope(isolate);
1633 {
1634 HandleScope scope(isolate);
1635 PerIsolateData data(isolate);
1636 Local<Context> context = Shell::CreateEvaluationContext(isolate);
1637 {
1638 Context::Scope cscope(context);
1639 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1640
1641 Handle<Object> global = context->Global();
1642 Handle<Value> this_value = External::New(isolate, this);
1643 Handle<FunctionTemplate> postmessage_fun_template =
1644 FunctionTemplate::New(isolate, PostMessageOut, this_value);
1645
1646 Handle<Function> postmessage_fun;
1647 if (postmessage_fun_template->GetFunction(context)
1648 .ToLocal(&postmessage_fun)) {
1649 global->Set(String::NewFromUtf8(isolate, "postMessage"),
1650 postmessage_fun);
1651 }
1652
1653 // First run the script
1654 Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed");
1655 Handle<String> source = String::NewFromUtf8(isolate, script_);
1656 Shell::ExecuteString(isolate, source, file_name, false, true);
1657
1658 // Get the message handler
1659 Handle<Value> onmessage =
1660 global->Get(String::NewFromUtf8(isolate, "onmessage"));
1661 if (onmessage->IsFunction()) {
1662 Handle<Function> onmessage_fun = Handle<Function>::Cast(onmessage);
1663 // Now wait for messages
1664 bool done = false;
1665 while (!done) {
1666 in_semaphore_.Wait();
1667 SerializationData* data;
1668 if (!in_queue_.Dequeue(&data)) continue;
1669 if (data == NULL) {
1670 done = true;
1671 break;
1672 }
1673 int offset = 0;
1674 Local<Value> data_value;
1675 if (Shell::DeserializeValue(isolate, *data, &offset)
1676 .ToLocal(&data_value)) {
1677 Handle<Value> argv[] = {data_value};
1678 (void)onmessage_fun->Call(context, global, 1, argv);
1679 }
1680 delete data;
1681 }
1682 }
1683 }
1684 }
1685 }
1686 Shell::CollectGarbage(isolate);
1687 isolate->Dispose();
1688 }
1689
1690
1691 void Worker::Cleanup() {
1692 delete thread_;
1693 thread_ = NULL;
1694 delete[] script_;
1695 script_ = NULL;
1696 in_queue_.Clear();
1697 out_queue_.Clear();
1698 }
1699
1700
1701 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
1702 Isolate* isolate = args.GetIsolate();
1703 HandleScope handle_scope(isolate);
1704
1705 if (args.Length() < 1) {
1706 Throw(isolate, "Invalid argument");
1707 return;
1708 }
1709
1710 Handle<Value> message = args[0];
1711
1712 // TODO(binji): Allow transferring from worker to main thread?
1713 Shell::ObjectList to_transfer;
1714
1715 Shell::ObjectList seen_objects;
1716 SerializationData* data = new SerializationData;
1717 if (Shell::SerializeValue(isolate, message, to_transfer, &seen_objects,
1718 data)) {
1719 DCHECK(args.Data()->IsExternal());
1720 Handle<External> this_value = Handle<External>::Cast(args.Data());
1721 Worker* worker = static_cast<Worker*>(this_value->Value());
1722 worker->out_queue_.Enqueue(data);
1723 worker->out_semaphore_.Signal();
1724 } else {
1725 delete data;
1726 }
1727 }
1728 #endif // !V8_SHARED 1372 #endif // !V8_SHARED
1729 1373
1730 1374
1731 void SetFlagsFromString(const char* flags) { 1375 void SetFlagsFromString(const char* flags) {
1732 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); 1376 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
1733 } 1377 }
1734 1378
1735 1379
1736 bool Shell::SetOptions(int argc, char* argv[]) { 1380 bool Shell::SetOptions(int argc, char* argv[]) {
1737 bool logfile_per_isolate = false; 1381 bool logfile_per_isolate = false;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 Context::Scope cscope(context); 1536 Context::Scope cscope(context);
1893 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); 1537 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1894 options.isolate_sources[0].Execute(isolate); 1538 options.isolate_sources[0].Execute(isolate);
1895 } 1539 }
1896 } 1540 }
1897 CollectGarbage(isolate); 1541 CollectGarbage(isolate);
1898 #ifndef V8_SHARED 1542 #ifndef V8_SHARED
1899 for (int i = 1; i < options.num_isolates; ++i) { 1543 for (int i = 1; i < options.num_isolates; ++i) {
1900 options.isolate_sources[i].WaitForThread(); 1544 options.isolate_sources[i].WaitForThread();
1901 } 1545 }
1902 CleanupWorkers();
1903 #endif // !V8_SHARED 1546 #endif // !V8_SHARED
1904 return 0; 1547 return 0;
1905 } 1548 }
1906 1549
1907 1550
1908 void Shell::CollectGarbage(Isolate* isolate) { 1551 void Shell::CollectGarbage(Isolate* isolate) {
1909 if (options.send_idle_notification) { 1552 if (options.send_idle_notification) {
1910 const double kLongIdlePauseInSeconds = 1.0; 1553 const double kLongIdlePauseInSeconds = 1.0;
1911 isolate->ContextDisposedNotification(); 1554 isolate->ContextDisposedNotification();
1912 isolate->IdleNotificationDeadline( 1555 isolate->IdleNotificationDeadline(
1913 g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds); 1556 g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds);
1914 } 1557 }
1915 if (options.invoke_weak_callbacks) { 1558 if (options.invoke_weak_callbacks) {
1916 // By sending a low memory notifications, we will try hard to collect all 1559 // By sending a low memory notifications, we will try hard to collect all
1917 // garbage and will therefore also invoke all weak callbacks of actually 1560 // garbage and will therefore also invoke all weak callbacks of actually
1918 // unreachable persistent handles. 1561 // unreachable persistent handles.
1919 isolate->LowMemoryNotification(); 1562 isolate->LowMemoryNotification();
1920 } 1563 }
1921 } 1564 }
1922 1565
1923 1566
1924 #ifndef V8_SHARED 1567 #ifndef V8_SHARED
1925 bool Shell::SerializeValue(Isolate* isolate, Handle<Value> value,
1926 const ObjectList& to_transfer,
1927 ObjectList* seen_objects,
1928 SerializationData* out_data) {
1929 DCHECK(out_data);
1930 HandleScope scope(isolate);
1931 Local<Context> context = isolate->GetCurrentContext();
1932
1933 if (value->IsUndefined()) {
1934 out_data->WriteTag(kSerializationTagUndefined);
1935 } else if (value->IsNull()) {
1936 out_data->WriteTag(kSerializationTagNull);
1937 } else if (value->IsTrue()) {
1938 out_data->WriteTag(kSerializationTagTrue);
1939 } else if (value->IsFalse()) {
1940 out_data->WriteTag(kSerializationTagFalse);
1941 } else if (value->IsNumber()) {
1942 Handle<Number> num = Handle<Number>::Cast(value);
1943 double value = num->Value();
1944 out_data->WriteTag(kSerializationTagNumber);
1945 out_data->Write(value);
1946 } else if (value->IsString()) {
1947 v8::String::Utf8Value str(value);
1948 out_data->WriteTag(kSerializationTagString);
1949 out_data->Write(str.length());
1950 out_data->WriteMemory(*str, str.length());
1951 } else if (value->IsArray()) {
1952 Handle<Array> array = Handle<Array>::Cast(value);
1953 if (FindInObjectList(array, *seen_objects)) {
1954 Throw(isolate, "Duplicated arrays not supported");
1955 return false;
1956 }
1957 seen_objects->Add(array);
1958 out_data->WriteTag(kSerializationTagArray);
1959 uint32_t length = array->Length();
1960 out_data->Write(length);
1961 for (uint32_t i = 0; i < length; ++i) {
1962 Local<Value> element_value;
1963 if (array->Get(context, i).ToLocal(&element_value)) {
1964 if (!SerializeValue(isolate, element_value, to_transfer, seen_objects,
1965 out_data))
1966 return false;
1967 }
1968 }
1969 } else if (value->IsArrayBuffer()) {
1970 Handle<ArrayBuffer> array_buffer = Handle<ArrayBuffer>::Cast(value);
1971 if (FindInObjectList(array_buffer, *seen_objects)) {
1972 Throw(isolate, "Duplicated array buffers not supported");
1973 return false;
1974 }
1975 seen_objects->Add(array_buffer);
1976 if (FindInObjectList(array_buffer, to_transfer)) {
1977 // Transfer ArrayBuffer
1978 if (!array_buffer->IsNeuterable()) {
1979 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
1980 return false;
1981 }
1982
1983 ArrayBuffer::Contents contents = array_buffer->Externalize();
1984 array_buffer->Neuter();
1985 out_data->WriteArrayBufferContents(contents);
1986 } else {
1987 ArrayBuffer::Contents contents = array_buffer->GetContents();
1988 // Clone ArrayBuffer
1989 if (contents.ByteLength() > i::kMaxUInt32) {
1990 Throw(isolate, "ArrayBuffer is too big to clone");
1991 return false;
1992 }
1993
1994 int byte_length = static_cast<int>(contents.ByteLength());
1995 out_data->WriteTag(kSerializationTagArrayBuffer);
1996 out_data->Write(byte_length);
1997 out_data->WriteMemory(contents.Data(),
1998 static_cast<int>(contents.ByteLength()));
1999 }
2000 } else if (value->IsSharedArrayBuffer()) {
2001 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value);
2002 if (FindInObjectList(sab, *seen_objects)) {
2003 Throw(isolate, "Duplicated shared array buffers not supported");
2004 return false;
2005 }
2006 seen_objects->Add(sab);
2007 if (!FindInObjectList(sab, to_transfer)) {
2008 Throw(isolate, "SharedArrayBuffer must be transferred");
2009 return false;
2010 }
2011
2012 SharedArrayBuffer::Contents contents = sab->Externalize();
2013 out_data->WriteSharedArrayBufferContents(contents);
2014 externalized_shared_contents_.Add(contents);
2015 } else if (value->IsObject()) {
2016 Handle<Object> object = Handle<Object>::Cast(value);
2017 if (FindInObjectList(object, *seen_objects)) {
2018 Throw(isolate, "Duplicated objects not supported");
2019 return false;
2020 }
2021 seen_objects->Add(object);
2022 Local<Array> property_names;
2023 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
2024 Throw(isolate, "Unable to get property names");
2025 return false;
2026 }
2027
2028 uint32_t length = property_names->Length();
2029 out_data->WriteTag(kSerializationTagObject);
2030 out_data->Write(length);
2031 for (uint32_t i = 0; i < length; ++i) {
2032 Handle<Value> name;
2033 Handle<Value> property_value;
2034 if (property_names->Get(context, i).ToLocal(&name) &&
2035 object->Get(context, name).ToLocal(&property_value)) {
2036 if (!SerializeValue(isolate, name, to_transfer, seen_objects, out_data))
2037 return false;
2038 if (!SerializeValue(isolate, property_value, to_transfer, seen_objects,
2039 out_data))
2040 return false;
2041 }
2042 }
2043 } else {
2044 Throw(isolate, "Don't know how to serialize object");
2045 return false;
2046 }
2047
2048 return true;
2049 }
2050
2051
2052 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate,
2053 const SerializationData& data,
2054 int* offset) {
2055 DCHECK(offset);
2056 EscapableHandleScope scope(isolate);
2057 // This function should not use utility_context_ because it is running on a
2058 // different thread.
2059 Local<Value> result;
2060 SerializationTag tag = data.ReadTag(offset);
2061
2062 switch (tag) {
2063 case kSerializationTagUndefined:
2064 result = Undefined(isolate);
2065 break;
2066 case kSerializationTagNull:
2067 result = Null(isolate);
2068 break;
2069 case kSerializationTagTrue:
2070 result = True(isolate);
2071 break;
2072 case kSerializationTagFalse:
2073 result = False(isolate);
2074 break;
2075 case kSerializationTagNumber:
2076 result = Number::New(isolate, data.Read<double>(offset));
2077 break;
2078 case kSerializationTagString: {
2079 int length = data.Read<int>(offset);
2080 static char s_buffer[128];
2081 char* p = s_buffer;
2082 bool allocated = false;
2083 if (length > static_cast<int>(sizeof(s_buffer))) {
2084 p = new char[length];
2085 allocated = true;
2086 }
2087 data.ReadMemory(p, length, offset);
2088 MaybeLocal<String> str =
2089 String::NewFromUtf8(isolate, p, String::kNormalString, length);
2090 if (!str.IsEmpty()) result = str.ToLocalChecked();
2091 if (allocated) delete[] p;
2092 break;
2093 }
2094 case kSerializationTagArray: {
2095 uint32_t length = data.Read<uint32_t>(offset);
2096 Handle<Array> array = Array::New(isolate, length);
2097 for (uint32_t i = 0; i < length; ++i) {
2098 Local<Value> element_value;
2099 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value));
2100 array->Set(i, element_value);
2101 }
2102 result = array;
2103 break;
2104 }
2105 case kSerializationTagObject: {
2106 int length = data.Read<int>(offset);
2107 Handle<Object> object = Object::New(isolate);
2108 for (int i = 0; i < length; ++i) {
2109 Local<Value> property_name;
2110 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_name));
2111 DCHECK(property_name->IsString());
2112 Local<Value> property_value;
2113 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_value));
2114 object->Set(property_name, property_value);
2115 }
2116 result = object;
2117 break;
2118 }
2119 case kSerializationTagArrayBuffer: {
2120 int byte_length = data.Read<int>(offset);
2121 Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
2122 ArrayBuffer::Contents contents = array_buffer->GetContents();
2123 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
2124 data.ReadMemory(contents.Data(), byte_length, offset);
2125 result = array_buffer;
2126 break;
2127 }
2128 case kSerializationTagTransferredArrayBuffer: {
2129 ArrayBuffer::Contents contents;
2130 data.ReadArrayBufferContents(&contents, offset);
2131 result =
2132 ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength());
2133 break;
2134 }
2135 case kSerializationTagTransferredSharedArrayBuffer: {
2136 SharedArrayBuffer::Contents contents;
2137 data.ReadSharedArrayBufferContents(&contents, offset);
2138 result = SharedArrayBuffer::New(isolate, contents.Data(),
2139 contents.ByteLength());
2140 break;
2141 }
2142 default:
2143 UNREACHABLE();
2144 }
2145
2146 return scope.Escape(result);
2147 }
2148
2149
2150 void Shell::CleanupWorkers() {
2151 worker_.Terminate();
2152 for (int i = 0; i < externalized_shared_contents_.length(); ++i) {
2153 const SharedArrayBuffer::Contents& contents =
2154 externalized_shared_contents_[i];
2155 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
2156 }
2157 externalized_shared_contents_.Clear();
2158 }
2159
2160
2161 static void DumpHeapConstants(i::Isolate* isolate) { 1568 static void DumpHeapConstants(i::Isolate* isolate) {
2162 i::Heap* heap = isolate->heap(); 1569 i::Heap* heap = isolate->heap();
2163 1570
2164 // Dump the INSTANCE_TYPES table to the console. 1571 // Dump the INSTANCE_TYPES table to the console.
2165 printf("# List of known V8 instance types.\n"); 1572 printf("# List of known V8 instance types.\n");
2166 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); 1573 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
2167 printf("INSTANCE_TYPES = {\n"); 1574 printf("INSTANCE_TYPES = {\n");
2168 INSTANCE_TYPE_LIST(DUMP_TYPE) 1575 INSTANCE_TYPE_LIST(DUMP_TYPE)
2169 printf("}\n"); 1576 printf("}\n");
2170 #undef DUMP_TYPE 1577 #undef DUMP_TYPE
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2237 v8::V8::Initialize(); 1644 v8::V8::Initialize();
2238 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 1645 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
2239 v8::StartupDataHandler startup_data(argv[0], options.natives_blob, 1646 v8::StartupDataHandler startup_data(argv[0], options.natives_blob,
2240 options.snapshot_blob); 1647 options.snapshot_blob);
2241 #endif 1648 #endif
2242 SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg"); 1649 SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg");
2243 SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg"); 1650 SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg");
2244 SetFlagsFromString("--redirect-code-traces-to=code.asm"); 1651 SetFlagsFromString("--redirect-code-traces-to=code.asm");
2245 int result = 0; 1652 int result = 0;
2246 Isolate::CreateParams create_params; 1653 Isolate::CreateParams create_params;
2247 ShellArrayBufferAllocator shell_array_buffer_allocator; 1654 ShellArrayBufferAllocator array_buffer_allocator;
2248 MockArrayBufferAllocator mock_arraybuffer_allocator; 1655 MockArrayBufferAllocator mock_arraybuffer_allocator;
2249 if (options.mock_arraybuffer_allocator) { 1656 if (options.mock_arraybuffer_allocator) {
2250 Shell::array_buffer_allocator = &mock_arraybuffer_allocator; 1657 create_params.array_buffer_allocator = &mock_arraybuffer_allocator;
2251 } else { 1658 } else {
2252 Shell::array_buffer_allocator = &shell_array_buffer_allocator; 1659 create_params.array_buffer_allocator = &array_buffer_allocator;
2253 } 1660 }
2254 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
2255 #if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE) 1661 #if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
2256 if (i::FLAG_gdbjit) { 1662 if (i::FLAG_gdbjit) {
2257 create_params.code_event_handler = i::GDBJITInterface::EventHandler; 1663 create_params.code_event_handler = i::GDBJITInterface::EventHandler;
2258 } 1664 }
2259 #endif 1665 #endif
2260 #ifdef ENABLE_VTUNE_JIT_INTERFACE 1666 #ifdef ENABLE_VTUNE_JIT_INTERFACE
2261 create_params.code_event_handler = vTune::GetVtuneCodeEventHandler(); 1667 create_params.code_event_handler = vTune::GetVtuneCodeEventHandler();
2262 #endif 1668 #endif
2263 #ifndef V8_SHARED 1669 #ifndef V8_SHARED
2264 create_params.constraints.ConfigureDefaults( 1670 create_params.constraints.ConfigureDefaults(
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2349 } 1755 }
2350 1756
2351 } // namespace v8 1757 } // namespace v8
2352 1758
2353 1759
2354 #ifndef GOOGLE3 1760 #ifndef GOOGLE3
2355 int main(int argc, char* argv[]) { 1761 int main(int argc, char* argv[]) {
2356 return v8::Shell::Main(argc, argv); 1762 return v8::Shell::Main(argc, argv);
2357 } 1763 }
2358 #endif 1764 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698