Chromium Code Reviews| Index: samples/shell.cc |
| diff --git a/samples/shell.cc b/samples/shell.cc |
| index 7c30beccd5f3b52a75f286ce7800e49632039e5d..8ed9d032aaf3ab4919e921f96c5185ad61dd7fba 100644 |
| --- a/samples/shell.cc |
| +++ b/samples/shell.cc |
| @@ -26,39 +26,28 @@ |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| #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 |
| +#ifdef COMPRESS_STARTUP_DATA_BZ2 |
| +#error Using compressed startup data is not supported for this sample |
| #endif |
| -static void ExitShell(int exit_code) { |
|
Yang
2011/07/13 16:08:46
Removed since there is no longer multi-threading.
|
| - // Use _exit instead of exit to avoid races between isolate |
| - // threads and static destructors. |
| - fflush(stdout); |
| - fflush(stderr); |
| - _exit(exit_code); |
| -} |
| +/** |
| + * This sample program shows how to implement a simple javascript shell |
| + * based on V8. This includes initializing V8 with command line options, |
| + * creating global functions, compiling and executing strings. |
| + * |
| + * For a more sophisticated shell, consider using the debug shell D8. |
| + */ |
| + |
| v8::Persistent<v8::Context> CreateShellContext(); |
| void RunShell(v8::Handle<v8::Context> context); |
| +int RunMain(int argc, char* argv[]); |
| bool ExecuteString(v8::Handle<v8::String> source, |
| v8::Handle<v8::Value> name, |
| bool print_result, |
| @@ -68,298 +57,28 @@ 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); |
|
Yang
2011/07/13 16:08:46
Removed external arrays completely.
|
| -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; |
| - |
|
Yang
2011/07/13 16:08:46
Removed support for --isolate.
|
| -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 bool run_shell; |
| -static SourceGroup* isolate_sources = NULL; |
| - |
|
Yang
2011/07/13 16:08:46
Removed support for compression.
|
| -#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[]) { |
| +int main(int argc, char* argv[]) { |
| v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
| + run_shell = (argc == 1); |
| v8::HandleScope handle_scope; |
| 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++) { |
| - 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); |
| - } |
| - } |
| - 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(); |
| + context->Enter(); |
| + int result = RunMain(argc, argv); |
| 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; |
| -} |
| - |
| - |
| -int main(int argc, char* argv[]) { |
| - // Figure out if we're requested to stress the optimization |
| - // infrastructure by running tests multiple times and forcing |
| - // optimization in the last run. |
| - bool FLAG_stress_opt = false; |
| - bool FLAG_stress_deopt = false; |
| - for (int i = 0; i < argc; i++) { |
| - if (strcmp(argv[i], "--stress-opt") == 0) { |
| - FLAG_stress_opt = true; |
| - argv[i] = NULL; |
| - } else if (strcmp(argv[i], "--stress-deopt") == 0) { |
| - FLAG_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. |
| - FLAG_stress_opt = false; |
| - FLAG_stress_deopt = false; |
| - break; |
| - } |
| - } |
| - |
| -#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 |
| - |
|
Yang
2011/07/13 16:08:46
Removed stress runs.
|
| - v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
| - int result = 0; |
| - if (FLAG_stress_opt || FLAG_stress_deopt) { |
| - v8::Testing::SetStressRunType(FLAG_stress_opt |
| - ? v8::Testing::kStressTypeOpt |
| - : v8::Testing::kStressTypeDeopt); |
| - int stress_runs = v8::Testing::GetStressRuns(); |
| - for (int i = 0; i < stress_runs && result == 0; i++) { |
| - 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; |
| } |
| @@ -386,26 +105,6 @@ v8::Persistent<v8::Context> CreateShellContext() { |
| // 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); |
| } |
| @@ -479,7 +178,9 @@ 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(); |
| - ExitShell(exit_code); |
| + fflush(stdout); |
| + fflush(stderr); |
| + exit(exit_code); |
| return v8::Undefined(); |
| } |
| @@ -489,113 +190,6 @@ 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.")); |
| - } |
| - static const int kMaxLength = 0x3fffffff; |
| - 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 > 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>(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"); |
| @@ -618,9 +212,41 @@ v8::Handle<v8::String> ReadFile(const char* name) { |
| } |
| +// Process remaining command line arguments and execute files |
| +int RunMain(int argc, char* argv[]) { |
| + for (int i = 1; i < argc; i++) { |
| + 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::Handle<v8::String> file_name = v8::String::New("unnamed"); |
| + v8::Handle<v8::String> source = v8::String::New(argv[++i]); |
| + if (!ExecuteString(source, file_name, false, true)) return 1; |
| + } else { |
| + // Use all other arguments as names of files to load and run. |
| + 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); |
| + continue; |
| + } |
| + if (!ExecuteString(source, file_name, false, true)) return 1; |
| + } |
| + } |
| + return 0; |
| +} |
| + |
| + |
| // The read-eval-execute loop of the shell. |
| void RunShell(v8::Handle<v8::Context> context) { |
| - printf("V8 version %s\n", v8::V8::GetVersion()); |
| + printf("V8 version %s [sample shell]\n", v8::V8::GetVersion()); |
| static const int kBufferSize = 256; |
| // Enter the execution environment before evaluating any code. |
| v8::Context::Scope context_scope(context); |