| Index: src/d8.cc
|
| ===================================================================
|
| --- src/d8.cc (revision 1168)
|
| +++ src/d8.cc (working copy)
|
| @@ -33,6 +33,7 @@
|
| #include "debug.h"
|
| #include "api.h"
|
| #include "natives.h"
|
| +#include "platform.h"
|
|
|
|
|
| namespace v8 {
|
| @@ -383,10 +384,10 @@
|
| }
|
|
|
|
|
| -// Reads a file into a v8 string.
|
| -Handle<String> Shell::ReadFile(const char* name) {
|
| +static char* ReadChars(const char *name, int* size_out) {
|
| + v8::Unlocker unlocker; // Release the V8 lock while reading files.
|
| FILE* file = i::OS::FOpen(name, "rb");
|
| - if (file == NULL) return Handle<String>();
|
| + if (file == NULL) return NULL;
|
|
|
| fseek(file, 0, SEEK_END);
|
| int size = ftell(file);
|
| @@ -399,7 +400,17 @@
|
| i += read;
|
| }
|
| fclose(file);
|
| - Handle<String> result = String::New(chars, size);
|
| + *size_out = size;
|
| + return chars;
|
| +}
|
| +
|
| +
|
| +// Reads a file into a v8 string.
|
| +Handle<String> Shell::ReadFile(const char* name) {
|
| + int size = 0;
|
| + char* chars = ReadChars(name, &size);
|
| + if (chars == NULL) return Handle<String>();
|
| + Handle<String> result = String::New(chars);
|
| delete[] chars;
|
| return result;
|
| }
|
| @@ -410,7 +421,9 @@
|
| printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
|
| editor->Open();
|
| while (true) {
|
| + Locker locker;
|
| HandleScope handle_scope;
|
| + Context::Scope context_scope(evaluation_context_);
|
| i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
|
| if (input.is_empty())
|
| break;
|
| @@ -423,6 +436,53 @@
|
| }
|
|
|
|
|
| +class ShellThread : public i::Thread {
|
| + public:
|
| + ShellThread(int no, i::Vector<const char> files)
|
| + : no_(no), files_(files) { }
|
| + virtual void Run();
|
| + private:
|
| + int no_;
|
| + i::Vector<const char> files_;
|
| +};
|
| +
|
| +
|
| +void ShellThread::Run() {
|
| + // Prepare the context for this thread.
|
| + Locker locker;
|
| + HandleScope scope;
|
| + Handle<ObjectTemplate> global_template = ObjectTemplate::New();
|
| + global_template->Set(String::New("print"),
|
| + FunctionTemplate::New(Shell::Print));
|
| + global_template->Set(String::New("load"),
|
| + FunctionTemplate::New(Shell::Load));
|
| + global_template->Set(String::New("version"),
|
| + FunctionTemplate::New(Shell::Version));
|
| +
|
| + Persistent<Context> thread_context = Context::New(NULL, global_template);
|
| + thread_context->SetSecurityToken(Undefined());
|
| +
|
| + Context::Scope context_scope(thread_context);
|
| +
|
| + char* ptr = const_cast<char*>(files_.start());
|
| + while ((ptr != NULL) && (*ptr != '\0')) {
|
| + // For each newline-separated line.
|
| + char *filename = ptr;
|
| + char* next = ::strchr(ptr, '\n');
|
| + if (next != NULL) {
|
| + *next = '\0';
|
| + ptr = (next + 1);
|
| + } else {
|
| + ptr = NULL;
|
| + }
|
| + Handle<String> str = Shell::ReadFile(filename);
|
| + Shell::ExecuteString(str, String::New(filename), false, false);
|
| + }
|
| +
|
| + thread_context.Dispose();
|
| +}
|
| +
|
| +
|
| int Shell::Main(int argc, char* argv[]) {
|
| i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
|
| if (i::FLAG_help) {
|
| @@ -430,42 +490,67 @@
|
| }
|
| Initialize();
|
| bool run_shell = (argc == 1);
|
| - Context::Scope context_scope(evaluation_context_);
|
| - for (int i = 1; i < argc; i++) {
|
| - char* str = argv[i];
|
| - if (strcmp(str, "--shell") == 0) {
|
| - run_shell = true;
|
| - } else if (strcmp(str, "-f") == 0) {
|
| - // Ignore any -f flags for compatibility with other stand-alone
|
| - // JavaScript engines.
|
| - continue;
|
| - } else if (strncmp(str, "--", 2) == 0) {
|
| - printf("Warning: unknown flag %s.\nTry --help for options\n", str);
|
| - } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
|
| - // Execute argument given to -e option directly.
|
| - v8::HandleScope handle_scope;
|
| - v8::Handle<v8::String> file_name = v8::String::New("unnamed");
|
| - v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
|
| - if (!ExecuteString(source, file_name, false, true))
|
| - return 1;
|
| - i++;
|
| - } else {
|
| - // Use all other arguments as names of files to load and run.
|
| - HandleScope handle_scope;
|
| - Handle<String> file_name = v8::String::New(str);
|
| - Handle<String> source = ReadFile(str);
|
| - if (source.IsEmpty()) {
|
| - printf("Error reading '%s'\n", str);
|
| - return 1;
|
| + i::List<i::Thread*> threads(1);
|
| +
|
| + {
|
| + // Acquire the V8 lock once initialization has finished. Since the thread
|
| + // below may spawn new threads accessing V8 holding the V8 lock here is
|
| + // mandatory.
|
| + Locker locker;
|
| + Context::Scope context_scope(evaluation_context_);
|
| + for (int i = 1; i < argc; i++) {
|
| + char* str = argv[i];
|
| + if (strcmp(str, "--shell") == 0) {
|
| + run_shell = true;
|
| + } else if (strcmp(str, "-f") == 0) {
|
| + // Ignore any -f flags for compatibility with other stand-alone
|
| + // JavaScript engines.
|
| + continue;
|
| + } else if (strncmp(str, "--", 2) == 0) {
|
| + printf("Warning: unknown flag %s.\nTry --help for options\n", str);
|
| + } else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
|
| + // Execute argument given to -e option directly.
|
| + v8::HandleScope handle_scope;
|
| + v8::Handle<v8::String> file_name = v8::String::New("unnamed");
|
| + v8::Handle<v8::String> source = v8::String::New(argv[i + 1]);
|
| + if (!ExecuteString(source, file_name, false, true))
|
| + return 1;
|
| + i++;
|
| + } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
|
| + // Use the lowest possible thread preemption interval to test as many
|
| + // edgecases as possible.
|
| + Locker::StartPreemption(1);
|
| + int size = 0;
|
| + const char *files = ReadChars(argv[++i], &size);
|
| + if (files == NULL) return 1;
|
| + ShellThread *thread =
|
| + new ShellThread(threads.length(),
|
| + i::Vector<const char>(files, size));
|
| + thread->Start();
|
| + threads.Add(thread);
|
| + } else {
|
| + // Use all other arguments as names of files to load and run.
|
| + HandleScope handle_scope;
|
| + Handle<String> file_name = v8::String::New(str);
|
| + Handle<String> source = ReadFile(str);
|
| + if (source.IsEmpty()) {
|
| + printf("Error reading '%s'\n", str);
|
| + return 1;
|
| + }
|
| + if (!ExecuteString(source, file_name, false, true))
|
| + return 1;
|
| }
|
| - if (!ExecuteString(source, file_name, false, true))
|
| - return 1;
|
| }
|
| + if (i::FLAG_debugger)
|
| + v8::Debug::AddDebugEventListener(HandleDebugEvent);
|
| }
|
| - if (i::FLAG_debugger)
|
| - v8::Debug::AddDebugEventListener(HandleDebugEvent);
|
| if (run_shell)
|
| RunShell();
|
| + for (int i = 0; i < threads.length(); i++) {
|
| + i::Thread *thread = threads[i];
|
| + thread->Join();
|
| + delete thread;
|
| + }
|
| OnExit();
|
| return 0;
|
| }
|
|
|