diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-06-29 17:26:51 +0200 |
commit | 33af2720f26c2b25bc7f75ce7eb454ff99db6d35 (patch) | |
tree | 9a38f0c96420edf503eebd6325dd8d2d8249f653 /deps/v8/samples/shell.cc | |
parent | 6afdca885adeeeed9eef8cbb01c3d97af0bc084d (diff) | |
download | android-node-v8-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.tar.gz android-node-v8-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.tar.bz2 android-node-v8-33af2720f26c2b25bc7f75ce7eb454ff99db6d35.zip |
Upgrade V8 to 3.4.8
Diffstat (limited to 'deps/v8/samples/shell.cc')
-rw-r--r-- | deps/v8/samples/shell.cc | 453 |
1 files changed, 407 insertions, 46 deletions
diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc index 64f78f02c6..15c1a5ad73 100644 --- a/deps/v8/samples/shell.cc +++ b/deps/v8/samples/shell.cc @@ -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: @@ -28,12 +28,36 @@ #include <v8.h> #include <v8-testing.h> #include <assert.h> +#ifdef COMPRESS_STARTUP_DATA_BZ2 +#include <bzlib.h> +#endif #include <fcntl.h> #include <string.h> #include <stdio.h> #include <stdlib.h> +// When building with V8 in a shared library we cannot use functions which +// is not explicitly a part of the public V8 API. This extensive use of +// #ifndef USING_V8_SHARED/#endif is a hack until we can resolve whether to +// still use the shell sample for testing or change to use the developer +// shell d8 TODO(1272). +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) +#include "../src/v8.h" +#endif // USING_V8_SHARED +#if !defined(_WIN32) && !defined(_WIN64) +#include <unistd.h> // NOLINT +#endif + +static void 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); +} + +v8::Persistent<v8::Context> CreateShellContext(); void RunShell(v8::Handle<v8::Context> context); bool ExecuteString(v8::Handle<v8::String> source, v8::Handle<v8::Value> name, @@ -44,62 +68,242 @@ v8::Handle<v8::Value> Read(const v8::Arguments& args); v8::Handle<v8::Value> Load(const v8::Arguments& args); v8::Handle<v8::Value> Quit(const v8::Arguments& args); v8::Handle<v8::Value> Version(const v8::Arguments& args); +v8::Handle<v8::Value> Int8Array(const v8::Arguments& args); +v8::Handle<v8::Value> Uint8Array(const v8::Arguments& args); +v8::Handle<v8::Value> Int16Array(const v8::Arguments& args); +v8::Handle<v8::Value> Uint16Array(const v8::Arguments& args); +v8::Handle<v8::Value> Int32Array(const v8::Arguments& args); +v8::Handle<v8::Value> Uint32Array(const v8::Arguments& args); +v8::Handle<v8::Value> Float32Array(const v8::Arguments& args); +v8::Handle<v8::Value> Float64Array(const v8::Arguments& args); +v8::Handle<v8::Value> PixelArray(const v8::Arguments& args); v8::Handle<v8::String> ReadFile(const char* name); void ReportException(v8::TryCatch* handler); +static bool last_run = true; + +class SourceGroup { + public: + SourceGroup() : +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) + next_semaphore_(v8::internal::OS::CreateSemaphore(0)), + done_semaphore_(v8::internal::OS::CreateSemaphore(0)), + thread_(NULL), +#endif // USING_V8_SHARED + argv_(NULL), + begin_offset_(0), + end_offset_(0) { } + + void Begin(char** argv, int offset) { + argv_ = const_cast<const char**>(argv); + begin_offset_ = offset; + } + + void End(int offset) { end_offset_ = offset; } + + void 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. + 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)) { + 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. + v8::HandleScope handle_scope; + v8::Handle<v8::String> file_name = v8::String::New(arg); + v8::Handle<v8::String> source = ReadFile(arg); + if (source.IsEmpty()) { + printf("Error reading '%s'\n", arg); + continue; + } + if (!ExecuteString(source, file_name, false, true)) { + ExitShell(1); + return; + } + } + } + } + +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) + void StartExecuteInThread() { + if (thread_ == NULL) { + thread_ = new IsolateThread(this); + thread_->Start(); + } + next_semaphore_->Signal(); + } + + void WaitForThread() { + if (thread_ == NULL) return; + if (last_run) { + thread_->Join(); + thread_ = NULL; + } else { + done_semaphore_->Wait(); + } + } +#endif // USING_V8_SHARED + + private: +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) + static v8::internal::Thread::Options GetThreadOptions() { + v8::internal::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; + } + + class IsolateThread : public v8::internal::Thread { + public: + explicit IsolateThread(SourceGroup* group) + : v8::internal::Thread(GetThreadOptions()), group_(group) {} + + virtual void Run() { + group_->ExecuteInThread(); + } + + private: + SourceGroup* group_; + }; + + void ExecuteInThread() { + v8::Isolate* isolate = v8::Isolate::New(); + do { + if (next_semaphore_ != NULL) next_semaphore_->Wait(); + { + v8::Isolate::Scope iscope(isolate); + v8::HandleScope scope; + v8::Persistent<v8::Context> context = CreateShellContext(); + { + v8::Context::Scope cscope(context); + Execute(); + } + context.Dispose(); + } + if (done_semaphore_ != NULL) done_semaphore_->Signal(); + } while (!last_run); + isolate->Dispose(); + } + + v8::internal::Semaphore* next_semaphore_; + v8::internal::Semaphore* done_semaphore_; + v8::internal::Thread* thread_; +#endif // USING_V8_SHARED + + const char** argv_; + int begin_offset_; + int end_offset_; +}; + + +static SourceGroup* isolate_sources = NULL; + + +#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 + + int RunMain(int argc, char* argv[]) { + v8::V8::SetFlagsFromCommandLine(&argc, argv, true); v8::HandleScope handle_scope; - // Create a template for the global object. - v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); - // Bind the global 'print' function to the C++ Print callback. - global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); - // Bind the global 'read' function to the C++ Read callback. - global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); - // Bind the global 'load' function to the C++ Load callback. - global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); - // Bind the 'quit' function - global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); - // Bind the 'version' function - global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); - // Create a new execution environment containing the built-in - // functions - v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); + v8::Persistent<v8::Context> context = CreateShellContext(); + // Enter the newly created execution environment. + context->Enter(); + if (context.IsEmpty()) { + printf("Error creating context\n"); + return 1; + } + bool run_shell = (argc == 1); + int num_isolates = 1; for (int i = 1; i < argc; i++) { - // Enter the execution environment before evaluating any code. - v8::Context::Scope context_scope(context); - const 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 the 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. - v8::HandleScope handle_scope; - v8::Handle<v8::String> file_name = v8::String::New(str); - v8::Handle<v8::String> source = ReadFile(str); - if (source.IsEmpty()) { - printf("Error reading '%s'\n", str); - return 1; + if (strcmp(argv[i], "--isolate") == 0) { +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) + ++num_isolates; +#else // USING_V8_SHARED + printf("Error: --isolate not supported when linked with shared " + "library\n"); + ExitShell(1); +#endif // USING_V8_SHARED + } + } + if (isolate_sources == NULL) { + isolate_sources = new SourceGroup[num_isolates]; + SourceGroup* current = 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 (strcmp(str, "--shell") == 0) { + run_shell = true; + } else if (strcmp(str, "-f") == 0) { + // Ignore any -f flags for compatibility with the other stand- + // alone JavaScript engines. + continue; + } else if (strncmp(str, "--", 2) == 0) { + printf("Warning: unknown flag %s.\nTry --help for options\n", str); } - if (!ExecuteString(source, file_name, false, true)) - return 1; } + current->End(argc); } +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) + for (int i = 1; i < num_isolates; ++i) { + isolate_sources[i].StartExecuteInThread(); + } +#endif // USING_V8_SHARED + isolate_sources[0].Execute(); if (run_shell) RunShell(context); +#if !(defined(USING_V8_SHARED) || defined(V8_SHARED)) + for (int i = 1; i < num_isolates; ++i) { + isolate_sources[i].WaitForThread(); + } +#endif // USING_V8_SHARED + if (last_run) { + delete[] isolate_sources; + isolate_sources = NULL; + } + context->Exit(); context.Dispose(); return 0; } @@ -126,6 +330,15 @@ int main(int argc, char* argv[]) { } } +#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); + } +#endif + v8::V8::SetFlagsFromCommandLine(&argc, argv, true); int result = 0; if (FLAG_stress_opt || FLAG_stress_deopt) { @@ -137,12 +350,16 @@ int main(int argc, char* argv[]) { printf("============ Stress %d/%d ============\n", i + 1, stress_runs); v8::Testing::PrepareStressRun(i); + last_run = (i == stress_runs - 1); result = RunMain(argc, argv); } + printf("======== Full Deoptimization =======\n"); + v8::Testing::DeoptimizeAll(); } else { result = RunMain(argc, argv); } v8::V8::Dispose(); + return result; } @@ -153,6 +370,46 @@ const char* ToCString(const v8::String::Utf8Value& value) { } +// Creates a new execution environment containing the built-in +// functions. +v8::Persistent<v8::Context> CreateShellContext() { + // Create a template for the global object. + v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); + // Bind the global 'print' function to the C++ Print callback. + global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); + // Bind the global 'read' function to the C++ Read callback. + global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); + // Bind the global 'load' function to the C++ Load callback. + global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); + // Bind the 'quit' function + global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); + // Bind the 'version' function + global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); + + // Bind the handlers for external arrays. + global->Set(v8::String::New("Int8Array"), + v8::FunctionTemplate::New(Int8Array)); + global->Set(v8::String::New("Uint8Array"), + v8::FunctionTemplate::New(Uint8Array)); + global->Set(v8::String::New("Int16Array"), + v8::FunctionTemplate::New(Int16Array)); + global->Set(v8::String::New("Uint16Array"), + v8::FunctionTemplate::New(Uint16Array)); + global->Set(v8::String::New("Int32Array"), + v8::FunctionTemplate::New(Int32Array)); + global->Set(v8::String::New("Uint32Array"), + v8::FunctionTemplate::New(Uint32Array)); + global->Set(v8::String::New("Float32Array"), + v8::FunctionTemplate::New(Float32Array)); + global->Set(v8::String::New("Float64Array"), + v8::FunctionTemplate::New(Float64Array)); + global->Set(v8::String::New("PixelArray"), + v8::FunctionTemplate::New(PixelArray)); + + return v8::Context::New(NULL, global); +} + + // The callback that is invoked by v8 whenever the JavaScript 'print' // function is called. Prints its arguments on stdout separated by // spaces and ending with a newline. @@ -222,7 +479,7 @@ v8::Handle<v8::Value> Quit(const v8::Arguments& args) { // If not arguments are given args[0] will yield undefined which // converts to the integer value 0. int exit_code = args[0]->Int32Value(); - exit(exit_code); + ExitShell(exit_code); return v8::Undefined(); } @@ -232,6 +489,110 @@ v8::Handle<v8::Value> Version(const v8::Arguments& args) { } +void ExternalArrayWeakCallback(v8::Persistent<v8::Value> object, void* data) { + free(data); + object.Dispose(); +} + + +v8::Handle<v8::Value> CreateExternalArray(const v8::Arguments& args, + v8::ExternalArrayType type, + size_t element_size) { + ASSERT(element_size == 1 || element_size == 2 || element_size == 4 || + element_size == 8); + if (args.Length() != 1) { + return v8::ThrowException( + v8::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 v8::ThrowException( + v8::String::New("Array length must not be negative.")); + } + if (raw_length > v8::internal::ExternalArray::kMaxLength) { + return v8::ThrowException( + v8::String::New("Array length exceeds maximum length.")); + } + length = static_cast<size_t>(raw_length); + } else { + return v8::ThrowException( + v8::String::New("Array length must be a number.")); + } + if (length > static_cast<size_t>(v8::internal::ExternalArray::kMaxLength)) { + return v8::ThrowException( + v8::String::New("Array length exceeds maximum length.")); + } + void* data = calloc(length, element_size); + if (data == NULL) { + return v8::ThrowException(v8::String::New("Memory allocation failed.")); + } + v8::Handle<v8::Object> array = v8::Object::New(); + v8::Persistent<v8::Object> persistent_array = + v8::Persistent<v8::Object>::New(array); + persistent_array.MakeWeak(data, ExternalArrayWeakCallback); + persistent_array.MarkIndependent(); + array->SetIndexedPropertiesToExternalArrayData(data, type, length); + array->Set(v8::String::New("length"), v8::Int32::New(length), + v8::ReadOnly); + array->Set(v8::String::New("BYTES_PER_ELEMENT"), + v8::Int32::New(element_size)); + return array; +} + + +v8::Handle<v8::Value> Int8Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); +} + + +v8::Handle<v8::Value> Uint8Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalUnsignedByteArray, + sizeof(uint8_t)); +} + + +v8::Handle<v8::Value> Int16Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalShortArray, sizeof(int16_t)); +} + + +v8::Handle<v8::Value> Uint16Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalUnsignedShortArray, + sizeof(uint16_t)); +} + +v8::Handle<v8::Value> Int32Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalIntArray, sizeof(int32_t)); +} + + +v8::Handle<v8::Value> Uint32Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalUnsignedIntArray, + sizeof(uint32_t)); +} + + +v8::Handle<v8::Value> Float32Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalFloatArray, + sizeof(float)); // NOLINT +} + + +v8::Handle<v8::Value> Float64Array(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalDoubleArray, + sizeof(double)); // NOLINT +} + + +v8::Handle<v8::Value> PixelArray(const v8::Arguments& args) { + return CreateExternalArray(args, v8::kExternalPixelArray, sizeof(uint8_t)); +} + + // Reads a file into a v8 string. v8::Handle<v8::String> ReadFile(const char* name) { FILE* file = fopen(name, "rb"); |