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

Side by Side Diff: src/d8.cc

Issue 1192923002: Add support for multiple Workers in d8 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: multiple Workers 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"
49 #include "src/v8.h" 50 #include "src/v8.h"
50 #endif // !V8_SHARED 51 #endif // !V8_SHARED
51 52
52 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 53 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
53 #include "src/startup-data-util.h" 54 #include "src/startup-data-util.h"
54 #endif // V8_USE_EXTERNAL_STARTUP_DATA 55 #endif // V8_USE_EXTERNAL_STARTUP_DATA
55 56
56 #if !defined(_WIN32) && !defined(_WIN64) 57 #if !defined(_WIN32) && !defined(_WIN64)
57 #include <unistd.h> // NOLINT 58 #include <unistd.h> // NOLINT
58 #else 59 #else
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 } 98 }
98 void* AllocateUninitialized(size_t length) override { 99 void* AllocateUninitialized(size_t length) override {
99 return length > 10 * MB ? malloc(1) : malloc(length); 100 return length > 10 * MB ? malloc(1) : malloc(length);
100 } 101 }
101 void Free(void* p, size_t) override { free(p); } 102 void Free(void* p, size_t) override { free(p); }
102 }; 103 };
103 104
104 105
105 v8::Platform* g_platform = NULL; 106 v8::Platform* g_platform = NULL;
106 107
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
107 } // namespace 121 } // namespace
108 122
109 123
110 static Handle<Value> Throw(Isolate* isolate, const char* message) { 124 static Handle<Value> Throw(Isolate* isolate, const char* message) {
111 return isolate->ThrowException(String::NewFromUtf8(isolate, message)); 125 return isolate->ThrowException(String::NewFromUtf8(isolate, message));
112 } 126 }
113 127
114 128
115 129
116 class PerIsolateData { 130 class PerIsolateData {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 198
185 #ifndef V8_SHARED 199 #ifndef V8_SHARED
186 CounterMap* Shell::counter_map_; 200 CounterMap* Shell::counter_map_;
187 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; 201 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
188 CounterCollection Shell::local_counters_; 202 CounterCollection Shell::local_counters_;
189 CounterCollection* Shell::counters_ = &local_counters_; 203 CounterCollection* Shell::counters_ = &local_counters_;
190 base::Mutex Shell::context_mutex_; 204 base::Mutex Shell::context_mutex_;
191 const base::TimeTicks Shell::kInitialTicks = 205 const base::TimeTicks Shell::kInitialTicks =
192 base::TimeTicks::HighResolutionNow(); 206 base::TimeTicks::HighResolutionNow();
193 Persistent<Context> Shell::utility_context_; 207 Persistent<Context> Shell::utility_context_;
208 i::List<Worker*> Shell::workers_;
209 i::List<SharedArrayBuffer::Contents> Shell::externalized_shared_contents_;
194 #endif // !V8_SHARED 210 #endif // !V8_SHARED
195 211
196 Persistent<Context> Shell::evaluation_context_; 212 Persistent<Context> Shell::evaluation_context_;
213 ArrayBuffer::Allocator* Shell::array_buffer_allocator;
197 ShellOptions Shell::options; 214 ShellOptions Shell::options;
198 const char* Shell::kPrompt = "d8> "; 215 const char* Shell::kPrompt = "d8> ";
199 216
200 #ifndef V8_SHARED 217 #ifndef V8_SHARED
201 bool CounterMap::Match(void* key1, void* key2) { 218 bool CounterMap::Match(void* key1, void* key2) {
202 const char* name1 = reinterpret_cast<const char*>(key1); 219 const char* name1 = reinterpret_cast<const char*>(key1);
203 const char* name2 = reinterpret_cast<const char*>(key2); 220 const char* name2 = reinterpret_cast<const char*>(key2);
204 return strcmp(name1, name2) == 0; 221 return strcmp(name1, name2) == 0;
205 } 222 }
206 #endif // !V8_SHARED 223 #endif // !V8_SHARED
(...skipping 12 matching lines...) Expand all
219 uint16_t* source_buffer = new uint16_t[source_length]; 236 uint16_t* source_buffer = new uint16_t[source_length];
220 source->Write(source_buffer, 0, source_length); 237 source->Write(source_buffer, 0, source_length);
221 int name_length = 0; 238 int name_length = 0;
222 uint16_t* name_buffer = NULL; 239 uint16_t* name_buffer = NULL;
223 if (name->IsString()) { 240 if (name->IsString()) {
224 Local<String> name_string = Local<String>::Cast(name); 241 Local<String> name_string = Local<String>::Cast(name);
225 name_length = name_string->Length(); 242 name_length = name_string->Length();
226 name_buffer = new uint16_t[name_length]; 243 name_buffer = new uint16_t[name_length];
227 name_string->Write(name_buffer, 0, name_length); 244 name_string->Write(name_buffer, 0, name_length);
228 } 245 }
229 ShellArrayBufferAllocator allocator;
230 Isolate::CreateParams create_params; 246 Isolate::CreateParams create_params;
231 create_params.array_buffer_allocator = &allocator; 247 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
232 Isolate* temp_isolate = Isolate::New(create_params); 248 Isolate* temp_isolate = Isolate::New(create_params);
233 ScriptCompiler::CachedData* result = NULL; 249 ScriptCompiler::CachedData* result = NULL;
234 { 250 {
235 Isolate::Scope isolate_scope(temp_isolate); 251 Isolate::Scope isolate_scope(temp_isolate);
236 HandleScope handle_scope(temp_isolate); 252 HandleScope handle_scope(temp_isolate);
237 Context::Scope context_scope(Context::New(temp_isolate)); 253 Context::Scope context_scope(Context::New(temp_isolate));
238 Local<String> source_copy = v8::String::NewFromTwoByte( 254 Local<String> source_copy = v8::String::NewFromTwoByte(
239 temp_isolate, source_buffer, v8::String::kNormalString, source_length); 255 temp_isolate, source_buffer, v8::String::kNormalString, source_length);
240 Local<Value> name_copy; 256 Local<Value> name_copy;
241 if (name_buffer) { 257 if (name_buffer) {
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 String::NewFromUtf8(args.GetIsolate(), *file), 670 String::NewFromUtf8(args.GetIsolate(), *file),
655 false, 671 false,
656 true)) { 672 true)) {
657 Throw(args.GetIsolate(), "Error executing file"); 673 Throw(args.GetIsolate(), "Error executing file");
658 return; 674 return;
659 } 675 }
660 } 676 }
661 } 677 }
662 678
663 679
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 Worker* worker = new Worker;
690 args.This()->SetInternalField(0, External::New(isolate, worker));
691 workers_.Add(worker);
692
693 String::Utf8Value function_string(args[0]->ToString());
694 worker->StartExecuteInThread(isolate, *function_string);
695 }
696
697
698 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
699 Isolate* isolate = args.GetIsolate();
700 HandleScope handle_scope(isolate);
701 Local<Context> context = isolate->GetCurrentContext();
702
703 if (args.Length() < 1) {
704 Throw(isolate, "Invalid argument");
705 return;
706 }
707
708 Local<Value> this_value = args.This()->GetInternalField(0);
709 if (!this_value->IsExternal()) {
710 Throw(isolate, "this is not a Worker");
711 return;
712 }
713
714 Worker* worker =
715 static_cast<Worker*>(Local<External>::Cast(this_value)->Value());
716
717 Handle<Value> message = args[0];
718 ObjectList to_transfer;
719 if (args.Length() >= 2) {
720 if (!args[1]->IsArray()) {
721 Throw(isolate, "Transfer list must be an Array");
722 return;
723 }
724
725 Handle<Array> transfer = Handle<Array>::Cast(args[1]);
726 uint32_t length = transfer->Length();
727 for (uint32_t i = 0; i < length; ++i) {
728 Handle<Value> element;
729 if (transfer->Get(context, i).ToLocal(&element)) {
730 if (!element->IsArrayBuffer() && !element->IsSharedArrayBuffer()) {
731 Throw(isolate,
732 "Transfer array elements must be an ArrayBuffer or "
733 "SharedArrayBuffer.");
734 break;
735 }
736
737 to_transfer.Add(Handle<Object>::Cast(element));
738 }
739 }
740 }
741
742 ObjectList seen_objects;
743 SerializationData* data = new SerializationData;
744 if (SerializeValue(isolate, message, to_transfer, &seen_objects, data)) {
745 worker->PostMessage(data);
746 } else {
747 delete data;
748 }
749 }
750
751
752 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
753 Isolate* isolate = args.GetIsolate();
754 HandleScope handle_scope(isolate);
755
756 Local<Value> this_value = args.This()->GetInternalField(0);
757 if (!this_value->IsExternal()) {
758 Throw(isolate, "this is not a Worker");
759 return;
760 }
761
762 Worker* worker =
763 static_cast<Worker*>(Local<External>::Cast(this_value)->Value());
764
765 SerializationData* data = worker->GetMessage();
766 if (data) {
767 int offset = 0;
768 Local<Value> data_value;
769 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) {
770 args.GetReturnValue().Set(data_value);
771 }
772 delete data;
773 }
774 }
775
776
777 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
778 Isolate* isolate = args.GetIsolate();
779 HandleScope handle_scope(isolate);
780 Local<Value> this_value = args.This()->GetInternalField(0);
781 if (!this_value->IsExternal()) {
782 Throw(isolate, "this is not a Worker");
783 return;
784 }
785
786 Worker* worker =
787 static_cast<Worker*>(Local<External>::Cast(this_value)->Value());
788 worker->Terminate();
789 workers_.RemoveElement(worker);
790 delete worker;
791 }
792 #endif // !V8_SHARED
793
794
664 void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) { 795 void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
665 int exit_code = args[0]->Int32Value(); 796 int exit_code = args[0]->Int32Value();
666 OnExit(args.GetIsolate()); 797 OnExit(args.GetIsolate());
667 exit(exit_code); 798 exit(exit_code);
668 } 799 }
669 800
670 801
671 void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) { 802 void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
672 args.GetReturnValue().Set( 803 args.GetReturnValue().Set(
673 String::NewFromUtf8(args.GetIsolate(), V8::GetVersion())); 804 String::NewFromUtf8(args.GetIsolate(), V8::GetVersion()));
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 realm_template->SetAccessor(String::NewFromUtf8(isolate, "shared"), 1116 realm_template->SetAccessor(String::NewFromUtf8(isolate, "shared"),
986 RealmSharedGet, RealmSharedSet); 1117 RealmSharedGet, RealmSharedSet);
987 global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template); 1118 global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template);
988 1119
989 #ifndef V8_SHARED 1120 #ifndef V8_SHARED
990 Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate); 1121 Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate);
991 performance_template->Set(String::NewFromUtf8(isolate, "now"), 1122 performance_template->Set(String::NewFromUtf8(isolate, "now"),
992 FunctionTemplate::New(isolate, PerformanceNow)); 1123 FunctionTemplate::New(isolate, PerformanceNow));
993 global_template->Set(String::NewFromUtf8(isolate, "performance"), 1124 global_template->Set(String::NewFromUtf8(isolate, "performance"),
994 performance_template); 1125 performance_template);
1126
1127 Handle<FunctionTemplate> worker_fun_template =
1128 FunctionTemplate::New(isolate, WorkerNew);
1129 worker_fun_template->PrototypeTemplate()->Set(
1130 String::NewFromUtf8(isolate, "terminate"),
1131 FunctionTemplate::New(isolate, WorkerTerminate));
1132 worker_fun_template->PrototypeTemplate()->Set(
1133 String::NewFromUtf8(isolate, "postMessage"),
1134 FunctionTemplate::New(isolate, WorkerPostMessage));
1135 worker_fun_template->PrototypeTemplate()->Set(
1136 String::NewFromUtf8(isolate, "getMessage"),
1137 FunctionTemplate::New(isolate, WorkerGetMessage));
1138 worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1);
1139 global_template->Set(String::NewFromUtf8(isolate, "Worker"),
1140 worker_fun_template);
995 #endif // !V8_SHARED 1141 #endif // !V8_SHARED
996 1142
997 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate); 1143 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
998 AddOSMethods(isolate, os_templ); 1144 AddOSMethods(isolate, os_templ);
999 global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ); 1145 global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ);
1000 1146
1001 return global_template; 1147 return global_template;
1002 } 1148 }
1003 1149
1004 1150
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 base::Thread::Options SourceGroup::GetThreadOptions() { 1464 base::Thread::Options SourceGroup::GetThreadOptions() {
1319 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less 1465 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
1320 // which is not enough to parse the big literal expressions used in tests. 1466 // which is not enough to parse the big literal expressions used in tests.
1321 // The stack size should be at least StackGuard::kLimitSize + some 1467 // The stack size should be at least StackGuard::kLimitSize + some
1322 // OS-specific padding for thread startup code. 2Mbytes seems to be enough. 1468 // OS-specific padding for thread startup code. 2Mbytes seems to be enough.
1323 return base::Thread::Options("IsolateThread", 2 * MB); 1469 return base::Thread::Options("IsolateThread", 2 * MB);
1324 } 1470 }
1325 1471
1326 1472
1327 void SourceGroup::ExecuteInThread() { 1473 void SourceGroup::ExecuteInThread() {
1328 ShellArrayBufferAllocator allocator;
1329 Isolate::CreateParams create_params; 1474 Isolate::CreateParams create_params;
1330 create_params.array_buffer_allocator = &allocator; 1475 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
1331 Isolate* isolate = Isolate::New(create_params); 1476 Isolate* isolate = Isolate::New(create_params);
1332 do { 1477 do {
1333 next_semaphore_.Wait(); 1478 next_semaphore_.Wait();
1334 { 1479 {
1335 Isolate::Scope iscope(isolate); 1480 Isolate::Scope iscope(isolate);
1336 { 1481 {
1337 HandleScope scope(isolate); 1482 HandleScope scope(isolate);
1338 PerIsolateData data(isolate); 1483 PerIsolateData data(isolate);
1339 Local<Context> context = Shell::CreateEvaluationContext(isolate); 1484 Local<Context> context = Shell::CreateEvaluationContext(isolate);
1340 { 1485 {
(...skipping 21 matching lines...) Expand all
1362 1507
1363 1508
1364 void SourceGroup::WaitForThread() { 1509 void SourceGroup::WaitForThread() {
1365 if (thread_ == NULL) return; 1510 if (thread_ == NULL) return;
1366 if (Shell::options.last_run) { 1511 if (Shell::options.last_run) {
1367 thread_->Join(); 1512 thread_->Join();
1368 } else { 1513 } else {
1369 done_semaphore_.Wait(); 1514 done_semaphore_.Wait();
1370 } 1515 }
1371 } 1516 }
1517
1518
1519 SerializationData::~SerializationData() {
1520 // Any ArrayBuffer::Contents are owned by this SerializationData object.
1521 // SharedArrayBuffer::Contents may be used by other threads, so must be
1522 // cleaned up by the main thread in Shell::CleanupWorkers().
1523 for (int i = 0; i < array_buffer_contents.length(); ++i) {
1524 ArrayBuffer::Contents& contents = array_buffer_contents[i];
1525 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
1526 }
1527 }
1528
1529
1530 void SerializationData::WriteTag(SerializationTag tag) { data.Add(tag); }
1531
1532
1533 void SerializationData::WriteMemory(const void* p, int length) {
1534 i::Vector<uint8_t> block = data.AddBlock(0, length);
1535 memcpy(&block[0], p, length);
1536 }
1537
1538
1539 void SerializationData::WriteArrayBufferContents(
1540 const ArrayBuffer::Contents& contents) {
1541 array_buffer_contents.Add(contents);
1542 WriteTag(kSerializationTagTransferredArrayBuffer);
1543 int index = array_buffer_contents.length() - 1;
1544 Write(index);
1545 }
1546
1547
1548 void SerializationData::WriteSharedArrayBufferContents(
1549 const SharedArrayBuffer::Contents& contents) {
1550 shared_array_buffer_contents.Add(contents);
1551 WriteTag(kSerializationTagTransferredSharedArrayBuffer);
1552 int index = shared_array_buffer_contents.length() - 1;
1553 Write(index);
1554 }
1555
1556
1557 SerializationTag SerializationData::ReadTag(int* offset) const {
1558 return static_cast<SerializationTag>(Read<uint8_t>(offset));
1559 }
1560
1561
1562 void SerializationData::ReadMemory(void* p, int length, int* offset) const {
1563 memcpy(p, &data[*offset], length);
1564 (*offset) += length;
1565 }
1566
1567
1568 void SerializationData::ReadArrayBufferContents(ArrayBuffer::Contents* contents,
1569 int* offset) const {
1570 int index = Read<int>(offset);
1571 DCHECK(index < array_buffer_contents.length());
1572 *contents = array_buffer_contents[index];
1573 }
1574
1575
1576 void SerializationData::ReadSharedArrayBufferContents(
1577 SharedArrayBuffer::Contents* contents, int* offset) const {
1578 int index = Read<int>(offset);
1579 DCHECK(index < shared_array_buffer_contents.length());
1580 *contents = shared_array_buffer_contents[index];
1581 }
1582
1583
1584 void SerializationDataQueue::Enqueue(SerializationData* data) {
1585 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1586 data_.Add(data);
1587 }
1588
1589
1590 bool SerializationDataQueue::Dequeue(SerializationData** data) {
1591 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1592 if (data_.is_empty()) return false;
1593 *data = data_.Remove(0);
1594 return true;
1595 }
1596
1597
1598 bool SerializationDataQueue::IsEmpty() {
1599 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1600 return data_.is_empty();
1601 }
1602
1603
1604 void SerializationDataQueue::Clear() {
1605 base::LockGuard<base::Mutex> lock_guard(&mutex_);
1606 for (int i = 0; i < data_.length(); ++i) {
1607 delete data_[i];
1608 }
1609 data_.Clear();
1610 }
1611
1612
1613 Worker::Worker()
1614 : in_semaphore_(0), out_semaphore_(0), thread_(NULL), script_(NULL) {}
1615
1616
1617 Worker::~Worker() { Cleanup(); }
1618
1619
1620 void Worker::StartExecuteInThread(Isolate* isolate,
1621 const char* function_string) {
1622 if (thread_) {
1623 Throw(isolate, "Only one worker allowed");
1624 return;
1625 }
1626
1627 static const char format[] = "(%s).call(this);";
1628 size_t len = strlen(function_string) + sizeof(format);
1629
1630 script_ = new char[len + 1];
1631 i::Vector<char> vec(script_, static_cast<int>(len + 1));
1632 i::SNPrintF(vec, format, function_string);
1633
1634 thread_ = new WorkerThread(this);
1635 thread_->Start();
1636 }
1637
1638
1639 void Worker::PostMessage(SerializationData* data) {
1640 in_queue_.Enqueue(data);
1641 in_semaphore_.Signal();
1642 }
1643
1644
1645 SerializationData* Worker::GetMessage() {
1646 SerializationData* data;
1647 while (!out_queue_.Dequeue(&data)) {
1648 out_semaphore_.Wait();
1649 }
1650
1651 return data;
1652 }
1653
1654
1655 void Worker::Terminate() {
1656 if (thread_ == NULL) return;
1657 PostMessage(NULL);
1658 thread_->Join();
1659 Cleanup();
1660 }
1661
1662
1663 void Worker::ExecuteInThread() {
1664 Isolate::CreateParams create_params;
1665 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
1666 Isolate* isolate = Isolate::New(create_params);
1667 {
1668 Isolate::Scope iscope(isolate);
1669 {
1670 HandleScope scope(isolate);
1671 PerIsolateData data(isolate);
1672 Local<Context> context = Shell::CreateEvaluationContext(isolate);
1673 {
1674 Context::Scope cscope(context);
1675 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1676
1677 Handle<Object> global = context->Global();
1678 Handle<Value> this_value = External::New(isolate, this);
1679 Handle<FunctionTemplate> postmessage_fun_template =
1680 FunctionTemplate::New(isolate, PostMessageOut, this_value);
1681
1682 Handle<Function> postmessage_fun;
1683 if (postmessage_fun_template->GetFunction(context)
1684 .ToLocal(&postmessage_fun)) {
1685 global->Set(String::NewFromUtf8(isolate, "postMessage"),
1686 postmessage_fun);
1687 }
1688
1689 // First run the script
1690 Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed");
1691 Handle<String> source = String::NewFromUtf8(isolate, script_);
1692 Shell::ExecuteString(isolate, source, file_name, false, true);
1693
1694 // Get the message handler
1695 Handle<Value> onmessage =
1696 global->Get(String::NewFromUtf8(isolate, "onmessage"));
1697 if (onmessage->IsFunction()) {
1698 Handle<Function> onmessage_fun = Handle<Function>::Cast(onmessage);
1699 // Now wait for messages
1700 bool done = false;
1701 while (!done) {
1702 in_semaphore_.Wait();
1703 SerializationData* data;
1704 if (!in_queue_.Dequeue(&data)) continue;
1705 if (data == NULL) {
1706 done = true;
1707 break;
1708 }
1709 int offset = 0;
1710 Local<Value> data_value;
1711 if (Shell::DeserializeValue(isolate, *data, &offset)
1712 .ToLocal(&data_value)) {
1713 Handle<Value> argv[] = {data_value};
1714 (void)onmessage_fun->Call(context, global, 1, argv);
1715 }
1716 delete data;
1717 }
1718 }
1719 }
1720 }
1721 }
1722 Shell::CollectGarbage(isolate);
1723 isolate->Dispose();
1724 }
1725
1726
1727 void Worker::Cleanup() {
1728 delete thread_;
1729 thread_ = NULL;
1730 delete[] script_;
1731 script_ = NULL;
1732 in_queue_.Clear();
1733 out_queue_.Clear();
1734 }
1735
1736
1737 void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args) {
1738 Isolate* isolate = args.GetIsolate();
1739 HandleScope handle_scope(isolate);
1740
1741 if (args.Length() < 1) {
1742 Throw(isolate, "Invalid argument");
1743 return;
1744 }
1745
1746 Handle<Value> message = args[0];
1747
1748 // TODO(binji): Allow transferring from worker to main thread?
1749 Shell::ObjectList to_transfer;
1750
1751 Shell::ObjectList seen_objects;
1752 SerializationData* data = new SerializationData;
1753 if (Shell::SerializeValue(isolate, message, to_transfer, &seen_objects,
1754 data)) {
1755 DCHECK(args.Data()->IsExternal());
1756 Handle<External> this_value = Handle<External>::Cast(args.Data());
1757 Worker* worker = static_cast<Worker*>(this_value->Value());
1758 worker->out_queue_.Enqueue(data);
1759 worker->out_semaphore_.Signal();
1760 } else {
1761 delete data;
1762 }
1763 }
1372 #endif // !V8_SHARED 1764 #endif // !V8_SHARED
1373 1765
1374 1766
1375 void SetFlagsFromString(const char* flags) { 1767 void SetFlagsFromString(const char* flags) {
1376 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); 1768 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
1377 } 1769 }
1378 1770
1379 1771
1380 bool Shell::SetOptions(int argc, char* argv[]) { 1772 bool Shell::SetOptions(int argc, char* argv[]) {
1381 bool logfile_per_isolate = false; 1773 bool logfile_per_isolate = false;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 Context::Scope cscope(context); 1928 Context::Scope cscope(context);
1537 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); 1929 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1538 options.isolate_sources[0].Execute(isolate); 1930 options.isolate_sources[0].Execute(isolate);
1539 } 1931 }
1540 } 1932 }
1541 CollectGarbage(isolate); 1933 CollectGarbage(isolate);
1542 #ifndef V8_SHARED 1934 #ifndef V8_SHARED
1543 for (int i = 1; i < options.num_isolates; ++i) { 1935 for (int i = 1; i < options.num_isolates; ++i) {
1544 options.isolate_sources[i].WaitForThread(); 1936 options.isolate_sources[i].WaitForThread();
1545 } 1937 }
1938 CleanupWorkers();
1546 #endif // !V8_SHARED 1939 #endif // !V8_SHARED
1547 return 0; 1940 return 0;
1548 } 1941 }
1549 1942
1550 1943
1551 void Shell::CollectGarbage(Isolate* isolate) { 1944 void Shell::CollectGarbage(Isolate* isolate) {
1552 if (options.send_idle_notification) { 1945 if (options.send_idle_notification) {
1553 const double kLongIdlePauseInSeconds = 1.0; 1946 const double kLongIdlePauseInSeconds = 1.0;
1554 isolate->ContextDisposedNotification(); 1947 isolate->ContextDisposedNotification();
1555 isolate->IdleNotificationDeadline( 1948 isolate->IdleNotificationDeadline(
1556 g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds); 1949 g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds);
1557 } 1950 }
1558 if (options.invoke_weak_callbacks) { 1951 if (options.invoke_weak_callbacks) {
1559 // By sending a low memory notifications, we will try hard to collect all 1952 // By sending a low memory notifications, we will try hard to collect all
1560 // garbage and will therefore also invoke all weak callbacks of actually 1953 // garbage and will therefore also invoke all weak callbacks of actually
1561 // unreachable persistent handles. 1954 // unreachable persistent handles.
1562 isolate->LowMemoryNotification(); 1955 isolate->LowMemoryNotification();
1563 } 1956 }
1564 } 1957 }
1565 1958
1566 1959
1567 #ifndef V8_SHARED 1960 #ifndef V8_SHARED
1961 bool Shell::SerializeValue(Isolate* isolate, Handle<Value> value,
1962 const ObjectList& to_transfer,
1963 ObjectList* seen_objects,
1964 SerializationData* out_data) {
1965 DCHECK(out_data);
1966 HandleScope scope(isolate);
1967 Local<Context> context = isolate->GetCurrentContext();
1968
1969 if (value->IsUndefined()) {
1970 out_data->WriteTag(kSerializationTagUndefined);
1971 } else if (value->IsNull()) {
1972 out_data->WriteTag(kSerializationTagNull);
1973 } else if (value->IsTrue()) {
1974 out_data->WriteTag(kSerializationTagTrue);
1975 } else if (value->IsFalse()) {
1976 out_data->WriteTag(kSerializationTagFalse);
1977 } else if (value->IsNumber()) {
1978 Handle<Number> num = Handle<Number>::Cast(value);
1979 double value = num->Value();
1980 out_data->WriteTag(kSerializationTagNumber);
1981 out_data->Write(value);
1982 } else if (value->IsString()) {
1983 v8::String::Utf8Value str(value);
1984 out_data->WriteTag(kSerializationTagString);
1985 out_data->Write(str.length());
1986 out_data->WriteMemory(*str, str.length());
1987 } else if (value->IsArray()) {
1988 Handle<Array> array = Handle<Array>::Cast(value);
1989 if (FindInObjectList(array, *seen_objects)) {
1990 Throw(isolate, "Duplicated arrays not supported");
1991 return false;
1992 }
1993 seen_objects->Add(array);
1994 out_data->WriteTag(kSerializationTagArray);
1995 uint32_t length = array->Length();
1996 out_data->Write(length);
1997 for (uint32_t i = 0; i < length; ++i) {
1998 Local<Value> element_value;
1999 if (array->Get(context, i).ToLocal(&element_value)) {
2000 if (!SerializeValue(isolate, element_value, to_transfer, seen_objects,
2001 out_data))
2002 return false;
2003 }
2004 }
2005 } else if (value->IsArrayBuffer()) {
2006 Handle<ArrayBuffer> array_buffer = Handle<ArrayBuffer>::Cast(value);
2007 if (FindInObjectList(array_buffer, *seen_objects)) {
2008 Throw(isolate, "Duplicated array buffers not supported");
2009 return false;
2010 }
2011 seen_objects->Add(array_buffer);
2012 if (FindInObjectList(array_buffer, to_transfer)) {
2013 // Transfer ArrayBuffer
2014 if (!array_buffer->IsNeuterable()) {
2015 Throw(isolate, "Attempting to transfer an un-neuterable ArrayBuffer");
2016 return false;
2017 }
2018
2019 ArrayBuffer::Contents contents = array_buffer->Externalize();
2020 array_buffer->Neuter();
2021 out_data->WriteArrayBufferContents(contents);
2022 } else {
2023 ArrayBuffer::Contents contents = array_buffer->GetContents();
2024 // Clone ArrayBuffer
2025 if (contents.ByteLength() > i::kMaxUInt32) {
2026 Throw(isolate, "ArrayBuffer is too big to clone");
2027 return false;
2028 }
2029
2030 int byte_length = static_cast<int>(contents.ByteLength());
2031 out_data->WriteTag(kSerializationTagArrayBuffer);
2032 out_data->Write(byte_length);
2033 out_data->WriteMemory(contents.Data(),
2034 static_cast<int>(contents.ByteLength()));
2035 }
2036 } else if (value->IsSharedArrayBuffer()) {
2037 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(value);
2038 if (FindInObjectList(sab, *seen_objects)) {
2039 Throw(isolate, "Duplicated shared array buffers not supported");
2040 return false;
2041 }
2042 seen_objects->Add(sab);
2043 if (!FindInObjectList(sab, to_transfer)) {
2044 Throw(isolate, "SharedArrayBuffer must be transferred");
2045 return false;
2046 }
2047
2048 SharedArrayBuffer::Contents contents = sab->Externalize();
2049 out_data->WriteSharedArrayBufferContents(contents);
2050 externalized_shared_contents_.Add(contents);
2051 } else if (value->IsObject()) {
2052 Handle<Object> object = Handle<Object>::Cast(value);
2053 if (FindInObjectList(object, *seen_objects)) {
2054 Throw(isolate, "Duplicated objects not supported");
2055 return false;
2056 }
2057 seen_objects->Add(object);
2058 Local<Array> property_names;
2059 if (!object->GetOwnPropertyNames(context).ToLocal(&property_names)) {
2060 Throw(isolate, "Unable to get property names");
2061 return false;
2062 }
2063
2064 uint32_t length = property_names->Length();
2065 out_data->WriteTag(kSerializationTagObject);
2066 out_data->Write(length);
2067 for (uint32_t i = 0; i < length; ++i) {
2068 Handle<Value> name;
2069 Handle<Value> property_value;
2070 if (property_names->Get(context, i).ToLocal(&name) &&
2071 object->Get(context, name).ToLocal(&property_value)) {
2072 if (!SerializeValue(isolate, name, to_transfer, seen_objects, out_data))
2073 return false;
2074 if (!SerializeValue(isolate, property_value, to_transfer, seen_objects,
2075 out_data))
2076 return false;
2077 }
2078 }
2079 } else {
2080 Throw(isolate, "Don't know how to serialize object");
2081 return false;
2082 }
2083
2084 return true;
2085 }
2086
2087
2088 MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate,
2089 const SerializationData& data,
2090 int* offset) {
2091 DCHECK(offset);
2092 EscapableHandleScope scope(isolate);
2093 // This function should not use utility_context_ because it is running on a
2094 // different thread.
2095 Local<Value> result;
2096 SerializationTag tag = data.ReadTag(offset);
2097
2098 switch (tag) {
2099 case kSerializationTagUndefined:
2100 result = Undefined(isolate);
2101 break;
2102 case kSerializationTagNull:
2103 result = Null(isolate);
2104 break;
2105 case kSerializationTagTrue:
2106 result = True(isolate);
2107 break;
2108 case kSerializationTagFalse:
2109 result = False(isolate);
2110 break;
2111 case kSerializationTagNumber:
2112 result = Number::New(isolate, data.Read<double>(offset));
2113 break;
2114 case kSerializationTagString: {
2115 int length = data.Read<int>(offset);
2116 static char s_buffer[128];
2117 char* p = s_buffer;
2118 bool allocated = false;
2119 if (length > static_cast<int>(sizeof(s_buffer))) {
2120 p = new char[length];
2121 allocated = true;
2122 }
2123 data.ReadMemory(p, length, offset);
2124 MaybeLocal<String> str =
2125 String::NewFromUtf8(isolate, p, String::kNormalString, length);
2126 if (!str.IsEmpty()) result = str.ToLocalChecked();
2127 if (allocated) delete[] p;
2128 break;
2129 }
2130 case kSerializationTagArray: {
2131 uint32_t length = data.Read<uint32_t>(offset);
2132 Handle<Array> array = Array::New(isolate, length);
2133 for (uint32_t i = 0; i < length; ++i) {
2134 Local<Value> element_value;
2135 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&element_value));
2136 array->Set(i, element_value);
2137 }
2138 result = array;
2139 break;
2140 }
2141 case kSerializationTagObject: {
2142 int length = data.Read<int>(offset);
2143 Handle<Object> object = Object::New(isolate);
2144 for (int i = 0; i < length; ++i) {
2145 Local<Value> property_name;
2146 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_name));
2147 DCHECK(property_name->IsString());
2148 Local<Value> property_value;
2149 CHECK(DeserializeValue(isolate, data, offset).ToLocal(&property_value));
2150 object->Set(property_name, property_value);
2151 }
2152 result = object;
2153 break;
2154 }
2155 case kSerializationTagArrayBuffer: {
2156 int byte_length = data.Read<int>(offset);
2157 Handle<ArrayBuffer> array_buffer = ArrayBuffer::New(isolate, byte_length);
2158 ArrayBuffer::Contents contents = array_buffer->GetContents();
2159 DCHECK(static_cast<size_t>(byte_length) == contents.ByteLength());
2160 data.ReadMemory(contents.Data(), byte_length, offset);
2161 result = array_buffer;
2162 break;
2163 }
2164 case kSerializationTagTransferredArrayBuffer: {
2165 ArrayBuffer::Contents contents;
2166 data.ReadArrayBufferContents(&contents, offset);
2167 result =
2168 ArrayBuffer::New(isolate, contents.Data(), contents.ByteLength());
2169 break;
2170 }
2171 case kSerializationTagTransferredSharedArrayBuffer: {
2172 SharedArrayBuffer::Contents contents;
2173 data.ReadSharedArrayBufferContents(&contents, offset);
2174 result = SharedArrayBuffer::New(isolate, contents.Data(),
2175 contents.ByteLength());
2176 break;
2177 }
2178 default:
2179 UNREACHABLE();
2180 }
2181
2182 return scope.Escape(result);
2183 }
2184
2185
2186 void Shell::CleanupWorkers() {
2187 for (int i = 0; i < workers_.length(); ++i) {
2188 Worker* worker = workers_[i];
2189 worker->Terminate();
2190 delete worker;
2191 }
2192 workers_.Clear();
2193
2194 for (int i = 0; i < externalized_shared_contents_.length(); ++i) {
2195 const SharedArrayBuffer::Contents& contents =
2196 externalized_shared_contents_[i];
2197 Shell::array_buffer_allocator->Free(contents.Data(), contents.ByteLength());
2198 }
2199 externalized_shared_contents_.Clear();
2200 }
2201
2202
1568 static void DumpHeapConstants(i::Isolate* isolate) { 2203 static void DumpHeapConstants(i::Isolate* isolate) {
1569 i::Heap* heap = isolate->heap(); 2204 i::Heap* heap = isolate->heap();
1570 2205
1571 // Dump the INSTANCE_TYPES table to the console. 2206 // Dump the INSTANCE_TYPES table to the console.
1572 printf("# List of known V8 instance types.\n"); 2207 printf("# List of known V8 instance types.\n");
1573 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); 2208 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
1574 printf("INSTANCE_TYPES = {\n"); 2209 printf("INSTANCE_TYPES = {\n");
1575 INSTANCE_TYPE_LIST(DUMP_TYPE) 2210 INSTANCE_TYPE_LIST(DUMP_TYPE)
1576 printf("}\n"); 2211 printf("}\n");
1577 #undef DUMP_TYPE 2212 #undef DUMP_TYPE
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1644 v8::V8::Initialize(); 2279 v8::V8::Initialize();
1645 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 2280 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
1646 v8::StartupDataHandler startup_data(argv[0], options.natives_blob, 2281 v8::StartupDataHandler startup_data(argv[0], options.natives_blob,
1647 options.snapshot_blob); 2282 options.snapshot_blob);
1648 #endif 2283 #endif
1649 SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg"); 2284 SetFlagsFromString("--trace-hydrogen-file=hydrogen.cfg");
1650 SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg"); 2285 SetFlagsFromString("--trace-turbo-cfg-file=turbo.cfg");
1651 SetFlagsFromString("--redirect-code-traces-to=code.asm"); 2286 SetFlagsFromString("--redirect-code-traces-to=code.asm");
1652 int result = 0; 2287 int result = 0;
1653 Isolate::CreateParams create_params; 2288 Isolate::CreateParams create_params;
1654 ShellArrayBufferAllocator array_buffer_allocator; 2289 ShellArrayBufferAllocator shell_array_buffer_allocator;
1655 MockArrayBufferAllocator mock_arraybuffer_allocator; 2290 MockArrayBufferAllocator mock_arraybuffer_allocator;
1656 if (options.mock_arraybuffer_allocator) { 2291 if (options.mock_arraybuffer_allocator) {
1657 create_params.array_buffer_allocator = &mock_arraybuffer_allocator; 2292 Shell::array_buffer_allocator = &mock_arraybuffer_allocator;
1658 } else { 2293 } else {
1659 create_params.array_buffer_allocator = &array_buffer_allocator; 2294 Shell::array_buffer_allocator = &shell_array_buffer_allocator;
1660 } 2295 }
2296 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
1661 #if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE) 2297 #if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
1662 if (i::FLAG_gdbjit) { 2298 if (i::FLAG_gdbjit) {
1663 create_params.code_event_handler = i::GDBJITInterface::EventHandler; 2299 create_params.code_event_handler = i::GDBJITInterface::EventHandler;
1664 } 2300 }
1665 #endif 2301 #endif
1666 #ifdef ENABLE_VTUNE_JIT_INTERFACE 2302 #ifdef ENABLE_VTUNE_JIT_INTERFACE
1667 create_params.code_event_handler = vTune::GetVtuneCodeEventHandler(); 2303 create_params.code_event_handler = vTune::GetVtuneCodeEventHandler();
1668 #endif 2304 #endif
1669 #ifndef V8_SHARED 2305 #ifndef V8_SHARED
1670 create_params.constraints.ConfigureDefaults( 2306 create_params.constraints.ConfigureDefaults(
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 } 2391 }
1756 2392
1757 } // namespace v8 2393 } // namespace v8
1758 2394
1759 2395
1760 #ifndef GOOGLE3 2396 #ifndef GOOGLE3
1761 int main(int argc, char* argv[]) { 2397 int main(int argc, char* argv[]) {
1762 return v8::Shell::Main(argc, argv); 2398 return v8::Shell::Main(argc, argv);
1763 } 2399 }
1764 #endif 2400 #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