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

Side by Side Diff: src/d8.cc

Issue 7318002: ported --isolate option to d8 and refactored to group together option parsing (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: bug fix for http://code.google.com/p/v8/issues/detail?id=1540 Created 9 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « src/d8.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 23 matching lines...) Expand all
34 34
35 #include "v8.h" 35 #include "v8.h"
36 36
37 #include "d8.h" 37 #include "d8.h"
38 #include "d8-debug.h" 38 #include "d8-debug.h"
39 #include "debug.h" 39 #include "debug.h"
40 #include "api.h" 40 #include "api.h"
41 #include "natives.h" 41 #include "natives.h"
42 #include "platform.h" 42 #include "platform.h"
43 43
44 #if !defined(_WIN32) && !defined(_WIN64)
45 #include <unistd.h> // NOLINT
46 #endif
44 47
45 namespace v8 { 48 namespace v8 {
46 49
47 50
48 const char* Shell::kHistoryFileName = ".d8_history"; 51 const char* Shell::kHistoryFileName = ".d8_history";
49 const char* Shell::kPrompt = "d8> "; 52 const char* Shell::kPrompt = "d8> ";
50 53
51 54
52 LineEditor *LineEditor::first_ = NULL; 55 LineEditor *LineEditor::first_ = NULL;
53 56
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 return i::SmartPointer<char>(str ? i::StrDup(str) : str); 93 return i::SmartPointer<char>(str ? i::StrDup(str) : str);
91 } 94 }
92 95
93 96
94 CounterMap* Shell::counter_map_; 97 CounterMap* Shell::counter_map_;
95 i::OS::MemoryMappedFile* Shell::counters_file_ = NULL; 98 i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
96 CounterCollection Shell::local_counters_; 99 CounterCollection Shell::local_counters_;
97 CounterCollection* Shell::counters_ = &local_counters_; 100 CounterCollection* Shell::counters_ = &local_counters_;
98 Persistent<Context> Shell::utility_context_; 101 Persistent<Context> Shell::utility_context_;
99 Persistent<Context> Shell::evaluation_context_; 102 Persistent<Context> Shell::evaluation_context_;
103 i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
104 ShellOptions Shell::options;
100 105
101 106
102 bool CounterMap::Match(void* key1, void* key2) { 107 bool CounterMap::Match(void* key1, void* key2) {
103 const char* name1 = reinterpret_cast<const char*>(key1); 108 const char* name1 = reinterpret_cast<const char*>(key1);
104 const char* name2 = reinterpret_cast<const char*>(key2); 109 const char* name2 = reinterpret_cast<const char*>(key2);
105 return strcmp(name1, name2) == 0; 110 return strcmp(name1, name2) == 0;
106 } 111 }
107 112
108 113
109 // Converts a V8 value to a C string. 114 // Converts a V8 value to a C string.
110 const char* Shell::ToCString(const v8::String::Utf8Value& value) { 115 const char* Shell::ToCString(const v8::String::Utf8Value& value) {
111 return *value ? *value : "<string conversion failed>"; 116 return *value ? *value : "<string conversion failed>";
112 } 117 }
113 118
114 119
115 // Executes a string within the current v8 context. 120 // Executes a string within the current v8 context.
116 bool Shell::ExecuteString(Handle<String> source, 121 bool Shell::ExecuteString(Handle<String> source,
117 Handle<Value> name, 122 Handle<Value> name,
118 bool print_result, 123 bool print_result,
119 bool report_exceptions) { 124 bool report_exceptions) {
120 HandleScope handle_scope; 125 HandleScope handle_scope;
121 TryCatch try_catch; 126 TryCatch try_catch;
127 options.script_executed = true;
122 if (i::FLAG_debugger) { 128 if (i::FLAG_debugger) {
123 // When debugging make exceptions appear to be uncaught. 129 // When debugging make exceptions appear to be uncaught.
124 try_catch.SetVerbose(true); 130 try_catch.SetVerbose(true);
125 } 131 }
126 Handle<Script> script = Script::Compile(source, name); 132 Handle<Script> script = Script::Compile(source, name);
127 if (script.IsEmpty()) { 133 if (script.IsEmpty()) {
128 // Print errors that happened during compilation. 134 // Print errors that happened during compilation.
129 if (report_exceptions && !i::FLAG_debugger) 135 if (report_exceptions && !i::FLAG_debugger)
130 ReportException(&try_catch); 136 ReportException(&try_catch);
131 return false; 137 return false;
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 i::Vector<const char> shell_source = 539 i::Vector<const char> shell_source =
534 i::NativesCollection<i::D8>::GetRawScriptSource(source_index); 540 i::NativesCollection<i::D8>::GetRawScriptSource(source_index);
535 i::Vector<const char> shell_source_name = 541 i::Vector<const char> shell_source_name =
536 i::NativesCollection<i::D8>::GetScriptName(source_index); 542 i::NativesCollection<i::D8>::GetScriptName(source_index);
537 Handle<String> source = String::New(shell_source.start(), 543 Handle<String> source = String::New(shell_source.start(),
538 shell_source.length()); 544 shell_source.length());
539 Handle<String> name = String::New(shell_source_name.start(), 545 Handle<String> name = String::New(shell_source_name.start(),
540 shell_source_name.length()); 546 shell_source_name.length());
541 Handle<Script> script = Script::Compile(source, name); 547 Handle<Script> script = Script::Compile(source, name);
542 script->Run(); 548 script->Run();
543
544 // Mark the d8 shell script as native to avoid it showing up as normal source 549 // Mark the d8 shell script as native to avoid it showing up as normal source
545 // in the debugger. 550 // in the debugger.
546 i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script); 551 i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
547 i::Handle<i::Script> script_object = compiled_script->IsJSFunction() 552 i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
548 ? i::Handle<i::Script>(i::Script::cast( 553 ? i::Handle<i::Script>(i::Script::cast(
549 i::JSFunction::cast(*compiled_script)->shared()->script())) 554 i::JSFunction::cast(*compiled_script)->shared()->script()))
550 : i::Handle<i::Script>(i::Script::cast( 555 : i::Handle<i::Script>(i::Script::cast(
551 i::SharedFunctionInfo::cast(*compiled_script)->script())); 556 i::SharedFunctionInfo::cast(*compiled_script)->script()));
552 script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE)); 557 script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
558
559 #ifdef ENABLE_DEBUGGER_SUPPORT
560 // Start the in-process debugger if requested.
Yang 2011/07/08 13:15:40 set the listener *after* d8.js has been loaded fix
561 if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
562 v8::Debug::SetDebugEventListener(HandleDebugEvent);
563 }
564 #endif
553 } 565 }
554 566
555 567
556 #ifdef COMPRESS_STARTUP_DATA_BZ2 568 #ifdef COMPRESS_STARTUP_DATA_BZ2
557 class BZip2Decompressor : public v8::StartupDataDecompressor { 569 class BZip2Decompressor : public v8::StartupDataDecompressor {
558 public: 570 public:
559 virtual ~BZip2Decompressor() { } 571 virtual ~BZip2Decompressor() { }
560 572
561 protected: 573 protected:
562 virtual int DecompressData(char* raw_data, 574 virtual int DecompressData(char* raw_data,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 #endif 630 #endif
619 631
620 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(); 632 Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
621 AddOSMethods(os_templ); 633 AddOSMethods(os_templ);
622 global_template->Set(String::New("os"), os_templ); 634 global_template->Set(String::New("os"), os_templ);
623 635
624 return global_template; 636 return global_template;
625 } 637 }
626 638
627 639
628 void Shell::Initialize(bool test_shell) { 640 void Shell::Initialize() {
629 #ifdef COMPRESS_STARTUP_DATA_BZ2 641 #ifdef COMPRESS_STARTUP_DATA_BZ2
630 BZip2Decompressor startup_data_decompressor; 642 BZip2Decompressor startup_data_decompressor;
631 int bz2_result = startup_data_decompressor.Decompress(); 643 int bz2_result = startup_data_decompressor.Decompress();
632 if (bz2_result != BZ_OK) { 644 if (bz2_result != BZ_OK) {
633 fprintf(stderr, "bzip error code: %d\n", bz2_result); 645 fprintf(stderr, "bzip error code: %d\n", bz2_result);
634 exit(1); 646 exit(1);
635 } 647 }
636 #endif 648 #endif
637 649
638 Shell::counter_map_ = new CounterMap(); 650 Shell::counter_map_ = new CounterMap();
639 // Set up counters 651 // Set up counters
640 if (i::StrLength(i::FLAG_map_counters) != 0) 652 if (i::StrLength(i::FLAG_map_counters) != 0)
641 MapCounters(i::FLAG_map_counters); 653 MapCounters(i::FLAG_map_counters);
642 if (i::FLAG_dump_counters) { 654 if (i::FLAG_dump_counters) {
643 V8::SetCounterFunction(LookupCounter); 655 V8::SetCounterFunction(LookupCounter);
644 V8::SetCreateHistogramFunction(CreateHistogram); 656 V8::SetCreateHistogramFunction(CreateHistogram);
645 V8::SetAddHistogramSampleFunction(AddHistogramSample); 657 V8::SetAddHistogramSampleFunction(AddHistogramSample);
646 } 658 }
647 659
648 if (test_shell) return; 660 if (options.test_shell) return;
649 661
650 Locker lock; 662 Locker lock;
651 HandleScope scope; 663 HandleScope scope;
652 Handle<ObjectTemplate> global_template = CreateGlobalTemplate(); 664 Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
653 utility_context_ = Context::New(NULL, global_template); 665 utility_context_ = Context::New(NULL, global_template);
654 666
655 #ifdef ENABLE_DEBUGGER_SUPPORT 667 #ifdef ENABLE_DEBUGGER_SUPPORT
656 // Start the debugger agent if requested. 668 // Start the debugger agent if requested.
657 if (i::FLAG_debugger_agent) { 669 if (i::FLAG_debugger_agent) {
658 v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true); 670 v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
659 } 671 }
660
661 // Start the in-process debugger if requested.
662 if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
663 v8::Debug::SetDebugEventListener(HandleDebugEvent);
664 }
665 #endif 672 #endif
666 } 673 }
667 674
668 675
669 void Shell::RenewEvaluationContext() { 676 Persistent<Context> Shell::CreateEvaluationContext() {
677 // This needs to be a critical section since this is not thread-safe
678 i::ScopedLock lock(context_mutex_);
670 // Initialize the global objects 679 // Initialize the global objects
671 HandleScope scope;
672 Handle<ObjectTemplate> global_template = CreateGlobalTemplate(); 680 Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
673 681 Persistent<Context> context = Context::New(NULL, global_template);
674 // (Re-)create the evaluation context 682 Context::Scope scope(context);
675 if (!evaluation_context_.IsEmpty()) {
676 evaluation_context_.Dispose();
677 }
678 evaluation_context_ = Context::New(NULL, global_template);
679 Context::Scope utility_scope(evaluation_context_);
680 683
681 i::JSArguments js_args = i::FLAG_js_arguments; 684 i::JSArguments js_args = i::FLAG_js_arguments;
682 i::Handle<i::FixedArray> arguments_array = 685 i::Handle<i::FixedArray> arguments_array =
683 FACTORY->NewFixedArray(js_args.argc()); 686 FACTORY->NewFixedArray(js_args.argc());
684 for (int j = 0; j < js_args.argc(); j++) { 687 for (int j = 0; j < js_args.argc(); j++) {
685 i::Handle<i::String> arg = 688 i::Handle<i::String> arg =
686 FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j])); 689 FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
687 arguments_array->set(j, *arg); 690 arguments_array->set(j, *arg);
688 } 691 }
689 i::Handle<i::JSArray> arguments_jsarray = 692 i::Handle<i::JSArray> arguments_jsarray =
690 FACTORY->NewJSArrayWithElements(arguments_array); 693 FACTORY->NewJSArrayWithElements(arguments_array);
691 evaluation_context_->Global()->Set(String::New("arguments"), 694 context->Global()->Set(String::New("arguments"),
692 Utils::ToLocal(arguments_jsarray)); 695 Utils::ToLocal(arguments_jsarray));
696 return context;
693 } 697 }
694 698
695 699
696 void Shell::OnExit() { 700 void Shell::OnExit() {
697 if (i::FLAG_dump_counters) { 701 if (i::FLAG_dump_counters) {
698 ::printf("+----------------------------------------+-------------+\n"); 702 printf("+----------------------------------------+-------------+\n");
699 ::printf("| Name | Value |\n"); 703 printf("| Name | Value |\n");
700 ::printf("+----------------------------------------+-------------+\n"); 704 printf("+----------------------------------------+-------------+\n");
701 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) { 705 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
702 Counter* counter = i.CurrentValue(); 706 Counter* counter = i.CurrentValue();
703 if (counter->is_histogram()) { 707 if (counter->is_histogram()) {
704 ::printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count()); 708 printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count());
705 ::printf("| t:%-36s | %11i |\n", 709 printf("| t:%-36s | %11i |\n", i.CurrentKey(), counter->sample_total());
706 i.CurrentKey(),
707 counter->sample_total());
708 } else { 710 } else {
709 ::printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count()); 711 printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count());
710 } 712 }
711 } 713 }
712 ::printf("+----------------------------------------+-------------+\n"); 714 printf("+----------------------------------------+-------------+\n");
713 } 715 }
714 if (counters_file_ != NULL) 716 if (counters_file_ != NULL)
715 delete counters_file_; 717 delete counters_file_;
716 } 718 }
717 719
718 720
719 static char* ReadChars(const char* name, int* size_out) { 721 static char* ReadChars(const char* name, int* size_out) {
720 v8::Unlocker unlocker; // Release the V8 lock while reading files. 722 // Release the V8 lock while reading files.
723 v8::Unlocker unlocker(Isolate::GetCurrent());
721 FILE* file = i::OS::FOpen(name, "rb"); 724 FILE* file = i::OS::FOpen(name, "rb");
722 if (file == NULL) return NULL; 725 if (file == NULL) return NULL;
723 726
724 fseek(file, 0, SEEK_END); 727 fseek(file, 0, SEEK_END);
725 int size = ftell(file); 728 int size = ftell(file);
726 rewind(file); 729 rewind(file);
727 730
728 char* chars = new char[size + 1]; 731 char* chars = new char[size + 1];
729 chars[size] = '\0'; 732 chars[size] = '\0';
730 for (int i = 0; i < size;) { 733 for (int i = 0; i < size;) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 : Thread("d8:ShellThread"), 802 : Thread("d8:ShellThread"),
800 no_(no), files_(files) { } 803 no_(no), files_(files) { }
801 virtual void Run(); 804 virtual void Run();
802 private: 805 private:
803 int no_; 806 int no_;
804 i::Vector<const char> files_; 807 i::Vector<const char> files_;
805 }; 808 };
806 809
807 810
808 void ShellThread::Run() { 811 void ShellThread::Run() {
809 // Prepare the context for this thread.
810 Locker locker;
811 HandleScope scope;
812 Handle<ObjectTemplate> global_template = Shell::CreateGlobalTemplate();
813
814 char* ptr = const_cast<char*>(files_.start()); 812 char* ptr = const_cast<char*>(files_.start());
815 while ((ptr != NULL) && (*ptr != '\0')) { 813 while ((ptr != NULL) && (*ptr != '\0')) {
816 // For each newline-separated line. 814 // For each newline-separated line.
817 char* next_line = ReadLine(ptr); 815 char* next_line = ReadLine(ptr);
818 816
819 if (*ptr == '#') { 817 if (*ptr == '#') {
820 // Skip comment lines. 818 // Skip comment lines.
821 ptr = next_line; 819 ptr = next_line;
822 continue; 820 continue;
823 } 821 }
824 822
825 Persistent<Context> thread_context = Context::New(NULL, global_template); 823 // Prepare the context for this thread.
824 Locker locker;
825 HandleScope scope;
826 Persistent<Context> thread_context = Shell::CreateEvaluationContext();
826 Context::Scope context_scope(thread_context); 827 Context::Scope context_scope(thread_context);
827 828
828 while ((ptr != NULL) && (*ptr != '\0')) { 829 while ((ptr != NULL) && (*ptr != '\0')) {
829 char* filename = ptr; 830 char* filename = ptr;
830 ptr = ReadWord(ptr); 831 ptr = ReadWord(ptr);
831 832
832 // Skip empty strings. 833 // Skip empty strings.
833 if (strlen(filename) == 0) { 834 if (strlen(filename) == 0) {
834 break; 835 break;
835 } 836 }
836 837
837 Handle<String> str = Shell::ReadFile(filename); 838 Handle<String> str = Shell::ReadFile(filename);
838 if (str.IsEmpty()) { 839 if (str.IsEmpty()) {
839 printf("WARNING: %s not found\n", filename); 840 printf("WARNING: %s not found\n", filename);
840 break; 841 break;
841 } 842 }
842 843
843 Shell::ExecuteString(str, String::New(filename), false, false); 844 Shell::ExecuteString(str, String::New(filename), false, false);
844 } 845 }
845 846
846 thread_context.Dispose(); 847 thread_context.Dispose();
847 ptr = next_line; 848 ptr = next_line;
848 } 849 }
849 } 850 }
850 851
851 int Shell::RunMain(int argc, char* argv[], bool* executed) { 852
852 // Default use preemption if threads are created. 853 void SourceGroup::ExitShell(int exit_code) {
853 bool use_preemption = true; 854 // Use _exit instead of exit to avoid races between isolate
854 855 // threads and static destructors.
855 // Default to use lowest possible thread preemption interval to test as many 856 fflush(stdout);
856 // edgecases as possible. 857 fflush(stderr);
857 int preemption_interval = 1; 858 _exit(exit_code);
858 859 }
860
861
862 void SourceGroup::Execute() {
863 for (int i = begin_offset_; i < end_offset_; ++i) {
864 const char* arg = argv_[i];
865 if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
866 // Execute argument given to -e option directly.
867 HandleScope handle_scope;
868 Handle<String> file_name = String::New("unnamed");
869 Handle<String> source = String::New(argv_[i + 1]);
870 if (!Shell::ExecuteString(source, file_name, false, true)) {
871 ExitShell(1);
872 return;
873 }
874 ++i;
875 } else if (arg[0] == '-') {
876 // Ignore other options. They have been parsed already.
877 } else {
878 // Use all other arguments as names of files to load and run.
879 HandleScope handle_scope;
880 Handle<String> file_name = String::New(arg);
881 Handle<String> source = ReadFile(arg);
882 if (source.IsEmpty()) {
883 printf("Error reading '%s'\n", arg);
884 ExitShell(1);
885 return;
886 }
887 if (!Shell::ExecuteString(source, file_name, false, true)) {
888 ExitShell(1);
889 return;
890 }
891 }
892 }
893 }
894
895
896 Handle<String> SourceGroup::ReadFile(const char* name) {
897 FILE* file = fopen(name, "rb");
898 if (file == NULL) return Handle<String>();
899
900 fseek(file, 0, SEEK_END);
901 int size = ftell(file);
902 rewind(file);
903
904 char* chars = new char[size + 1];
905 chars[size] = '\0';
906 for (int i = 0; i < size;) {
907 int read = fread(&chars[i], 1, size - i, file);
908 i += read;
909 }
910 fclose(file);
911 Handle<String> result = String::New(chars, size);
912 delete[] chars;
913 return result;
914 }
915
916
917 i::Thread::Options SourceGroup::GetThreadOptions() {
918 i::Thread::Options options;
919 options.name = "IsolateThread";
920 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
921 // which is not enough to parse the big literal expressions used in tests.
922 // The stack size should be at least StackGuard::kLimitSize + some
923 // OS-specific padding for thread startup code.
924 options.stack_size = 2 << 20; // 2 Mb seems to be enough
925 return options;
926 }
927
928
929 void SourceGroup::ExecuteInThread() {
930 Isolate* isolate = Isolate::New();
931 do {
932 if (next_semaphore_ != NULL) next_semaphore_->Wait();
933 {
934 Isolate::Scope iscope(isolate);
935 Locker lock(isolate);
936 HandleScope scope;
937 Persistent<Context> context = Shell::CreateEvaluationContext();
938 {
939 Context::Scope cscope(context);
940 Execute();
941 }
942 context.Dispose();
943 }
944 if (done_semaphore_ != NULL) done_semaphore_->Signal();
945 } while (!Shell::options.last_run);
946 isolate->Dispose();
947 }
948
949
950 void SourceGroup::StartExecuteInThread() {
951 if (thread_ == NULL) {
952 thread_ = new IsolateThread(this);
953 thread_->Start();
954 }
955 next_semaphore_->Signal();
956 }
957
958
959 void SourceGroup::WaitForThread() {
960 if (thread_ == NULL) return;
961 if (Shell::options.last_run) {
962 thread_->Join();
963 thread_ = NULL;
964 } else {
965 done_semaphore_->Wait();
966 }
967 }
968
969
970 bool Shell::SetOptions(int argc, char* argv[]) {
971 Locker lock;
972
973 for (int i = 0; i < argc; i++) {
974 if (strcmp(argv[i], "--stress-opt") == 0) {
975 options.stress_opt = true;
976 argv[i] = NULL;
977 } else if (strcmp(argv[i], "--stress-deopt") == 0) {
978 options.stress_deopt = true;
979 argv[i] = NULL;
980 } else if (strcmp(argv[i], "--noalways-opt") == 0) {
981 // No support for stressing if we can't use --always-opt.
982 options.stress_opt = false;
983 options.stress_deopt = false;
984 } else if (strcmp(argv[i], "--shell") == 0) {
985 options.interactive_shell = true;
986 argv[i] = NULL;
987 } else if (strcmp(argv[i], "--test") == 0) {
988 options.test_shell = true;
989 argv[i] = NULL;
990 } else if (strcmp(argv[i], "--preemption") == 0) {
991 options.use_preemption = true;
992 argv[i] = NULL;
993 } else if (strcmp(argv[i], "--no-preemption") == 0) {
994 options.use_preemption = false;
995 argv[i] = NULL;
996 } else if (strcmp(argv[i], "--preemption-interval") == 0) {
997 if (++i < argc) {
998 argv[i-1] = NULL;
999 char* end = NULL;
1000 options.preemption_interval = strtol(argv[i], &end, 10); // NOLINT
1001 if (options.preemption_interval <= 0
1002 || *end != '\0'
1003 || errno == ERANGE) {
1004 printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
1005 return false;
1006 }
1007 argv[i] = NULL;
1008 } else {
1009 printf("Missing value for --preemption-interval\n");
1010 return false;
1011 }
1012 } else if (strcmp(argv[i], "-f") == 0) {
1013 // Ignore any -f flags for compatibility with other stand-alone
1014 // JavaScript engines.
1015 continue;
1016 } else if (strcmp(argv[i], "--isolate") == 0) {
1017 options.num_isolates++;
1018 }
1019 }
1020
1021 // Run parallel threads if we are not using --isolate
1022 for (int i = 1; i < argc; i++) {
1023 if (argv[i] == NULL) continue;
1024 if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
1025 if (options.num_isolates > 1) {
1026 printf("-p is not compatible with --isolate\n");
1027 return false;
1028 }
1029 argv[i] = NULL;
1030 if (options.parallel_files == NULL) {
1031 options.parallel_files = new i::List<i::Vector<const char> >();
1032 }
1033 int size = 0;
1034 const char* files = ReadChars(argv[++i], &size);
1035 if (files == NULL) {
1036 printf("-p option incomplete\n");
1037 return false;
1038 }
1039 argv[i] = NULL;
1040 options.parallel_files->Add(i::Vector<const char>(files, size));
1041 }
1042 }
1043
1044 v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
1045
1046 // set up isolated source groups
1047 options.isolate_sources = new SourceGroup[options.num_isolates];
1048 SourceGroup* current = options.isolate_sources;
1049 current->Begin(argv, 1);
1050 for (int i = 1; i < argc; i++) {
1051 const char* str = argv[i];
1052 if (strcmp(str, "--isolate") == 0) {
1053 current->End(i);
1054 current++;
1055 current->Begin(argv, i + 1);
1056 } else if (strncmp(argv[i], "--", 2) == 0) {
1057 printf("Warning: unknown flag %s.\nTry --help for options\n", argv[i]);
1058 }
1059 }
1060 current->End(argc);
1061
1062 return true;
1063 }
1064
1065
1066 int Shell::RunMain(int argc, char* argv[]) {
859 i::List<i::Thread*> threads(1); 1067 i::List<i::Thread*> threads(1);
860 1068
861 { 1069 {
862 // Since the thread below may spawn new threads accessing V8 holding the 1070 if (options.parallel_files != NULL)
863 // V8 lock here is mandatory. 1071 for (int i = 0; i < options.parallel_files->length(); i++) {
864 Locker locker; 1072 i::Vector<const char> files = options.parallel_files->at(i);
865 RenewEvaluationContext(); 1073 ShellThread* thread = new ShellThread(threads.length(), files);
866 Context::Scope context_scope(evaluation_context_);
867 for (int i = 1; i < argc; i++) {
868 char* str = argv[i];
869 if (strcmp(str, "--preemption") == 0) {
870 use_preemption = true;
871 } else if (strcmp(str, "--no-preemption") == 0) {
872 use_preemption = false;
873 } else if (strcmp(str, "--preemption-interval") == 0) {
874 if (i + 1 < argc) {
875 char* end = NULL;
876 preemption_interval = strtol(argv[++i], &end, 10); // NOLINT
877 if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) {
878 printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
879 return 1;
880 }
881 } else {
882 printf("Missing value for --preemption-interval\n");
883 return 1;
884 }
885 } else if (strcmp(str, "-f") == 0) {
886 // Ignore any -f flags for compatibility with other stand-alone
887 // JavaScript engines.
888 continue;
889 } else if (strncmp(str, "--", 2) == 0) {
890 printf("Warning: unknown flag %s.\nTry --help for options\n", str);
891 } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
892 // Execute argument given to -e option directly.
893 v8::HandleScope handle_scope;
894 v8::Handle<v8::String> file_name = v8::String::New("unnamed");
895 v8::Handle<v8::String> source = v8::String::New(argv[++i]);
896 (*executed) = true;
897 if (!ExecuteString(source, file_name, false, true)) {
898 OnExit();
899 return 1;
900 }
901 } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
902 int size = 0;
903 const char* files = ReadChars(argv[++i], &size);
904 if (files == NULL) return 1;
905 ShellThread* thread =
906 new ShellThread(threads.length(),
907 i::Vector<const char>(files, size));
908 thread->Start(); 1074 thread->Start();
909 threads.Add(thread); 1075 threads.Add(thread);
910 (*executed) = true; 1076 }
911 } else { 1077
912 // Use all other arguments as names of files to load and run. 1078 for (int i = 1; i < options.num_isolates; ++i) {
913 HandleScope handle_scope; 1079 options.isolate_sources[i].StartExecuteInThread();
914 Handle<String> file_name = v8::String::New(str); 1080 }
915 Handle<String> source = ReadFile(str); 1081
916 (*executed) = true; 1082 Locker lock;
917 if (source.IsEmpty()) { 1083 HandleScope scope;
918 printf("Error reading '%s'\n", str); 1084 Persistent<Context> context = CreateEvaluationContext();
919 return 1; 1085 {
920 } 1086 Context::Scope cscope(context);
921 if (!ExecuteString(source, file_name, false, true)) { 1087 options.isolate_sources[0].Execute();
922 OnExit(); 1088 }
923 return 1; 1089 if (options.last_run) {
924 } 1090 // Keep using the same context in the interactive shell
925 } 1091 evaluation_context_ = context;
926 } 1092 } else {
927 1093 context.Dispose();
1094 }
928 // Start preemption if threads have been created and preemption is enabled. 1095 // Start preemption if threads have been created and preemption is enabled.
929 if (threads.length() > 0 && use_preemption) { 1096 if (options.parallel_files != NULL
930 Locker::StartPreemption(preemption_interval); 1097 && threads.length() > 0
931 } 1098 && options.use_preemption) {
932 } 1099 Locker::StartPreemption(options.preemption_interval);
933 1100 }
934 for (int i = 0; i < threads.length(); i++) { 1101 }
935 i::Thread* thread = threads[i]; 1102
936 thread->Join(); 1103 for (int i = 1; i < options.num_isolates; ++i) {
937 delete thread; 1104 options.isolate_sources[i].WaitForThread();
938 } 1105 }
1106
1107 if (options.parallel_files != NULL)
1108 for (int i = 0; i < threads.length(); i++) {
1109 i::Thread* thread = threads[i];
1110 thread->Join();
1111 delete thread;
1112 }
1113
939 OnExit(); 1114 OnExit();
940 return 0; 1115 return 0;
941 } 1116 }
942 1117
943 1118
944 int Shell::Main(int argc, char* argv[]) { 1119 int Shell::Main(int argc, char* argv[]) {
945 // Figure out if we're requested to stress the optimization 1120 if (!SetOptions(argc, argv)) return 1;
946 // infrastructure by running tests multiple times and forcing 1121 Initialize();
947 // optimization in the last run.
948 bool FLAG_stress_opt = false;
949 bool FLAG_stress_deopt = false;
950 bool FLAG_interactive_shell = false;
951 bool FLAG_test_shell = false;
952 bool script_executed = false;
953
954 for (int i = 0; i < argc; i++) {
955 if (strcmp(argv[i], "--stress-opt") == 0) {
956 FLAG_stress_opt = true;
957 argv[i] = NULL;
958 } else if (strcmp(argv[i], "--stress-deopt") == 0) {
959 FLAG_stress_deopt = true;
960 argv[i] = NULL;
961 } else if (strcmp(argv[i], "--noalways-opt") == 0) {
962 // No support for stressing if we can't use --always-opt.
963 FLAG_stress_opt = false;
964 FLAG_stress_deopt = false;
965 } else if (strcmp(argv[i], "--shell") == 0) {
966 FLAG_interactive_shell = true;
967 argv[i] = NULL;
968 } else if (strcmp(argv[i], "--test") == 0) {
969 FLAG_test_shell = true;
970 argv[i] = NULL;
971 }
972 }
973
974 v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
975
976 Initialize(FLAG_test_shell);
977 1122
978 int result = 0; 1123 int result = 0;
979 if (FLAG_stress_opt || FLAG_stress_deopt) { 1124 if (options.stress_opt || options.stress_deopt) {
980 v8::Testing::SetStressRunType( 1125 Testing::SetStressRunType(
981 FLAG_stress_opt ? v8::Testing::kStressTypeOpt 1126 options.stress_opt ? Testing::kStressTypeOpt
982 : v8::Testing::kStressTypeDeopt); 1127 : Testing::kStressTypeDeopt);
983 int stress_runs = v8::Testing::GetStressRuns(); 1128 int stress_runs = Testing::GetStressRuns();
984 for (int i = 0; i < stress_runs && result == 0; i++) { 1129 for (int i = 0; i < stress_runs && result == 0; i++) {
985 printf("============ Stress %d/%d ============\n", i + 1, stress_runs); 1130 printf("============ Stress %d/%d ============\n", i + 1, stress_runs);
986 v8::Testing::PrepareStressRun(i); 1131 Testing::PrepareStressRun(i);
987 result = RunMain(argc, argv, &script_executed); 1132 options.last_run = (i == stress_runs - 1);
1133 result = RunMain(argc, argv);
988 } 1134 }
989 printf("======== Full Deoptimization =======\n"); 1135 printf("======== Full Deoptimization =======\n");
990 v8::Testing::DeoptimizeAll(); 1136 Testing::DeoptimizeAll();
991 } else { 1137 } else {
992 result = RunMain(argc, argv, &script_executed); 1138 result = RunMain(argc, argv);
993 } 1139 }
994 1140
995 #ifdef ENABLE_DEBUGGER_SUPPORT 1141 #ifdef ENABLE_DEBUGGER_SUPPORT
996 // Run remote debugger if requested, but never on --test 1142 // Run remote debugger if requested, but never on --test
997 if (i::FLAG_remote_debugger && !FLAG_test_shell) { 1143 if (i::FLAG_remote_debugger && !options.test_shell) {
998 InstallUtilityScript(); 1144 InstallUtilityScript();
999 RunRemoteDebugger(i::FLAG_debugger_port); 1145 RunRemoteDebugger(i::FLAG_debugger_port);
1000 return 0; 1146 return 0;
1001 } 1147 }
1002 #endif 1148 #endif
1003 1149
1004 // Run interactive shell if explicitly requested or if no script has been 1150 // Run interactive shell if explicitly requested or if no script has been
1005 // executed, but never on --test 1151 // executed, but never on --test
1006 if ((FLAG_interactive_shell || !script_executed) && !FLAG_test_shell) { 1152
1153 if (( options.interactive_shell
1154 || !options.script_executed )
1155 && !options.test_shell ) {
1007 InstallUtilityScript(); 1156 InstallUtilityScript();
1008 RunShell(); 1157 RunShell();
1009 } 1158 }
1010 1159
1011 v8::V8::Dispose(); 1160 V8::Dispose();
1012 1161
1013 return result; 1162 return result;
1014 } 1163 }
1015 1164
1016 } // namespace v8 1165 } // namespace v8
1017 1166
1018 1167
1019 #ifndef GOOGLE3 1168 #ifndef GOOGLE3
1020 int main(int argc, char* argv[]) { 1169 int main(int argc, char* argv[]) {
1021 return v8::Shell::Main(argc, argv); 1170 return v8::Shell::Main(argc, argv);
1022 } 1171 }
1023 #endif 1172 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698