Commit 113434a6 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Fixing parallel execution in d8 (with -p) and some memory leaks.

Review URL: http://codereview.chromium.org/7891005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9262 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ff5c242a
...@@ -203,7 +203,7 @@ Handle<Value> Shell::Write(const Arguments& args) { ...@@ -203,7 +203,7 @@ Handle<Value> Shell::Write(const Arguments& args) {
int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout)); int n = static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout));
if (n != str.length()) { if (n != str.length()) {
printf("Error in fwrite\n"); printf("Error in fwrite\n");
exit(1); Exit(1);
} }
} }
return Undefined(); return Undefined();
...@@ -521,7 +521,7 @@ void Shell::MapCounters(const char* name) { ...@@ -521,7 +521,7 @@ void Shell::MapCounters(const char* name) {
NULL : counters_file_->memory(); NULL : counters_file_->memory();
if (memory == NULL) { if (memory == NULL) {
printf("Could not map counters file %s\n", name); printf("Could not map counters file %s\n", name);
exit(1); Exit(1);
} }
counters_ = static_cast<CounterCollection*>(memory); counters_ = static_cast<CounterCollection*>(memory);
V8::SetCounterFunction(LookupCounter); V8::SetCounterFunction(LookupCounter);
...@@ -718,7 +718,7 @@ void Shell::Initialize() { ...@@ -718,7 +718,7 @@ void Shell::Initialize() {
int bz2_result = startup_data_decompressor.Decompress(); int bz2_result = startup_data_decompressor.Decompress();
if (bz2_result != BZ_OK) { if (bz2_result != BZ_OK) {
fprintf(stderr, "bzip error code: %d\n", bz2_result); fprintf(stderr, "bzip error code: %d\n", bz2_result);
exit(1); Exit(1);
} }
#endif #endif
...@@ -780,6 +780,15 @@ Persistent<Context> Shell::CreateEvaluationContext() { ...@@ -780,6 +780,15 @@ Persistent<Context> Shell::CreateEvaluationContext() {
} }
void Shell::Exit(int exit_code) {
// Use _exit instead of exit to avoid races between isolate
// threads and static destructors.
fflush(stdout);
fflush(stderr);
_exit(exit_code);
}
#ifndef V8_SHARED #ifndef V8_SHARED
void Shell::OnExit() { void Shell::OnExit() {
if (i::FLAG_dump_counters) { if (i::FLAG_dump_counters) {
...@@ -918,18 +927,24 @@ void Shell::RunShell() { ...@@ -918,18 +927,24 @@ void Shell::RunShell() {
#ifndef V8_SHARED #ifndef V8_SHARED
class ShellThread : public i::Thread { class ShellThread : public i::Thread {
public: public:
ShellThread(int no, i::Vector<const char> files) // Takes ownership of the underlying char array of |files|.
ShellThread(int no, char* files)
: Thread("d8:ShellThread"), : Thread("d8:ShellThread"),
no_(no), files_(files) { } no_(no), files_(files) { }
~ShellThread() {
delete[] files_;
}
virtual void Run(); virtual void Run();
private: private:
int no_; int no_;
i::Vector<const char> files_; char* files_;
}; };
void ShellThread::Run() { void ShellThread::Run() {
char* ptr = const_cast<char*>(files_.start()); char* ptr = files_;
while ((ptr != NULL) && (*ptr != '\0')) { while ((ptr != NULL) && (*ptr != '\0')) {
// For each newline-separated line. // For each newline-separated line.
char* next_line = ReadLine(ptr); char* next_line = ReadLine(ptr);
...@@ -942,23 +957,24 @@ void ShellThread::Run() { ...@@ -942,23 +957,24 @@ void ShellThread::Run() {
// Prepare the context for this thread. // Prepare the context for this thread.
Locker locker; Locker locker;
HandleScope scope; HandleScope outer_scope;
Persistent<Context> thread_context = Shell::CreateEvaluationContext(); Persistent<Context> thread_context = Shell::CreateEvaluationContext();
Context::Scope context_scope(thread_context); Context::Scope context_scope(thread_context);
while ((ptr != NULL) && (*ptr != '\0')) { while ((ptr != NULL) && (*ptr != '\0')) {
HandleScope inner_scope;
char* filename = ptr; char* filename = ptr;
ptr = ReadWord(ptr); ptr = ReadWord(ptr);
// Skip empty strings. // Skip empty strings.
if (strlen(filename) == 0) { if (strlen(filename) == 0) {
break; continue;
} }
Handle<String> str = Shell::ReadFile(filename); Handle<String> str = Shell::ReadFile(filename);
if (str.IsEmpty()) { if (str.IsEmpty()) {
printf("WARNING: %s not found\n", filename); printf("File '%s' not found\n", filename);
break; Shell::Exit(1);
} }
Shell::ExecuteString(str, String::New(filename), false, false); Shell::ExecuteString(str, String::New(filename), false, false);
...@@ -983,15 +999,6 @@ SourceGroup::~SourceGroup() { ...@@ -983,15 +999,6 @@ SourceGroup::~SourceGroup() {
} }
void SourceGroup::ExitShell(int exit_code) {
// Use _exit instead of exit to avoid races between isolate
// threads and static destructors.
fflush(stdout);
fflush(stderr);
_exit(exit_code);
}
void SourceGroup::Execute() { void SourceGroup::Execute() {
for (int i = begin_offset_; i < end_offset_; ++i) { for (int i = begin_offset_; i < end_offset_; ++i) {
const char* arg = argv_[i]; const char* arg = argv_[i];
...@@ -1001,8 +1008,7 @@ void SourceGroup::Execute() { ...@@ -1001,8 +1008,7 @@ void SourceGroup::Execute() {
Handle<String> file_name = String::New("unnamed"); Handle<String> file_name = String::New("unnamed");
Handle<String> source = String::New(argv_[i + 1]); Handle<String> source = String::New(argv_[i + 1]);
if (!Shell::ExecuteString(source, file_name, false, true)) { if (!Shell::ExecuteString(source, file_name, false, true)) {
ExitShell(1); Shell::Exit(1);
return;
} }
++i; ++i;
} else if (arg[0] == '-') { } else if (arg[0] == '-') {
...@@ -1014,12 +1020,10 @@ void SourceGroup::Execute() { ...@@ -1014,12 +1020,10 @@ void SourceGroup::Execute() {
Handle<String> source = ReadFile(arg); Handle<String> source = ReadFile(arg);
if (source.IsEmpty()) { if (source.IsEmpty()) {
printf("Error reading '%s'\n", arg); printf("Error reading '%s'\n", arg);
ExitShell(1); Shell::Exit(1);
return;
} }
if (!Shell::ExecuteString(source, file_name, false, true)) { if (!Shell::ExecuteString(source, file_name, false, true)) {
ExitShell(1); Shell::Exit(1);
return;
} }
} }
} }
...@@ -1090,16 +1094,6 @@ void SourceGroup::WaitForThread() { ...@@ -1090,16 +1094,6 @@ void SourceGroup::WaitForThread() {
#endif // V8_SHARED #endif // V8_SHARED
ShellOptions::~ShellOptions() {
delete[] isolate_sources;
isolate_sources = NULL;
#ifndef V8_SHARED
delete parallel_files;
parallel_files = NULL;
#endif // V8_SHARED
}
bool Shell::SetOptions(int argc, char* argv[]) { bool Shell::SetOptions(int argc, char* argv[]) {
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--stress-opt") == 0) { if (strcmp(argv[i], "--stress-opt") == 0) {
...@@ -1165,14 +1159,17 @@ bool Shell::SetOptions(int argc, char* argv[]) { ...@@ -1165,14 +1159,17 @@ bool Shell::SetOptions(int argc, char* argv[]) {
return false; return false;
#endif // V8_SHARED #endif // V8_SHARED
options.num_isolates++; options.num_isolates++;
} else if (strcmp(argv[i], "-p") == 0) {
options.num_parallel_files++;
#ifdef V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#endif // V8_SHARED
} }
#ifdef V8_SHARED #ifdef V8_SHARED
else if (strcmp(argv[i], "--dump-counters") == 0) { else if (strcmp(argv[i], "--dump-counters") == 0) {
printf("D8 with shared library does not include counters\n"); printf("D8 with shared library does not include counters\n");
return false; return false;
} else if (strcmp(argv[i], "-p") == 0) {
printf("D8 with shared library does not support multi-threading\n");
return false;
} else if (strcmp(argv[i], "--debugger") == 0) { } else if (strcmp(argv[i], "--debugger") == 0) {
printf("Javascript debugger not included\n"); printf("Javascript debugger not included\n");
return false; return false;
...@@ -1182,6 +1179,8 @@ bool Shell::SetOptions(int argc, char* argv[]) { ...@@ -1182,6 +1179,8 @@ bool Shell::SetOptions(int argc, char* argv[]) {
#ifndef V8_SHARED #ifndef V8_SHARED
// Run parallel threads if we are not using --isolate // Run parallel threads if we are not using --isolate
options.parallel_files = new char*[options.num_parallel_files];
int parallel_files_set = 0;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (argv[i] == NULL) continue; if (argv[i] == NULL) continue;
if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) { if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
...@@ -1190,20 +1189,16 @@ bool Shell::SetOptions(int argc, char* argv[]) { ...@@ -1190,20 +1189,16 @@ bool Shell::SetOptions(int argc, char* argv[]) {
return false; return false;
} }
argv[i] = NULL; argv[i] = NULL;
if (options.parallel_files == NULL) { i++;
options.parallel_files = new i::List<i::Vector<const char> >(); options.parallel_files[parallel_files_set] = argv[i];
} parallel_files_set++;
int size = 0;
const char* files = ReadChars(argv[++i], &size);
if (files == NULL) {
printf("-p option incomplete\n");
return false;
}
argv[i] = NULL; argv[i] = NULL;
options.parallel_files->Add(i::Vector<const char>(files, size));
delete[] files;
} }
} }
if (parallel_files_set != options.num_parallel_files) {
printf("-p requires a file containing a list of files as parameter\n");
return false;
}
#endif // V8_SHARED #endif // V8_SHARED
v8::V8::SetFlagsFromCommandLine(&argc, argv, true); v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
...@@ -1231,14 +1226,22 @@ bool Shell::SetOptions(int argc, char* argv[]) { ...@@ -1231,14 +1226,22 @@ bool Shell::SetOptions(int argc, char* argv[]) {
int Shell::RunMain(int argc, char* argv[]) { int Shell::RunMain(int argc, char* argv[]) {
#ifndef V8_SHARED #ifndef V8_SHARED
i::List<i::Thread*> threads(1); i::List<i::Thread*> threads(1);
if (options.parallel_files != NULL) if (options.parallel_files != NULL) {
for (int i = 0; i < options.parallel_files->length(); i++) { for (int i = 0; i < options.num_parallel_files; i++) {
i::Vector<const char> files = options.parallel_files->at(i); char* files = NULL;
{ Locker lock(Isolate::GetCurrent());
int size = 0;
files = ReadChars(options.parallel_files[i], &size);
}
if (files == NULL) {
printf("File list '%s' not found\n", options.parallel_files[i]);
Exit(1);
}
ShellThread* thread = new ShellThread(threads.length(), files); ShellThread* thread = new ShellThread(threads.length(), files);
thread->Start(); thread->Start();
threads.Add(thread); threads.Add(thread);
} }
}
for (int i = 1; i < options.num_isolates; ++i) { for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].StartExecuteInThread(); options.isolate_sources[i].StartExecuteInThread();
} }
...@@ -1260,8 +1263,7 @@ int Shell::RunMain(int argc, char* argv[]) { ...@@ -1260,8 +1263,7 @@ int Shell::RunMain(int argc, char* argv[]) {
#ifndef V8_SHARED #ifndef V8_SHARED
// Start preemption if threads have been created and preemption is enabled. // Start preemption if threads have been created and preemption is enabled.
if (options.parallel_files != NULL if (threads.length() > 0
&& threads.length() > 0
&& options.use_preemption) { && options.use_preemption) {
Locker::StartPreemption(options.preemption_interval); Locker::StartPreemption(options.preemption_interval);
} }
...@@ -1273,12 +1275,16 @@ int Shell::RunMain(int argc, char* argv[]) { ...@@ -1273,12 +1275,16 @@ int Shell::RunMain(int argc, char* argv[]) {
options.isolate_sources[i].WaitForThread(); options.isolate_sources[i].WaitForThread();
} }
if (options.parallel_files != NULL) for (int i = 0; i < threads.length(); i++) {
for (int i = 0; i < threads.length(); i++) { i::Thread* thread = threads[i];
i::Thread* thread = threads[i]; thread->Join();
thread->Join(); delete thread;
delete thread; }
}
if (threads.length() > 0 && options.use_preemption) {
Locker lock;
Locker::StopPreemption();
}
#endif // V8_SHARED #endif // V8_SHARED
return 0; return 0;
} }
......
...@@ -180,6 +180,7 @@ class ShellOptions { ...@@ -180,6 +180,7 @@ class ShellOptions {
#ifndef V8_SHARED #ifndef V8_SHARED
use_preemption(true), use_preemption(true),
preemption_interval(10), preemption_interval(10),
num_parallel_files(0),
parallel_files(NULL), parallel_files(NULL),
#endif // V8_SHARED #endif // V8_SHARED
script_executed(false), script_executed(false),
...@@ -191,12 +192,18 @@ class ShellOptions { ...@@ -191,12 +192,18 @@ class ShellOptions {
num_isolates(1), num_isolates(1),
isolate_sources(NULL) { } isolate_sources(NULL) { }
~ShellOptions(); ~ShellOptions() {
#ifndef V8_SHARED
delete[] parallel_files;
#endif // V8_SHARED
delete[] isolate_sources;
}
#ifndef V8_SHARED #ifndef V8_SHARED
bool use_preemption; bool use_preemption;
int preemption_interval; int preemption_interval;
i::List< i::Vector<const char> >* parallel_files; int num_parallel_files;
char** parallel_files;
#endif // V8_SHARED #endif // V8_SHARED
bool script_executed; bool script_executed;
bool last_run; bool last_run;
...@@ -225,6 +232,7 @@ class Shell : public i::AllStatic { ...@@ -225,6 +232,7 @@ class Shell : public i::AllStatic {
static Persistent<Context> CreateEvaluationContext(); static Persistent<Context> CreateEvaluationContext();
static int RunMain(int argc, char* argv[]); static int RunMain(int argc, char* argv[]);
static int Main(int argc, char* argv[]); static int Main(int argc, char* argv[]);
static void Exit(int exit_code);
#ifndef V8_SHARED #ifndef V8_SHARED
static Handle<Array> GetCompletions(Handle<String> text, static Handle<Array> GetCompletions(Handle<String> text,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment