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

Side by Side Diff: src/d8.cc

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

Powered by Google App Engine
This is Rietveld 408576698