summaryrefslogtreecommitdiff
path: root/deps/v8/samples/shell.cc
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-06-29 17:26:51 +0200
committerRyan Dahl <ry@tinyclouds.org>2011-06-29 17:26:51 +0200
commit33af2720f26c2b25bc7f75ce7eb454ff99db6d35 (patch)
tree9a38f0c96420edf503eebd6325dd8d2d8249f653 /deps/v8/samples/shell.cc
parent6afdca885adeeeed9eef8cbb01c3d97af0bc084d (diff)
downloadandroid-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.cc453
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");