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

Unified Diff: src/d8.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/d8.h ('k') | src/d8.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/d8.cc
===================================================================
--- src/d8.cc (revision 8618)
+++ src/d8.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -26,8 +26,11 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef COMPRESS_STARTUP_DATA_BZ2
+#include <bzlib.h>
+#endif
+#include <errno.h>
#include <stdlib.h>
-#include <errno.h>
#include "v8.h"
@@ -38,6 +41,9 @@
#include "natives.h"
#include "platform.h"
+#if !defined(_WIN32) && !defined(_WIN64)
+#include <unistd.h> // NOLINT
+#endif
namespace v8 {
@@ -94,6 +100,8 @@
CounterCollection* Shell::counters_ = &local_counters_;
Persistent<Context> Shell::utility_context_;
Persistent<Context> Shell::evaluation_context_;
+i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
+ShellOptions Shell::options;
bool CounterMap::Match(void* key1, void* key2) {
@@ -116,6 +124,7 @@
bool report_exceptions) {
HandleScope handle_scope;
TryCatch try_catch;
+ options.script_executed = true;
if (i::FLAG_debugger) {
// When debugging make exceptions appear to be uncaught.
try_catch.SetVerbose(true);
@@ -218,6 +227,103 @@
}
+Handle<Value> Shell::CreateExternalArray(const Arguments& args,
+ ExternalArrayType type,
+ size_t element_size) {
+ ASSERT(element_size == 1 || element_size == 2 || element_size == 4 ||
+ element_size == 8);
+ if (args.Length() != 1) {
+ return ThrowException(
+ String::New("Array constructor needs one parameter."));
+ }
+ size_t length = 0;
+ if (args[0]->IsUint32()) {
+ length = args[0]->Uint32Value();
+ } else if (args[0]->IsNumber()) {
+ double raw_length = args[0]->NumberValue();
+ if (raw_length < 0) {
+ return ThrowException(String::New("Array length must not be negative."));
+ }
+ if (raw_length > i::ExternalArray::kMaxLength) {
+ return ThrowException(
+ String::New("Array length exceeds maximum length."));
+ }
+ length = static_cast<size_t>(raw_length);
+ } else {
+ return ThrowException(String::New("Array length must be a number."));
+ }
+ if (length > static_cast<size_t>(i::ExternalArray::kMaxLength)) {
+ return ThrowException(String::New("Array length exceeds maximum length."));
+ }
+ void* data = calloc(length, element_size);
+ if (data == NULL) {
+ return ThrowException(String::New("Memory allocation failed."));
+ }
+ Handle<Object> array = Object::New();
+ Persistent<Object> persistent_array = Persistent<Object>::New(array);
+ persistent_array.MakeWeak(data, ExternalArrayWeakCallback);
+ persistent_array.MarkIndependent();
+ array->SetIndexedPropertiesToExternalArrayData(data, type, length);
+ array->Set(String::New("length"), Int32::New(length), ReadOnly);
+ array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size));
+ return array;
+}
+
+
+void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) {
+ free(data);
+ object.Dispose();
+}
+
+
+Handle<Value> Shell::Int8Array(const Arguments& args) {
+ return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t));
+}
+
+
+Handle<Value> Shell::Uint8Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalUnsignedByteArray, sizeof(uint8_t));
+}
+
+
+Handle<Value> Shell::Int16Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalShortArray, sizeof(int16_t));
+}
+
+
+Handle<Value> Shell::Uint16Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalUnsignedShortArray,
+ sizeof(uint16_t));
+}
+
+
+Handle<Value> Shell::Int32Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalIntArray, sizeof(int32_t));
+}
+
+
+Handle<Value> Shell::Uint32Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalUnsignedIntArray, sizeof(uint32_t));
+}
+
+
+Handle<Value> Shell::Float32Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalFloatArray,
+ sizeof(float)); // NOLINT
+}
+
+
+Handle<Value> Shell::Float64Array(const Arguments& args) {
+ return CreateExternalArray(args, kExternalDoubleArray,
+ sizeof(double)); // NOLINT
+}
+
+
+Handle<Value> Shell::PixelArray(const Arguments& args) {
+ return CreateExternalArray(args, kExternalPixelArray, sizeof(uint8_t));
+}
+
+
Handle<Value> Shell::Yield(const Arguments& args) {
v8::Unlocker unlocker;
return Undefined();
@@ -408,20 +514,85 @@
counter->AddSample(sample);
}
+void Shell::InstallUtilityScript() {
+ Locker lock;
+ HandleScope scope;
+ // If we use the utility context, we have to set the security tokens so that
+ // utility, evaluation and debug context can all access each other.
+ utility_context_->SetSecurityToken(Undefined());
+ evaluation_context_->SetSecurityToken(Undefined());
+ Context::Scope utility_scope(utility_context_);
-void Shell::Initialize() {
- Shell::counter_map_ = new CounterMap();
- // Set up counters
- if (i::StrLength(i::FLAG_map_counters) != 0)
- MapCounters(i::FLAG_map_counters);
- if (i::FLAG_dump_counters) {
- V8::SetCounterFunction(LookupCounter);
- V8::SetCreateHistogramFunction(CreateHistogram);
- V8::SetAddHistogramSampleFunction(AddHistogramSample);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ // Install the debugger object in the utility scope
+ i::Debug* debug = i::Isolate::Current()->debug();
+ debug->Load();
+ i::Handle<i::JSObject> js_debug
+ = i::Handle<i::JSObject>(debug->debug_context()->global());
+ utility_context_->Global()->Set(String::New("$debug"),
+ Utils::ToLocal(js_debug));
+ debug->debug_context()->set_security_token(HEAP->undefined_value());
+#endif
+
+ // Run the d8 shell utility script in the utility context
+ int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
+ i::Vector<const char> shell_source =
+ i::NativesCollection<i::D8>::GetRawScriptSource(source_index);
+ i::Vector<const char> shell_source_name =
+ i::NativesCollection<i::D8>::GetScriptName(source_index);
+ Handle<String> source = String::New(shell_source.start(),
+ shell_source.length());
+ Handle<String> name = String::New(shell_source_name.start(),
+ shell_source_name.length());
+ Handle<Script> script = Script::Compile(source, name);
+ script->Run();
+ // Mark the d8 shell script as native to avoid it showing up as normal source
+ // in the debugger.
+ i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
+ i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
+ ? i::Handle<i::Script>(i::Script::cast(
+ i::JSFunction::cast(*compiled_script)->shared()->script()))
+ : i::Handle<i::Script>(i::Script::cast(
+ i::SharedFunctionInfo::cast(*compiled_script)->script()));
+ script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ // Start the in-process debugger if requested.
+ if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
+ v8::Debug::SetDebugEventListener(HandleDebugEvent);
}
+#endif
+}
- // Initialize the global objects
- HandleScope scope;
+
+#ifdef COMPRESS_STARTUP_DATA_BZ2
+class BZip2Decompressor : public v8::StartupDataDecompressor {
+ public:
+ virtual ~BZip2Decompressor() { }
+
+ protected:
+ virtual int DecompressData(char* raw_data,
+ int* raw_data_size,
+ const char* compressed_data,
+ int compressed_data_size) {
+ ASSERT_EQ(v8::StartupData::kBZip2,
+ v8::V8::GetCompressedStartupDataAlgorithm());
+ unsigned int decompressed_size = *raw_data_size;
+ int result =
+ BZ2_bzBuffToBuffDecompress(raw_data,
+ &decompressed_size,
+ const_cast<char*>(compressed_data),
+ compressed_data_size,
+ 0, 1);
+ if (result == BZ_OK) {
+ *raw_data_size = decompressed_size;
+ }
+ return result;
+ }
+};
+#endif
+
+Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
Handle<ObjectTemplate> global_template = ObjectTemplate::New();
global_template->Set(String::New("print"), FunctionTemplate::New(Print));
global_template->Set(String::New("write"), FunctionTemplate::New(Write));
@@ -432,6 +603,26 @@
global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
global_template->Set(String::New("version"), FunctionTemplate::New(Version));
+ // Bind the handlers for external arrays.
+ global_template->Set(String::New("Int8Array"),
+ FunctionTemplate::New(Int8Array));
+ global_template->Set(String::New("Uint8Array"),
+ FunctionTemplate::New(Uint8Array));
+ global_template->Set(String::New("Int16Array"),
+ FunctionTemplate::New(Int16Array));
+ global_template->Set(String::New("Uint16Array"),
+ FunctionTemplate::New(Uint16Array));
+ global_template->Set(String::New("Int32Array"),
+ FunctionTemplate::New(Int32Array));
+ global_template->Set(String::New("Uint32Array"),
+ FunctionTemplate::New(Uint32Array));
+ global_template->Set(String::New("Float32Array"),
+ FunctionTemplate::New(Float32Array));
+ global_template->Set(String::New("Float64Array"),
+ FunctionTemplate::New(Float64Array));
+ global_template->Set(String::New("PixelArray"),
+ FunctionTemplate::New(PixelArray));
+
#ifdef LIVE_OBJECT_LIST
global_template->Set(String::New("lol_is_enabled"), Boolean::New(true));
#else
@@ -442,94 +633,85 @@
AddOSMethods(os_templ);
global_template->Set(String::New("os"), os_templ);
- utility_context_ = Context::New(NULL, global_template);
- utility_context_->SetSecurityToken(Undefined());
- Context::Scope utility_scope(utility_context_);
+ return global_template;
+}
- i::JSArguments js_args = i::FLAG_js_arguments;
- i::Handle<i::FixedArray> arguments_array =
- FACTORY->NewFixedArray(js_args.argc());
- for (int j = 0; j < js_args.argc(); j++) {
- i::Handle<i::String> arg =
- FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
- arguments_array->set(j, *arg);
+
+void Shell::Initialize() {
+#ifdef COMPRESS_STARTUP_DATA_BZ2
+ BZip2Decompressor startup_data_decompressor;
+ int bz2_result = startup_data_decompressor.Decompress();
+ if (bz2_result != BZ_OK) {
+ fprintf(stderr, "bzip error code: %d\n", bz2_result);
+ exit(1);
}
- i::Handle<i::JSArray> arguments_jsarray =
- FACTORY->NewJSArrayWithElements(arguments_array);
- global_template->Set(String::New("arguments"),
- Utils::ToLocal(arguments_jsarray));
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Install the debugger object in the utility scope
- i::Debug* debug = i::Isolate::Current()->debug();
- debug->Load();
- i::Handle<i::JSObject> js_debug
- = i::Handle<i::JSObject>(debug->debug_context()->global());
- utility_context_->Global()->Set(String::New("$debug"),
- Utils::ToLocal(js_debug));
#endif
- // Run the d8 shell utility script in the utility context
- int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
- i::Vector<const char> shell_source
- = i::NativesCollection<i::D8>::GetScriptSource(source_index);
- i::Vector<const char> shell_source_name
- = i::NativesCollection<i::D8>::GetScriptName(source_index);
- Handle<String> source = String::New(shell_source.start(),
- shell_source.length());
- Handle<String> name = String::New(shell_source_name.start(),
- shell_source_name.length());
- Handle<Script> script = Script::Compile(source, name);
- script->Run();
+ Shell::counter_map_ = new CounterMap();
+ // Set up counters
+ if (i::StrLength(i::FLAG_map_counters) != 0)
+ MapCounters(i::FLAG_map_counters);
+ if (i::FLAG_dump_counters) {
+ V8::SetCounterFunction(LookupCounter);
+ V8::SetCreateHistogramFunction(CreateHistogram);
+ V8::SetAddHistogramSampleFunction(AddHistogramSample);
+ }
- // Mark the d8 shell script as native to avoid it showing up as normal source
- // in the debugger.
- i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
- i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
- ? i::Handle<i::Script>(i::Script::cast(
- i::JSFunction::cast(*compiled_script)->shared()->script()))
- : i::Handle<i::Script>(i::Script::cast(
- i::SharedFunctionInfo::cast(*compiled_script)->script()));
- script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
+ if (options.test_shell) return;
- // Create the evaluation context
- evaluation_context_ = Context::New(NULL, global_template);
- evaluation_context_->SetSecurityToken(Undefined());
+ Locker lock;
+ HandleScope scope;
+ Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
+ utility_context_ = Context::New(NULL, global_template);
#ifdef ENABLE_DEBUGGER_SUPPORT
- // Set the security token of the debug context to allow access.
- debug->debug_context()->set_security_token(HEAP->undefined_value());
-
// Start the debugger agent if requested.
if (i::FLAG_debugger_agent) {
v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
}
+#endif
+}
- // Start the in-process debugger if requested.
- if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
- v8::Debug::SetDebugEventListener(HandleDebugEvent);
+
+Persistent<Context> Shell::CreateEvaluationContext() {
+ // This needs to be a critical section since this is not thread-safe
+ i::ScopedLock lock(context_mutex_);
+ // Initialize the global objects
+ Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
+ Persistent<Context> context = Context::New(NULL, global_template);
+ Context::Scope scope(context);
+
+ i::JSArguments js_args = i::FLAG_js_arguments;
+ i::Handle<i::FixedArray> arguments_array =
+ FACTORY->NewFixedArray(js_args.argc());
+ for (int j = 0; j < js_args.argc(); j++) {
+ i::Handle<i::String> arg =
+ FACTORY->NewStringFromUtf8(i::CStrVector(js_args[j]));
+ arguments_array->set(j, *arg);
}
-#endif
+ i::Handle<i::JSArray> arguments_jsarray =
+ FACTORY->NewJSArrayWithElements(arguments_array);
+ context->Global()->Set(String::New("arguments"),
+ Utils::ToLocal(arguments_jsarray));
+ return context;
}
void Shell::OnExit() {
if (i::FLAG_dump_counters) {
- ::printf("+----------------------------------------+-------------+\n");
- ::printf("| Name | Value |\n");
- ::printf("+----------------------------------------+-------------+\n");
+ printf("+----------------------------------------+-------------+\n");
+ printf("| Name | Value |\n");
+ printf("+----------------------------------------+-------------+\n");
for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
Counter* counter = i.CurrentValue();
if (counter->is_histogram()) {
- ::printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count());
- ::printf("| t:%-36s | %11i |\n",
- i.CurrentKey(),
- counter->sample_total());
+ printf("| c:%-36s | %11i |\n", i.CurrentKey(), counter->count());
+ printf("| t:%-36s | %11i |\n", i.CurrentKey(), counter->sample_total());
} else {
- ::printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count());
+ printf("| %-38s | %11i |\n", i.CurrentKey(), counter->count());
}
}
- ::printf("+----------------------------------------+-------------+\n");
+ printf("+----------------------------------------+-------------+\n");
}
if (counters_file_ != NULL)
delete counters_file_;
@@ -537,7 +719,8 @@
static char* ReadChars(const char* name, int* size_out) {
- v8::Unlocker unlocker; // Release the V8 lock while reading files.
+ // Release the V8 lock while reading files.
+ v8::Unlocker unlocker(Isolate::GetCurrent());
FILE* file = i::OS::FOpen(name, "rb");
if (file == NULL) return NULL;
@@ -595,6 +778,7 @@
if (i::FLAG_debugger) {
printf("JavaScript debugger enabled\n");
}
+
editor->Open();
while (true) {
Locker locker;
@@ -614,8 +798,8 @@
class ShellThread : public i::Thread {
public:
- ShellThread(i::Isolate* isolate, int no, i::Vector<const char> files)
- : Thread(isolate, "d8:ShellThread"),
+ ShellThread(int no, i::Vector<const char> files)
+ : Thread("d8:ShellThread"),
no_(no), files_(files) { }
virtual void Run();
private:
@@ -625,25 +809,6 @@
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("write"),
- FunctionTemplate::New(Shell::Write));
- global_template->Set(String::New("read"),
- FunctionTemplate::New(Shell::Read));
- global_template->Set(String::New("readline"),
- FunctionTemplate::New(Shell::ReadLine));
- global_template->Set(String::New("load"),
- FunctionTemplate::New(Shell::Load));
- global_template->Set(String::New("yield"),
- FunctionTemplate::New(Shell::Yield));
- global_template->Set(String::New("version"),
- FunctionTemplate::New(Shell::Version));
-
char* ptr = const_cast<char*>(files_.start());
while ((ptr != NULL) && (*ptr != '\0')) {
// For each newline-separated line.
@@ -655,8 +820,10 @@
continue;
}
- Persistent<Context> thread_context = Context::New(NULL, global_template);
- thread_context->SetSecurityToken(Undefined());
+ // Prepare the context for this thread.
+ Locker locker;
+ HandleScope scope;
+ Persistent<Context> thread_context = Shell::CreateEvaluationContext();
Context::Scope context_scope(thread_context);
while ((ptr != NULL) && (*ptr != '\0')) {
@@ -683,116 +850,316 @@
}
-int Shell::Main(int argc, char* argv[]) {
- i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
- if (i::FLAG_help) {
- return 1;
+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() {
+ for (int i = begin_offset_; i < end_offset_; ++i) {
+ const char* arg = argv_[i];
+ if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
+ // Execute argument given to -e option directly.
+ HandleScope handle_scope;
+ Handle<String> file_name = String::New("unnamed");
+ Handle<String> source = String::New(argv_[i + 1]);
+ if (!Shell::ExecuteString(source, file_name, false, true)) {
+ ExitShell(1);
+ return;
+ }
+ ++i;
+ } else if (arg[0] == '-') {
+ // Ignore other options. They have been parsed already.
+ } else {
+ // Use all other arguments as names of files to load and run.
+ HandleScope handle_scope;
+ Handle<String> file_name = String::New(arg);
+ Handle<String> source = ReadFile(arg);
+ if (source.IsEmpty()) {
+ printf("Error reading '%s'\n", arg);
+ ExitShell(1);
+ return;
+ }
+ if (!Shell::ExecuteString(source, file_name, false, true)) {
+ ExitShell(1);
+ return;
+ }
+ }
}
- Initialize();
- bool run_shell = (argc == 1);
+}
- // Default use preemption if threads are created.
- bool use_preemption = true;
- // Default to use lowest possible thread preemption interval to test as many
- // edgecases as possible.
- int preemption_interval = 1;
+Handle<String> SourceGroup::ReadFile(const char* name) {
+ FILE* file = fopen(name, "rb");
+ if (file == NULL) return Handle<String>();
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+ rewind(file);
+
+ char* chars = new char[size + 1];
+ chars[size] = '\0';
+ for (int i = 0; i < size;) {
+ int read = fread(&chars[i], 1, size - i, file);
+ i += read;
+ }
+ fclose(file);
+ Handle<String> result = String::New(chars, size);
+ delete[] chars;
+ return result;
+}
+
+
+i::Thread::Options SourceGroup::GetThreadOptions() {
+ i::Thread::Options options;
+ options.name = "IsolateThread";
+ // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
+ // which is not enough to parse the big literal expressions used in tests.
+ // The stack size should be at least StackGuard::kLimitSize + some
+ // OS-specific padding for thread startup code.
+ options.stack_size = 2 << 20; // 2 Mb seems to be enough
+ return options;
+}
+
+
+void SourceGroup::ExecuteInThread() {
+ Isolate* isolate = Isolate::New();
+ do {
+ if (next_semaphore_ != NULL) next_semaphore_->Wait();
+ {
+ Isolate::Scope iscope(isolate);
+ Locker lock(isolate);
+ HandleScope scope;
+ Persistent<Context> context = Shell::CreateEvaluationContext();
+ {
+ Context::Scope cscope(context);
+ Execute();
+ }
+ context.Dispose();
+ }
+ if (done_semaphore_ != NULL) done_semaphore_->Signal();
+ } while (!Shell::options.last_run);
+ isolate->Dispose();
+}
+
+
+void SourceGroup::StartExecuteInThread() {
+ if (thread_ == NULL) {
+ thread_ = new IsolateThread(this);
+ thread_->Start();
+ }
+ next_semaphore_->Signal();
+}
+
+
+void SourceGroup::WaitForThread() {
+ if (thread_ == NULL) return;
+ if (Shell::options.last_run) {
+ thread_->Join();
+ thread_ = NULL;
+ } else {
+ done_semaphore_->Wait();
+ }
+}
+
+
+bool Shell::SetOptions(int argc, char* argv[]) {
+ for (int i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "--stress-opt") == 0) {
+ options.stress_opt = true;
+ argv[i] = NULL;
+ } else if (strcmp(argv[i], "--stress-deopt") == 0) {
+ options.stress_deopt = true;
+ argv[i] = NULL;
+ } else if (strcmp(argv[i], "--noalways-opt") == 0) {
+ // No support for stressing if we can't use --always-opt.
+ options.stress_opt = false;
+ options.stress_deopt = false;
+ } else if (strcmp(argv[i], "--shell") == 0) {
+ options.interactive_shell = true;
+ argv[i] = NULL;
+ } else if (strcmp(argv[i], "--test") == 0) {
+ options.test_shell = true;
+ argv[i] = NULL;
+ } else if (strcmp(argv[i], "--preemption") == 0) {
+ options.use_preemption = true;
+ argv[i] = NULL;
+ } else if (strcmp(argv[i], "--no-preemption") == 0) {
+ options.use_preemption = false;
+ argv[i] = NULL;
+ } else if (strcmp(argv[i], "--preemption-interval") == 0) {
+ if (++i < argc) {
+ argv[i-1] = NULL;
+ char* end = NULL;
+ options.preemption_interval = strtol(argv[i], &end, 10); // NOLINT
+ if (options.preemption_interval <= 0
+ || *end != '\0'
+ || errno == ERANGE) {
+ printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
+ return false;
+ }
+ argv[i] = NULL;
+ } else {
+ printf("Missing value for --preemption-interval\n");
+ return false;
+ }
+ } else if (strcmp(argv[i], "-f") == 0) {
+ // Ignore any -f flags for compatibility with other stand-alone
+ // JavaScript engines.
+ continue;
+ } else if (strcmp(argv[i], "--isolate") == 0) {
+ options.num_isolates++;
+ }
+ }
+
+ // Run parallel threads if we are not using --isolate
+ for (int i = 1; i < argc; i++) {
+ if (argv[i] == NULL) continue;
+ if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
+ if (options.num_isolates > 1) {
+ printf("-p is not compatible with --isolate\n");
+ return false;
+ }
+ argv[i] = NULL;
+ if (options.parallel_files == NULL) {
+ options.parallel_files = new i::List<i::Vector<const char> >();
+ }
+ int size = 0;
+ const char* files = ReadChars(argv[++i], &size);
+ if (files == NULL) {
+ printf("-p option incomplete\n");
+ return false;
+ }
+ argv[i] = NULL;
+ options.parallel_files->Add(i::Vector<const char>(files, size));
+ }
+ }
+
+ v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
+
+ // set up isolated source groups
+ options.isolate_sources = new SourceGroup[options.num_isolates];
+ SourceGroup* current = options.isolate_sources;
+ current->Begin(argv, 1);
+ for (int i = 1; i < argc; i++) {
+ const char* str = argv[i];
+ if (strcmp(str, "--isolate") == 0) {
+ current->End(i);
+ current++;
+ current->Begin(argv, i + 1);
+ } else if (strncmp(argv[i], "--", 2) == 0) {
+ printf("Warning: unknown flag %s.\nTry --help for options\n", argv[i]);
+ }
+ }
+ current->End(argc);
+
+ return true;
+}
+
+
+int Shell::RunMain(int argc, char* argv[]) {
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, "--preemption") == 0) {
- use_preemption = true;
- } else if (strcmp(str, "--no-preemption") == 0) {
- use_preemption = false;
- } else if (strcmp(str, "--preemption-interval") == 0) {
- if (i + 1 < argc) {
- char* end = NULL;
- preemption_interval = strtol(argv[++i], &end, 10); // NOLINT
- if (preemption_interval <= 0 || *end != '\0' || errno == ERANGE) {
- printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
- return 1;
- }
- } else {
- printf("Missing value for --preemption-interval\n");
- return 1;
- }
- } 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)) {
- OnExit();
- return 1;
- }
- i++;
- } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
- int size = 0;
- const char* files = ReadChars(argv[++i], &size);
- if (files == NULL) return 1;
- ShellThread* thread =
- new ShellThread(i::Isolate::Current(),
- threads.length(),
- i::Vector<const char>(files, size));
+ if (options.parallel_files != NULL)
+ for (int i = 0; i < options.parallel_files->length(); i++) {
+ i::Vector<const char> files = options.parallel_files->at(i);
+ ShellThread* thread = new ShellThread(threads.length(), files);
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)) {
- OnExit();
- return 1;
- }
}
+
+ for (int i = 1; i < options.num_isolates; ++i) {
+ options.isolate_sources[i].StartExecuteInThread();
}
+ Locker lock;
+ HandleScope scope;
+ Persistent<Context> context = CreateEvaluationContext();
+ {
+ Context::Scope cscope(context);
+ options.isolate_sources[0].Execute();
+ }
+ if (options.last_run) {
+ // Keep using the same context in the interactive shell
+ evaluation_context_ = context;
+ } else {
+ context.Dispose();
+ }
// Start preemption if threads have been created and preemption is enabled.
- if (threads.length() > 0 && use_preemption) {
- Locker::StartPreemption(preemption_interval);
+ if (options.parallel_files != NULL
+ && threads.length() > 0
+ && options.use_preemption) {
+ Locker::StartPreemption(options.preemption_interval);
}
+ }
+ for (int i = 1; i < options.num_isolates; ++i) {
+ options.isolate_sources[i].WaitForThread();
+ }
+
+ if (options.parallel_files != NULL)
+ for (int i = 0; i < threads.length(); i++) {
+ i::Thread* thread = threads[i];
+ thread->Join();
+ delete thread;
+ }
+
+ OnExit();
+ return 0;
+}
+
+
+int Shell::Main(int argc, char* argv[]) {
+ if (!SetOptions(argc, argv)) return 1;
+ Initialize();
+
+ int result = 0;
+ if (options.stress_opt || options.stress_deopt) {
+ Testing::SetStressRunType(
+ options.stress_opt ? Testing::kStressTypeOpt
+ : Testing::kStressTypeDeopt);
+ int stress_runs = Testing::GetStressRuns();
+ for (int i = 0; i < stress_runs && result == 0; i++) {
+ printf("============ Stress %d/%d ============\n", i + 1, stress_runs);
+ Testing::PrepareStressRun(i);
+ options.last_run = (i == stress_runs - 1);
+ result = RunMain(argc, argv);
+ }
+ printf("======== Full Deoptimization =======\n");
+ Testing::DeoptimizeAll();
+ } else {
+ result = RunMain(argc, argv);
+ }
+
#ifdef ENABLE_DEBUGGER_SUPPORT
- // Run the remote debugger if requested.
- if (i::FLAG_remote_debugger) {
- RunRemoteDebugger(i::FLAG_debugger_port);
- return 0;
- }
+ // Run remote debugger if requested, but never on --test
+ if (i::FLAG_remote_debugger && !options.test_shell) {
+ InstallUtilityScript();
+ RunRemoteDebugger(i::FLAG_debugger_port);
+ return 0;
+ }
#endif
- }
- if (run_shell)
+
+ // Run interactive shell if explicitly requested or if no script has been
+ // executed, but never on --test
+
+ if (( options.interactive_shell
+ || !options.script_executed )
+ && !options.test_shell ) {
+ InstallUtilityScript();
RunShell();
- for (int i = 0; i < threads.length(); i++) {
- i::Thread* thread = threads[i];
- thread->Join();
- delete thread;
}
- OnExit();
- return 0;
+
+ V8::Dispose();
+
+ return result;
}
-
} // namespace v8
« no previous file with comments | « src/d8.h ('k') | src/d8.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698