summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-08-23 15:17:13 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-08-23 15:17:57 -0700
commitb15ab5de51e51d8f9dfaba8bcf4f62eee74ff721 (patch)
tree547337c3abc3395f274d5d5fe75d6f9cc42a9d02
parent42529ddfb500cc7df3601c3b5f1d1da9f787d08e (diff)
downloadandroid-node-v8-b15ab5de51e51d8f9dfaba8bcf4f62eee74ff721.tar.gz
android-node-v8-b15ab5de51e51d8f9dfaba8bcf4f62eee74ff721.tar.bz2
android-node-v8-b15ab5de51e51d8f9dfaba8bcf4f62eee74ff721.zip
Upgrade V8 to 3.5.7
-rw-r--r--deps/v8/ChangeLog9
-rw-r--r--deps/v8/build/common.gypi40
-rw-r--r--deps/v8/samples/shell.cc485
-rw-r--r--deps/v8/src/api.h4
-rw-r--r--deps/v8/src/arm/full-codegen-arm.cc12
-rw-r--r--deps/v8/src/d8.js12
-rw-r--r--deps/v8/src/debug-debugger.js20
-rw-r--r--deps/v8/src/elements.cc371
-rw-r--r--deps/v8/src/elements.h38
-rw-r--r--deps/v8/src/full-codegen.cc51
-rw-r--r--deps/v8/src/full-codegen.h113
-rw-r--r--deps/v8/src/ia32/full-codegen-ia32.cc17
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc2
-rw-r--r--deps/v8/src/isolate.cc6
-rw-r--r--deps/v8/src/json.js2
-rw-r--r--deps/v8/src/messages.js52
-rw-r--r--deps/v8/src/mips/full-codegen-mips.cc18
-rw-r--r--deps/v8/src/objects.cc82
-rw-r--r--deps/v8/src/regexp.js15
-rw-r--r--deps/v8/src/scanner-base.cc93
-rw-r--r--deps/v8/src/scanner-base.h6
-rw-r--r--deps/v8/src/spaces.h1
-rw-r--r--deps/v8/src/string.js4
-rw-r--r--deps/v8/src/v8natives.js30
-rw-r--r--deps/v8/src/v8threads.cc4
-rw-r--r--deps/v8/src/version.cc2
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc12
-rw-r--r--deps/v8/test/cctest/test-api.cc46
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1620.js54
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1625.js36
-rw-r--r--deps/v8/test/mjsunit/regress/regress-219.js128
-rw-r--r--deps/v8/test/mjsunit/regress/regress-87.js57
-rw-r--r--deps/v8/test/mozilla/mozilla.status5
-rw-r--r--deps/v8/test/sputnik/sputnik.status16
-rw-r--r--deps/v8/tools/gyp/v8.gyp6
35 files changed, 870 insertions, 979 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 6d188b89d1..aeeea78ac1 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,12 @@
+2011-08-22: Version 3.5.7
+
+ Make scanner handle invalid unicode escapes in identifiers correctly.
+
+ Make regexp flag parsing stricter.
+
+ Fix several memory leaks.
+
+
2011-08-17: Version 3.5.6
Fixed issue that could cause crashes when running with --heap-stats.
diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi
index 5a3da526a8..c41b2b2b62 100644
--- a/deps/v8/build/common.gypi
+++ b/deps/v8/build/common.gypi
@@ -32,25 +32,30 @@
'visibility%': 'hidden',
'msvs_multi_core_compile%': '1',
'variables': {
- 'conditions': [
- [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
- # This handles the Linux platforms we generally deal with. Anything
- # else gets passed through, which probably won't work very well; such
- # hosts should pass an explicit target_arch to gyp.
- 'host_arch%':
- '<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/")',
- }, { # OS!="linux" and OS!="freebsd" and OS!="openbsd"
- 'host_arch%': 'ia32',
- }],
- ],
+ 'variables': {
+ 'conditions': [
+ [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ # This handles the Linux platforms we generally deal with. Anything
+ # else gets passed through, which probably won't work very well; such
+ # hosts should pass an explicit target_arch to gyp.
+ 'host_arch%':
+ '<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/")',
+ }, { # OS!="linux" and OS!="freebsd" and OS!="openbsd"
+ 'host_arch%': 'ia32',
+ }],
+ ],
+ },
+ 'host_arch%': '<(host_arch)',
+ 'target_arch%': '<(host_arch)',
+ 'v8_target_arch%': '<(target_arch)',
},
'host_arch%': '<(host_arch)',
- 'target_arch%': '<(host_arch)',
- 'v8_target_arch%': '<(target_arch)',
+ 'target_arch%': '<(target_arch)',
+ 'v8_target_arch%': '<(v8_target_arch)',
'v8_enable_debugger_support%': 1,
'conditions': [
- ['(target_arch=="arm" and host_arch!="arm") or \
- (target_arch=="x64" and host_arch!="x64")', {
+ ['(v8_target_arch=="arm" and host_arch!="arm") or \
+ (v8_target_arch=="x64" and host_arch!="x64")', {
'want_separate_host_toolset': 1,
}, {
'want_separate_host_toolset': 0,
@@ -80,8 +85,9 @@
'conditions': [
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
'target_defaults': {
- 'cflags': [ '-Wall', '-pthread', '-fno-rtti', '-fno-exceptions',
- '-pedantic' ],
+ 'cflags': [ '-Wall', '-Werror', '-W', '-Wno-unused-parameter',
+ '-Wnon-virtual-dtor', '-pthread', '-fno-rtti',
+ '-fno-exceptions', '-pedantic' ],
'ldflags': [ '-pthread', ],
'conditions': [
[ 'target_arch=="ia32"', {
diff --git a/deps/v8/samples/shell.cc b/deps/v8/samples/shell.cc
index f37e731f38..8ed9d032aa 100644
--- a/deps/v8/samples/shell.cc
+++ b/deps/v8/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) {
- // 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,305 +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);
-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) { }
-
-#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
- ~SourceGroup() {
- delete next_semaphore_;
- delete done_semaphore_;
- }
-#endif // USING_V8_SHARED
-
- 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;
-
-#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
-
- 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;
}
@@ -393,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);
}
@@ -486,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();
}
@@ -496,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");
@@ -625,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);
diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h
index ce39d630a1..07723cb32c 100644
--- a/deps/v8/src/api.h
+++ b/deps/v8/src/api.h
@@ -406,6 +406,10 @@ class HandleScopeImplementer {
spare_(NULL),
call_depth_(0) { }
+ ~HandleScopeImplementer() {
+ DeleteArray(spare_);
+ }
+
// Threading support for handle data.
static int ArchiveSpacePerThread();
char* RestoreThread(char* from);
diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc
index 3116ca455b..d8ce956ec9 100644
--- a/deps/v8/src/arm/full-codegen-arm.cc
+++ b/deps/v8/src/arm/full-codegen-arm.cc
@@ -878,7 +878,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
- __ b(nested_statement.break_target());
+ __ b(nested_statement.break_label());
} else {
__ b(default_clause->body_target());
}
@@ -892,7 +892,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
- __ bind(nested_statement.break_target());
+ __ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@@ -1023,7 +1023,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Load the current count to r0, load the length to r1.
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
__ cmp(r0, r1); // Compare to the array length.
- __ b(hs, loop_statement.break_target());
+ __ b(hs, loop_statement.break_label());
// Get the current entry of the array into register r3.
__ ldr(r2, MemOperand(sp, 2 * kPointerSize));
@@ -1049,7 +1049,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(r3); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ mov(r3, Operand(r0), SetCC);
- __ b(eq, loop_statement.continue_target());
+ __ b(eq, loop_statement.continue_label());
// Update the 'each' property or variable from the possibly filtered
// entry in register r3.
@@ -1065,7 +1065,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for the going to the next element by incrementing
// the index (smi) stored on top of the stack.
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
__ pop(r0);
__ add(r0, r0, Operand(Smi::FromInt(1)));
__ push(r0);
@@ -1074,7 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ b(&loop);
// Remove the pointers stored on the stack.
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
__ Drop(5);
// Exit and decrement the loop depth.
diff --git a/deps/v8/src/d8.js b/deps/v8/src/d8.js
index 3523e54abd..a2b9585ce8 100644
--- a/deps/v8/src/d8.js
+++ b/deps/v8/src/d8.js
@@ -392,14 +392,14 @@ function DebugRequest(cmd_line) {
this.frameCommandToJSONRequest_('' +
(Debug.State.currentFrame + 1));
break;
-
+
case 'down':
case 'do':
this.request_ =
this.frameCommandToJSONRequest_('' +
(Debug.State.currentFrame - 1));
break;
-
+
case 'set':
case 'print':
case 'p':
@@ -1072,7 +1072,7 @@ DebugRequest.prototype.changeBreakpointCommandToJSONRequest_ =
arg2 = 'uncaught';
}
excType = arg2;
-
+
// Check for:
// en[able] [all|unc[aught]] exc[eptions]
// dis[able] [all|unc[aught]] exc[eptions]
@@ -1131,7 +1131,7 @@ DebugRequest.prototype.changeBreakpointCommandToJSONRequest_ =
request.arguments.ignoreCount = parseInt(otherArgs);
break;
default:
- throw new Error('Invalid arguments.');
+ throw new Error('Invalid arguments.');
}
} else {
throw new Error('Invalid arguments.');
@@ -1252,7 +1252,7 @@ DebugRequest.prototype.lolMakeListRequest =
start_index = parseInt(args[i]);
// The user input start index starts at 1:
if (start_index <= 0) {
- throw new Error('Invalid index ' + args[i] + '.');
+ throw new Error('Invalid index ' + args[i] + '.');
}
start_index -= 1;
is_verbose = true;
@@ -2021,7 +2021,7 @@ function DebugResponseDetails(response) {
} else if (body.breakOnUncaughtExceptions) {
result += '* breaking on UNCAUGHT exceptions is enabled\n';
} else {
- result += '* all exception breakpoints are disabled\n';
+ result += '* all exception breakpoints are disabled\n';
}
details.text = result;
break;
diff --git a/deps/v8/src/debug-debugger.js b/deps/v8/src/debug-debugger.js
index 36b624e574..d254ee5696 100644
--- a/deps/v8/src/debug-debugger.js
+++ b/deps/v8/src/debug-debugger.js
@@ -404,7 +404,7 @@ ScriptBreakPoint.prototype.matchesScript = function(script) {
return this.script_name_ == script.nameOrSourceURL();
} else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
return this.script_regexp_object_.test(script.nameOrSourceURL());
- } else {
+ } else {
throw new Error("Unexpected breakpoint type " + this.type_);
}
}
@@ -1579,7 +1579,7 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
response.failed('Missing argument "type" or "target"');
return;
}
-
+
// Either function or script break point.
var break_point_number;
if (type == 'function') {
@@ -1623,10 +1623,10 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
break_point_number =
Debug.setScriptBreakPointByName(target, line, column, condition,
groupId);
- } else if (type == 'scriptId') {
+ } else if (type == 'scriptId') {
break_point_number =
Debug.setScriptBreakPointById(target, line, column, condition, groupId);
- } else if (type == 'scriptRegExp') {
+ } else if (type == 'scriptRegExp') {
break_point_number =
Debug.setScriptBreakPointByRegExp(target, line, column, condition,
groupId);
@@ -1797,7 +1797,7 @@ DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(request, resp
description.type = 'scriptRegExp';
description.script_regexp = break_point.script_regexp_object().source;
} else {
- throw new Error("Internal error: Unexpected breakpoint type: " + break_point.type());
+ throw new Error("Internal error: Unexpected breakpoint type: " + break_point.type());
}
array.push(description);
}
@@ -1838,7 +1838,7 @@ DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
enabled = !Debug.isBreakOnException();
} else if (type == 'uncaught') {
enabled = !Debug.isBreakOnUncaughtException();
- }
+ }
// Pull out and check the 'enabled' argument if present:
if (!IS_UNDEFINED(request.arguments.enabled)) {
@@ -2022,22 +2022,22 @@ DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
if (!IS_UNDEFINED(frame) && global) {
return response.failed('Arguments "frame" and "global" are exclusive');
}
-
+
var additional_context_object;
if (additional_context) {
additional_context_object = {};
for (var i = 0; i < additional_context.length; i++) {
var mapping = additional_context[i];
if (!IS_STRING(mapping.name) || !IS_NUMBER(mapping.handle)) {
- return response.failed("Context element #" + i +
+ return response.failed("Context element #" + i +
" must contain name:string and handle:number");
- }
+ }
var context_value_mirror = LookupMirror(mapping.handle);
if (!context_value_mirror) {
return response.failed("Context object '" + mapping.name +
"' #" + mapping.handle + "# not found");
}
- additional_context_object[mapping.name] = context_value_mirror.value();
+ additional_context_object[mapping.name] = context_value_mirror.value();
}
}
diff --git a/deps/v8/src/elements.cc b/deps/v8/src/elements.cc
index 9927cd5ced..70d58b31ac 100644
--- a/deps/v8/src/elements.cc
+++ b/deps/v8/src/elements.cc
@@ -29,6 +29,7 @@
#include "objects.h"
#include "elements.h"
+#include "utils.h"
namespace v8 {
namespace internal {
@@ -70,24 +71,34 @@ bool HasKey(FixedArray* array, Object* key) {
// specialization of SomeElementsAccessor methods).
template <typename ElementsAccessorSubclass, typename BackingStoreClass>
class ElementsAccessorBase : public ElementsAccessor {
- public:
+ protected:
ElementsAccessorBase() { }
- virtual MaybeObject* GetWithReceiver(JSObject* obj,
- Object* receiver,
- uint32_t index) {
- BackingStoreClass* backing_store = BackingStoreClass::cast(obj->elements());
- if (index < ElementsAccessorSubclass::GetLength(backing_store)) {
- return backing_store->get(index);
+ virtual MaybeObject* Get(FixedArrayBase* backing_store,
+ uint32_t key,
+ JSObject* obj,
+ Object* receiver) {
+ return ElementsAccessorSubclass::Get(
+ BackingStoreClass::cast(backing_store), key, obj, receiver);
+ }
+
+ static MaybeObject* Get(BackingStoreClass* backing_store,
+ uint32_t key,
+ JSObject* obj,
+ Object* receiver) {
+ if (key < ElementsAccessorSubclass::GetCapacity(backing_store)) {
+ return backing_store->get(key);
}
- return obj->GetHeap()->the_hole_value();
+ return backing_store->GetHeap()->the_hole_value();
}
virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ uint32_t key,
JSReceiver::DeleteMode mode) = 0;
virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from,
- FixedArray* to) {
+ FixedArray* to,
+ JSObject* holder,
+ Object* receiver) {
int len0 = to->length();
#ifdef DEBUG
if (FLAG_enable_slow_asserts) {
@@ -97,7 +108,7 @@ class ElementsAccessorBase : public ElementsAccessor {
}
#endif
BackingStoreClass* backing_store = BackingStoreClass::cast(from);
- int len1 = ElementsAccessorSubclass::GetCapacity(backing_store);
+ uint32_t len1 = ElementsAccessorSubclass::GetCapacity(backing_store);
// Optimize if 'other' is empty.
// We cannot optimize if 'this' is empty, as other may have holes.
@@ -105,12 +116,22 @@ class ElementsAccessorBase : public ElementsAccessor {
// Compute how many elements are not in other.
int extra = 0;
- for (int y = 0; y < len1; y++) {
- Object* value;
- MaybeObject* maybe_value =
- ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y);
- if (!maybe_value->ToObject(&value)) return maybe_value;
- if (!value->IsTheHole() && !HasKey(to, value)) extra++;
+ for (uint32_t y = 0; y < len1; y++) {
+ if (ElementsAccessorSubclass::HasElementAtIndex(backing_store,
+ y,
+ holder,
+ receiver)) {
+ uint32_t key =
+ ElementsAccessorSubclass::GetKeyForIndex(backing_store, y);
+ MaybeObject* maybe_value =
+ ElementsAccessorSubclass::Get(backing_store, key, holder, receiver);
+ Object* value;
+ if (!maybe_value->ToObject(&value)) return maybe_value;
+ ASSERT(!value->IsTheHole());
+ if (!HasKey(to, value)) {
+ extra++;
+ }
+ }
}
if (extra == 0) return to;
@@ -133,32 +154,67 @@ class ElementsAccessorBase : public ElementsAccessor {
}
// Fill in the extra values.
int index = 0;
- for (int y = 0; y < len1; y++) {
- MaybeObject* maybe_value =
- ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y);
- Object* value;
- if (!maybe_value->ToObject(&value)) return maybe_value;
- if (!value->IsTheHole() && !HasKey(to, value)) {
- result->set(len0 + index, value);
- index++;
+ for (uint32_t y = 0; y < len1; y++) {
+ if (ElementsAccessorSubclass::HasElementAtIndex(backing_store,
+ y,
+ holder,
+ receiver)) {
+ uint32_t key =
+ ElementsAccessorSubclass::GetKeyForIndex(backing_store, y);
+ MaybeObject* maybe_value =
+ ElementsAccessorSubclass::Get(backing_store, key, holder, receiver);
+ Object* value;
+ if (!maybe_value->ToObject(&value)) return maybe_value;
+ if (!value->IsTheHole() && !HasKey(to, value)) {
+ result->set(len0 + index, value);
+ index++;
+ }
}
}
ASSERT(extra == index);
return result;
}
- static uint32_t GetLength(BackingStoreClass* backing_store) {
+ protected:
+ static uint32_t GetCapacity(BackingStoreClass* backing_store) {
return backing_store->length();
}
- static uint32_t GetCapacity(BackingStoreClass* backing_store) {
- return GetLength(backing_store);
+ virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
+ return ElementsAccessorSubclass::GetCapacity(
+ BackingStoreClass::cast(backing_store));
}
- static MaybeObject* GetElementAtCapacityIndex(
- BackingStoreClass* backing_store,
- int index) {
- return backing_store->get(index);
+ static bool HasElementAtIndex(BackingStoreClass* backing_store,
+ uint32_t index,
+ JSObject* holder,
+ Object* receiver) {
+ uint32_t key =
+ ElementsAccessorSubclass::GetKeyForIndex(backing_store, index);
+ MaybeObject* element = ElementsAccessorSubclass::Get(backing_store,
+ key,
+ holder,
+ receiver);
+ return !element->IsTheHole();
+ }
+
+ virtual bool HasElementAtIndex(FixedArrayBase* backing_store,
+ uint32_t index,
+ JSObject* holder,
+ Object* receiver) {
+ return ElementsAccessorSubclass::HasElementAtIndex(
+ BackingStoreClass::cast(backing_store), index, holder, receiver);
+ }
+
+ static uint32_t GetKeyForIndex(BackingStoreClass* backing_store,
+ uint32_t index) {
+ return index;
+ }
+
+ virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
+ uint32_t index) {
+ return ElementsAccessorSubclass::GetKeyForIndex(
+ BackingStoreClass::cast(backing_store), index);
}
private:
@@ -170,7 +226,7 @@ class FastElementsAccessor
: public ElementsAccessorBase<FastElementsAccessor, FixedArray> {
public:
static MaybeObject* DeleteCommon(JSObject* obj,
- uint32_t index) {
+ uint32_t key) {
ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements());
Heap* heap = obj->GetHeap();
FixedArray* backing_store = FixedArray::cast(obj->elements());
@@ -186,8 +242,8 @@ class FastElementsAccessor
obj->IsJSArray()
? Smi::cast(JSArray::cast(obj)->length())->value()
: backing_store->length());
- if (index < length) {
- backing_store->set_the_hole(index);
+ if (key < length) {
+ backing_store->set_the_hole(key);
// If an old space backing store is larger than a certain size and
// has too few used values, normalize it.
// To avoid doing the check on every delete we require at least
@@ -196,8 +252,8 @@ class FastElementsAccessor
const int kMinLengthForSparsenessCheck = 64;
if (backing_store->length() >= kMinLengthForSparsenessCheck &&
!heap->InNewSpace(backing_store) &&
- ((index > 0 && backing_store->get(index - 1) == hole) ||
- (index + 1 < length && backing_store->get(index + 1) == hole))) {
+ ((key > 0 && backing_store->get(key - 1) == hole) ||
+ (key + 1 < length && backing_store->get(key + 1) == hole))) {
int num_used = 0;
for (int i = 0; i < backing_store->length(); ++i) {
if (backing_store->get(i) != hole) ++num_used;
@@ -213,10 +269,11 @@ class FastElementsAccessor
return heap->true_value();
}
+ protected:
virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ uint32_t key,
JSReceiver::DeleteMode mode) {
- return DeleteCommon(obj, index);
+ return DeleteCommon(obj, key);
}
};
@@ -224,17 +281,28 @@ class FastElementsAccessor
class FastDoubleElementsAccessor
: public ElementsAccessorBase<FastDoubleElementsAccessor,
FixedDoubleArray> {
+ protected:
+ friend class ElementsAccessorBase<FastDoubleElementsAccessor,
+ FixedDoubleArray>;
+
virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ uint32_t key,
JSReceiver::DeleteMode mode) {
int length = obj->IsJSArray()
? Smi::cast(JSArray::cast(obj)->length())->value()
: FixedDoubleArray::cast(obj->elements())->length();
- if (index < static_cast<uint32_t>(length)) {
- FixedDoubleArray::cast(obj->elements())->set_the_hole(index);
+ if (key < static_cast<uint32_t>(length)) {
+ FixedDoubleArray::cast(obj->elements())->set_the_hole(key);
}
return obj->GetHeap()->true_value();
}
+
+ static bool HasElementAtIndex(FixedDoubleArray* backing_store,
+ uint32_t index,
+ JSObject* holder,
+ Object* receiver) {
+ return !backing_store->is_the_hole(index);
+ }
};
@@ -244,20 +312,23 @@ template<typename ExternalElementsAccessorSubclass,
class ExternalElementsAccessor
: public ElementsAccessorBase<ExternalElementsAccessorSubclass,
ExternalArray> {
- public:
- virtual MaybeObject* GetWithReceiver(JSObject* obj,
- Object* receiver,
- uint32_t index) {
- ExternalArray* backing_store = ExternalArray::cast(obj->elements());
- if (index < ExternalElementsAccessorSubclass::GetLength(backing_store)) {
- return backing_store->get(index);
+ protected:
+ friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
+ ExternalArray>;
+
+ static MaybeObject* Get(ExternalArray* backing_store,
+ uint32_t key,
+ JSObject* obj,
+ Object* receiver) {
+ if (key < ExternalElementsAccessorSubclass::GetCapacity(backing_store)) {
+ return backing_store->get(key);
} else {
- return obj->GetHeap()->undefined_value();
+ return backing_store->GetHeap()->undefined_value();
}
}
virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ uint32_t key,
JSReceiver::DeleteMode mode) {
// External arrays always ignore deletes.
return obj->GetHeap()->true_value();
@@ -323,30 +394,8 @@ class DictionaryElementsAccessor
: public ElementsAccessorBase<DictionaryElementsAccessor,
NumberDictionary> {
public:
- static MaybeObject* GetNumberDictionaryElement(
- JSObject* obj,
- Object* receiver,
- NumberDictionary* backing_store,
- uint32_t index) {
- int entry = backing_store->FindEntry(index);
- if (entry != NumberDictionary::kNotFound) {
- Object* element = backing_store->ValueAt(entry);
- PropertyDetails details = backing_store->DetailsAt(entry);
- if (details.type() == CALLBACKS) {
- return obj->GetElementWithCallback(receiver,
- element,
- index,
- obj);
- } else {
- return element;
- }
- }
- return obj->GetHeap()->the_hole_value();
- }
-
-
static MaybeObject* DeleteCommon(JSObject* obj,
- uint32_t index,
+ uint32_t key,
JSReceiver::DeleteMode mode) {
Isolate* isolate = obj->GetIsolate();
Heap* heap = isolate->heap();
@@ -357,11 +406,11 @@ class DictionaryElementsAccessor
backing_store = FixedArray::cast(backing_store->get(1));
}
NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
- int entry = dictionary->FindEntry(index);
+ int entry = dictionary->FindEntry(key);
if (entry != NumberDictionary::kNotFound) {
Object* result = dictionary->DeleteProperty(entry, mode);
if (result == heap->true_value()) {
- MaybeObject* maybe_elements = dictionary->Shrink(index);
+ MaybeObject* maybe_elements = dictionary->Shrink(key);
FixedArray* new_elements = NULL;
if (!maybe_elements->To(&new_elements)) {
return maybe_elements;
@@ -378,7 +427,7 @@ class DictionaryElementsAccessor
// throws an exception.
HandleScope scope(isolate);
Handle<Object> holder(obj);
- Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
+ Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
Handle<Object> args[2] = { name, holder };
Handle<Object> error =
isolate->factory()->NewTypeError("strict_delete_property",
@@ -389,32 +438,40 @@ class DictionaryElementsAccessor
return heap->true_value();
}
+ protected:
+ friend class ElementsAccessorBase<DictionaryElementsAccessor,
+ NumberDictionary>;
+
virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ uint32_t key,
JSReceiver::DeleteMode mode) {
- return DeleteCommon(obj, index, mode);
- }
-
- virtual MaybeObject* GetWithReceiver(JSObject* obj,
- Object* receiver,
- uint32_t index) {
- return GetNumberDictionaryElement(obj,
- receiver,
- obj->element_dictionary(),
- index);
+ return DeleteCommon(obj, key, mode);
}
- static uint32_t GetCapacity(NumberDictionary* dict) {
- return dict->Capacity();
+ static MaybeObject* Get(NumberDictionary* backing_store,
+ uint32_t key,
+ JSObject* obj,
+ Object* receiver) {
+ int entry = backing_store->FindEntry(key);
+ if (entry != NumberDictionary::kNotFound) {
+ Object* element = backing_store->ValueAt(entry);
+ PropertyDetails details = backing_store->DetailsAt(entry);
+ if (details.type() == CALLBACKS) {
+ return obj->GetElementWithCallback(receiver,
+ element,
+ key,
+ obj);
+ } else {
+ return element;
+ }
+ }
+ return obj->GetHeap()->the_hole_value();
}
- static MaybeObject* GetElementAtCapacityIndex(NumberDictionary* dict,
- int index) {
- if (dict->IsKey(dict->KeyAt(index))) {
- return dict->ValueAt(index);
- } else {
- return dict->GetHeap()->the_hole_value();
- }
+ static uint32_t GetKeyForIndex(NumberDictionary* dict,
+ uint32_t index) {
+ Object* key = dict->KeyAt(index);
+ return Smi::cast(key)->value();
}
};
@@ -422,15 +479,16 @@ class DictionaryElementsAccessor
class NonStrictArgumentsElementsAccessor
: public ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
FixedArray> {
- public:
- virtual MaybeObject* GetWithReceiver(JSObject* obj,
- Object* receiver,
- uint32_t index) {
- FixedArray* parameter_map = FixedArray::cast(obj->elements());
- uint32_t length = parameter_map->length();
- Object* probe =
- (index < length - 2) ? parameter_map->get(index + 2) : NULL;
- if (probe != NULL && !probe->IsTheHole()) {
+ protected:
+ friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
+ FixedArray>;
+
+ static MaybeObject* Get(FixedArray* parameter_map,
+ uint32_t key,
+ JSObject* obj,
+ Object* receiver) {
+ Object* probe = GetParameterMapArg(parameter_map, key);
+ if (!probe->IsTheHole()) {
Context* context = Context::cast(parameter_map->get(0));
int context_index = Smi::cast(probe)->value();
ASSERT(!context->get(context_index)->IsTheHole());
@@ -438,56 +496,105 @@ class NonStrictArgumentsElementsAccessor
} else {
// Object is not mapped, defer to the arguments.
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- if (arguments->IsDictionary()) {
- return DictionaryElementsAccessor::GetNumberDictionaryElement(
- obj,
- receiver,
- NumberDictionary::cast(arguments),
- index);
- } else if (index < static_cast<uint32_t>(arguments->length())) {
- return arguments->get(index);
- }
+ return ElementsAccessor::ForArray(arguments)->Get(arguments,
+ key,
+ obj,
+ receiver);
}
- return obj->GetHeap()->the_hole_value();
}
virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ uint32_t key
+ ,
JSReceiver::DeleteMode mode) {
FixedArray* parameter_map = FixedArray::cast(obj->elements());
- uint32_t length = parameter_map->length();
- Object* probe =
- index < (length - 2) ? parameter_map->get(index + 2) : NULL;
- if (probe != NULL && !probe->IsTheHole()) {
+ Object* probe = GetParameterMapArg(parameter_map, key);
+ if (!probe->IsTheHole()) {
// TODO(kmillikin): We could check if this was the last aliased
// parameter, and revert to normal elements in that case. That
// would enable GC of the context.
- parameter_map->set_the_hole(index + 2);
+ parameter_map->set_the_hole(key + 2);
} else {
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
if (arguments->IsDictionary()) {
- return DictionaryElementsAccessor::DeleteCommon(obj, index, mode);
+ return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
} else {
- return FastElementsAccessor::DeleteCommon(obj, index);
+ return FastElementsAccessor::DeleteCommon(obj, key);
}
}
return obj->GetHeap()->true_value();
}
- static uint32_t GetCapacity(FixedArray* obj) {
- // TODO(danno): Return max of parameter map length or backing store
- // capacity.
- return 0;
+ static uint32_t GetCapacity(FixedArray* parameter_map) {
+ FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
+ return Max(static_cast<uint32_t>(parameter_map->length() - 2),
+ ForArray(arguments)->GetCapacity(arguments));
}
- static MaybeObject* GetElementAtCapacityIndex(FixedArray* obj, int index) {
- // TODO(danno): Return either value from parameter map of backing
- // store value at index.
- return obj->GetHeap()->the_hole_value();
+ static uint32_t GetKeyForIndex(FixedArray* dict,
+ uint32_t index) {
+ return index;
+ }
+
+ static bool HasElementAtIndex(FixedArray* parameter_map,
+ uint32_t index,
+ JSObject* holder,
+ Object* receiver) {
+ Object* probe = GetParameterMapArg(parameter_map, index);
+ if (!probe->IsTheHole()) {
+ return true;
+ } else {
+ FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
+ ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
+ return !accessor->Get(arguments, index, holder, receiver)->IsTheHole();
+ }
+ }
+
+ private:
+ static Object* GetParameterMapArg(FixedArray* parameter_map,
+ uint32_t key) {
+ uint32_t length = parameter_map->length();
+ return key < (length - 2 )
+ ? parameter_map->get(key + 2)
+ : parameter_map->GetHeap()->the_hole_value();
}
};
+ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
+ switch (array->map()->instance_type()) {
+ case FIXED_ARRAY_TYPE:
+ if (array->IsDictionary()) {
+ return elements_accessors_[JSObject::DICTIONARY_ELEMENTS];
+ } else {
+ return elements_accessors_[JSObject::FAST_ELEMENTS];
+ }
+ case EXTERNAL_BYTE_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_BYTE_ELEMENTS];
+ case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
+ case EXTERNAL_SHORT_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_SHORT_ELEMENTS];
+ case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
+ case EXTERNAL_INT_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_INT_ELEMENTS];
+ case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS];
+ case EXTERNAL_FLOAT_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_FLOAT_ELEMENTS];
+ case EXTERNAL_DOUBLE_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_DOUBLE_ELEMENTS];
+ case EXTERNAL_PIXEL_ARRAY_TYPE:
+ return elements_accessors_[JSObject::EXTERNAL_PIXEL_ELEMENTS];
+ default:
+ UNREACHABLE();
+ return NULL;
+ break;
+ }
+}
+
+
void ElementsAccessor::InitializeOncePerProcess() {
static struct ConcreteElementsAccessors {
FastElementsAccessor fast_elements_handler;
diff --git a/deps/v8/src/elements.h b/deps/v8/src/elements.h
index 74e4ad6659..3eae303ed1 100644
--- a/deps/v8/src/elements.h
+++ b/deps/v8/src/elements.h
@@ -39,16 +39,19 @@ class ElementsAccessor {
public:
ElementsAccessor() { }
virtual ~ElementsAccessor() { }
- virtual MaybeObject* GetWithReceiver(JSObject* obj,
- Object* receiver,
- uint32_t index) = 0;
+ virtual MaybeObject* Get(FixedArrayBase* backing_store,
+ uint32_t key,
+ JSObject* holder,
+ Object* receiver) = 0;
- virtual MaybeObject* Delete(JSObject* obj,
- uint32_t index,
+ virtual MaybeObject* Delete(JSObject* holder,
+ uint32_t key,
JSReceiver::DeleteMode mode) = 0;
virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from,
- FixedArray* to) = 0;
+ FixedArray* to,
+ JSObject* holder,
+ Object* receiver) = 0;
// Returns a shared ElementsAccessor for the specified ElementsKind.
static ElementsAccessor* ForKind(JSObject::ElementsKind elements_kind) {
@@ -56,8 +59,31 @@ class ElementsAccessor {
return elements_accessors_[elements_kind];
}
+ static ElementsAccessor* ForArray(FixedArrayBase* array);
+
static void InitializeOncePerProcess();
+ protected:
+ friend class NonStrictArgumentsElementsAccessor;
+
+ virtual uint32_t GetCapacity(FixedArrayBase* backing_store) = 0;
+
+ virtual bool HasElementAtIndex(FixedArrayBase* backing_store,
+ uint32_t index,
+ JSObject* holder,
+ Object* receiver) = 0;
+
+ // Element handlers distinguish between indexes and keys when the manipulate
+ // elements. Indexes refer to elements in terms of their location in the
+ // underlying storage's backing store representation, and are between 0
+ // GetCapacity. Keys refer to elements in terms of the value that would be
+ // specific in JavaScript to access the element. In most implementations, keys
+ // are equivalent to indexes, and GetKeyForIndex returns the same value it is
+ // passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps the
+ // index to a key using the KeyAt method on the NumberDictionary.
+ virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
+ uint32_t index) = 0;
+
private:
static ElementsAccessor** elements_accessors_;
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc
index 732a8fe7d0..fc7b6899bc 100644
--- a/deps/v8/src/full-codegen.cc
+++ b/deps/v8/src/full-codegen.cc
@@ -862,7 +862,7 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
VisitStatements(stmt->statements());
scope_ = saved_scope;
- __ bind(nested_statement.break_target());
+ __ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@@ -932,8 +932,7 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
context_register());
}
- Iteration* loop = current->AsIteration();
- __ jmp(loop->continue_target());
+ __ jmp(current->AsIteration()->continue_label());
}
@@ -961,8 +960,7 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
context_register());
}
- Breakable* target = current->AsBreakable();
- __ jmp(target->break_target());
+ __ jmp(current->AsBreakable()->break_label());
}
@@ -1030,12 +1028,12 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
// Record the position of the do while condition and make sure it is
// possible to break on the condition.
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
SetExpressionPosition(stmt->cond(), stmt->condition_position());
VisitForControl(stmt->cond(),
&stack_check,
- loop_statement.break_target(),
+ loop_statement.break_label(),
&stack_check);
// Check stack before looping.
@@ -1045,7 +1043,7 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
__ jmp(&body);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
decrement_loop_depth();
}
@@ -1066,7 +1064,7 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
// Emit the statement position here as this is where the while
// statement code starts.
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
SetStatementPosition(stmt);
// Check stack before looping.
@@ -1075,11 +1073,11 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
__ bind(&test);
VisitForControl(stmt->cond(),
&body,
- loop_statement.break_target(),
- loop_statement.break_target());
+ loop_statement.break_label(),
+ loop_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
decrement_loop_depth();
}
@@ -1102,7 +1100,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
Visit(stmt->body());
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
SetStatementPosition(stmt);
if (stmt->next() != NULL) {
Visit(stmt->next());
@@ -1119,14 +1117,14 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
if (stmt->cond() != NULL) {
VisitForControl(stmt->cond(),
&body,
- loop_statement.break_target(),
- loop_statement.break_target());
+ loop_statement.break_label(),
+ loop_statement.break_label());
} else {
__ jmp(&body);
}
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
decrement_loop_depth();
}
@@ -1144,7 +1142,7 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// to introduce a new scope to bind the catch variable and to remove
// that scope again afterwards.
- Label try_handler_setup, catch_entry, done;
+ Label try_handler_setup, done;
__ Call(&try_handler_setup);
// Try handler code, exception in result register.
@@ -1170,12 +1168,13 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// Try block code. Sets up the exception handler chain.
__ bind(&try_handler_setup);
{
- TryCatch try_block(this, &catch_entry);
+ const int delta = StackHandlerConstants::kSize / kPointerSize;
+ TryCatch try_block(this);
__ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
- increment_stack_height(StackHandlerConstants::kSize / kPointerSize);
+ increment_stack_height(delta);
Visit(stmt->try_block());
__ PopTryHandler();
- decrement_stack_height(StackHandlerConstants::kSize / kPointerSize);
+ decrement_stack_height(delta);
}
__ bind(&done);
}
@@ -1208,9 +1207,6 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Label finally_entry;
Label try_handler_setup;
const int original_stack_height = stack_height();
- const int finally_block_stack_height = original_stack_height + 2;
- const int try_block_stack_height = original_stack_height + 5;
- STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
// Setup the try-handler chain. Use a call to
// Jump to try-handler setup and try-block code. Use call to put try-handler
@@ -1219,9 +1215,9 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// Try handler code. Return address of call is pushed on handler stack.
{
// This code is only executed during stack-handler traversal when an
- // exception is thrown. The execption is in the result register, which
+ // exception is thrown. The exception is in the result register, which
// is retained by the finally block.
- // Call the finally block and then rethrow the exception.
+ // Call the finally block and then rethrow the exception if it returns.
__ Call(&finally_entry);
__ push(result_register());
__ CallRuntime(Runtime::kReThrow, 1);
@@ -1232,7 +1228,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// Finally block implementation.
Finally finally_block(this);
EnterFinallyBlock();
- set_stack_height(finally_block_stack_height);
+ set_stack_height(original_stack_height + Finally::kElementCount);
Visit(stmt->finally_block());
ExitFinallyBlock(); // Return to the calling code.
}
@@ -1240,9 +1236,10 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
__ bind(&try_handler_setup);
{
// Setup try handler (stack pointer registers).
+ const int delta = StackHandlerConstants::kSize / kPointerSize;
TryFinally try_block(this, &finally_entry);
__ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
- set_stack_height(try_block_stack_height);
+ set_stack_height(original_stack_height + delta);
Visit(stmt->try_block());
__ PopTryHandler();
set_stack_height(original_stack_height);
diff --git a/deps/v8/src/full-codegen.h b/deps/v8/src/full-codegen.h
index 2fc0553661..0ed26a149e 100644
--- a/deps/v8/src/full-codegen.h
+++ b/deps/v8/src/full-codegen.h
@@ -111,10 +111,7 @@ class FullCodeGenerator: public AstVisitor {
private:
class Breakable;
class Iteration;
- class TryCatch;
- class TryFinally;
- class Finally;
- class ForIn;
+
class TestContext;
class NestedStatement BASE_EMBEDDED {
@@ -132,10 +129,6 @@ class FullCodeGenerator: public AstVisitor {
virtual Breakable* AsBreakable() { return NULL; }
virtual Iteration* AsIteration() { return NULL; }
- virtual TryCatch* AsTryCatch() { return NULL; }
- virtual TryFinally* AsTryFinally() { return NULL; }
- virtual Finally* AsFinally() { return NULL; }
- virtual ForIn* AsForIn() { return NULL; }
virtual bool IsContinueTarget(Statement* target) { return false; }
virtual bool IsBreakTarget(Statement* target) { return false; }
@@ -158,110 +151,102 @@ class FullCodeGenerator: public AstVisitor {
DISALLOW_COPY_AND_ASSIGN(NestedStatement);
};
+ // A breakable statement such as a block.
class Breakable : public NestedStatement {
public:
- Breakable(FullCodeGenerator* codegen,
- BreakableStatement* break_target)
- : NestedStatement(codegen),
- target_(break_target) {}
+ Breakable(FullCodeGenerator* codegen, BreakableStatement* statement)
+ : NestedStatement(codegen), statement_(statement) {
+ }
virtual ~Breakable() {}
+
virtual Breakable* AsBreakable() { return this; }
- virtual bool IsBreakTarget(Statement* statement) {
- return target_ == statement;
+ virtual bool IsBreakTarget(Statement* target) {
+ return statement() == target;
}
- BreakableStatement* statement() { return target_; }
- Label* break_target() { return &break_target_label_; }
+
+ BreakableStatement* statement() { return statement_; }
+ Label* break_label() { return &break_label_; }
+
private:
- BreakableStatement* target_;
- Label break_target_label_;
- DISALLOW_COPY_AND_ASSIGN(Breakable);
+ BreakableStatement* statement_;
+ Label break_label_;
};
+ // An iteration statement such as a while, for, or do loop.
class Iteration : public Breakable {
public:
- Iteration(FullCodeGenerator* codegen,
- IterationStatement* iteration_statement)
- : Breakable(codegen, iteration_statement) {}
+ Iteration(FullCodeGenerator* codegen, IterationStatement* statement)
+ : Breakable(codegen, statement) {
+ }
virtual ~Iteration() {}
+
virtual Iteration* AsIteration() { return this; }
- virtual bool IsContinueTarget(Statement* statement) {
- return this->statement() == statement;
+ virtual bool IsContinueTarget(Statement* target) {
+ return statement() == target;
}
- Label* continue_target() { return &continue_target_label_; }
+
+ Label* continue_label() { return &continue_label_; }
+
private:
- Label continue_target_label_;
- DISALLOW_COPY_AND_ASSIGN(Iteration);
+ Label continue_label_;
};
- // The environment inside the try block of a try/catch statement.
+ // The try block of a try/catch statement.
class TryCatch : public NestedStatement {
public:
- explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
- : NestedStatement(codegen), catch_entry_(catch_entry) { }
+ explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
+ }
virtual ~TryCatch() {}
- virtual TryCatch* AsTryCatch() { return this; }
- Label* catch_entry() { return catch_entry_; }
+
virtual NestedStatement* Exit(int* stack_depth, int* context_length);
- private:
- Label* catch_entry_;
- DISALLOW_COPY_AND_ASSIGN(TryCatch);
};
- // The environment inside the try block of a try/finally statement.
+ // The try block of a try/finally statement.
class TryFinally : public NestedStatement {
public:
- explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
- : NestedStatement(codegen), finally_entry_(finally_entry) { }
+ TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
+ : NestedStatement(codegen), finally_entry_(finally_entry) {
+ }
virtual ~TryFinally() {}
- virtual TryFinally* AsTryFinally() { return this; }
- Label* finally_entry() { return finally_entry_; }
+
virtual NestedStatement* Exit(int* stack_depth, int* context_length);
+
private:
Label* finally_entry_;
- DISALLOW_COPY_AND_ASSIGN(TryFinally);
};
- // A FinallyEnvironment represents being inside a finally block.
- // Abnormal termination of the finally block needs to clean up
- // the block's parameters from the stack.
+ // The finally block of a try/finally statement.
class Finally : public NestedStatement {
public:
+ static const int kElementCount = 2;
+
explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
virtual ~Finally() {}
- virtual Finally* AsFinally() { return this; }
+
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
- *stack_depth += kFinallyStackElementCount;
+ *stack_depth += kElementCount;
return previous_;
}
- private:
- // Number of extra stack slots occupied during a finally block.
- static const int kFinallyStackElementCount = 2;
- DISALLOW_COPY_AND_ASSIGN(Finally);
};
- // A ForInEnvironment represents being inside a for-in loop.
- // Abnormal termination of the for-in block needs to clean up
- // the block's temporary storage from the stack.
+ // The body of a for/in loop.
class ForIn : public Iteration {
public:
- ForIn(FullCodeGenerator* codegen,
- ForInStatement* statement)
- : Iteration(codegen, statement) { }
+ static const int kElementCount = 5;
+
+ ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
+ : Iteration(codegen, statement) {
+ }
virtual ~ForIn() {}
- virtual ForIn* AsForIn() { return this; }
+
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
- *stack_depth += kForInStackElementCount;
+ *stack_depth += kElementCount;
return previous_;
}
- private:
- static const int kForInStackElementCount = 5;
- DISALLOW_COPY_AND_ASSIGN(ForIn);
};
- // A WithOrCatch represents being inside the body of a with or catch
- // statement. Exiting the body needs to remove a link from the context
- // chain.
+ // The body of a with or catch.
class WithOrCatch : public NestedStatement {
public:
explicit WithOrCatch(FullCodeGenerator* codegen)
diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc
index bb75b1e6ac..07fd725823 100644
--- a/deps/v8/src/ia32/full-codegen-ia32.cc
+++ b/deps/v8/src/ia32/full-codegen-ia32.cc
@@ -875,7 +875,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
- __ jmp(nested_statement.break_target());
+ __ jmp(nested_statement.break_label());
} else {
__ jmp(default_clause->body_target());
}
@@ -890,7 +890,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
- __ bind(nested_statement.break_target());
+ __ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@@ -1006,12 +1006,13 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(eax); // Fixed array length (as smi).
__ push(Immediate(Smi::FromInt(0))); // Initial index.
- increment_stack_height(4);
+ // 1 ~ The object has already been pushed.
+ increment_stack_height(ForIn::kElementCount - 1);
// Generate code for doing the condition check.
__ bind(&loop);
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
- __ j(above_equal, loop_statement.break_target());
+ __ j(above_equal, loop_statement.break_label());
// Get the current entry of the array into register ebx.
__ mov(ebx, Operand(esp, 2 * kPointerSize));
@@ -1035,7 +1036,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(ebx); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ test(eax, Operand(eax));
- __ j(equal, loop_statement.continue_target());
+ __ j(equal, loop_statement.continue_label());
__ mov(ebx, Operand(eax));
// Update the 'each' property or variable from the possibly filtered
@@ -1052,17 +1053,17 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for going to the next element by incrementing the
// index (smi) stored on top of the stack.
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
__ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
EmitStackCheck(stmt);
__ jmp(&loop);
// Remove the pointers stored on the stack.
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
__ add(Operand(esp), Immediate(5 * kPointerSize));
- decrement_stack_height(5);
+ decrement_stack_height(ForIn::kElementCount);
// Exit and decrement the loop depth.
__ bind(&exit);
decrement_loop_depth();
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index 04e6cde4ed..9df5cad915 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -69,8 +69,8 @@ void MacroAssembler::RecordWriteHelper(Register object,
// Compute number of region covering addr. See Page::GetRegionNumberForAddress
// method for more details.
- and_(addr, Page::kPageAlignmentMask);
shr(addr, Page::kRegionSizeLog2);
+ and_(addr, Page::kPageAlignmentMask >> Page::kRegionSizeLog2);
// Set dirty mark for region.
// Bit tests with a memory operand should be avoided on Intel processors,
diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc
index eae812bcd9..09cbc8a1e6 100644
--- a/deps/v8/src/isolate.cc
+++ b/deps/v8/src/isolate.cc
@@ -1335,6 +1335,7 @@ void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
if (list_ == data) list_ = data->next_;
if (data->next_ != NULL) data->next_->prev_ = data->prev_;
if (data->prev_ != NULL) data->prev_->next_ = data->next_;
+ delete data;
}
@@ -1536,6 +1537,9 @@ Isolate::~Isolate() {
// Has to be called while counters_ are still alive.
zone_.DeleteKeptSegment();
+ delete[] assembler_spare_buffer_;
+ assembler_spare_buffer_ = NULL;
+
delete unicode_cache_;
unicode_cache_ = NULL;
@@ -1569,6 +1573,8 @@ Isolate::~Isolate() {
handle_scope_implementer_ = NULL;
delete break_access_;
break_access_ = NULL;
+ delete debugger_access_;
+ debugger_access_ = NULL;
delete compilation_cache_;
compilation_cache_ = NULL;
diff --git a/deps/v8/src/json.js b/deps/v8/src/json.js
index 6c984a157d..8fd410fa4d 100644
--- a/deps/v8/src/json.js
+++ b/deps/v8/src/json.js
@@ -237,7 +237,7 @@ function BasicSerializeArray(value, stack, builder) {
}
}
stack.pop();
- builder.push("]");
+ builder.push("]");
}
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index 58c9a53025..8ea31eaadb 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 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:
@@ -57,7 +57,7 @@ function FormatString(format, message) {
for (var i = 0; i < format.length; i++) {
var str = format[i];
for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
- if (format[i] !== kReplacementMarkers[arg_num]) continue;
+ if (str !== kReplacementMarkers[arg_num]) continue;
try {
str = ToDetailString(args[arg_num]);
} catch (e) {
@@ -100,7 +100,8 @@ function ToStringCheckErrorObject(obj) {
function ToDetailString(obj) {
- if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
+ if (obj != null && IS_OBJECT(obj) &&
+ obj.toString === $Object.prototype.toString) {
var constructor = obj.constructor;
if (!constructor) return ToStringCheckErrorObject(obj);
var constructorName = constructor.name;
@@ -207,7 +208,7 @@ function FormatMessage(message) {
stack_overflow: ["Maximum call stack size exceeded"],
// SyntaxError
unable_to_parse: ["Parse error"],
- duplicate_regexp_flag: ["Duplicate RegExp flag ", "%0"],
+ invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
illegal_break: ["Illegal break statement"],
illegal_continue: ["Illegal continue statement"],
@@ -560,6 +561,7 @@ function SourceLocation(script, position, line, column, start, end) {
this.end = end;
}
+SourceLocation.prototype.__proto__ = null;
const kLineLengthLimit = 78;
@@ -649,6 +651,7 @@ function SourceSlice(script, from_line, to_line, from_position, to_position) {
this.to_position = to_position;
}
+SourceSlice.prototype.__proto__ = null;
/**
* Get the source text for a SourceSlice
@@ -716,23 +719,28 @@ function CallSite(receiver, fun, pos) {
this.pos = pos;
}
+CallSite.prototype.__proto__ = null;
+
CallSite.prototype.getThis = function () {
return this.receiver;
};
CallSite.prototype.getTypeName = function () {
var constructor = this.receiver.constructor;
- if (!constructor)
+ if (!constructor) {
return %_CallFunction(this.receiver, ObjectToString);
+ }
var constructorName = constructor.name;
- if (!constructorName)
+ if (!constructorName) {
return %_CallFunction(this.receiver, ObjectToString);
+ }
return constructorName;
};
CallSite.prototype.isToplevel = function () {
- if (this.receiver == null)
+ if (this.receiver == null) {
return true;
+ }
return IS_GLOBAL(this.receiver);
};
@@ -765,8 +773,9 @@ CallSite.prototype.getFunctionName = function () {
}
// Maybe this is an evaluation?
var script = %FunctionGetScript(this.fun);
- if (script && script.compilation_type == COMPILATION_TYPE_EVAL)
+ if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
return "eval";
+ }
return null;
};
@@ -788,13 +797,15 @@ CallSite.prototype.getMethodName = function () {
this.receiver.__lookupSetter__(prop) === this.fun ||
(!this.receiver.__lookupGetter__(prop) && this.receiver[prop] === this.fun)) {
// If we find more than one match bail out to avoid confusion.
- if (name)
+ if (name) {
return null;
+ }
name = prop;
}
}
- if (name)
+ if (name) {
return name;
+ }
return null;
};
@@ -804,8 +815,9 @@ CallSite.prototype.getFileName = function () {
};
CallSite.prototype.getLineNumber = function () {
- if (this.pos == -1)
+ if (this.pos == -1) {
return null;
+ }
var script = %FunctionGetScript(this.fun);
var location = null;
if (script) {
@@ -815,8 +827,9 @@ CallSite.prototype.getLineNumber = function () {
};
CallSite.prototype.getColumnNumber = function () {
- if (this.pos == -1)
+ if (this.pos == -1) {
return null;
+ }
var script = %FunctionGetScript(this.fun);
var location = null;
if (script) {
@@ -836,15 +849,17 @@ CallSite.prototype.getPosition = function () {
CallSite.prototype.isConstructor = function () {
var constructor = this.receiver ? this.receiver.constructor : null;
- if (!constructor)
+ if (!constructor) {
return false;
+ }
return this.fun === constructor;
};
function FormatEvalOrigin(script) {
var sourceURL = script.nameOrSourceURL();
- if (sourceURL)
+ if (sourceURL) {
return sourceURL;
+ }
var eval_origin = "eval at ";
if (script.eval_from_function_name) {
@@ -1042,8 +1057,9 @@ function DefineError(f) {
function captureStackTrace(obj, cons_opt) {
var stackTraceLimit = $Error.stackTraceLimit;
if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
- if (stackTraceLimit < 0 || stackTraceLimit > 10000)
+ if (stackTraceLimit < 0 || stackTraceLimit > 10000) {
stackTraceLimit = 10000;
+ }
var raw_stack = %CollectStackTrace(cons_opt
? cons_opt
: captureStackTrace, stackTraceLimit);
@@ -1117,8 +1133,10 @@ function errorToString() {
} catch(e) {
// If this error message was encountered already return the empty
// string for it instead of recursively formatting it.
- if (isCyclicErrorMarker(e)) return '';
- else throw e;
+ if (isCyclicErrorMarker(e)) {
+ return '';
+ }
+ throw e;
}
}
diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc
index d8909c9ddd..e1a23b4ed2 100644
--- a/deps/v8/src/mips/full-codegen-mips.cc
+++ b/deps/v8/src/mips/full-codegen-mips.cc
@@ -747,9 +747,9 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ li(a2, Operand(variable->name()));
// Declaration nodes are always introduced in one of two modes.
ASSERT(mode == Variable::VAR ||
- mode == Variable::CONST);
- PropertyAttributes attr =
- (mode == Variable::VAR) ? NONE : READ_ONLY;
+ mode == Variable::CONST ||
+ mode == Variable::LET);
+ PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
__ li(a1, Operand(Smi::FromInt(attr)));
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
@@ -886,7 +886,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
- __ Branch(nested_statement.break_target());
+ __ Branch(nested_statement.break_label());
} else {
__ Branch(default_clause->body_target());
}
@@ -900,7 +900,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
- __ bind(nested_statement.break_target());
+ __ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@@ -1026,7 +1026,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Load the current count to a0, load the length to a1.
__ lw(a0, MemOperand(sp, 0 * kPointerSize));
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
- __ Branch(loop_statement.break_target(), hs, a0, Operand(a1));
+ __ Branch(loop_statement.break_label(), hs, a0, Operand(a1));
// Get the current entry of the array into register a3.
__ lw(a2, MemOperand(sp, 2 * kPointerSize));
@@ -1053,7 +1053,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(a3); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ mov(a3, result_register());
- __ Branch(loop_statement.continue_target(), eq, a3, Operand(zero_reg));
+ __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg));
// Update the 'each' property or variable from the possibly filtered
// entry in register a3.
@@ -1069,7 +1069,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for the going to the next element by incrementing
// the index (smi) stored on top of the stack.
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
__ pop(a0);
__ Addu(a0, a0, Operand(Smi::FromInt(1)));
__ push(a0);
@@ -1078,7 +1078,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Branch(&loop);
// Remove the pointers stored on the stack.
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
__ Drop(5);
// Exit and decrement the loop depth.
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 337dd65db0..1b29071324 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -656,10 +656,11 @@ MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
}
if (js_object->elements() != heap->empty_fixed_array()) {
- MaybeObject* result = js_object->GetElementsAccessor()->GetWithReceiver(
+ MaybeObject* result = js_object->GetElementsAccessor()->Get(
+ js_object->elements(),
+ index,
js_object,
- receiver,
- index);
+ receiver);
if (result != heap->the_hole_value()) return result;
}
}
@@ -4466,20 +4467,6 @@ void CodeCacheHashTable::RemoveByIndex(int index) {
}
-static bool HasKey(FixedArray* array, Object* key) {
- int len0 = array->length();
- for (int i = 0; i < len0; i++) {
- Object* element = array->get(i);
- if (element->IsSmi() && key->IsSmi() && (element == key)) return true;
- if (element->IsString() &&
- key->IsString() && String::cast(element)->Equals(String::cast(key))) {
- return true;
- }
- }
- return false;
-}
-
-
MaybeObject* PolymorphicCodeCache::Update(MapList* maps,
Code::Flags flags,
Code* code) {
@@ -4641,7 +4628,7 @@ MaybeObject* PolymorphicCodeCacheHashTable::Put(MapList* maps,
MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
ElementsAccessor* accessor = array->GetElementsAccessor();
MaybeObject* maybe_result =
- accessor->AddElementsToFixedArray(array->elements(), this);
+ accessor->AddElementsToFixedArray(array->elements(), this, array, array);
FixedArray* result;
if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
#ifdef DEBUG
@@ -4657,55 +4644,19 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
- int len0 = length();
+ ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
+ MaybeObject* maybe_result =
+ accessor->AddElementsToFixedArray(other, this, NULL, NULL);
+ FixedArray* result;
+ if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
#ifdef DEBUG
if (FLAG_enable_slow_asserts) {
- for (int i = 0; i < len0; i++) {
- ASSERT(get(i)->IsString() || get(i)->IsNumber());
+ for (int i = 0; i < result->length(); i++) {
+ Object* current = result->get(i);
+ ASSERT(current->IsNumber() || current->IsString());
}
}
#endif
- int len1 = other->length();
- // Optimize if 'other' is empty.
- // We cannot optimize if 'this' is empty, as other may have holes
- // or non keys.
- if (len1 == 0) return this;
-
- // Compute how many elements are not in this.
- int extra = 0;
- for (int y = 0; y < len1; y++) {
- Object* value = other->get(y);
- if (!value->IsTheHole() && !HasKey(this, value)) extra++;
- }
-
- if (extra == 0) return this;
-
- // Allocate the result
- Object* obj;
- { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- // Fill in the content
- AssertNoAllocation no_gc;
- FixedArray* result = FixedArray::cast(obj);
- WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
- for (int i = 0; i < len0; i++) {
- Object* e = get(i);
- ASSERT(e->IsString() || e->IsNumber());
- result->set(i, e, mode);
- }
- // Fill in the extra keys.
- int index = 0;
- for (int y = 0; y < len1; y++) {
- Object* value = other->get(y);
- if (!value->IsTheHole() && !HasKey(this, value)) {
- Object* e = other->get(y);
- ASSERT(e->IsString() || e->IsNumber());
- result->set(len0 + index, e, mode);
- index++;
- }
- }
- ASSERT(extra == index);
return result;
}
@@ -8718,9 +8669,10 @@ MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
Heap* heap = holder_handle->GetHeap();
ElementsAccessor* handler = holder_handle->GetElementsAccessor();
- MaybeObject* raw_result = handler->GetWithReceiver(*holder_handle,
- *this_handle,
- index);
+ MaybeObject* raw_result = handler->Get(holder_handle->elements(),
+ index,
+ *holder_handle,
+ *this_handle);
if (raw_result != heap->the_hole_value()) return raw_result;
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js
index 7b851a3574..a7f42d59c2 100644
--- a/deps/v8/src/regexp.js
+++ b/deps/v8/src/regexp.js
@@ -50,24 +50,29 @@ function DoConstructRegExp(object, pattern, flags) {
var global = false;
var ignoreCase = false;
var multiline = false;
-
for (var i = 0; i < flags.length; i++) {
var c = %_CallFunction(flags, i, StringCharAt);
switch (c) {
case 'g':
- // Allow duplicate flags to be consistent with JSC and others.
+ if (global) {
+ throw MakeSyntaxError("invalid_regexp_flags", [flags]);
+ }
global = true;
break;
case 'i':
+ if (ignoreCase) {
+ throw MakeSyntaxError("invalid_regexp_flags", [flags]);
+ }
ignoreCase = true;
break;
case 'm':
+ if (multiline) {
+ throw MakeSyntaxError("invalid_regexp_flags", [flags]);
+ }
multiline = true;
break;
default:
- // Ignore flags that have no meaning to be consistent with
- // JSC.
- break;
+ throw MakeSyntaxError("invalid_regexp_flags", [flags]);
}
}
diff --git a/deps/v8/src/scanner-base.cc b/deps/v8/src/scanner-base.cc
index 2ecbfd2a95..62eee1a548 100644
--- a/deps/v8/src/scanner-base.cc
+++ b/deps/v8/src/scanner-base.cc
@@ -41,12 +41,12 @@ Scanner::Scanner(UnicodeCache* unicode_cache)
: unicode_cache_(unicode_cache) { }
-uc32 Scanner::ScanHexEscape(uc32 c, int length) {
- ASSERT(length <= 4); // prevent overflow
+uc32 Scanner::ScanHexNumber(int expected_length) {
+ ASSERT(expected_length <= 4); // prevent overflow
- uc32 digits[4];
+ uc32 digits[4] = { 0, 0, 0, 0 };
uc32 x = 0;
- for (int i = 0; i < length; i++) {
+ for (int i = 0; i < expected_length; i++) {
digits[i] = c0_;
int d = HexValue(c0_);
if (d < 0) {
@@ -54,12 +54,11 @@ uc32 Scanner::ScanHexEscape(uc32 c, int length) {
// should be illegal, but other JS VMs just return the
// non-escaped version of the original character.
- // Push back digits read, except the last one (in c0_).
+ // Push back digits that we have advanced past.
for (int j = i-1; j >= 0; j--) {
PushBack(digits[j]);
}
- // Notice: No handling of error - treat it as "\u"->"u".
- return c;
+ return -1;
}
x = x * 16 + d;
Advance();
@@ -640,9 +639,17 @@ void JavaScriptScanner::ScanEscape() {
case 'n' : c = '\n'; break;
case 'r' : c = '\r'; break;
case 't' : c = '\t'; break;
- case 'u' : c = ScanHexEscape(c, 4); break;
+ case 'u' : {
+ c = ScanHexNumber(4);
+ if (c < 0) c = 'u';
+ break;
+ }
case 'v' : c = '\v'; break;
- case 'x' : c = ScanHexEscape(c, 2); break;
+ case 'x' : {
+ c = ScanHexNumber(2);
+ if (c < 0) c = 'x';
+ break;
+ }
case '0' : // fall through
case '1' : // fall through
case '2' : // fall through
@@ -802,13 +809,11 @@ Token::Value JavaScriptScanner::ScanNumber(bool seen_period) {
uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() {
Advance();
- if (c0_ != 'u') return unibrow::Utf8::kBadChar;
+ if (c0_ != 'u') return -1;
Advance();
- uc32 c = ScanHexEscape('u', 4);
- // We do not allow a unicode escape sequence to start another
- // unicode escape sequence.
- if (c == '\\') return unibrow::Utf8::kBadChar;
- return c;
+ uc32 result = ScanHexNumber(4);
+ if (result < 0) PushBack('u');
+ return result;
}
@@ -926,7 +931,11 @@ Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
if (c0_ == '\\') {
uc32 c = ScanIdentifierUnicodeEscape();
// Only allow legal identifier start characters.
- if (!unicode_cache_->IsIdentifierStart(c)) return Token::ILLEGAL;
+ if (c < 0 ||
+ c == '\\' || // No recursive escapes.
+ !unicode_cache_->IsIdentifierStart(c)) {
+ return Token::ILLEGAL;
+ }
AddLiteralChar(c);
return ScanIdentifierSuffix(&literal);
}
@@ -966,7 +975,11 @@ Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) {
if (c0_ == '\\') {
uc32 c = ScanIdentifierUnicodeEscape();
// Only allow legal identifier part characters.
- if (!unicode_cache_->IsIdentifierPart(c)) return Token::ILLEGAL;
+ if (c < 0 ||
+ c == '\\' ||
+ !unicode_cache_->IsIdentifierPart(c)) {
+ return Token::ILLEGAL;
+ }
AddLiteralChar(c);
} else {
AddLiteralChar(c0_);
@@ -992,8 +1005,9 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
// the scanner should pass uninterpreted bodies to the RegExp
// constructor.
LiteralScope literal(this);
- if (seen_equal)
+ if (seen_equal) {
AddLiteralChar('=');
+ }
while (c0_ != '/' || in_character_class) {
if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
@@ -1025,20 +1039,47 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
}
+bool JavaScriptScanner::ScanLiteralUnicodeEscape() {
+ ASSERT(c0_ == '\\');
+ uc32 chars_read[6] = {'\\', 'u', 0, 0, 0, 0};
+ Advance();
+ int i = 1;
+ if (c0_ == 'u') {
+ i++;
+ while (i < 6) {
+ Advance();
+ if (!IsHexDigit(c0_)) break;
+ chars_read[i] = c0_;
+ i++;
+ }
+ }
+ if (i < 6) {
+ // Incomplete escape. Undo all advances and return false.
+ while (i > 0) {
+ i--;
+ PushBack(chars_read[i]);
+ }
+ return false;
+ }
+ // Complete escape. Add all chars to current literal buffer.
+ for (int i = 0; i < 6; i++) {
+ AddLiteralChar(chars_read[i]);
+ }
+ return true;
+}
+
+
bool JavaScriptScanner::ScanRegExpFlags() {
// Scan regular expression flags.
LiteralScope literal(this);
while (unicode_cache_->IsIdentifierPart(c0_)) {
- if (c0_ == '\\') {
- uc32 c = ScanIdentifierUnicodeEscape();
- if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
- // We allow any escaped character, unlike the restriction on
- // IdentifierPart when it is used to build an IdentifierName.
- AddLiteralChar(c);
- continue;
+ if (c0_ != '\\') {
+ AddLiteralCharAdvance();
+ } else {
+ if (!ScanLiteralUnicodeEscape()) {
+ break;
}
}
- AddLiteralCharAdvance();
}
literal.Complete();
diff --git a/deps/v8/src/scanner-base.h b/deps/v8/src/scanner-base.h
index 3e1772a3d2..a7062a34af 100644
--- a/deps/v8/src/scanner-base.h
+++ b/deps/v8/src/scanner-base.h
@@ -419,7 +419,7 @@ class Scanner {
}
}
- uc32 ScanHexEscape(uc32 c, int length);
+ uc32 ScanHexNumber(int expected_length);
// Return the current source position.
int source_pos() {
@@ -537,6 +537,10 @@ class JavaScriptScanner : public Scanner {
// Decodes a unicode escape-sequence which is part of an identifier.
// If the escape sequence cannot be decoded the result is kBadChar.
uc32 ScanIdentifierUnicodeEscape();
+ // Recognizes a uniocde escape-sequence and adds its characters,
+ // uninterpreted, to the current literal. Used for parsing RegExp
+ // flags.
+ bool ScanLiteralUnicodeEscape();
// Start position of the octal literal last scanned.
Location octal_pos_;
diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h
index d8ed27e490..a0f4ba155d 100644
--- a/deps/v8/src/spaces.h
+++ b/deps/v8/src/spaces.h
@@ -409,6 +409,7 @@ class Space : public Malloced {
class CodeRange {
public:
explicit CodeRange(Isolate* isolate);
+ ~CodeRange() { TearDown(); }
// Reserves a range of virtual memory, but does not commit any of it.
// Can only be called once, at heap initialization time.
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index 2a5c95e450..e0f20c2f69 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -170,7 +170,7 @@ function StringLocaleCompare(other) {
["String.prototype.localeCompare"]);
}
if (%_ArgumentsLength() === 0) return 0;
- return %StringLocaleCompare(TO_STRING_INLINE(this),
+ return %StringLocaleCompare(TO_STRING_INLINE(this),
TO_STRING_INLINE(other));
}
@@ -914,6 +914,8 @@ function ReplaceResultBuilder(str) {
this.special_string = str;
}
+ReplaceResultBuilder.prototype.__proto__ = null;
+
ReplaceResultBuilder.prototype.add = function(str) {
str = TO_STRING_INLINE(str);
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
index 88525f6b44..c16d73e82e 100644
--- a/deps/v8/src/v8natives.js
+++ b/deps/v8/src/v8natives.js
@@ -462,6 +462,7 @@ function PropertyDescriptor() {
}
PropertyDescriptor.prototype.__proto__ = null;
+
PropertyDescriptor.prototype.toString = function() {
return "[object PropertyDescriptor]";
};
@@ -1015,24 +1016,27 @@ function ObjectDefineProperty(obj, p, attributes) {
}
+function GetOwnEnumerablePropertyNames(properties) {
+ var names = new InternalArray();
+ for (var key in properties) {
+ if (%HasLocalProperty(properties, key)) {
+ names.push(key);
+ }
+ }
+ return names;
+}
+
+
// ES5 section 15.2.3.7.
function ObjectDefineProperties(obj, properties) {
if (!IS_SPEC_OBJECT(obj))
throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]);
var props = ToObject(properties);
- var key_values = [];
- for (var key in props) {
- if (%HasLocalProperty(props, key)) {
- key_values.push(key);
- var value = props[key];
- var desc = ToPropertyDescriptor(value);
- key_values.push(desc);
- }
- }
- for (var i = 0; i < key_values.length; i += 2) {
- var key = key_values[i];
- var desc = key_values[i + 1];
- DefineOwnProperty(obj, key, desc, true);
+ var names = GetOwnEnumerablePropertyNames(props);
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ var desc = ToPropertyDescriptor(props[name]);
+ DefineOwnProperty(obj, name, desc, true);
}
return obj;
}
diff --git a/deps/v8/src/v8threads.cc b/deps/v8/src/v8threads.cc
index 52f82e2911..3881d66fb0 100644
--- a/deps/v8/src/v8threads.cc
+++ b/deps/v8/src/v8threads.cc
@@ -305,7 +305,9 @@ ThreadManager::ThreadManager()
ThreadManager::~ThreadManager() {
- // TODO(isolates): Destroy mutexes.
+ delete mutex_;
+ delete free_anchor_;
+ delete in_use_anchor_;
}
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index c39af566f9..e3cecdf99d 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 5
-#define BUILD_NUMBER 6
+#define BUILD_NUMBER 7
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index d0c71be12f..5567df2fa6 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -842,7 +842,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
- __ jmp(nested_statement.break_target());
+ __ jmp(nested_statement.break_label());
} else {
__ jmp(default_clause->body_target());
}
@@ -856,7 +856,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
- __ bind(nested_statement.break_target());
+ __ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@@ -982,7 +982,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&loop);
__ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
__ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
- __ j(above_equal, loop_statement.break_target());
+ __ j(above_equal, loop_statement.break_label());
// Get the current entry of the array into register rbx.
__ movq(rbx, Operand(rsp, 2 * kPointerSize));
@@ -1010,7 +1010,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(rbx); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ Cmp(rax, Smi::FromInt(0));
- __ j(equal, loop_statement.continue_target());
+ __ j(equal, loop_statement.continue_label());
__ movq(rbx, rax);
// Update the 'each' property or variable from the possibly filtered
@@ -1027,14 +1027,14 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for going to the next element by incrementing the
// index (smi) stored on top of the stack.
- __ bind(loop_statement.continue_target());
+ __ bind(loop_statement.continue_label());
__ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
EmitStackCheck(stmt);
__ jmp(&loop);
// Remove the pointers stored on the stack.
- __ bind(loop_statement.break_target());
+ __ bind(loop_statement.break_label());
__ addq(rsp, Immediate(5 * kPointerSize));
// Exit and decrement the loop depth.
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index d5e17b89a7..3ed6b523f0 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -3617,6 +3617,52 @@ THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
}
+Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator(
+ const AccessorInfo& info) {
+ // Force the list of returned keys to be stored in a Arguments object.
+ Local<Script> indexed_property_names_script = Script::Compile(v8_str(
+ "function f(w,x) {"
+ " return arguments;"
+ "}"
+ "keys = f(0, 1, 2, 3);"
+ "keys;"));
+ Local<Value> result = indexed_property_names_script->Run();
+ return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result)));
+}
+
+
+static v8::Handle<Value> NonStrictIndexedPropertyGetter(
+ uint32_t index,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ if (index < 4) {
+ return v8::Handle<Value>(v8_num(index));
+ }
+ return v8::Handle<Value>();
+}
+
+
+// Make sure that the the interceptor code in the runtime properly handles
+// merging property name lists for non-string arguments arrays.
+THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
+ 0,
+ 0,
+ 0,
+ NonStrictArgsIndexedPropertyEnumerator);
+ LocalContext context;
+ context->Global()->Set(v8_str("obj"), templ->NewInstance());
+ Local<Script> create_args_script =
+ Script::Compile(v8_str(
+ "var key_count = 0;"
+ "for (x in obj) {key_count++;} key_count;"));
+ Local<Value> result = create_args_script->Run();
+ CHECK_EQ(v8_num(4), result);
+}
+
+
static v8::Handle<Value> IdentityIndexedPropertyGetter(
uint32_t index,
const AccessorInfo& info) {
diff --git a/deps/v8/test/mjsunit/regress/regress-1620.js b/deps/v8/test/mjsunit/regress/regress-1620.js
new file mode 100644
index 0000000000..6d72974566
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1620.js
@@ -0,0 +1,54 @@
+// 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:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Don't allow malformed unicode escape sequences in identifiers.
+// In strings and regexps we currently allow malformed unicode escape
+// sequences without throwing a SyntaxError. Instead "\u22gk" would
+// treat the "\u" as an identity escape, and evaluate to "u22gk".
+// Due to code sharing, we did the same in identifiers. This should
+// no longer be the case.
+// See: http://code.google.com/p/v8/issues/detail?id=1620
+
+assertThrows("var \\u\\u\\u = 42;");
+assertThrows("var \\u41 = 42;");
+assertThrows("var \\u123 = 42;");
+eval("var \\u1234 = 42;");
+assertEquals(42, eval("\u1234"));
+assertThrows("var uuu = 42; var x = \\u\\u\\u");
+
+// Regressions introduced and fixed again while fixing the above.
+
+// Handle 0xFFFD correctly (it's a valid value, and shouldn't be used
+// to mark an error).
+assertEquals(0xFFFD, "\uFFFD".charCodeAt(0));
+
+// Handle unicode escapes in regexp flags correctly.
+assertThrows("/x/g\\uim", SyntaxError);
+assertThrows("/x/g\\u2im", SyntaxError);
+assertThrows("/x/g\\u22im", SyntaxError);
+assertThrows("/x/g\\u222im", SyntaxError);
+assertThrows("/x/g\\\\u2222im", SyntaxError);
diff --git a/deps/v8/test/mjsunit/regress/regress-1625.js b/deps/v8/test/mjsunit/regress/regress-1625.js
new file mode 100644
index 0000000000..a2ef8df652
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1625.js
@@ -0,0 +1,36 @@
+// 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:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that overwriting Array.prototype.push does not make
+// Object.defineProperties misbehave.
+
+Array.prototype.push = 1;
+var desc = {foo: {value: 10}, bar: {get: function() {return 42; }}};
+var obj = {};
+var x = Object.defineProperties(obj, desc);
+assertEquals(x.foo, 10);
+assertEquals(x.bar, 42);
diff --git a/deps/v8/test/mjsunit/regress/regress-219.js b/deps/v8/test/mjsunit/regress/regress-219.js
index 4bfabdcf43..b751f0f60f 100644
--- a/deps/v8/test/mjsunit/regress/regress-219.js
+++ b/deps/v8/test/mjsunit/regress/regress-219.js
@@ -30,6 +30,10 @@
// We should now allow duplicates of flags.
// (See http://code.google.com/p/v8/issues/detail?id=219)
+// This has been reversed by issue 1628, since other browsers have also
+// tightened their syntax.
+// (See http://code.google.com/p/v8/issues/detail?id=1628)
+
// Base tests: we recognize the basic flags
function assertFlags(re, global, multiline, ignoreCase) {
@@ -53,124 +57,92 @@ assertFlags(re, true, true, true)
// Double i's
-re = /a/ii;
-assertFlags(re, false, false, true)
-
-re = /a/gii;
-assertFlags(re, true, false, true)
+assertThrows("/a/ii");
-re = /a/igi;
-assertFlags(re, true, false, true)
+assertThrows("/a/gii");
-re = /a/iig;
-assertFlags(re, true, false, true)
+assertThrows("/a/igi");
-re = /a/gimi;
-assertFlags(re, true, true, true)
+assertThrows("/a/iig");
-re = /a/giim;
-assertFlags(re, true, true, true)
+assertThrows("/a/gimi");
-re = /a/igim;
-assertFlags(re, true, true, true)
+assertThrows("/a/giim");
+assertThrows("/a/igim");
-re = RegExp("a", "ii");
-assertFlags(re, false, false, true)
+assertThrows(function(){ return RegExp("a", "ii"); })
-re = RegExp("a", "gii");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "gii"); })
-re = RegExp("a", "igi");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "igi"); })
-re = RegExp("a", "iig");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "iig"); })
-re = RegExp("a", "gimi");
-assertFlags(re, true, true, true)
+assertThrows(function(){ return RegExp("a", "gimi"); })
-re = RegExp("a", "giim");
-assertFlags(re, true, true, true)
+assertThrows(function(){ return RegExp("a", "giim"); })
-re = RegExp("a", "igim");
-assertFlags(re, true, true, true)
+assertThrows(function(){ return RegExp("a", "igim"); })
// Tripple i's
-re = /a/iii;
-assertFlags(re, false, false, true)
+assertThrows("/a/iii");
-re = /a/giii;
-assertFlags(re, true, false, true)
+assertThrows("/a/giii");
-re = /a/igii;
-assertFlags(re, true, false, true)
+assertThrows("/a/igii");
-re = /a/iigi;
-assertFlags(re, true, false, true)
+assertThrows("/a/iigi");
-re = /a/iiig;
-assertFlags(re, true, false, true)
-
-re = /a/miiig;
-assertFlags(re, true, true, true)
+assertThrows("/a/iiig");
+assertThrows("/a/miiig");
-re = RegExp("a", "iii");
-assertFlags(re, false, false, true)
+assertThrows(function(){ return RegExp("a", "iii"); })
-re = RegExp("a", "giii");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "giii"); })
-re = RegExp("a", "igii");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "igii"); })
-re = RegExp("a", "iigi");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "iigi"); })
-re = RegExp("a", "iiig");
-assertFlags(re, true, false, true)
+assertThrows(function(){ return RegExp("a", "iiig"); })
-re = RegExp("a", "miiig");
-assertFlags(re, true, true, true)
+assertThrows(function(){ return RegExp("a", "miiig"); })
-// Illegal flags - flags late in string.
+// Illegal flags - valid flags late in string.
-re = /a/arglebargleglopglyf;
-assertFlags(re, true, false, false)
+assertThrows("/a/arglebargleglopglyf");
-re = /a/arglebargleglopglif;
-assertFlags(re, true, false, true)
+assertThrows("/a/arglebargleglopglif");
-re = /a/arglebargleglopglym;
-assertFlags(re, true, true, false)
+assertThrows("/a/arglebargleglopglym");
-re = /a/arglebargleglopglim;
-assertFlags(re, true, true, true)
+assertThrows("/a/arglebargleglopglim");
// Case of flags still matters.
-re = /a/gmi;
+var re = /a/gmi;
assertFlags(re, true, true, true)
-re = /a/Gmi;
-assertFlags(re, false, true, true)
+assertThrows("/a/Gmi");
-re = /a/gMi;
-assertFlags(re, true, false, true)
+assertThrows("/a/gMi");
-re = /a/gmI;
-assertFlags(re, true, true, false)
+assertThrows("/a/gmI");
-re = /a/GMi;
-assertFlags(re, false, false, true)
+assertThrows("/a/GMi");
-re = /a/GmI;
-assertFlags(re, false, true, false)
+assertThrows("/a/GmI");
-re = /a/gMI;
-assertFlags(re, true, false, false)
+assertThrows("/a/gMI");
-re = /a/GMI;
-assertFlags(re, false, false, false)
+assertThrows("/a/GMI");
+
+// Unicode escape sequences are not interpreted.
+
+assertThrows("/a/\\u0067");
+assertThrows("/a/\\u0069");
+assertThrows("/a/\\u006d");
+assertThrows("/a/\\u006D");
diff --git a/deps/v8/test/mjsunit/regress/regress-87.js b/deps/v8/test/mjsunit/regress/regress-87.js
index 131cb58edc..10446fdf45 100644
--- a/deps/v8/test/mjsunit/regress/regress-87.js
+++ b/deps/v8/test/mjsunit/regress/regress-87.js
@@ -25,34 +25,29 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-function testFlags(flagstring, global, ignoreCase, multiline) {
- var text = "/x/"+flagstring;
- var re = eval(text);
- assertEquals(global, re.global, text + ".global");
- assertEquals(ignoreCase, re.ignoreCase, text + ".ignoreCase");
- assertEquals(multiline, re.multiline, text + ".multiline");
-}
-
-testFlags("", false, false, false);
-
-testFlags("\u0067", true, false, false);
-
-testFlags("\u0069", false, true, false)
-
-testFlags("\u006d", false, false, true);
-
-testFlags("\u0068", false, false, false);
-
-testFlags("\u0020", false, false, false);
-
-
-testFlags("\u0067g", true, false, false);
-
-testFlags("g\u0067", true, false, false);
-
-testFlags("abc\u0067efg", true, false, false);
-
-testFlags("i\u0067", true, true, false);
-
-testFlags("\u0067i", true, true, false);
-
+// In Issue 87, we allowed unicode escape sequences in RegExp flags.
+// However, according to ES5, they should not be interpreted, but passed
+// verbatim to the RegExp constructor.
+// (On top of that, the original test was bugged and never tested anything).
+// The behavior was changed in r8969 to not interpret escapes, but this
+// test didn't test that, and only failed when making invalid flag characters
+// an error too.
+
+assertThrows("/x/\\u0067");
+assertThrows("/x/\\u0069");
+assertThrows("/x/\\u006d");
+
+assertThrows("/x/\\u0067i");
+assertThrows("/x/\\u0069m");
+assertThrows("/x/\\u006dg");
+
+assertThrows("/x/m\\u0067");
+assertThrows("/x/g\\u0069");
+assertThrows("/x/i\\u006d");
+
+assertThrows("/x/m\\u0067i");
+assertThrows("/x/g\\u0069m");
+assertThrows("/x/i\\u006dg");
+
+assertThrows("/x/\\u0068");
+assertThrows("/x/\\u0020");
diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status
index c62d7705ad..f6d69257c6 100644
--- a/deps/v8/test/mozilla/mozilla.status
+++ b/deps/v8/test/mozilla/mozilla.status
@@ -246,9 +246,8 @@ ecma_3/Number/15.7.4.7-1: FAIL_OK
ecma_3/Number/15.7.4.6-1: FAIL_OK
#:=== RegExp:===
-# To be compatible with JSC we silently ignore flags that do not make
-# sense. These tests expects us to throw exceptions.
-ecma_3/RegExp/regress-57631: FAIL_OK
+# We don't match the syntax error message of Mozilla for invalid
+# RegExp flags.
ecma_3/RegExp/15.10.4.1-6: FAIL_OK
# PCRE doesn't allow subpattern nesting deeper than 200, this tests
diff --git a/deps/v8/test/sputnik/sputnik.status b/deps/v8/test/sputnik/sputnik.status
index 82d8a61c7a..868509d7c5 100644
--- a/deps/v8/test/sputnik/sputnik.status
+++ b/deps/v8/test/sputnik/sputnik.status
@@ -56,15 +56,6 @@ S15.10.6.3_A1_T16: FAIL_OK
# errors, for compatibility.
S15.10.2.11_A1_T2: FAIL
S15.10.2.11_A1_T3: FAIL
-S15.10.4.1_A5_T1: FAIL
-S15.10.4.1_A5_T2: FAIL
-S15.10.4.1_A5_T3: FAIL
-S15.10.4.1_A5_T4: FAIL
-S15.10.4.1_A5_T5: FAIL
-S15.10.4.1_A5_T6: FAIL
-S15.10.4.1_A5_T7: FAIL
-S15.10.4.1_A5_T8: FAIL
-S15.10.4.1_A5_T9: FAIL
# We are more lenient in which string character escapes we allow than
# the spec (7.8.4 p. 19) wants us to be. This is for compatibility.
@@ -99,6 +90,13 @@ S7.8.4_A7.4_T1: FAIL_OK
S7.8.4_A4.3_T5: FAIL_OK
S7.8.4_A7.2_T5: FAIL_OK
+# Sputnik expects unicode escape sequences in RegExp flags to be interpreted.
+# The specification requires them to be passed uninterpreted to the RegExp
+# constructor. We now implement that.
+S7.8.5_A3.1_T7: FAIL_OK
+S7.8.5_A3.1_T8: FAIL_OK
+S7.8.5_A3.1_T9: FAIL_OK
+
# We allow some keywords to be used as identifiers.
S7.5.3_A1.15: FAIL_OK
S7.5.3_A1.18: FAIL_OK
diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp
index 03972463aa..97dc392bd1 100644
--- a/deps/v8/tools/gyp/v8.gyp
+++ b/deps/v8/tools/gyp/v8.gyp
@@ -144,7 +144,6 @@
'Debug': {
'defines': [
'DEBUG',
- '_DEBUG',
'ENABLE_DISASSEMBLER',
'V8_ENABLE_CHECKS',
'OBJECT_PRINT',
@@ -372,7 +371,10 @@
'<(INTERMEDIATE_DIR)/snapshot.cc',
],
'variables': {
- 'mksnapshot_flags': [],
+ 'mksnapshot_flags': [
+ '--log-snapshot-positions',
+ '--logfile', '<(INTERMEDIATE_DIR)/snapshot.log',
+ ],
},
'conditions': [
['v8_target_arch=="arm"', {