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

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: . 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 138
139 private: 139 private:
140 friend class Shell; 140 friend class Shell;
141 friend class RealmScope; 141 friend class RealmScope;
142 Isolate* isolate_; 142 Isolate* isolate_;
143 int realm_count_; 143 int realm_count_;
144 int realm_current_; 144 int realm_current_;
145 int realm_switch_; 145 int realm_switch_;
146 Persistent<Context>* realms_; 146 Persistent<Context>* realms_;
147 Persistent<Value> realm_shared_; 147 Persistent<Value> realm_shared_;
148 ArrayBuffer::Allocator* array_buffer_allocator_;
148 149
149 int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args, 150 int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
150 int arg_offset); 151 int arg_offset);
151 int RealmFind(Handle<Context> context); 152 int RealmFind(Handle<Context> context);
152 }; 153 };
153 154
154 155
155 LineEditor *LineEditor::current_ = NULL; 156 LineEditor *LineEditor::current_ = NULL;
156 157
157 158
(...skipping 26 matching lines...) Expand all
184 185
185 #ifndef V8_SHARED 186 #ifndef V8_SHARED
186 CounterMap* Shell::counter_map_; 187 CounterMap* Shell::counter_map_;
187 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL; 188 base::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
188 CounterCollection Shell::local_counters_; 189 CounterCollection Shell::local_counters_;
189 CounterCollection* Shell::counters_ = &local_counters_; 190 CounterCollection* Shell::counters_ = &local_counters_;
190 base::Mutex Shell::context_mutex_; 191 base::Mutex Shell::context_mutex_;
191 const base::TimeTicks Shell::kInitialTicks = 192 const base::TimeTicks Shell::kInitialTicks =
192 base::TimeTicks::HighResolutionNow(); 193 base::TimeTicks::HighResolutionNow();
193 Persistent<Context> Shell::utility_context_; 194 Persistent<Context> Shell::utility_context_;
195 Worker Shell::worker_;
196 i::List<v8::SharedArrayBuffer::Contents> Shell::externalized_shared_contents_;
194 #endif // !V8_SHARED 197 #endif // !V8_SHARED
195 198
196 Persistent<Context> Shell::evaluation_context_; 199 Persistent<Context> Shell::evaluation_context_;
197 ShellOptions Shell::options; 200 ShellOptions Shell::options;
198 const char* Shell::kPrompt = "d8> "; 201 const char* Shell::kPrompt = "d8> ";
199 202
200 #ifndef V8_SHARED 203 #ifndef V8_SHARED
201 bool CounterMap::Match(void* key1, void* key2) { 204 bool CounterMap::Match(void* key1, void* key2) {
202 const char* name1 = reinterpret_cast<const char*>(key1); 205 const char* name1 = reinterpret_cast<const char*>(key1);
203 const char* name2 = reinterpret_cast<const char*>(key2); 206 const char* name2 = reinterpret_cast<const char*>(key2);
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 String::NewFromUtf8(args.GetIsolate(), *file), 657 String::NewFromUtf8(args.GetIsolate(), *file),
655 false, 658 false,
656 true)) { 659 true)) {
657 Throw(args.GetIsolate(), "Error executing file"); 660 Throw(args.GetIsolate(), "Error executing file");
658 return; 661 return;
659 } 662 }
660 } 663 }
661 } 664 }
662 665
663 666
667 #ifndef V8_SHARED
668 void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
669 Isolate* isolate = args.GetIsolate();
670 HandleScope handle_scope(isolate);
671 if (args.Length() < 1 || !args[0]->IsFunction()) {
672 Throw(args.GetIsolate(), "1st argument must be function");
673 return;
674 }
675 if (args.Length() >= 2 && !args[1]->IsSharedArrayBuffer()) {
676 Throw(args.GetIsolate(), "2nd argument must be SharedArrayBuffer");
677 return;
678 }
679
680 String::Utf8Value function_string(args[0]->ToString());
681 v8::SharedArrayBuffer::Contents contents;
682 if (args.Length() >= 2) {
683 Handle<SharedArrayBuffer> sab = Handle<SharedArrayBuffer>::Cast(args[1]);
684 contents = sab->Externalize();
685 externalized_shared_contents_.Add(contents);
686 }
687 worker_.StartExecuteInThread(isolate, *function_string, contents);
688 }
689
690
691 void Shell::WorkerJoin(const v8::FunctionCallbackInfo<v8::Value>& args) {
692 Isolate* isolate = args.GetIsolate();
693 HandleScope handle_scope(isolate);
694 Handle<Value> result = worker_.WaitForThread(isolate);
695 args.GetReturnValue().Set(result);
696 }
697 #endif // !V8_SHARED
698
699
664 void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) { 700 void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
665 int exit_code = args[0]->Int32Value(); 701 int exit_code = args[0]->Int32Value();
666 OnExit(args.GetIsolate()); 702 OnExit(args.GetIsolate());
667 exit(exit_code); 703 exit(exit_code);
668 } 704 }
669 705
670 706
671 void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) { 707 void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& args) {
672 args.GetReturnValue().Set( 708 args.GetReturnValue().Set(
673 String::NewFromUtf8(args.GetIsolate(), V8::GetVersion())); 709 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"), 1021 realm_template->SetAccessor(String::NewFromUtf8(isolate, "shared"),
986 RealmSharedGet, RealmSharedSet); 1022 RealmSharedGet, RealmSharedSet);
987 global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template); 1023 global_template->Set(String::NewFromUtf8(isolate, "Realm"), realm_template);
988 1024
989 #ifndef V8_SHARED 1025 #ifndef V8_SHARED
990 Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate); 1026 Handle<ObjectTemplate> performance_template = ObjectTemplate::New(isolate);
991 performance_template->Set(String::NewFromUtf8(isolate, "now"), 1027 performance_template->Set(String::NewFromUtf8(isolate, "now"),
992 FunctionTemplate::New(isolate, PerformanceNow)); 1028 FunctionTemplate::New(isolate, PerformanceNow));
993 global_template->Set(String::NewFromUtf8(isolate, "performance"), 1029 global_template->Set(String::NewFromUtf8(isolate, "performance"),
994 performance_template); 1030 performance_template);
1031
1032 Handle<ObjectTemplate> worker_template = ObjectTemplate::New(isolate);
1033 worker_template->Set(String::NewFromUtf8(isolate, "new"),
1034 FunctionTemplate::New(isolate, WorkerNew));
1035 worker_template->Set(String::NewFromUtf8(isolate, "join"),
1036 FunctionTemplate::New(isolate, WorkerJoin));
1037 global_template->Set(String::NewFromUtf8(isolate, "Worker"), worker_template);
995 #endif // !V8_SHARED 1038 #endif // !V8_SHARED
996 1039
997 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate); 1040 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
998 AddOSMethods(isolate, os_templ); 1041 AddOSMethods(isolate, os_templ);
999 global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ); 1042 global_template->Set(String::NewFromUtf8(isolate, "os"), os_templ);
1000 1043
1001 return global_template; 1044 return global_template;
1002 } 1045 }
1003 1046
1004 1047
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 1405
1363 1406
1364 void SourceGroup::WaitForThread() { 1407 void SourceGroup::WaitForThread() {
1365 if (thread_ == NULL) return; 1408 if (thread_ == NULL) return;
1366 if (Shell::options.last_run) { 1409 if (Shell::options.last_run) {
1367 thread_->Join(); 1410 thread_->Join();
1368 } else { 1411 } else {
1369 done_semaphore_.Wait(); 1412 done_semaphore_.Wait();
1370 } 1413 }
1371 } 1414 }
1415
1416
1417 Worker::Worker() : thread_(NULL), script_(NULL), result_json_(NULL) {}
1418
1419
1420 Worker::~Worker() { Cleanup(); }
1421
1422
1423 void Worker::StartExecuteInThread(
1424 Isolate* isolate, const char* function_string,
1425 const v8::SharedArrayBuffer::Contents& contents) {
1426 if (thread_) {
1427 Throw(isolate, "Only one worker allowed");
1428 return;
1429 }
1430
1431 static const char format[] = "JSON.stringify((%s).call(this, sab));";
binji 2015/06/15 19:11:48 Better way to do this?
1432 size_t len = strlen(function_string) + sizeof(format);
1433
1434 script_ = new char[len + 1];
1435 snprintf(script_, len, format, function_string);
1436 script_[len] = 0;
1437
1438 contents_ = contents;
1439
1440 thread_ = new WorkerThread(this);
1441 thread_->Start();
1442 }
1443
1444
1445 Handle<Value> Worker::WaitForThread(Isolate* isolate) {
1446 EscapableHandleScope handle_scope(isolate);
1447 Handle<Value> result;
1448
1449 if (thread_ == NULL) return result;
1450 thread_->Join();
1451
1452 if (result_json_) {
1453 Local<String> result_json = String::NewFromUtf8(isolate, result_json_);
1454 MaybeLocal<Value> maybe_result = JSON::Parse(isolate, result_json);
1455 if (!maybe_result.IsEmpty()) {
1456 result = maybe_result.ToLocalChecked();
1457 }
1458 }
1459
1460 Cleanup();
1461 return handle_scope.Escape(Local<Value>::Cast(result));
1462 }
1463
1464
1465 void Worker::ExecuteInThread() {
binji 2015/06/15 19:11:48 A lot of this function is copy/paste from other pl
1466 ShellArrayBufferAllocator allocator;
1467 Isolate::CreateParams create_params;
1468 create_params.array_buffer_allocator = &allocator;
1469 Isolate* isolate = Isolate::New(create_params);
1470 {
1471 Isolate::Scope iscope(isolate);
1472 {
1473 HandleScope scope(isolate);
1474 PerIsolateData data(isolate);
1475 Local<Context> context = Shell::CreateEvaluationContext(isolate);
1476 {
1477 Context::Scope cscope(context);
1478 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1479
1480 Handle<String> sab_name = String::NewFromUtf8(isolate, "sab");
1481 if (contents_.Data()) {
1482 Handle<v8::SharedArrayBuffer> sab = v8::SharedArrayBuffer::New(
1483 isolate, contents_.Data(), contents_.ByteLength());
1484 context->Global()->Set(sab_name, sab);
1485 } else {
1486 context->Global()->Set(sab_name, v8::Undefined(isolate));
1487 }
1488
1489 Handle<String> file_name = String::NewFromUtf8(isolate, "unnamed");
1490 Handle<String> source = String::NewFromUtf8(isolate, script_);
1491
1492 TryCatch try_catch(isolate);
1493 Handle<Script> script =
1494 Shell::CompileString(isolate, source, file_name,
1495 Shell::options.compile_options, Shell::SCRIPT);
1496 result_json_ = NULL;
1497 if (script.IsEmpty()) {
1498 // Print errors that happened during compilation.
1499 // TODO(binji): support debugger?
1500 Shell::ReportException(isolate, &try_catch);
1501 } else {
1502 Handle<Value> result = script->Run();
1503 if (result->IsString()) {
1504 Handle<String> str_result = Handle<String>::Cast(result);
1505 v8::String::Utf8Value str(str_result);
1506 result_json_ = new char[str.length() + 1];
1507 memcpy(result_json_, *str, str.length() + 1);
1508 }
1509 }
1510 }
1511 }
1512 }
1513 Shell::CollectGarbage(isolate);
1514 isolate->Dispose();
1515 }
1516
1517
1518 void Worker::Cleanup() {
1519 delete thread_;
1520 thread_ = NULL;
1521 delete[] script_;
1522 script_ = NULL;
1523 delete[] result_json_;
1524 result_json_ = NULL;
1525 }
1372 #endif // !V8_SHARED 1526 #endif // !V8_SHARED
1373 1527
1374 1528
1375 void SetFlagsFromString(const char* flags) { 1529 void SetFlagsFromString(const char* flags) {
1376 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags))); 1530 v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
1377 } 1531 }
1378 1532
1379 1533
1380 bool Shell::SetOptions(int argc, char* argv[]) { 1534 bool Shell::SetOptions(int argc, char* argv[]) {
1381 bool logfile_per_isolate = false; 1535 bool logfile_per_isolate = false;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 Context::Scope cscope(context); 1690 Context::Scope cscope(context);
1537 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); 1691 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
1538 options.isolate_sources[0].Execute(isolate); 1692 options.isolate_sources[0].Execute(isolate);
1539 } 1693 }
1540 } 1694 }
1541 CollectGarbage(isolate); 1695 CollectGarbage(isolate);
1542 #ifndef V8_SHARED 1696 #ifndef V8_SHARED
1543 for (int i = 1; i < options.num_isolates; ++i) { 1697 for (int i = 1; i < options.num_isolates; ++i) {
1544 options.isolate_sources[i].WaitForThread(); 1698 options.isolate_sources[i].WaitForThread();
1545 } 1699 }
1700 CleanupWorker(isolate);
1546 #endif // !V8_SHARED 1701 #endif // !V8_SHARED
1547 return 0; 1702 return 0;
1548 } 1703 }
1549 1704
1550 1705
1551 void Shell::CollectGarbage(Isolate* isolate) { 1706 void Shell::CollectGarbage(Isolate* isolate) {
1552 if (options.send_idle_notification) { 1707 if (options.send_idle_notification) {
1553 const double kLongIdlePauseInSeconds = 1.0; 1708 const double kLongIdlePauseInSeconds = 1.0;
1554 isolate->ContextDisposedNotification(); 1709 isolate->ContextDisposedNotification();
1555 isolate->IdleNotificationDeadline( 1710 isolate->IdleNotificationDeadline(
1556 g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds); 1711 g_platform->MonotonicallyIncreasingTime() + kLongIdlePauseInSeconds);
1557 } 1712 }
1558 if (options.invoke_weak_callbacks) { 1713 if (options.invoke_weak_callbacks) {
1559 // By sending a low memory notifications, we will try hard to collect all 1714 // 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 1715 // garbage and will therefore also invoke all weak callbacks of actually
1561 // unreachable persistent handles. 1716 // unreachable persistent handles.
1562 isolate->LowMemoryNotification(); 1717 isolate->LowMemoryNotification();
1563 } 1718 }
1564 } 1719 }
1565 1720
1566 1721
1567 #ifndef V8_SHARED 1722 #ifndef V8_SHARED
1723 void Shell::CleanupWorker(Isolate* isolate) {
1724 {
1725 HandleScope scope(isolate);
1726 worker_.WaitForThread(isolate);
1727 }
1728 PerIsolateData* data = PerIsolateData::Get(isolate);
1729
1730 for (int i = 0; i < externalized_shared_contents_.length(); ++i) {
1731 const v8::SharedArrayBuffer::Contents& contents =
1732 externalized_shared_contents_[i];
1733 data->array_buffer_allocator_->Free(contents.Data(), contents.ByteLength());
1734 }
1735 externalized_shared_contents_.Clear();
1736 }
1737
1738
1568 static void DumpHeapConstants(i::Isolate* isolate) { 1739 static void DumpHeapConstants(i::Isolate* isolate) {
1569 i::Heap* heap = isolate->heap(); 1740 i::Heap* heap = isolate->heap();
1570 1741
1571 // Dump the INSTANCE_TYPES table to the console. 1742 // Dump the INSTANCE_TYPES table to the console.
1572 printf("# List of known V8 instance types.\n"); 1743 printf("# List of known V8 instance types.\n");
1573 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T); 1744 #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", i::T, #T);
1574 printf("INSTANCE_TYPES = {\n"); 1745 printf("INSTANCE_TYPES = {\n");
1575 INSTANCE_TYPE_LIST(DUMP_TYPE) 1746 INSTANCE_TYPE_LIST(DUMP_TYPE)
1576 printf("}\n"); 1747 printf("}\n");
1577 #undef DUMP_TYPE 1748 #undef DUMP_TYPE
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 create_params.create_histogram_callback = CreateHistogram; 1848 create_params.create_histogram_callback = CreateHistogram;
1678 create_params.add_histogram_sample_callback = AddHistogramSample; 1849 create_params.add_histogram_sample_callback = AddHistogramSample;
1679 } 1850 }
1680 #endif 1851 #endif
1681 Isolate* isolate = Isolate::New(create_params); 1852 Isolate* isolate = Isolate::New(create_params);
1682 DumbLineEditor dumb_line_editor(isolate); 1853 DumbLineEditor dumb_line_editor(isolate);
1683 { 1854 {
1684 Isolate::Scope scope(isolate); 1855 Isolate::Scope scope(isolate);
1685 Initialize(isolate); 1856 Initialize(isolate);
1686 PerIsolateData data(isolate); 1857 PerIsolateData data(isolate);
1858 data.array_buffer_allocator_ = create_params.array_buffer_allocator;
1687 InitializeDebugger(isolate); 1859 InitializeDebugger(isolate);
1688 1860
1689 #ifndef V8_SHARED 1861 #ifndef V8_SHARED
1690 if (options.dump_heap_constants) { 1862 if (options.dump_heap_constants) {
1691 DumpHeapConstants(reinterpret_cast<i::Isolate*>(isolate)); 1863 DumpHeapConstants(reinterpret_cast<i::Isolate*>(isolate));
1692 return 0; 1864 return 0;
1693 } 1865 }
1694 #endif 1866 #endif
1695 1867
1696 if (options.stress_opt || options.stress_deopt) { 1868 if (options.stress_opt || options.stress_deopt) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 } 1927 }
1756 1928
1757 } // namespace v8 1929 } // namespace v8
1758 1930
1759 1931
1760 #ifndef GOOGLE3 1932 #ifndef GOOGLE3
1761 int main(int argc, char* argv[]) { 1933 int main(int argc, char* argv[]) {
1762 return v8::Shell::Main(argc, argv); 1934 return v8::Shell::Main(argc, argv);
1763 } 1935 }
1764 #endif 1936 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/d8-worker.js » ('j') | test/mjsunit/d8-worker.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698